Text_Wiki
[ class tree: Text_Wiki ] [ index: Text_Wiki ] [ all elements ]

Source for file Wiki.php

Documentation is available at Wiki.php

  1. <?php
  2.  
  3. /**
  4. * The baseline abstract parser class.
  5. */
  6.  
  7. require_once 'Text/Wiki/Parse.php';
  8.  
  9. /**
  10. * The baseline abstract render class.
  11. */
  12.  
  13. require_once 'Text/Wiki/Render.php';
  14.  
  15. /**
  16. * 
  17. * Parse structured wiki text and render into arbitrary formats such as XHTML.
  18. * 
  19. * This is the "master" class for handling the management and convenience
  20. * functions to transform Wiki-formatted text.
  21. * 
  22. * $Id: Wiki.php,v 1.25 2004/10/08 17:51:16 pmjones Exp $
  23. * 
  24. * @author Paul M. Jones <pmjones@ciaweb.net>
  25. * 
  26. * @package Text_Wiki
  27. * 
  28. * @version 0.23.1
  29. *
  30. * @license LGPL
  31. * 
  32. */
  33.  
  34. class Text_Wiki {
  35.     
  36.     /**
  37.     * 
  38.     * The default list of rules, in order, to apply to the source text.
  39.     * 
  40.     * @access public
  41.     * 
  42.     * @var array 
  43.     * 
  44.     */
  45.     
  46.     var $rules = array(
  47.         'Prefilter',
  48.         'Delimiter',
  49.         'Code',
  50.         'Function',
  51.         'Html',
  52.         'Raw',
  53.         'Include',
  54.         'Embed',
  55.         'Anchor',
  56.         'Heading',
  57.         'Toc',
  58.         'Horiz',
  59.         'Break',
  60.         'Blockquote',
  61.         'List',
  62.         'Deflist',
  63.         'Table',
  64.         'Image',
  65.         'Phplookup',
  66.         'Center',
  67.         'Newline',
  68.         'Paragraph',
  69.         'Url',
  70.         'Freelink',
  71.         'Interwiki',
  72.         'Wikilink',
  73.         'Colortext',
  74.         'Strong',
  75.         'Bold',
  76.         'Emphasis',
  77.         'Italic',
  78.         'Tt',
  79.         'Superscript',
  80.         'Revise',
  81.         'Tighten'
  82.     );
  83.     
  84.     
  85.     /**
  86.     * 
  87.     * The list of rules to not-apply to the source text.
  88.     * 
  89.     * @access public
  90.     * 
  91.     * @var array 
  92.     * 
  93.     */
  94.     
  95.     var $disable = array(
  96.         'Html',
  97.         'Include',
  98.         'Embed'
  99.     );
  100.     
  101.     
  102.     /**
  103.     * 
  104.     * Custom configuration for rules at the parsing stage.
  105.     *
  106.     * In this array, the key is the parsing rule name, and the value is
  107.     * an array of key-value configuration pairs corresponding to the $conf
  108.     * property in the target parsing rule.
  109.     * 
  110.     * For example:
  111.     * 
  112.     * <code>
  113.     * $parseConf = array(
  114.     *     'Include' => array(
  115.     *         'base' => '/path/to/scripts/'
  116.     *     )
  117.     * );
  118.     * </code>
  119.     * 
  120.     * Note that most default rules do not need any parsing configuration.
  121.     * 
  122.     * @access public
  123.     * 
  124.     * @var array 
  125.     * 
  126.     */
  127.     
  128.     var $parseConf = array();
  129.     
  130.     
  131.     /**
  132.     * 
  133.     * Custom configuration for rules at the rendering stage.
  134.     *
  135.     * Because rendering may be different for each target format, the
  136.     * first-level element in this array is always a format name (e.g.,
  137.     * 'Xhtml').
  138.     * 
  139.     * Within that first level element, the subsequent elements match the
  140.     * $parseConf format. That is, the sub-key is the rendering rule name,
  141.     * and the sub-value is an array of key-value configuration pairs
  142.     * corresponding to the $conf property in the target rendering rule.
  143.     * 
  144.     * @access public
  145.     * 
  146.     * @var array 
  147.     * 
  148.     */
  149.     
  150.     var $renderConf = array(
  151.         'Docbook' => array(),
  152.         'Latex' => array(),
  153.         'Pdf' => array(),
  154.         'Plain' => array(),
  155.         'Rtf' => array(),
  156.         'Xhtml' => array()
  157.     );
  158.     
  159.     
  160.     /**
  161.     * 
  162.     * Custom configuration for the output format itself.
  163.     *
  164.     * Even though Text_Wiki will render the tokens from parsed text,
  165.     * the format itself may require some configuration.  For example,
  166.     * RTF needs to know font names and sizes, PDF requires page layout
  167.     * information, and DocBook needs a section hierarchy.  This array
  168.     * matches the $conf property of the the format-level renderer
  169.     * (e.g., Text_Wiki_Render_Xhtml).
  170.     * 
  171.     * In this array, the key is the rendering format name, and the value is
  172.     * an array of key-value configuration pairs corresponding to the $conf
  173.     * property in the rendering format rule.
  174.     * 
  175.     * @access public
  176.     * 
  177.     * @var array 
  178.     * 
  179.     */
  180.     
  181.     var $formatConf = array(
  182.         'Docbook' => array(),
  183.         'Latex' => array(),
  184.         'Pdf' => array(),
  185.         'Plain' => array(),
  186.         'Rtf' => array(),
  187.         'Xhtml' => array()
  188.     );
  189.     
  190.     
  191.     /**
  192.     * 
  193.     * The delimiter for token numbers of parsed elements in source text.
  194.     * 
  195.     * @access public
  196.     * 
  197.     * @var string 
  198.     * 
  199.     */
  200.     
  201.     var $delim = "\xFF"; 
  202.     
  203.     
  204.     /**
  205.     * 
  206.     * The tokens generated by rules as the source text is parsed.
  207.     * 
  208.     * As Text_Wiki applies rule classes to the source text, it will
  209.     * replace portions of the text with a delimited token number.  This
  210.     * is the array of those tokens, representing the replaced text and
  211.     * any options set by the parser for that replaced text.
  212.     * 
  213.     * The tokens array is sequential; each element is itself a sequential
  214.     * array where element 0 is the name of the rule that generated the
  215.     * token, and element 1 is an associative array where the key is an
  216.     * option name and the value is an option value.
  217.     * 
  218.     * @access private
  219.     * 
  220.     * @var array 
  221.     * 
  222.     */
  223.     
  224.     var $tokens = array();
  225.     
  226.     
  227.     /**
  228.     * 
  229.     * The source text to which rules will be applied.
  230.     * 
  231.     * This text will be transformed in-place, which means that it will
  232.     * change as the rules are applied.
  233.     * 
  234.     * @access private
  235.     * 
  236.     * @var string 
  237.     * 
  238.     */
  239.     
  240.     var $source = '';
  241.     
  242.     
  243.     /**
  244.     * 
  245.     * Array of rule parsers.
  246.     * 
  247.     * Text_Wiki creates one instance of every rule that is applied to
  248.     * the source text; this array holds those instances.  The array key
  249.     * is the rule name, and the array value is an instance of the rule
  250.     * class.
  251.     * 
  252.     * @access private
  253.     * 
  254.     * @var array 
  255.     * 
  256.     */
  257.     
  258.     var $parseObj = array();
  259.     
  260.     
  261.     /**
  262.     * 
  263.     * Array of rule renderers.
  264.     * 
  265.     * Text_Wiki creates one instance of every rule that is applied to
  266.     * the source text; this array holds those instances.  The array key
  267.     * is the rule name, and the array value is an instance of the rule
  268.     * class.
  269.     * 
  270.     * @access private
  271.     * 
  272.     * @var array 
  273.     * 
  274.     */
  275.     
  276.     var $renderObj = array();
  277.     
  278.     
  279.     /**
  280.     * 
  281.     * Array of format renderers.
  282.     * 
  283.     * @access private
  284.     * 
  285.     * @var array 
  286.     * 
  287.     */
  288.     
  289.     var $formatObj = array();
  290.     
  291.     
  292.     /**
  293.     * 
  294.     * Array of paths to search, in order, for parsing and rendering rules.
  295.     * 
  296.     * @access private
  297.     * 
  298.     * @var array 
  299.     * 
  300.     */
  301.     
  302.     var $path = array(
  303.         'parse' => array(),
  304.         'render' => array()
  305.     );
  306.     
  307.     
  308.     
  309.     /**
  310.     * 
  311.     * The directory separator character.
  312.     * 
  313.     * @access private
  314.     * 
  315.     * @var string 
  316.     * 
  317.     */
  318.     
  319.     var $_dirSep = DIRECTORY_SEPARATOR;
  320.     
  321.     
  322.     /**
  323.     * 
  324.     * Constructor.
  325.     * 
  326.     * @access public
  327.     * 
  328.     * @param array $rules The set of rules to load for this object.
  329.     *     
  330.     */
  331.     
  332.     function Text_Wiki($rules = null)
  333.     {
  334.         if (is_array($rules)) {
  335.             $this->rules = $rules;
  336.         }
  337.         
  338.         $this->addPath(
  339.             'parse',
  340.             $this->fixPath(dirname(__FILE__)) . 'Wiki/Parse/'
  341.         );
  342.         
  343.         $this->addPath(
  344.             'render',
  345.             $this->fixPath(dirname(__FILE__)) . 'Wiki/Render/'
  346.         );
  347.         
  348.     }
  349.     
  350.     
  351.     /**
  352.     * 
  353.     * Set parser configuration for a specific rule and key.
  354.     * 
  355.     * @access public
  356.     * 
  357.     * @param string $rule The parse rule to set config for.
  358.     * 
  359.     * @param array|string$arg1 The full config array to use for the
  360.     *  parse rule, or a conf key in that array.
  361.     * 
  362.     * @param string $arg2 The config value for the key.
  363.     * 
  364.     * @return void 
  365.     *
  366.     */
  367.     
  368.     function setParseConf($rule, $arg1, $arg2 = null)
  369.     {
  370.         $rule = ucwords(strtolower($rule));
  371.         
  372.         if (! isset($this->parseConf[$rule])) {
  373.             $this->parseConf[$rule] = array();
  374.         }
  375.         
  376.         // if first arg is an array, use it as the entire
  377.         // conf array for the rule.  otherwise, treat arg1
  378.         // as a key and arg2 as a value for the rule conf.
  379.         if (is_array($arg1)) {
  380.             $this->parseConf[$rule] = $arg1;
  381.         } else {
  382.             $this->parseConf[$rule][$arg1] = $arg2;
  383.         }
  384.     }
  385.     
  386.     
  387.     /**
  388.     * 
  389.     * Get parser configuration for a specific rule and key.
  390.     * 
  391.     * @access public
  392.     * 
  393.     * @param string $rule The parse rule to get config for.
  394.     * 
  395.     * @param string $key A key in the conf array; if null,
  396.     *  returns the entire conf array.
  397.     * 
  398.     * @return mixed The whole conf array if no key is specified,
  399.     *  or the specific conf key value.
  400.     *
  401.     */
  402.     
  403.     function getParseConf($rule, $key = null)
  404.     {
  405.         $rule = ucwords(strtolower($rule));
  406.         
  407.         // the rule does not exist
  408.         if (! isset($this->parseConf[$rule])) {
  409.             return null;
  410.         }
  411.         
  412.         // no key requested, return the whole array
  413.         if (is_null($key)) {
  414.             return $this->parseConf[$rule];
  415.         }
  416.         
  417.         // does the requested key exist?
  418.         if (isset($this->parseConf[$rule][$key])) {
  419.             // yes, return that value
  420.             return $this->parseConf[$rule][$key];
  421.         } else {
  422.             // no
  423.             return null;
  424.         }
  425.     }
  426.     
  427.     
  428.     /**
  429.     * 
  430.     * Set renderer configuration for a specific format, rule, and key.
  431.     * 
  432.     * @access public
  433.     * 
  434.     * @param string $format The render format to set config for.
  435.     * 
  436.     * @param string $rule The render rule to set config for in the format.
  437.     * 
  438.     * @param array|string$arg1 The config array, or the config key
  439.     *  within the render rule.
  440.     * 
  441.     * @param string $arg2 The config value for the key.
  442.     * 
  443.     * @return void 
  444.     *
  445.     */
  446.     
  447.     function setRenderConf($format, $rule, $arg1, $arg2 = null)
  448.     {
  449.         $format = ucwords(strtolower($format));
  450.         $rule = ucwords(strtolower($rule));
  451.         
  452.         if (! isset($this->renderConf[$format])) {
  453.             $this->renderConf[$format] = array();
  454.         }
  455.         
  456.         if (! isset($this->renderConf[$format][$rule])) {
  457.             $this->renderConf[$format][$rule] = array();
  458.         }
  459.         
  460.         // if first arg is an array, use it as the entire
  461.         // conf array for the render rule.  otherwise, treat arg1
  462.         // as a key and arg2 as a value for the render rule conf.
  463.         if (is_array($arg1)) {
  464.             $this->renderConf[$format][$rule] = $arg1;
  465.         } else {
  466.             $this->renderConf[$format][$rule][$arg1] = $arg2;
  467.         }
  468.     }
  469.     
  470.     
  471.     /**
  472.     * 
  473.     * Get renderer configuration for a specific format, rule, and key.
  474.     * 
  475.     * @access public
  476.     * 
  477.     * @param string $format The render format to get config for.
  478.     * 
  479.     * @param string $rule The render format rule to get config for.
  480.     * 
  481.     * @param string $key A key in the conf array; if null,
  482.     *  returns the entire conf array.
  483.     * 
  484.     * @return mixed The whole conf array if no key is specified,
  485.     *  or the specific conf key value.
  486.     *
  487.     */
  488.     
  489.     function getRenderConf($format, $rule, $key = null)
  490.     {
  491.         $format = ucwords(strtolower($format));
  492.         $rule = ucwords(strtolower($rule));
  493.         
  494.         if (! isset($this->renderConf[$format]) ||
  495.             ! isset($this->renderConf[$format][$rule])) {
  496.             return null;
  497.         }
  498.         
  499.         // no key requested, return the whole array
  500.         if (is_null($key)) {
  501.             return $this->renderConf[$format][$rule];
  502.         }
  503.         
  504.         // does the requested key exist?
  505.         if (isset($this->renderConf[$format][$rule][$key])) {
  506.             // yes, return that value
  507.             return $this->renderConf[$format][$rule][$key];
  508.         } else {
  509.             // no
  510.             return null;
  511.         }
  512.         
  513.     }
  514.     
  515.     /**
  516.     * 
  517.     * Set format configuration for a specific rule and key.
  518.     * 
  519.     * @access public
  520.     * 
  521.     * @param string $format The format to set config for.
  522.     * 
  523.     * @param string $key The config key within the format.
  524.     * 
  525.     * @param string $val The config value for the key.
  526.     * 
  527.     * @return void 
  528.     *
  529.     */
  530.     
  531.     function setFormatConf($format, $arg1, $arg2 = null)
  532.     {
  533.         if (! is_array($this->formatConf[$format])) {
  534.             $this->formatConf[$format] = array();
  535.         }
  536.         
  537.         // if first arg is an array, use it as the entire
  538.         // conf array for the format.  otherwise, treat arg1
  539.         // as a key and arg2 as a value for the format conf.
  540.         if (is_array($arg1)) {
  541.             $this->formatConf[$format] = $arg1;
  542.         } else {
  543.             $this->formatConf[$format][$arg1] = $arg2;
  544.         }
  545.     }
  546.     
  547.     
  548.     
  549.     /**
  550.     * 
  551.     * Get configuration for a specific format and key.
  552.     * 
  553.     * @access public
  554.     * 
  555.     * @param string $format The format to get config for.
  556.     * 
  557.     * @param mixed $key A key in the conf array; if null,
  558.     *  returns the entire conf array.
  559.     * 
  560.     * @return mixed The whole conf array if no key is specified,
  561.     *  or the specific conf key value.
  562.     *
  563.     */
  564.     
  565.     function getFormatConf($format, $key = null)
  566.     {
  567.         // the format does not exist
  568.         if (! isset($this->formatConf[$format])) {
  569.             return null;
  570.         }
  571.         
  572.         // no key requested, return the whole array
  573.         if (is_null($key)) {
  574.             return $this->formatConf[$format];
  575.         }
  576.         
  577.         // does the requested key exist?
  578.         if (isset($this->formatConf[$format][$key])) {
  579.             // yes, return that value
  580.             return $this->formatConf[$format][$key];
  581.         } else {
  582.             // no
  583.             return null;
  584.         }
  585.     }
  586.     
  587.     
  588.     /**
  589.     * 
  590.     * Inserts a rule into to the rule set.
  591.     * 
  592.     * @access public
  593.     * 
  594.     * @param string $name The name of the rule.  Should be different from
  595.     *  all other keys in the rule set.
  596.     * 
  597.     * @param string $tgt The rule after which to insert this new rule.  By
  598.     *  default (null) the rule is inserted at the end; if set to '', inserts
  599.     *  at the beginning.
  600.     * 
  601.     * @return void 
  602.     * 
  603.     */
  604.     
  605.     function insertRule($name, $tgt = null)
  606.     {
  607.         $name = ucwords(strtolower($name));
  608.         if (! is_null($tgt)) {
  609.             $tgt = ucwords(strtolower($tgt));
  610.         }
  611.         
  612.         // does the rule name to be inserted already exist?
  613.         if (in_array($name, $this->rules)) {
  614.             // yes, return
  615.             return null;
  616.         }
  617.         
  618.         // the target name is not null, and not '', but does not exist
  619.         // in the list of rules. this means we're trying to insert after
  620.         // a target key, but the target key isn't there.
  621.         if (! is_null($tgt) && $tgt != '' &&
  622.             ! in_array($tgt, $this->rules)) {
  623.             return false;
  624.         }
  625.         
  626.         // if $tgt is null, insert at the end.  We know this is at the
  627.         // end (instead of resetting an existing rule) becuase we exited
  628.         // at the top of this method if the rule was already in place.
  629.         if (is_null($tgt)) {
  630.             $this->rules[] = $name;
  631.             return true;
  632.         }
  633.         
  634.         // save a copy of the current rules, then reset the rule set
  635.         // so we can insert in the proper place later.
  636.         // where to insert the rule?
  637.         if ($tgt == '') {
  638.             // insert at the beginning
  639.             array_unshift($this->rules, $name);
  640.             return true;
  641.         }
  642.         
  643.         // insert after the named rule
  644.         $tmp = $this->rules;
  645.         $this->rules = array();
  646.         
  647.         foreach ($tmp as $val) {
  648.             $this->rules[] = $val;
  649.             if ($val == $tgt) {
  650.                 $this->rules[] = $name;
  651.             }
  652.         }
  653.         
  654.         return true;
  655.         
  656.     }
  657.     
  658.     
  659.     /**
  660.     * 
  661.     * Delete (remove or unset) a rule from the $rules property.
  662.     * 
  663.     * @access public
  664.     * 
  665.     * @param string $rule The name of the rule to remove.
  666.     * 
  667.     * @return void 
  668.     *     
  669.     */
  670.     
  671.     function deleteRule($name)
  672.     {
  673.         $name = ucwords(strtolower($name));
  674.         $key = array_search($name, $this->rules);
  675.         if ($key !== false) {
  676.             unset($this->rules[$key]);
  677.         }
  678.     }
  679.     
  680.     
  681.     /**
  682.     * 
  683.     * Change from one rule to another in-place.
  684.     * 
  685.     * @access public
  686.     * 
  687.     * @param string $old The name of the rule to change from.
  688.     * 
  689.     * @param string $new The name of the rule to change to.
  690.     * 
  691.     * @return void 
  692.     *     
  693.     */
  694.     
  695.     function changeRule($old, $new)
  696.     {
  697.         $old = ucwords(strtolower($old));
  698.         $new = ucwords(strtolower($new));
  699.         $key = array_search($old, $this->rules);
  700.         if ($key !== false) {
  701.             $this->rules[$old] = $new;
  702.         }
  703.     }
  704.     
  705.     
  706.     /**
  707.     * 
  708.     * Enables a rule so that it is applied when parsing.
  709.     * 
  710.     * @access public
  711.     * 
  712.     * @param string $rule The name of the rule to enable.
  713.     * 
  714.     * @return void 
  715.     *     
  716.     */
  717.     
  718.     function enableRule($name)
  719.     {
  720.         $name = ucwords(strtolower($name));
  721.         $key = array_search($name, $this->disable);
  722.         if ($key !== false) {
  723.             unset($this->disable[$key]);
  724.         }
  725.     }
  726.     
  727.     
  728.     /**
  729.     * 
  730.     * Disables a rule so that it is not applied when parsing.
  731.     * 
  732.     * @access public
  733.     * 
  734.     * @param string $rule The name of the rule to disable.
  735.     * 
  736.     * @return void 
  737.     *     
  738.     */
  739.     
  740.     function disableRule($name)
  741.     {
  742.         $name = ucwords(strtolower($name));
  743.         $key = array_search($name, $this->disable);
  744.         if ($key === false) {
  745.             $this->disable[] = $name;
  746.         }
  747.     }
  748.     
  749.     
  750.     /**
  751.     * 
  752.     * Parses and renders the text passed to it, and returns the results.
  753.     * 
  754.     * First, the method parses the source text, applying rules to the
  755.     * text as it goes.  These rules will modify the source text
  756.     * in-place, replacing some text with delimited tokens (and
  757.     * populating the $this->tokens array as it goes).
  758.     * 
  759.     * Next, the method renders the in-place tokens into the requested
  760.     * output format.
  761.     * 
  762.     * Finally, the method returns the transformed text.  Note that the
  763.     * source text is transformed in place; once it is transformed, it is
  764.     * no longer the same as the original source text.
  765.     * 
  766.     * @access public
  767.     * 
  768.     * @param string $text The source text to which wiki rules should be
  769.     *  applied, both for parsing and for rendering.
  770.     * 
  771.     * @param string $format The target output format, typically 'xhtml'.
  772.     *   If a rule does not support a given format, the output from that
  773.     *  rule is rule-specific.
  774.     * 
  775.     * @return string The transformed wiki text.
  776.     * 
  777.     */
  778.     
  779.     function transform($text, $format = 'Xhtml')
  780.     {
  781.         $this->parse($text);
  782.         return $this->render($format);
  783.     }
  784.     
  785.     
  786.     /**
  787.     * 
  788.     * Sets the $_source text property, then parses it in place and
  789.     * retains tokens in the $_tokens array property.
  790.     * 
  791.     * @access public
  792.     * 
  793.     * @param string $text The source text to which wiki rules should be
  794.     *  applied, both for parsing and for rendering.
  795.     * 
  796.     * @return void 
  797.     * 
  798.     */
  799.     
  800.     function parse($text)
  801.     {
  802.         // set the object property for the source text
  803.         $this->source = $text;
  804.         
  805.         // reset the tokens.
  806.         $this->tokens = array();
  807.         
  808.         // apply the parse() method of each requested rule to the source
  809.         // text.
  810.         foreach ($this->rules as $name) {
  811.             // do not parse the rules listed in $disable
  812.             if (! in_array($name, $this->disable)) {
  813.                 
  814.                 // load the parsing object
  815.                 $this->loadParseObj($name);
  816.                 
  817.                 // load may have failed; only parse if
  818.                 // an object is in the array now
  819.                 if (is_object($this->parseObj[$name])) {
  820.                     $this->parseObj[$name]->parse();
  821.                 }
  822.             }
  823.         }
  824.     }
  825.     
  826.     
  827.     /**
  828.     * 
  829.     * Renders tokens back into the source text, based on the requested format.
  830.     * 
  831.     * @access public
  832.     * 
  833.     * @param string $format The target output format, typically 'xhtml'.
  834.     *  If a rule does not support a given format, the output from that
  835.     *  rule is rule-specific.
  836.     * 
  837.     * @return string The transformed wiki text.
  838.     * 
  839.     */
  840.     
  841.     function render($format = 'Xhtml')
  842.     {
  843.         // the rendering method we're going to use from each rule
  844.         $format = ucwords(strtolower($format));
  845.         
  846.         // the eventual output text
  847.         $output = '';
  848.         
  849.         // when passing through the parsed source text, keep track of when
  850.         // we are in a delimited section
  851.         $in_delim = false;
  852.         
  853.         // when in a delimited section, capture the token key number
  854.         $key = '';
  855.         
  856.         // load the format object
  857.         $this->loadFormatObj($format);
  858.         
  859.         // pre-rendering activity
  860.         if (is_object($this->formatObj[$format])) {
  861.             $output .= $this->formatObj[$format]->pre();
  862.         }
  863.         
  864.         // load the render objects
  865.         foreach (array_keys($this->parseObj) as $rule) {
  866.             $this->loadRenderObj($format, $rule);
  867.         }
  868.         
  869.         // pass through the parsed source text character by character
  870.         $k = strlen($this->source);
  871.         for ($i = 0; $i < $k; $i++) {
  872.             
  873.             // the current character
  874.             $char = $this->source{$i};
  875.             
  876.             // are alredy in a delimited section?
  877.             if ($in_delim) {
  878.             
  879.                 // yes; are we ending the section?
  880.                 if ($char == $this->delim) {
  881.                     
  882.                     // yes, get the replacement text for the delimited
  883.                     // token number and unset the flag.
  884.                     $key = (int)$key;
  885.                     $rule = $this->tokens[$key][0];
  886.                     $opts = $this->tokens[$key][1];
  887.                     $output .= $this->renderObj[$rule]->token($opts);
  888.                     $in_delim = false;
  889.                     
  890.                 } else {
  891.                 
  892.                     // no, add to the dlimited token key number
  893.                     $key .= $char;
  894.                     
  895.                 }
  896.                 
  897.             } else {
  898.                 
  899.                 // not currently in a delimited section.
  900.                 // are we starting into a delimited section?
  901.                 if ($char == $this->delim) {
  902.                     // yes, reset the previous key and
  903.                     // set the flag.
  904.                     $key = '';
  905.                     $in_delim = true;
  906.                 } else {
  907.                     // no, add to the output as-is
  908.                     $output .= $char;
  909.                 }
  910.             }
  911.         }
  912.         
  913.         // post-rendering activity
  914.         if (is_object($this->formatObj[$format])) {
  915.             $output .= $this->formatObj[$format]->post();
  916.         }
  917.         
  918.         // return the rendered source text.
  919.         return $output;
  920.     }
  921.     
  922.     
  923.     /**
  924.     * 
  925.     * Returns the parsed source text with delimited token placeholders.
  926.     * 
  927.     * @access public
  928.     * 
  929.     * @return string The parsed source text.
  930.     * 
  931.     */
  932.     
  933.     function getSource()
  934.     {
  935.         return $this->source;
  936.     }
  937.     
  938.     
  939.     /**
  940.     * 
  941.     * Returns tokens that have been parsed out of the source text.
  942.     * 
  943.     * @access public
  944.     * 
  945.     * @param array $rules If an array of rule names is passed, only return
  946.     *  tokens matching these rule names.  If no array is passed, return all
  947.     *  tokens.
  948.     * 
  949.     * @return array An array of tokens.
  950.     * 
  951.     */
  952.     
  953.     function getTokens($rules = null)
  954.     {
  955.         if (is_null($rules)) {
  956.             return $this->tokens;
  957.         } else {
  958.             settype($rules, 'array');
  959.             $result = array();
  960.             foreach ($this->tokens as $key => $val) {
  961.                 if (in_array($val[0], $rules)) {
  962.                     $result[] = $val;
  963.                 }
  964.             }
  965.             return $result;
  966.         }
  967.     }
  968.     
  969.     
  970.     /**
  971.     * 
  972.     * Add a token to the Text_Wiki tokens array, and return a delimited
  973.     * token number.
  974.     * 
  975.     * @access public
  976.     * 
  977.     * @param array $options An associative array of options for the new
  978.     *  token array element.  The keys and values are specific to the
  979.     *  rule, and may or may not be common to other rule options.  Typical
  980.     *  options keys are 'text' and 'type' but may include others.
  981.     * 
  982.     * @param boolean $id_only If true, return only the token number, not
  983.     *  a delimited token string.
  984.     * 
  985.     * @return string|intBy default, return the number of the
  986.     *  newly-created token array element with a delimiter prefix and
  987.     *  suffix; however, if $id_only is set to true, return only the token
  988.     *  number (no delimiters).
  989.     * 
  990.     */
  991.     
  992.     function addToken($rule, $options = array(), $id_only = false)
  993.     {
  994.         // increment the token ID number.  note that if you parse
  995.         // multiple times with the same Text_Wiki object, the ID number
  996.         // will not reset to zero.
  997.         static $id;
  998.         if (! isset($id)) {
  999.             $id = 0;
  1000.         } else {
  1001.             $id ++;
  1002.         }
  1003.         
  1004.         // force the options to be an array
  1005.         settype($options, 'array');
  1006.         
  1007.         // add the token
  1008.         $this->tokens[$id] = array(
  1009.             0 => $rule,
  1010.             1 => $options
  1011.         );
  1012.         
  1013.         // return a value
  1014.         if ($id_only) {
  1015.             // return the last token number
  1016.             return $id;
  1017.         } else {
  1018.             // return the token number with delimiters
  1019.             return $this->delim . $id . $this->delim;
  1020.         }
  1021.     }
  1022.     
  1023.     
  1024.     /**
  1025.     * 
  1026.     * Set or re-set a token with specific information, overwriting any
  1027.     * previous rule name and rule options.
  1028.     * 
  1029.     * @access public
  1030.     * 
  1031.     * @param int $id The token number to reset.
  1032.     * 
  1033.     * @param int $rule The rule name to use.
  1034.     * 
  1035.     * @param array $options An associative array of options for the
  1036.     *  token array element.  The keys and values are specific to the
  1037.     *  rule, and may or may not be common to other rule options.  Typical
  1038.     *  options keys are 'text' and 'type' but may include others.
  1039.     * 
  1040.     * @return void 
  1041.     * 
  1042.     */
  1043.     
  1044.     function setToken($id, $rule, $options = array())
  1045.     {
  1046.         // reset the token
  1047.         $this->tokens[$id] = array(
  1048.             0 => $rule,
  1049.             1 => $options
  1050.         );
  1051.     }
  1052.     
  1053.     
  1054.     /**
  1055.     * 
  1056.     * Load a rule parser class file.
  1057.     * 
  1058.     * @access public
  1059.     * 
  1060.     * @return bool True if loaded, false if not.
  1061.     * 
  1062.     */
  1063.     
  1064.     function loadParseObj($rule)
  1065.     {
  1066.         $rule = ucwords(strtolower($rule));
  1067.         $file = $rule . '.php';
  1068.         $class = "Text_Wiki_Parse_$rule";
  1069.         
  1070.         if (! class_exists($class)) {
  1071.             $loc = $this->findFile('parse', $file);
  1072.             if ($loc) {
  1073.                 // found the class
  1074.                 include_once $loc;
  1075.             } else {
  1076.                 // can't find the class
  1077.                 $this->parseObj[$rule] = null;
  1078.                 return false;
  1079.             }
  1080.         }
  1081.         
  1082.         $this->parseObj[$rule] =& new $class($this);
  1083.  
  1084.     }
  1085.     
  1086.     
  1087.     /**
  1088.     * 
  1089.     * Load a rule-render class file.
  1090.     * 
  1091.     * @access public
  1092.     * 
  1093.     * @return bool True if loaded, false if not.
  1094.     * 
  1095.     */
  1096.     
  1097.     function loadRenderObj($format, $rule)
  1098.     {
  1099.         $format = ucwords(strtolower($format));
  1100.         $rule = ucwords(strtolower($rule));
  1101.         $file = "$format/$rule.php";
  1102.         $class = "Text_Wiki_Render_$format" . "_$rule";
  1103.         
  1104.         if (! class_exists($class)) {
  1105.             // load the class
  1106.             $loc = $this->findFile('render', $file);
  1107.             if ($loc) {
  1108.                 // found the class
  1109.                 include_once $loc;
  1110.             } else {
  1111.                 // can't find the class
  1112.                 return false;
  1113.             }
  1114.         }
  1115.         
  1116.         $this->renderObj[$rule] =& new $class($this);
  1117.     }
  1118.     
  1119.     
  1120.     /**
  1121.     * 
  1122.     * Load a format-render class file.
  1123.     * 
  1124.     * @access public
  1125.     * 
  1126.     * @return bool True if loaded, false if not.
  1127.     * 
  1128.     */
  1129.     
  1130.     function loadFormatObj($format)
  1131.     {
  1132.         $format = ucwords(strtolower($format));
  1133.         $file = $format . '.php';
  1134.         $class = "Text_Wiki_Render_$format";
  1135.         
  1136.         if (! class_exists($class)) {
  1137.             $loc = $this->findFile('render', $file);
  1138.             if ($loc) {
  1139.                 // found the class
  1140.                 include_once $loc;
  1141.             } else {
  1142.                 // can't find the class
  1143.                 return false;
  1144.             }
  1145.         }
  1146.         
  1147.         $this->formatObj[$format] =& new $class($this);
  1148.     }
  1149.     
  1150.     
  1151.     /**
  1152.     * 
  1153.     * Add a path to a path array.
  1154.     * 
  1155.     * @access public
  1156.     * 
  1157.     * @param string $type The path-type to add (parse or render).
  1158.     * 
  1159.     * @param string $dir The directory to add to the path-type.
  1160.     * 
  1161.     * @return void 
  1162.     * 
  1163.     */
  1164.     
  1165.     function addPath($type, $dir)
  1166.     {
  1167.         $dir = $this->fixPath($dir);
  1168.         if (! isset($this->path[$type])) {
  1169.             $this->path[$type] = array($dir);
  1170.         } else {
  1171.             array_unshift($this->path[$type], $dir);
  1172.         }
  1173.     }
  1174.     
  1175.     
  1176.     /**
  1177.     * 
  1178.     * Get the current path array for a path-type.
  1179.     * 
  1180.     * @access public
  1181.     * 
  1182.     * @param string $type The path-type to look up (plugin, filter, or
  1183.     *  template).  If not set, returns all path types.
  1184.     * 
  1185.     * @return array The array of paths for the requested type.
  1186.     * 
  1187.     */
  1188.     
  1189.     function getPath($type = null)
  1190.     {
  1191.         if (is_null($type)) {
  1192.             return $this->path;
  1193.         } elseif (! isset($this->path[$type])) {
  1194.             return array();
  1195.         } else {
  1196.             return $this->path[$type];
  1197.         }
  1198.     }
  1199.     
  1200.     
  1201.     /**
  1202.     * 
  1203.     * Searches a series of paths for a given file.
  1204.     * 
  1205.     * @param array $type The type of paths to search (template, plugin,
  1206.     *  or filter).
  1207.     * 
  1208.     * @param string $file The file name to look for.
  1209.     * 
  1210.     * @return string|boolThe full path and file name for the target file,
  1211.     *  or boolean false if the file is not found in any of the paths.
  1212.     *
  1213.     */
  1214.     
  1215.     function findFile($type, $file)
  1216.     {
  1217.         // get the set of paths
  1218.         $set = $this->getPath($type);
  1219.         
  1220.         // start looping through them
  1221.         foreach ($set as $path) {
  1222.             $fullname = $path . $file;
  1223.             if (file_exists($fullname) && is_readable($fullname)) {
  1224.                 return $fullname;
  1225.             }
  1226.         }
  1227.         
  1228.         // could not find the file in the set of paths
  1229.         return false;
  1230.     }
  1231.     
  1232.     
  1233.     /**
  1234.     * 
  1235.     * Append a trailing '/' to paths, unless the path is empty.
  1236.     * 
  1237.     * @access private
  1238.     * 
  1239.     * @param string $path The file path to fix
  1240.     * 
  1241.     * @return string The fixed file path
  1242.     * 
  1243.     */
  1244.     
  1245.     function fixPath($path)
  1246.     {
  1247.         $len = strlen($this->_dirSep);
  1248.         
  1249.         if (! empty($path) &&
  1250.             substr($path, -1 * $len, $len) != $this->_dirSep)    {
  1251.             return $path . $this->_dirSep;
  1252.         } else {
  1253.             return $path;
  1254.         }
  1255.     }
  1256. }
  1257.  
  1258. ?>

Documentation generated on Mon, 11 Mar 2019 13:56:55 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.