includes/wikiformat.php
changeset 1 fe660c52c48f
child 32 4d87aad3c4c0
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     1 <?php
       
     2 /**
       
     3  * Parse structured wiki text and render into arbitrary formats such as XHTML.
       
     4  *
       
     5  * PHP versions 4 and 5
       
     6  *
       
     7  * @category   Text
       
     8  * @package    Text_Wiki
       
     9  * @author     Paul M. Jones <pmjones@php.net>
       
    10  * @license    http://www.gnu.org/licenses/lgpl.html
       
    11  * @version    CVS: $Id: Wiki.php,v 1.44 2006/03/02 04:04:59 justinpatrin Exp $
       
    12  * @link       http://wiki.ciaweb.net/yawiki/index.php?area=Text_Wiki
       
    13  *
       
    14  * This code was modified for use in Enano. The Text_Wiki engine is licensed
       
    15  * under the GNU Lesser General Public License; see
       
    16  * http://www.gnu.org/licenses/lgpl.html for details.
       
    17  *
       
    18  */
       
    19 
       
    20 require_once ENANO_ROOT.'/includes/wikiengine/Parse.php';
       
    21 require_once ENANO_ROOT.'/includes/wikiengine/Render.php';
       
    22 
       
    23 class Text_Wiki {
       
    24 
       
    25   var $rules = array(
       
    26         'Prefilter',
       
    27         'Delimiter',
       
    28         'Code',
       
    29         'Function',
       
    30         'Html',
       
    31         'Raw',
       
    32         'Include',
       
    33         'Embed',
       
    34         'Anchor',
       
    35         'Heading',
       
    36         'Toc',
       
    37         'Horiz',
       
    38         'Break',
       
    39         'Blockquote',
       
    40         'List',
       
    41         'Deflist',
       
    42         'Table',
       
    43         'Image',
       
    44         'Phplookup',
       
    45         'Center',
       
    46         'Newline',
       
    47         'Paragraph',
       
    48         'Url',
       
    49         'Freelink',
       
    50         'Interwiki',
       
    51         'Wikilink',
       
    52         'Colortext',
       
    53         'Strong',
       
    54         'Bold',
       
    55         'Emphasis',
       
    56         'Italic',
       
    57         'Underline',
       
    58         'Tt',
       
    59         'Superscript',
       
    60         'Subscript',
       
    61         'Revise',
       
    62         'Tighten'
       
    63     );
       
    64 
       
    65     var $disable = array(
       
    66         'Html',
       
    67         'Include',
       
    68         'Embed'
       
    69     );
       
    70 
       
    71     var $parseConf = array();
       
    72 
       
    73     var $renderConf = array(
       
    74         'Docbook' => array(),
       
    75         'Latex' => array(),
       
    76         'Pdf' => array(),
       
    77         'Plain' => array(),
       
    78         'Rtf' => array(),
       
    79         'Xhtml' => array()
       
    80     );
       
    81 
       
    82     var $formatConf = array(
       
    83         'Docbook' => array(),
       
    84         'Latex' => array(),
       
    85         'Pdf' => array(),
       
    86         'Plain' => array(),
       
    87         'Rtf' => array(),
       
    88         'Xhtml' => array()
       
    89     );
       
    90     var $delim = "\xFF";
       
    91     var $tokens = array();
       
    92     var $_countRulesTokens = array();
       
    93     var $source = '';
       
    94     var $parseObj = array();
       
    95     var $renderObj = array();
       
    96     var $formatObj = array();
       
    97     var $path = array(
       
    98         'parse' => array(),
       
    99         'render' => array()
       
   100     );
       
   101     var $_dirSep = DIRECTORY_SEPARATOR;
       
   102     function Text_Wiki($rules = null)
       
   103     {
       
   104         if (is_array($rules)) {
       
   105             $this->rules = $rules;
       
   106         }
       
   107 
       
   108         $this->addPath(
       
   109             'parse',
       
   110             $this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Parse/Default/'
       
   111         );
       
   112         $this->addPath(
       
   113             'render',
       
   114             $this->fixPath(ENANO_ROOT) . 'includes/wikiengine/Render/'
       
   115         );
       
   116 
       
   117     }
       
   118 
       
   119     function &singleton($parser = 'Default', $rules = null)
       
   120     {
       
   121         static $only = array();
       
   122         if (!isset($only[$parser])) {
       
   123             $ret =& Text_Wiki::factory($parser, $rules);
       
   124             if (!$ret) {
       
   125                 return $ret;
       
   126             }
       
   127             $only[$parser] =& $ret;
       
   128         }
       
   129         return $only[$parser];
       
   130     }
       
   131 
       
   132     function &factory($parser = 'Default', $rules = null)
       
   133     {
       
   134         $d=getcwd();
       
   135         chdir(ENANO_ROOT);
       
   136         
       
   137         $class = 'Text_Wiki_' . $parser;
       
   138         $c2 = '._includes_wikiengine_' . $parser;
       
   139         $file = str_replace('_', '/', $c2).'.php';
       
   140         if (!class_exists($class)) {
       
   141             $fp = @fopen($file, 'r', true);
       
   142             if ($fp === false) {
       
   143                 die_semicritical('Wiki formatting engine error', '<p>Could not find file '.$file.' in include_path</p>');
       
   144             }
       
   145             fclose($fp);
       
   146             include_once($file);
       
   147             if (!class_exists($class)) {
       
   148                 die_semicritical('Wiki formatting engine error', '<p>Class '.$class.' does not exist after including '.$file.'</p>');
       
   149             }
       
   150         }
       
   151         
       
   152         chdir($d);
       
   153 
       
   154         $obj =& new $class($rules);
       
   155         return $obj;
       
   156     }
       
   157 
       
   158     function setParseConf($rule, $arg1, $arg2 = null)
       
   159     {
       
   160         $rule = ucwords(strtolower($rule));
       
   161 
       
   162         if (! isset($this->parseConf[$rule])) {
       
   163             $this->parseConf[$rule] = array();
       
   164         }
       
   165 
       
   166                                 if (is_array($arg1)) {
       
   167             $this->parseConf[$rule] = $arg1;
       
   168         } else {
       
   169             $this->parseConf[$rule][$arg1] = $arg2;
       
   170         }
       
   171     }
       
   172 
       
   173     function getParseConf($rule, $key = null)
       
   174     {
       
   175         $rule = ucwords(strtolower($rule));
       
   176 
       
   177                 if (! isset($this->parseConf[$rule])) {
       
   178             return null;
       
   179         }
       
   180 
       
   181                 if (is_null($key)) {
       
   182             return $this->parseConf[$rule];
       
   183         }
       
   184 
       
   185                 if (isset($this->parseConf[$rule][$key])) {
       
   186                         return $this->parseConf[$rule][$key];
       
   187         } else {
       
   188                         return null;
       
   189         }
       
   190     }
       
   191 
       
   192     function setRenderConf($format, $rule, $arg1, $arg2 = null)
       
   193     {
       
   194         $format = ucwords(strtolower($format));
       
   195         $rule = ucwords(strtolower($rule));
       
   196 
       
   197         if (! isset($this->renderConf[$format])) {
       
   198             $this->renderConf[$format] = array();
       
   199         }
       
   200 
       
   201         if (! isset($this->renderConf[$format][$rule])) {
       
   202             $this->renderConf[$format][$rule] = array();
       
   203         }
       
   204 
       
   205                                 if (is_array($arg1)) {
       
   206             $this->renderConf[$format][$rule] = $arg1;
       
   207         } else {
       
   208             $this->renderConf[$format][$rule][$arg1] = $arg2;
       
   209         }
       
   210     }
       
   211 
       
   212     function getRenderConf($format, $rule, $key = null)
       
   213     {
       
   214         $format = ucwords(strtolower($format));
       
   215         $rule = ucwords(strtolower($rule));
       
   216 
       
   217         if (! isset($this->renderConf[$format]) ||
       
   218             ! isset($this->renderConf[$format][$rule])) {
       
   219           return null;
       
   220         }
       
   221 
       
   222         if (is_null($key)) {
       
   223           return $this->renderConf[$format][$rule];
       
   224         }
       
   225 
       
   226         if (isset($this->renderConf[$format][$rule][$key])) {
       
   227           return $this->renderConf[$format][$rule][$key];
       
   228         } else {
       
   229           return null;
       
   230         }
       
   231 
       
   232     }
       
   233 
       
   234     function setFormatConf($format, $arg1, $arg2 = null)
       
   235     {
       
   236       if (! is_array($this->formatConf[$format])) {
       
   237         $this->formatConf[$format] = array();
       
   238       }
       
   239 
       
   240       if (is_array($arg1)) {
       
   241         $this->formatConf[$format] = $arg1;
       
   242       } else {
       
   243         $this->formatConf[$format][$arg1] = $arg2;
       
   244       }
       
   245     }
       
   246 
       
   247     function getFormatConf($format, $key = null)
       
   248     {
       
   249       if (! isset($this->formatConf[$format])) {
       
   250         return null;
       
   251       }
       
   252 
       
   253       if (is_null($key)) {
       
   254         return $this->formatConf[$format];
       
   255       }
       
   256 
       
   257       if (isset($this->formatConf[$format][$key])) {
       
   258         return $this->formatConf[$format][$key];
       
   259       } else {
       
   260         return null;
       
   261       }
       
   262     }
       
   263 
       
   264     function insertRule($name, $tgt = null)
       
   265     {
       
   266       $name = ucwords(strtolower($name));
       
   267       if (! is_null($tgt)) {
       
   268         $tgt = ucwords(strtolower($tgt));
       
   269       }
       
   270       if (in_array($name, $this->rules)) {
       
   271         return null;
       
   272       }
       
   273 
       
   274       if (! is_null($tgt) && $tgt != '' &&
       
   275         ! in_array($tgt, $this->rules)) {
       
   276         return false;
       
   277       }
       
   278 
       
   279       if (is_null($tgt)) {
       
   280         $this->rules[] = $name;
       
   281         return true;
       
   282       }
       
   283 
       
   284       if ($tgt == '') {
       
   285         array_unshift($this->rules, $name);
       
   286         return true;
       
   287       }
       
   288 
       
   289       $tmp = $this->rules;
       
   290       $this->rules = array();
       
   291 
       
   292       foreach ($tmp as $val) {
       
   293         $this->rules[] = $val;
       
   294         if ($val == $tgt) {
       
   295           $this->rules[] = $name;
       
   296         }
       
   297       }
       
   298 
       
   299       return true;
       
   300     }
       
   301 
       
   302     function deleteRule($name)
       
   303     {
       
   304       $name = ucwords(strtolower($name));
       
   305       $key = array_search($name, $this->rules);
       
   306       if ($key !== false) {
       
   307         unset($this->rules[$key]);
       
   308       }
       
   309     }
       
   310 
       
   311     function changeRule($old, $new)
       
   312     {
       
   313       $old = ucwords(strtolower($old));
       
   314       $new = ucwords(strtolower($new));
       
   315       $key = array_search($old, $this->rules);
       
   316       if ($key !== false) {
       
   317         $this->deleteRule($new);
       
   318         $this->rules[$key] = $new;
       
   319       }
       
   320     }
       
   321 
       
   322     function enableRule($name)
       
   323     {
       
   324       $name = ucwords(strtolower($name));
       
   325       $key = array_search($name, $this->disable);
       
   326       if ($key !== false) {
       
   327         unset($this->disable[$key]);
       
   328       }
       
   329     }
       
   330 
       
   331     function disableRule($name)
       
   332     {
       
   333       $name = ucwords(strtolower($name));
       
   334       $key = array_search($name, $this->disable);
       
   335       if ($key === false) {
       
   336         $this->disable[] = $name;
       
   337       }
       
   338     }
       
   339 
       
   340     function transform($text, $format = 'Xhtml')
       
   341     {
       
   342       $this->parse($text);
       
   343       return $this->render($format);
       
   344     }
       
   345 
       
   346     function parse($text)
       
   347     {
       
   348       $this->source = $text;
       
   349 
       
   350       $this->tokens = array();
       
   351       $this->_countRulesTokens = array();
       
   352 
       
   353       foreach ($this->rules as $name) {
       
   354         if (! in_array($name, $this->disable)) {
       
   355           $this->loadParseObj($name);
       
   356 
       
   357           if (is_object($this->parseObj[$name])) {
       
   358             $this->parseObj[$name]->parse();
       
   359           }
       
   360         }
       
   361       }
       
   362     }
       
   363 
       
   364     function render($format = 'Xhtml')
       
   365     {
       
   366       $format = ucwords(strtolower($format));
       
   367 
       
   368       $output = '';
       
   369 
       
   370       $in_delim = false;
       
   371 
       
   372       $key = '';
       
   373 
       
   374       $result = $this->loadFormatObj($format);
       
   375       if ($this->isError($result)) {
       
   376         return $result;
       
   377       }
       
   378 
       
   379       if (is_object($this->formatObj[$format])) {
       
   380         $output .= $this->formatObj[$format]->pre();
       
   381       }
       
   382 
       
   383       foreach (array_keys($this->_countRulesTokens) as $rule) {
       
   384         $this->loadRenderObj($format, $rule);
       
   385       }
       
   386 
       
   387       $k = strlen($this->source);
       
   388       for ($i = 0; $i < $k; $i++) {
       
   389 
       
   390         $char = $this->source{$i};
       
   391 
       
   392         if ($in_delim) {
       
   393 
       
   394           if ($char == $this->delim) {
       
   395 
       
   396             $key = (int)$key;
       
   397             $rule = $this->tokens[$key][0];
       
   398             $opts = $this->tokens[$key][1];
       
   399             $output .= $this->renderObj[$rule]->token($opts);
       
   400             $in_delim = false;
       
   401 
       
   402           } else {
       
   403 
       
   404             $key .= $char;
       
   405 
       
   406           }
       
   407 
       
   408         } else {
       
   409 
       
   410           if ($char == $this->delim) {
       
   411             $key = '';
       
   412             $in_delim = true;
       
   413           } else {
       
   414             $output .= $char;
       
   415           }
       
   416         }
       
   417       }
       
   418 
       
   419       if (is_object($this->formatObj[$format])) {
       
   420         $output .= $this->formatObj[$format]->post();
       
   421       }
       
   422 
       
   423       return $output;
       
   424     }
       
   425 
       
   426     function getSource()
       
   427     {
       
   428       return $this->source;
       
   429     }
       
   430 
       
   431     function getTokens($rules = null)
       
   432     {
       
   433         if (is_null($rules)) {
       
   434             return $this->tokens;
       
   435         } else {
       
   436             settype($rules, 'array');
       
   437             $result = array();
       
   438             foreach ($this->tokens as $key => $val) {
       
   439                 if (in_array($val[0], $rules)) {
       
   440                     $result[$key] = $val;
       
   441                 }
       
   442             }
       
   443             return $result;
       
   444         }
       
   445     }
       
   446 
       
   447     function addToken($rule, $options = array(), $id_only = false)
       
   448     {
       
   449                                 static $id;
       
   450         if (! isset($id)) {
       
   451             $id = 0;
       
   452         } else {
       
   453             $id ++;
       
   454         }
       
   455 
       
   456                 settype($options, 'array');
       
   457 
       
   458                 $this->tokens[$id] = array(
       
   459             0 => $rule,
       
   460             1 => $options
       
   461         );
       
   462         if (!isset($this->_countRulesTokens[$rule])) {
       
   463             $this->_countRulesTokens[$rule] = 1;
       
   464         } else {
       
   465             ++$this->_countRulesTokens[$rule];
       
   466         }
       
   467 
       
   468                 if ($id_only) {
       
   469                         return $id;
       
   470         } else {
       
   471                         return $this->delim . $id . $this->delim;
       
   472         }
       
   473     }
       
   474 
       
   475     function setToken($id, $rule, $options = array())
       
   476     {
       
   477         $oldRule = $this->tokens[$id][0];
       
   478                 $this->tokens[$id] = array(
       
   479             0 => $rule,
       
   480             1 => $options
       
   481         );
       
   482         if ($rule != $oldRule) {
       
   483             if (!($this->_countRulesTokens[$oldRule]--)) {
       
   484                 unset($this->_countRulesTokens[$oldRule]);
       
   485             }
       
   486             if (!isset($this->_countRulesTokens[$rule])) {
       
   487                 $this->_countRulesTokens[$rule] = 1;
       
   488             } else {
       
   489                 ++$this->_countRulesTokens[$rule];
       
   490             }
       
   491         }
       
   492     }
       
   493 
       
   494     function loadParseObj($rule)
       
   495     {
       
   496         $rule = ucwords(strtolower($rule));
       
   497         $file = $rule . '.php';
       
   498         $class = "Text_Wiki_Parse_$rule";
       
   499 
       
   500         if (! class_exists($class)) {
       
   501             $loc = $this->findFile('parse', $file);
       
   502             if ($loc) {
       
   503                                 include_once $loc;
       
   504             } else {
       
   505                                 $this->parseObj[$rule] = null;
       
   506                                 return $this->error(
       
   507                     "Parse rule '$rule' not found"
       
   508                 );
       
   509             }
       
   510         }
       
   511 
       
   512         $this->parseObj[$rule] =& new $class($this);
       
   513 
       
   514     }
       
   515 
       
   516     function loadRenderObj($format, $rule)
       
   517     {
       
   518         $format = ucwords(strtolower($format));
       
   519         $rule = ucwords(strtolower($rule));
       
   520         $file = "$format/$rule.php";
       
   521         $class = "Text_Wiki_Render_$format" . "_$rule";
       
   522 
       
   523         if (! class_exists($class)) {
       
   524                         $loc = $this->findFile('render', $file);
       
   525             if ($loc) {
       
   526                                 include_once $loc;
       
   527             } else {
       
   528                 return $this->error(
       
   529                     "Render rule '$rule' in format '$format' not found"
       
   530                 );
       
   531             }
       
   532         }
       
   533 
       
   534         $this->renderObj[$rule] =& new $class($this);
       
   535     }
       
   536 
       
   537     function loadFormatObj($format)
       
   538     {
       
   539         $format = ucwords(strtolower($format));
       
   540         $file = $format . '.php';
       
   541         $class = "Text_Wiki_Render_$format";
       
   542 
       
   543         if (! class_exists($class)) {
       
   544             $loc = $this->findFile('render', $file);
       
   545             if ($loc) {
       
   546                 include_once $loc;
       
   547             } else {
       
   548                 return $this->error(
       
   549                     "Rendering format class '$class' not found"
       
   550                 );
       
   551             }
       
   552         }
       
   553 
       
   554         $this->formatObj[$format] =& new $class($this);
       
   555     }
       
   556 
       
   557     function addPath($type, $dir)
       
   558     {
       
   559         $dir = $this->fixPath($dir);
       
   560         if (! isset($this->path[$type])) {
       
   561             $this->path[$type] = array($dir);
       
   562         } else {
       
   563             array_unshift($this->path[$type], $dir);
       
   564         }
       
   565     }
       
   566 
       
   567     function getPath($type = null)
       
   568     {
       
   569         if (is_null($type)) {
       
   570             return $this->path;
       
   571         } elseif (! isset($this->path[$type])) {
       
   572             return array();
       
   573         } else {
       
   574             return $this->path[$type];
       
   575         }
       
   576     }
       
   577 
       
   578     function findFile($type, $file)
       
   579     {
       
   580       $set = $this->getPath($type);
       
   581 
       
   582       foreach ($set as $path) {
       
   583             $fullname = $path . $file;
       
   584             if (file_exists($fullname) && is_readable($fullname)) {
       
   585                 return $fullname;
       
   586             }
       
   587         }
       
   588 
       
   589       return false;
       
   590     }
       
   591 
       
   592     function fixPath($path)
       
   593     {
       
   594         $len = strlen($this->_dirSep);
       
   595 
       
   596         if (! empty($path) &&
       
   597             substr($path, -1 * $len, $len) != $this->_dirSep)    {
       
   598             return $path . $this->_dirSep;
       
   599         } else {
       
   600             return $path;
       
   601         }
       
   602     }
       
   603 
       
   604     function &error($message)
       
   605     {
       
   606         die($message);
       
   607     }
       
   608 
       
   609     function isError(&$obj)
       
   610     {
       
   611         return is_a($obj, 'PEAR_Error');
       
   612     }
       
   613 }
       
   614 
       
   615 ?>