// // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. // // To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/1.0/ // // or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. // // Francais (brouillon): http://creativecommons.org/projects/international/fr/translated-license // ////////////////////////////////////////////////////////////////////////////////////////////////////// // Rendu des pages // v0.2.40 class rendu { var $err = array( "stop" => "oui", "log" => "oui", "debug" => "oui"); var $chemin = "../datas/"; var $types_boucles = array("ecrits","mois","forums","forums_mois"); // Gestion des erreurs function _err($err,$debug="") { // Si le debug est activé if($this->err[debug] == "oui" && !empty($debug)) $err.= "\n// DEBUG //\n".$debug; // Si on log les erreurs if($this->err[log] == "oui") $this->erreurs[] = $err; // Si on s'arrête sur les erreurs if($this->err[stop] == "oui") { echo "
".htmlentities(stripslashes($err))."
"; exit; } $this->erreur = $err; return FALSE; } // Traite les balises genre "#TITRE" // Options possibles: [Texte optionnel(#TITRE)texte optionnel] // Ou: (#TITRE|fonction_php) // Ou encore: (#TITRE|fonction1{argument1,argument2...}|fonction2...) function balise($tag,$valeur,$entree) { $sortie = $entree; preg_match_all("/\[([^\[\n]*)\(".$tag."(\*)?((\|[^\]]+)+)\)([^\]\n]*)\]/Ui",$sortie,$out,PREG_SET_ORDER); // Pour chaque balise récupérée dans le texte for($i=0; $i < count($out); $i++) { if(empty($valeur)) { $sortie = str_replace($out[$i][0],"",$sortie); break; } // On récupère le nom des fonctions $fonctions = $out[$i][4]; $fonctions = substr($fonctions,1); $fonctions = explode("|",$fonctions); $clef = $out[$i][0]; if(empty($out[$i][2])) { $valeur_boucle = htmlentities(stripslashes($valeur)); } else $valeur_boucle = $valeur; // On traite la balise avec chaque fonction for($j = 0; $j < count($fonctions); $j++) { // On regarde si la fonction a des paramètres en entrée $params = array(); if($pos = strpos($fonctions[$j],"{")) { $params = substr($fonctions[$j],$pos+1,-1); $fonctions[$j] = substr($fonctions[$j],0,$pos); $params = explode(",",$params); } // On ajoute la valeur de la balise au début du tableau des paramètres array_unshift($params,$valeur_boucle); if(!empty($valeur_boucle)) { $valeur3 = call_user_func_array($fonctions[$j],$params); $sortie = str_replace($clef,$valeur3,$sortie); $clef = $valeur3; $valeur_boucle = $valeur3; } // Si éléments optionnels avant/après on le remet $sortie = str_replace($clef,$out[$i][1].$valeur3.$out[$i][5],$sortie); unset($params); } } preg_match_all("/\(".$tag."(\*)?((\|[^\]]+)+)\)/Ui",$sortie,$out2,PREG_SET_ORDER); for($i=0; $i < count($out2); $i++) { // On récupère le nom des fonctions $fonctions = $out2[$i][2]; $fonctions = substr($fonctions,1); $fonctions = explode("|",$fonctions); $clef = $out2[$i][0]; if(empty($out[$i][1])) { $valeur_boucle = htmlentities(stripslashes($valeur)); } else $valeur_boucle = $valeur; // On traite la balise avec chaque fonction for($j = 0; $j < count($fonctions); $j++) { // On regarde si la fonction a des paramètres en entrée $params = array(); if($pos = strpos($fonctions[$j],"{")) { $params = substr($fonctions[$j],$pos+1,-1); $fonctions[$j] = substr($fonctions[$j],0,$pos); $params = explode(",",$params); } // On ajoute la valeur de la balise au début du tableau des paramètres array_unshift($params,$valeur_boucle); if(!empty($valeur_boucle)) { $valeur2 = call_user_func_array($fonctions[$j],$params); } $sortie = str_replace($clef,$valeur2,$sortie); $clef = $valeur2; $valeur_boucle = $valeur2; unset($params); } } preg_match_all("/\[([^\[\n]*)\(".$tag."(\*)?\)([^\]\n]*)\]/Ui",$sortie,$outt,PREG_SET_ORDER); for($i = 0; $i < count($outt); $i++) { if(empty($valeur)) $sortie = str_replace($outt[$i][0],"",$sortie); else $sortie = str_replace($outt[$i][0],$outt[$i][1].$valeur.$outt[$i][3],$sortie); } preg_match_all("/\(".$tag."(\*)?\)/Ui",$sortie,$out4,PREG_SET_ORDER); for($i = 0; $i < count($out4); $i++) { if(empty($valeur)) $sortie = str_replace($out4[$i][0],"",$sortie); else $sortie = str_replace($out4[$i][0],$valeur,$sortie); } // Sinon $sortie = str_replace($tag,htmlentities(stripslashes($valeur)),$sortie); return $sortie; } // Retourne le contenu d'une boucle dans un tableau function decoupe_boucle($texte,$b) { $pos_debut = strpos($texte,$b[0]); if(($d = strpos($texte,""))) { $d2 = $d + strlen(""); $boucle['pre'] = substr($texte,$d2,($pos_debut - $d2)); } $pos_fin = strpos($texte,"") + strlen(""); if($f = strpos($texte,"")) { $boucle['post'] = substr($texte,$pos_fin,($f - $pos_fin)); $pos_fin = $f + strlen(""); } if($a = strpos($texte,"")) { $boucle['alt'] = substr($texte,$pos_fin,$a - $pos_fin); $pos_fin = $a + strlen(""); } if($d) $deb = $d; else $deb = $pos_debut; $boucle['total'] = substr($texte,$deb,($pos_fin - $deb)); return $boucle; } function traiter_boucles($journal) { $boucles_mortes = array(); // On repère toutes les boucles de la page preg_match_all("§§U",$this->contenu,$out,PREG_SET_ORDER); if(count($out) < 0) return FALSE; // On fait le boulot pour chaque boucle for($i=0; $i < count($out); $i++) { $orderCount = 0; $nom = $out[$i][1]; // On vérifie qu'il y a une balise fermante contenu,"")) return $this->_err("La boucle n'a pas de balise fermante. Vérifiez le squelette."); // Si le nom de la boucle commence par un tiret bas, on le vire if(substr($nom,0,1) == "_") $nom = substr($nom,1); // On récupère le type de boucle $type = strtolower($out[$i][2]); if(!in_array($type,$this->types_boucles)) return $this->_err("La boucle {$nom} a un type {$type} inconnu. Vérifiez le squelette."); // On récupère tous les critères de la boucle dans un tableau $options = strtolower($out[$i][3]); $options = substr(trim($options),1,-1); $options = explode("}{",$options); $criteres = array(); // On détermine les options/critères de la boucle for($j=0; $j < count($options); $j++) { $o = array(); // remet à 0 $o pour éviter les bugs if($options[$j] == "parent" && $type == "forums") $req[where][] = "(parent='{$GLOBALS[id]}')"; // Ordre inverse elseif($options[$j] == "inverse") $req[orderby][$orderCount].= " DESC"; // Si c'est un séparateur de boucle {", "} par exemple elseif(substr($options[$j],0,1) == '"') $separ = substr($options[$j],1,-1); // Si c'est un critère de limite des résultats affichés elseif(ereg("(debut_([a-z0-9_-]+)|([0-9]+)),([0-9]+)?",$options[$j],$o)) { if(substr($o[1],0,6) == "debut_") $debut = $GLOBALS[$o[1]]; else $debut = $o[3]; if(empty($debut)) $debut = 0; if(trim($o[4]) == "") $o[4] = "-1"; $req['limit'] = $debut.",".$o[4]; } // Si c'est un critère de recherche elseif($options[$j] == "recherche") { if(in_array("sujet",$tables[$type])) $req[where][] = "(sujet LIKE \"%".addslashes($GLOBALS[recherche])."%\")"; if(in_array("titre",$tables[$type])) $req[where][] = "(titre LIKE \"%".addslashes($GLOBALS[recherche])."%\")"; if(in_array("chapo",$tables[$type])) $req[where][] = "(chapo LIKE \"%".addslashes($GLOBALS[recherche])."%\")"; if(in_array("texte",$tables[$type])) $req[where][] = "(texte LIKE \"%".addslashes($GLOBALS[recherche])."%\")"; } // Critère de comparaison REGEXP elseif(ereg("(==|!==)",$options[$j],$o)) { $pos = strpos($options[$j],$o[1]); $c = substr($options[$j],0,$pos); $expr = substr($options[$j],$pos+strlen($o[1])); if($o[1] == "==") $op = "REGEXP"; else $op = "NOT REGEXP"; $req[where][] = "(".trim($c)." ".$op." \"".trim($expr)."\")"; } // Si c'est un critère de comparaison LIKE elseif(ereg("(=~|!=~)",$options[$j],$o)) { $pos = strpos($options[$j],$o[1]); $c = substr($options[$j],0,$pos); $expr = substr($options[$j],$pos+strlen($o[1])); if($o[1] == "=~") $op = "LIKE"; else $op = "NOT LIKE"; $req[where][] = "(".trim($c)." ".$op." \"".trim($expr)."\")"; } // Si c'est un critère de comparaison classique elseif(ereg("(<|>|=|>=|<=|!=)",$options[$j],$o)) { $pos = strpos($options[$j],$o[1]); $c = substr($options[$j],$pos+strlen($o[1])); if(substr(trim($c),0,1) == "$") { $c = substr(trim($c),1); $c = $GLOBALS[$c]; } $c = "'".trim($c)."'"; $req[where][] = "(".substr($options[$j],0,$pos+strlen($o[1])).$c.")"; } // Trier par... elseif(substr($options[$j],0,3) == "par") { $orderCount++; $req[orderby][$orderCount] = substr($options[$j],4); if($req[orderby][$orderCount] == "hasard") $req[orderby][$j] = "RAND()"; } elseif(($options[$j] == "id") || ($options[$j] == "mois")) $req[where][] = "({$options[$j]}='{$GLOBALS[$options[$j]]}')"; elseif($options[$j] == "tout") $tout = TRUE; // Sinon ça veut dire que cette option n'existe pas else { $this->_err("Le critère {{$options[$j]}} de la boucle '{$nom}' n'est pas compris."); return FALSE; } } $requete = "SELECT * FROM ".$type; $requete.= " WHERE journal='{$journal}'"; if($type == "ecrits") $requete.= " AND statut != 'prive' AND valide='oui'"; if(!$tout) { if(count($req['where']) > 0) { $requete.= " AND "; $requete.= implode(" AND ",$req['where']); } } if($req['orderby']) $requete.= " ORDER BY ".implode(", ",$req[orderby]); if($req['limit']) $requete.= " LIMIT ".$req[limit]; if($type == "mois") { if($type == "mois") $requete = "SELECT mois FROM ecrits WHERE journal='{$journal}' AND statut!='prive' AND valide='oui' GROUP BY mois ORDER BY mois"; #elseif($type == "forums_mois") $requete = "SELECT mois FROM forums WHERE journal='{$journal}' AND parent='0' GROUP BY mois ORDER BY mois"; if($req['orderby'][0] == " DESC") $requete.= " DESC"; } $res = mysql_query($requete) or die($this->_err("Erreur mySQL.",$requete."\n --> ".mysql_error())); $nb_items = mysql_num_rows($res); // On récupère le contenu de la boucle $bcl = $this->decoupe_boucle($this->contenu,$out[$i]); // Si pas d'enregistrement retourné, on vire la boucle if($nb_items < 1) { // On référence les boucles mortes preg_match_all("§§U",substr($bcl[total],7),$k,PREG_SET_ORDER); for($l=0; $l < count($k); $l++) { $boucles_mortes[] = $k[$l][1]; } $this->contenu = str_replace($bcl['total'],$bcl['alt'],$this->contenu); } // Sinon on traite le contenu de la boucle else { // On récupère le contenu lui-même de la boucle (sans les balises BOUCLE) $d = strpos($this->contenu,$out[$i][0]) + strlen($out[$i][0]); $f = strpos($this->contenu,"contenu,$d,$f); // Si ya des sous-boucles, on les vire le temps d'exécution pour éviter de confondre les tags if(strpos($boucle,"]+>%Us",$boucle,$temp,PREG_SET_ORDER); for($s=0;$s < count($temp); $s++) { $boucle = str_replace($temp[$s][0],"",$boucle); } } // On réitère le contenu de la boucle pour chaque enregistrement while($rec = mysql_fetch_assoc($res)) { // Si c'est un ID, on le met dans les doublons (à ne pas réafficher) #if(isset($rec['nom']) && empty($rec['nom'])) $rec['nom'] = "Anonyme"; if($rec['id']) $doublons[$type][] = $rec[id]; if($type == "mois" || $type == "forums_mois") { $rec["date"] = $rec['mois']; $rec['mois'] = mktime(1,1,1,substr($rec["date"],4,2),1,substr($rec["date"],0,4)); } elseif($type == "ecrits") { $txtRes = mysql_query('SELECT t.texte,h.texte AS texte_html FROM ecrits_textes AS t, ecrits_html AS h WHERE t.id="'.$rec['id'].'" AND t.id=h.id'); $txtRec = mysql_fetch_row($txtRes); $rec['texte_html'] = stripslashes($txtRec[1]); $rec['texte'] = stripslashes($txtRec[0]); } elseif($type == "forums") { $txtRes = mysql_query('SELECT texte FROM forums_textes WHERE id="'.$rec['id'].'"'); $txtRec = mysql_fetch_row($txtRes); $rec['texte_html'] = $GLOBALS['forum']->parseText($txtRec[0]); $rec['texte'] = stripslashes($txtRec[0]); } // Si ya une séparation entre chaque itération de la boucle if($b && $separ) $b = $separ.$boucle; else $b = $boucle; // Pour chaque champ de la table on remplace les balises correspondantes foreach($rec as $val=>$v) { // Si c'est un nombre on le met en globales avec id_ en préfixe (pour critères {id_texte} et cie.) if(is_numeric($rec[$val])) { if($val != "id") $v2 = "id_".$val; else $v2 = "id_".substr($type,0,-1); if($v2 == "id_parent") $var[$v2] = $rec[id]; else $var[$v2] = $rec[$val]; } // Remplacement de la balise $b = $this->balise("#".strtoupper($val),stripslashes($rec[$val]),$b); } $sortie.= $b; // Balise #INTRO (conforme SPIP & PHPInk) if(!empty($rec['texte_html'])) { $intro = strip_tags($rec['texte_html']); if(strlen($intro) > 600) { $intro = substr($intro,0,600); $pos = strrpos($intro," "); if($pos > 1) $intro = substr($intro,0,$pos); } } $sortie = $this->balise("#INTRO",$intro,$sortie); if($type == "ecrits") { #if(empty($rec['name'])) $url = $rec['id']; #else $url = $rec['name']; #$url = date("/Y/m/d/",$rec['date']).$url; $url = "/".$rec['uri']; } elseif($type == "forums") { $url = "/forum/".$rec['uri']; #$url = "/forum".date("/Y/m/d/",$rec[date]).$url; } elseif($type == "mois") $url = "/".substr($rec["date"],0,4)."/".substr($rec["date"],4,2)."/"; #elseif($type == "forums_mois") $url = "/forum/".substr($rec["date"],0,4)."/".substr($rec["date"],4,2)."/"; $sortie = $this->balise("#URL",$url,$sortie); if(strchr($sortie,"#_COULEUR")) $sortie = $this->balise("#_COULEUR","#eee",$sortie); } // On remet les sous-boucles aux bons endroits if($temp) { for($s=0; $s < count($temp); $s++) { $sortie = str_replace("",$temp[$s][0],$sortie); } } $bcl['post'] = $this->balise("#TOTAL_BOUCLE",$nb_items,$bcl['post']); $this->contenu = str_replace($bcl['total'],$bcl['pre'].$sortie.$bcl['post'],$this->contenu); $this->var = $var; $var2[$i] = $var; } if(count($temp) > 0) { if(empty($niveau[$i])) $niveau[$i] = 0; for($c = 1; $c <= count($temp); $c++) { $niveau[$i+$c] = $niveau[$i] + 1; } $pere[$niveau[$i]] = $i; } else { $var = $var2[$niveau[$i]-1]; } // On fait le ménage unset($temp,$ordre,$unique,$tout,$criteres,$inverse,$limit,$b,$separ,$boucle,$sortie,$intro,$req); } return $this->contenu; } // On récupère le chemin du CSS function get_css($visuel,$journal) { if($visuel == "custom") $css = $this->chemin."documents/".$journal."/default.css"; else $css = $this->chemin."templates/".$visuel."/default.css"; return $css; } // On récupère le template correspondant au membre function get_template($visuel,$journal,$template) { if($visuel == "custom") { $path = $this->chemin."/documents/".$journal."/skel_".$template.".html"; if(!file_exists($path)) $path = $this->chemin."templates/default/".$template.".html"; } else { $path = $this->chemin."/templates/".$visuel."/".$template.".html"; if(!file_exists($path)) $path = $this->chemin."templates/default/".$template.".html"; } // On inclut le CSS $css = $this->get_css($visuel,$journal); $f = @file($path); if(!$f) return $this->_err("Impossible d'accéder au template."); $f = implode("",$f); $f = str_replace("#CSS",'',$f); return $f; } // On parse les tags généraux affichés sur toutes les pages function parse_general($journal,$template) { // On parse la boucle des mois dispos //$template = $this->boucle_mois($template,$journal[mois]); // Relatif aux forums et autres if($journal['forum'] == "non") $journal['forum'] = ""; else $journal['forum'] = "/forum/"; if($journal['suivimail'] == "oui") $journal['suivimail'] = "/membre/abon?new=".$journal[id]; else $journal['suivimail'] = ""; // Remplissage des tags $tags = array( "#TITRE_JOURNAL"=> $journal['titre'], "#URL_JOURNAL" => $journal['url'], "#TEXTE_JOURNAL"=> $journal['texte'], "#ID_JOURNAL" => $journal['id'], "#STATUT_JOURNAL"=> $journal['statut'], "#FORUM" => $journal['forum'], "#SUIVIMAIL" => $journal['suivimail'], "#IDENTIFIANT" => $journal['id'], "#SABONNER" => $journal['suivimail'], "#FORMULAIRE" => "/addmessage.php?login=".$journal['id']); foreach($tags as $key=>$value) { $template = $this->balise($key,$value,$template); } $this->contenu = $template; $GLOBALS['mois'] = $journal['select_mois']; $this->traiter_boucles($journal['id']); return $this->contenu; } // rendu d'un écrit function skel_ecrit($journal,$ecrit) { // On récupère le template $template = $this->get_template($journal['visuel'],$journal['id'],"ecrit"); // Parsage des tags généraux $template = $this->parse_general($journal,$template); // On parse les tags spécifiques à la page $tags = array( "#ID" => $ecrit['id'], "#TITRE" => $ecrit['titre'], "#TEXTE_HTML" => $ecrit['texte_html'], "#TEXTE" => $ecrit['texte'], "#DATE" => $ecrit['date'], "#STATUT" => $ecrit['statut'], "#VALIDE" => $ecrit['valide'], "#SYNTAXE" => $ecrit['syntaxe'], "#URI" => $ecrit['uri']); foreach($tags as $key=>$value) { $template = $this->balise($key,$value,$template); } return $template; } // Rendu de l'index d'un mois function skel_mois($journal) { $template = $this->get_template($journal['visuel'],$journal['id'],"mois"); // Parsage des tags généraux $template = $this->parse_general($journal,$template); $m = $journal['select_mois']; $template = $this->balise("#MOIS",mktime(1,1,1,substr($m,4,2),1,substr($m,0,4)),$template); return $template; } // Rendu de l'index d'un mois function skel_accueil($journal) { $template = $this->get_template($journal['visuel'],$journal['id'],"accueil"); // Parsage des tags généraux $template = $this->parse_general($journal,$template); $m = $journal['select_mois']; $template = $this->balise("#MOIS",mktime(1,1,1,substr($m,4,2),1,substr($m,0,4)),$template); return $template; } // Rendu de l'index dun mois de forum function skel_forum_page($journal,$liste) { $template = $this->get_template($journal['visuel'],$journal['id'],"forum_page"); $template = $this->parse_general($journal,$template); return $template; } // rendu d'un message de forum function skel_forum_message($journal,$message) { // On récupère le template $template = $this->get_template($journal['visuel'],$journal['id'],"forum_message"); // Parsage des tags généraux $template = $this->parse_general($journal,$template); // On parse les tags spécifiques à la page $tags = array( "#ID" => $message['id'], "#TITRE" => $message['titre'], "#TEXTE_HTML" => $message['texte_html'], "#TEXTE" => $message['texte'], "#DATE" => $message['date'], "#STATUT" => $message['statut'], "#URI" => $message['uri'], "#NOM" => $message['nom'], "#EMAIL" => $message['email'], "#AUTEUR" => $message['auteur'], "#URL_FORUM" => "/forum/"); foreach($tags as $key=>$value) { $template = $this->balise($key,$value,$template); } return $template; } } ?>