[ Index ]
 

Code source de Plume CMS 1.2.2

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/manager/extinc/ -> WikiRenderer.lib.php (source)

   1  <?php
   2  
   3  /**
   4   * Bibliotheque d'objets permettant de tranformer un texte, contenant des 
   5   * signes de formatages
   6   * simples de type wiki, en un autre format tel que XHTML 1.0/strict
   7   * @author Laurent Jouanneau <jouanneau@netcourrier.com>
   8   * @copyright 2003-2004 Laurent Jouanneau
   9   * @module Wiki Renderer
  10   * @version 2.0dev-php5
  11   * @since 28/11/2004
  12   * http://ljouanneau.com/softs/wikirenderer/
  13   * Thanks to all users who found bugs : 
  14   * Loic, Edouard Guerin, Sylvain, Ludovic L.
  15   *
  16   * This library is free software; you can redistribute it and/or
  17   * modify it under the terms of the GNU Lesser General Public
  18   * License as published by the Free Software Foundation; either
  19   * version 2.1 of the License, or (at your option) any later version.
  20   *
  21   * This library is distributed in the hope that it will be useful,
  22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  24   * Lesser General Public License for more details.
  25   *
  26   * You should have received a copy of the GNU Lesser General Public
  27   * License along with this library; if not, write to the Free Software
  28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  29   * ----------------------------------------------------------------------------
  30   * Contributeurs :
  31   *    Edouard Guérin <eguerin@icitrus.net> (Adapatation PHP5)
  32   */
  33  
  34  define('WIKIRENDERER_PATH', dirname(__FILE__).'/');
  35  define('WIKIRENDERER_VERSION', '2.0dev-php5');
  36  
  37  
  38  if (version_compare(phpversion(), '5.0') < 0) {
  39      eval('
  40      function clone($object) {
  41        return $object;
  42      }
  43      ');
  44  }
  45  
  46  /**
  47   * Implémente les propriétés d'un tag inline wiki et 
  48   * le fonctionnement pour la génération
  49   * du code html correspondant
  50   */
  51  
  52  class WikiTag {
  53  
  54      var $name;
  55      var $beginTag;
  56      var $endTag;
  57      var $useSeparator = true;
  58      var $attribute = array();
  59      var $builderFunction = null;
  60  
  61      var $contents = array();
  62      var $separatorCount = 0;
  63      var $isDummy = false;
  64  
  65      function WikiTag($name, $properties){
  66          $this->name=$name;
  67          $this->beginTag=$properties[0];
  68          $this->endTag=$properties[1];
  69          if($this->name == 'dummie')
  70              $this->isDummy=true;
  71  
  72          if(is_null($properties[2])) {
  73              $this->attribute=array();
  74              $this->useSeparator=false;
  75          }
  76          else {
  77              $this->attribute=$properties[2];
  78              $this->useSeparator=(count($this->attribute)>0);
  79          }
  80          $this->builderFunction=$properties[3];
  81      }
  82  
  83      function addContent($string, $escape=true){
  84          if(!isset($this->contents[$this->separatorCount]))
  85              $this->contents[$this->separatorCount]='';
  86  
  87          if($escape)
  88              $this->contents[$this->separatorCount].= htmlspecialchars($string);
  89          else
  90              $this->contents[$this->separatorCount] .= $string;
  91      }
  92  
  93      function addSeparator() {
  94          $this->separatorCount++;
  95      }
  96  
  97      function getBeginTag() {
  98          return $this->beginTag;
  99      }
 100  
 101      function getEndTag() {
 102          return $this->endTag;
 103      }
 104  
 105      function getNumberSeparator() {
 106          return $this->separatorCount;
 107      }
 108  
 109      function useSeparator() {
 110          return $this->useSeparator;
 111      }
 112  
 113      function isDummy() {
 114          return $this->isDummy;
 115      }
 116  
 117      function getHtmlContent() {
 118          if(is_null($this->builderFunction)) {
 119              $attr='';
 120              if($this->useSeparator) {
 121                  $cntattr=count($this->attribute);
 122                  $count=($this->separatorCount > $cntattr?$cntattr:$this->separatorCount);
 123                  for($i=1;$i<=$count;$i++) {
 124                      $attr.=' '.$this->attribute[$i-1].'="'.$this->contents[$i].'"';
 125                  }
 126              }
 127              if(isset($this->contents[0]))
 128                  return '<'.$this->name.$attr.'>'.$this->contents[0].'</'.$this->name.'>';
 129              else
 130                  return '<'.$this->name.$attr.' />';
 131          }
 132          else {
 133              $fct=$this->builderFunction;
 134              return $fct($this->contents, $this->attribute);
 135          }
 136      }
 137  
 138  }
 139  
 140  
 141  /**
 142   * Moteur permettant de transformer les tags wiki inline 
 143   * d'une chaine en équivalent HTML
 144   */
 145  class WikiInlineParser {
 146  
 147      var $resultline='';
 148      var $error=false;
 149      var $listTag=array();
 150      var $str=array();
 151      var $splitPattern='';
 152      var $checkWikiWord=false;
 153      var $checkWikiWordFunction=null;
 154      var $simpletags = null;
 155      var $_separator;
 156      var $escapeHtml=true;
 157      var $end=0;
 158  
 159      /**
 160       * constructeur
 161       * @param array $inlinetags liste des tags permis
 162       * @param string caractère séparateur des différents composants 
 163       *               d'un tag wiki
 164       */
 165  
 166      function WikiInlineParser(
 167                           $inlinetags,
 168                           $simpletags,
 169                           $separator='|',
 170                           $checkWikiWord=false,
 171                           $funcCheckWikiWord=null,
 172                           $escapeHtml=true
 173                           ) {
 174  
 175          foreach($inlinetags as $name=>$prop){
 176              $this->listTag[$prop[0]]=new WikiTag($name,$prop);
 177  
 178              $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$prop[0]).')|(';
 179              if($prop[1] != $prop[0])
 180                  $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$prop[1]).')|(';
 181          }
 182          foreach($simpletags as $tag=>$html){
 183              $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$tag).')|(';
 184          }
 185  
 186          $this->simpletags=$simpletags;
 187          $this->_separator=$separator;
 188          $this->checkWikiWord=$checkWikiWord;
 189          $this->checkWikiWordFunction=$funcCheckWikiWord;
 190          $this->escapeHtml=$escapeHtml;
 191      }
 192  
 193      /**
 194       * fonction principale du parser.
 195       * @param   string   $line avec des eventuels tag wiki
 196       * @return  string   chaine $line avec les tags wiki transformé en HTML
 197       */
 198      function parse($line) {
 199          $this->error=false;
 200  
 201          $this->str=preg_split('/('.$this->splitPattern.'\\'.$this->_separator.')|(\\\\)/',$line, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
 202          $this->end=count($this->str);
 203          if($this->end > 1) {
 204              $firsttag=new WikiTag('dummie',array('','', null,'wikibuilddummie'));
 205              $pos=-1;
 206              return $this->_parse($firsttag, $pos);
 207          }
 208          else {
 209              if($this->escapeHtml) {
 210                  if($this->checkWikiWord && $this->checkWikiWordFunction !== null)
 211                      return  $this->_doCheckWikiWord(htmlspecialchars($line));
 212                  else
 213                      return htmlspecialchars($line);
 214              }
 215              else {
 216                  if($this->checkWikiWord && $this->checkWikiWordFunction !== null)
 217                      return  $this->_doCheckWikiWord($line);
 218                  else
 219                      return $line;
 220              }
 221  
 222          }
 223      }
 224  
 225      /**
 226       * coeur du parseur. Appelé récursivement
 227       */
 228  
 229      function _parse($tag, &$posstart) {
 230  
 231          $checkNextTag=true;
 232          $checkBeginTag=true;
 233  
 234          // on parcours la chaine,  morceau aprés morceau
 235          for($i=$posstart+1; $i < $this->end; $i++) {
 236  
 237              $t=&$this->str[$i];
 238              // a t-on un antislash ?
 239              if($t=='\\'){
 240                  if($checkNextTag){
 241                      $t=''; // oui -> on l'efface et on ignore le tag (on continue)
 242                      $checkNextTag=false;
 243                  }
 244                  else {
 245                      $tag->addContent('\\',false);
 246                  }
 247  
 248                  // est-ce un séparateur ?
 249              }
 250              elseif($t == $this->_separator) {
 251                  if($tag->isDummy() || !$checkNextTag)
 252                      $tag->addContent($this->_separator,false);
 253                  elseif($tag->useSeparator()) {
 254                      $checkBeginTag=false;
 255                      $tag->addSeparator();
 256                  }
 257                  else {
 258                      $tag->addContent($this->_separator,false);
 259                  }
 260                  // a-t-on une balise de fin du tag ?
 261              }
 262              elseif($checkNextTag && $tag->getEndTag() == $t && !$tag->isDummy()) {
 263                  $posstart=$i;
 264                  return $tag->getHtmlContent();
 265  
 266                  // a-t-on une balise de debut de tag quelconque ?
 267              }
 268              elseif($checkBeginTag && $checkNextTag && isset($this->listTag[$t]) ) {
 269  
 270                  $content = $this->_parse(clone($this->listTag[$t]),$i); // clone indispensable sinon plantage !!!
 271                  if($content)
 272                      $tag->addContent($content,false);
 273                  else {
 274                      if($tag->getNumberSeparator() == 0 && $this->checkWikiWord && $this->checkWikiWordFunction !== null) {
 275                          if($this->escapeHtml)
 276                              $tag->addContent($this->_doCheckWikiWord(htmlspecialchars($t)),false);
 277                          else
 278                              $tag->addContent($this->_doCheckWikiWord($t),false);
 279                      }
 280                      else
 281                          $tag->addContent($t,$this->escapeHtml);
 282                  }
 283  
 284                  // a-t-on un saut de ligne forcé ?
 285              }
 286              elseif($checkNextTag && $checkBeginTag && isset($this->simpletags[$t])) {
 287                  $tag->addContent($this->simpletags[$t],false);
 288              }
 289              else {
 290                  if($tag->getNumberSeparator() == 0 && $this->checkWikiWord && $this->checkWikiWordFunction !== null) {
 291                      if($this->escapeHtml)
 292                          $tag->addContent($this->_doCheckWikiWord(htmlspecialchars($t)),false);
 293                      else
 294                          $tag->addContent($this->_doCheckWikiWord($t),false);
 295                  }
 296                  else
 297                      $tag->addContent($t,$this->escapeHtml);
 298                  $checkNextTag=true;
 299              }
 300          }
 301          if(!$tag->isDummy()) {
 302              //--- on n'a pas trouvé le tag de fin
 303              // on met en erreur
 304              $this->error=true;
 305              return false;
 306          }
 307          else
 308              return $tag->getHtmlContent();
 309      }
 310  
 311      function _doCheckWikiWord($string) {
 312          if(preg_match_all("/(?<=\b)[A-Z][a-z]+[A-Z0-9]\w*/", $string, $matches)){
 313              $fct=$this->checkWikiWordFunction;
 314              $match = array_unique($matches[0]); // il faut avoir une liste sans doublon, à cause du str_replace plus loin...
 315              $string=str_replace($match, $fct($match), $string);
 316          }
 317          return $string;
 318      }
 319  
 320      function getError() {
 321          return $this->error;
 322      }
 323  
 324  }
 325  
 326  
 327  
 328  /**
 329   * classe de base pour la transformation des élements de type bloc
 330   * @abstract
 331   */
 332  class WikiRendererBloc {
 333  
 334      /**
 335       * @var string code identifiant le type de bloc
 336       * @access protected
 337       */
 338      var $type='';
 339  
 340      /**
 341       * @var string  chaine contenant le tag XHTML d'ouverture du bloc
 342       * @access protected
 343       */
 344      var $_openTag='';
 345  
 346      /**
 347       * @var string  chaine contenant le tag XHTML de fermeture du bloc
 348       * @access protected
 349       */
 350      var $_closeTag='';
 351  
 352      /**
 353       * @var boolean indique si le bloc doit être immediatement fermé aprés détection
 354       * @access protected
 355       */
 356      var $_closeNow=false;
 357  
 358      /**
 359       * @var WikiRenderer      référence à la classe principale
 360       * @access protected
 361       */
 362      var $engine=null;
 363  
 364      /**
 365       * @var array liste des élements trouvés par l'expression régulière regexp
 366       * @access protected
 367       */
 368      var $_detectMatch=null;
 369  
 370      /**
 371       * @var string expression régulière permettant de reconnaitre le bloc
 372       * @access protected
 373       */
 374      var $regexp='';
 375  
 376      /**
 377       * constructeur à surcharger pour définir les valeurs des différentes proprietés
 378       * @param WikiRender $wr l'objet moteur wiki
 379       */
 380  
 381      function WikiRendererBloc($wr) {
 382          $this->engine = $wr;
 383      }
 384  
 385      /**
 386       * renvoi une chaine correspondant à l'ouverture du bloc
 387       * @return string
 388       * @access public
 389       */
 390  
 391      function open() {
 392          return $this->_openTag;
 393      }
 394  
 395      /**
 396       * renvoi une chaine correspondant à la fermeture du bloc
 397       * @return string
 398       * @access public
 399       */
 400  
 401      function close() {
 402          return $this->_closeTag;
 403      }
 404  
 405      /**
 406       * indique si le bloc doit etre immédiatement fermé
 407       * @return string
 408       * @access public
 409       */
 410  
 411      function closeNow() {
 412          return $this->_closeNow;
 413      }
 414  
 415      /**
 416       * test si la chaine correspond au debut ou au contenu d'un bloc
 417       * @param string $string
 418       * @return boolean true: appartient au bloc
 419       * @access public
 420       */
 421  
 422      function detect($string) {
 423          return preg_match($this->regexp, $string, $this->_detectMatch);
 424      }
 425  
 426      /**
 427       * renvoi la ligne, traitée pour le bloc. A surcharger éventuellement.
 428       * @return string
 429       * @access public
 430       */
 431  
 432      function getRenderedLine() {
 433          return $this->_renderInlineTag($this->_detectMatch[1]);
 434      }
 435  
 436      /**
 437       * renvoi le type du bloc en cours de traitement
 438       * @return string
 439       * @access public
 440       */
 441  
 442      function getType() {
 443          return $this->type;
 444      }
 445  
 446      /**
 447       * définit la liste des élements trouvés par l'expression régulière regexp
 448       * @return array
 449       * @access public
 450       */
 451  
 452      function setMatch($match) {
 453          $this->_detectMatch = $match;
 454      }
 455  
 456      /**
 457       * renvoi la liste des élements trouvés par l'expression régulière regexp
 458       * @return array
 459       * @access public
 460       */
 461  
 462      function getMatch() {
 463          return $this->_detectMatch;
 464      }
 465  
 466      /**
 467       * traite le rendu des signes de type inline (qui se trouvent necessairement dans des blocs
 468       * @param   string  $string une chaine contenant une ou plusieurs balises wiki
 469       * @return  string  la chaine transformée en XHTML
 470       * @access protected
 471       * @see WikiRendererInline
 472       */
 473  
 474      function _renderInlineTag($string) {
 475          $parser = $this->engine->getInlineParser();
 476          return $parser->parse($string);
 477      }
 478  
 479      /**
 480       * détection d'attributs de bloc (ex:  >°°attr1|attr2|attr3°° la citation )
 481       * @todo à terminer pour une version ulterieure
 482       * @access protected
 483       */
 484  
 485      function _checkAttributes(&$string) {
 486          $bat=$this->engine->config->blocAttributeTag;
 487          if(preg_match("/^$bat(.*)$bat(.*)$/",$string,$result)) {
 488              $string=$result[2];
 489              return explode($this->engine->config->inlineTagSeparator,$result[1]);
 490          } else
 491              return false;
 492      }
 493  
 494  }
 495  
 496  require (WIKIRENDERER_PATH . 'WikiRenderer.conf.php');
 497  
 498  
 499  
 500  /**
 501   * Moteur de rendu. Classe principale à instancier pour transformer un texte wiki en texte XHTML.
 502   * utilisation :
 503   *      $ctr = new WikiRenderer();
 504   *      $monTexteXHTML = $ctr->render($montexte);
 505   */
 506  
 507  class WikiRenderer {
 508  
 509      /**
 510       * @var string contient la version HTML du texte analysé
 511       * @access private
 512       */
 513  
 514      var $_newtext;
 515  
 516      /**
 517       * @var boolean
 518       * @access private
 519       */
 520  
 521      var $_isBlocOpen=false;
 522  
 523      /**
 524       * @var WikiRendererBloc element bloc ouvert en cours
 525       * @access private
 526       */
 527  
 528      var $_currentBloc;
 529  
 530      /**
 531       * @var array liste des differents types de blocs disponibles
 532       * @access private
 533       */
 534  
 535      var $_blocList= array();
 536  
 537      /**
 538       * @var array liste de paramètres pour le moteur
 539       * @access private
 540       */
 541  
 542      var $params=array();
 543  
 544      /**
 545       * @var WikiInlineParser analyseur pour les tags wiki inline
 546       * @access private
 547       */
 548  
 549      var $inlineParser=null;
 550  
 551      /**
 552       * liste des lignes où il y a une erreur wiki
 553       * @access private
 554       */
 555  
 556      var $errors;
 557  
 558      /**
 559       * @var WikiRendererConfig objet de configuration, permet de modifier
 560       * @see WikiRendererConfig
 561       * @access private
 562       */
 563  
 564      var $config=null;
 565  
 566      /**
 567       * instancie les différents objets pour le rendu des elements inline et bloc.
 568       */
 569  
 570      function WikiRenderer($config=null, $prefix='WRB_') {
 571          if(is_null($config))
 572              $this->config = new WikiRendererConfig();
 573          else
 574              $this->config=$config;
 575  
 576          $this->_currentBloc = new WikiRendererBloc($this); // bloc 'fantome'
 577          $this->inlineParser = new WikiInlineParser(
 578                                                     $this->config->inlinetags,
 579                                                     $this->config->simpletags,
 580                                                     $this->config->inlineTagSeparator,
 581                                                     $this->config->checkWikiWord,
 582                                                     $this->config->checkWikiWordFunction,
 583                                                     $this->config->escapeSpecialChars
 584                                                     );
 585  
 586          foreach($this->config->bloctags as $name=>$ok) {
 587              $name=$prefix.$name;
 588              if($ok) $this->_blocList[] = new $name($this);
 589          }
 590      }
 591  
 592      /**
 593       * Methode principale qui transforme les tags wiki en tag XHTML
 594       * @param   string  $texte le texte à convertir
 595       * @return  string  le texte converti en XHTML
 596       * @access public
 597       */
 598      function render($texte) {
 599  
 600          // on remplace les \r (mac), les \n (unix) et les \r\n (windows) par un autre caractère pour découper proprement
 601          $lignes=preg_split("/\015\012|\015|\012/",$texte);
 602  
 603          $this->_newtext=array();
 604          $this->_isBlocOpen=false;
 605          $this->errors=false;
 606          $this->_currentBloc = new WikiRendererBloc($this);
 607  
 608          // parcours de l'ensemble des lignes du texte
 609          foreach($lignes as $num=>$ligne){
 610  
 611              if($ligne == '') { // pas de trim à cause des pre
 612                  // ligne vide
 613                  $this->_closeBloc();
 614              }
 615              else {
 616  
 617                  // detection de debut de bloc (liste, tableau, hr, titre)
 618                  foreach($this->_blocList as $bloc) {
 619                      if($bloc->detect($ligne))
 620                          break;
 621                  }
 622  
 623                  // c'est le debut d'un bloc (ou ligne d'un bloc en cours)
 624                  if($bloc->getType() != $this->_currentBloc->getType()) {
 625                      $this->_closeBloc(); // on ferme le precedent si c'etait un different
 626                      $this->_currentBloc= $bloc;
 627                      if($this->_openBloc()) {
 628                          $this->_newtext[]=$this->_currentBloc->getRenderedLine();
 629                      }
 630                      else {
 631                          $this->_newtext[]=$this->_currentBloc->getRenderedLine();
 632                          $this->_newtext[]=$this->_currentBloc->close();
 633                          $this->_isBlocOpen = false;
 634                          $this->_currentBloc = new WikiRendererBloc($this);
 635                      }
 636  
 637                  }
 638                  else {
 639                      $this->_currentBloc->setMatch($bloc->getMatch());
 640                      $this->_newtext[]=$this->_currentBloc->getRenderedLine();
 641                  }
 642                  if($this->inlineParser->getError()) {
 643                      $this->errors[$num+1]=$ligne;
 644                  }
 645              }
 646          }
 647  
 648          $this->_closeBloc();
 649          return implode("\n",$this->_newtext);
 650      }
 651  
 652      /**
 653       * renvoi l'objet de configuration
 654       * @access public
 655       * @see WikiRendererConfig
 656       * @return WikiRendererConfig
 657       */
 658  
 659      function getConfig() {
 660          return $this->config;
 661      }
 662  
 663      /**
 664       * Retourne l'objet inlineParser (WikiInlineParser) utilisé dans le moteur
 665       * @access public
 666       * @see WikiInlineParser
 667       * @return WikiInlineParser
 668       */
 669  
 670      function getInlineParser() {
 671          return $this->inlineParser;
 672      }
 673  
 674      /**
 675       * renvoi la liste des erreurs detectées par le moteur
 676       * @access public
 677       * @return array
 678       */
 679  
 680      function getErrors() {
 681          return $this->errors;
 682      }
 683  
 684      /**
 685       * renvoi la version de wikirenderer
 686       * @access public
 687       * @return string   version
 688       */
 689      function getVersion(){
 690          return WIKIRENDERER_VERSION;
 691      }
 692  
 693      /**
 694       * ferme un bloc
 695       * @access private
 696       */
 697  
 698      function _closeBloc() {
 699          if($this->_isBlocOpen) {
 700              $this->_isBlocOpen=false;
 701              $this->_newtext[]=$this->_currentBloc->close();
 702              $this->_currentBloc = new WikiRendererBloc($this);
 703          }
 704      }
 705  
 706      /**
 707       * ouvre un bloc et le referme eventuellement suivant sa nature
 708       * @return boolean  indique si le bloc reste ouvert ou pas
 709       * @access private
 710       */
 711  
 712      function _openBloc() {
 713          if(!$this->_isBlocOpen) {
 714              $this->_newtext[]=$this->_currentBloc->open();
 715              $this->_isBlocOpen=true;
 716              return !$this->_currentBloc->closeNow();
 717          }
 718          else
 719              return true;
 720      }
 721  
 722  }
 723  
 724  
 725  ?>


Généré le : Mon Nov 26 11:57:01 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics