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

Source for file List.php

Documentation is available at List.php

  1. <?php
  2. // $Id: List.php,v 1.2 2004/09/25 19:05:13 pmjones Exp $
  3.  
  4.  
  5. /**
  6. * This class implements a Text_Wiki_Parse to find source text marked as
  7. * a bulleted or numbered list.  In short, if a line starts with '* ' then
  8. * it is a bullet list item; if a line starts with '# ' then it is a
  9. * number list item.  Spaces in front of the * or # indicate an indented
  10. * sub-list.  The list items must be on sequential lines, and may be
  11. * separated by blank lines to improve readability.  Using a non-* non-#
  12. * non-whitespace character at the beginning of a line ends the list.
  13. *
  14. @author Paul M. Jones <pmjones@ciaweb.net>
  15. *
  16. @package Text_Wiki
  17. *
  18. */
  19.  
  20.     
  21.     
  22.     /**
  23.     * 
  24.     * The regular expression used to parse the source text and find
  25.     * matches conforming to this rule.  Used by the parse() method.
  26.     * 
  27.     * @access public
  28.     * 
  29.     * @var string 
  30.     * 
  31.     * @see parse()
  32.     * 
  33.     */
  34.     
  35.     var $regex = '/\n((\*|#) .*\n)(?! {0,}(\* |# |\n))/Us';
  36.     
  37.     
  38.     /**
  39.     * 
  40.     * Generates a replacement for the matched text.  Token options are:
  41.     * 
  42.     * 'type' =>
  43.     *     'bullet_start' : the start of a bullet list
  44.     *     'bullet_end'   : the end of a bullet list
  45.     *     'number_start' : the start of a number list
  46.     *     'number_end'   : the end of a number list
  47.     *     'item_start'   : the start of item text (bullet or number)
  48.     *     'item_end'     : the end of item text (bullet or number)
  49.     *     'unknown'      : unknown type of list or item
  50.     *
  51.     * 'level' => the indent level (0 for the first level, 1 for the
  52.     * second, etc)
  53.     *
  54.     * 'count' => the list item number at this level. not needed for
  55.     * xhtml, but very useful for PDF and RTF.
  56.     * 
  57.     * @access public
  58.     *
  59.     * @param array &$matches The array of matches from parse().
  60.     *
  61.     * @return series of text and delimited tokens marking the different
  62.     *  list text and list elements.
  63.     *
  64.     */
  65.     
  66.     function process(&$matches)
  67.     {
  68.         // the replacement text we will return
  69.         $return '';
  70.         
  71.         // the list of post-processing matches
  72.         $list = array();
  73.         
  74.         // a stack of list-start and list-end types; we keep this
  75.         // so that we know what kind of list we're working with
  76.         // (bullet or number) and what indent level we're at.
  77.         $stack = array();
  78.         
  79.         // the item count is the number of list items for any
  80.         // given list-type on the stack
  81.         $itemcount = array();
  82.         
  83.         // have we processed the very first list item?
  84.         $pastFirst = false;
  85.         
  86.         // populate $list with this set of matches. $matches[1] is the
  87.         // text matched as a list set by parse().
  88.         preg_match_all(
  89.             '=^( {0,})(\*|#) (.*)$=Ums',
  90.             $matches[1],
  91.             $list,
  92.             PREG_SET_ORDER
  93.         );
  94.         
  95.         // loop through each list-item element.
  96.         foreach ($list as $key => $val{
  97.             
  98.             // $val[0] is the full matched list-item line
  99.             // $val[1] is the number of initial spaces (indent level)
  100.             // $val[2] is the list item type (* or #)
  101.             // $val[3] is the list item text
  102.             
  103.             // how many levels are we indented? (1 means the "root"
  104.             // list level, no indenting.)
  105.             $level strlen($val[1]+ 1;
  106.             
  107.             // get the list item type
  108.             if ($val[2== '*'{
  109.                 $type 'bullet';
  110.             elseif ($val[2== '#'{
  111.                 $type 'number';
  112.             else {
  113.                 $type 'unknown';
  114.             }
  115.             
  116.             // get the text of the list item
  117.             $text $val[3];
  118.             
  119.             // add a level to the list?
  120.             if ($level count($stack)) {
  121.                 
  122.                 // the current indent level is greater than the
  123.                 // number of stack elements, so we must be starting
  124.                 // a new list.  push the new list type onto the
  125.                 // stack...
  126.                 array_push($stack$type);
  127.                 
  128.                 // ...and add a list-start token to the return.
  129.                 $return .= $this->wiki->addToken(
  130.                     $this->rule
  131.                     array(
  132.                         'type' => $type '_list_start',
  133.                         'level' => $level - 1
  134.                     )
  135.                 );
  136.             }
  137.             
  138.             // remove a level from the list?
  139.             while (count($stack$level{
  140.                 
  141.                 // so we don't keep counting the stack, we set up a temp
  142.                 // var for the count.  -1 becuase we're going to pop the
  143.                 // stack in the next command.  $tmp will then equal the
  144.                 // current level of indent.
  145.                 $tmp count($stack- 1;
  146.                 
  147.                 // as long as the stack count is greater than the
  148.                 // current indent level, we need to end list types. 
  149.                 // continue adding end-list tokens until the stack count
  150.                 // and the indent level are the same.
  151.                 $return .= $this->wiki->addToken(
  152.                     $this->rule
  153.                     array (
  154.                         'type' => array_pop($stack'_list_end',
  155.                         'level' => $tmp
  156.                     )
  157.                 );
  158.                 
  159.                 // reset to the current (previous) list type so that
  160.                 // the new list item matches the proper list type.
  161.                 $type $stack[$tmp - 1];
  162.                 
  163.                 // reset the item count for the popped indent level
  164.                 unset($itemcount[$tmp + 1]);
  165.             }
  166.             
  167.             // add to the item count for this list (taking into account
  168.             // which level we are at).
  169.             if (isset($itemcount[$level])) {
  170.                 // first count
  171.                 $itemcount[$level= 0;
  172.             else {
  173.                 // increment count
  174.                 $itemcount[$level]++;
  175.             }
  176.             
  177.             // is this the very first item in the list?
  178.             if ($pastFirst{
  179.                 $first = true;
  180.                 $pastFirst = true;
  181.             else {
  182.                 $first = false;
  183.             }
  184.             
  185.             // create a list-item starting token.
  186.             $start $this->wiki->addToken(
  187.                 $this->rule
  188.                 array(
  189.                     'type' => $type '_item_start',
  190.                     'level' => $level,
  191.                     'count' => $itemcount[$level],
  192.                     'first' => $first
  193.                 )
  194.             );
  195.             
  196.             // create a list-item ending token.
  197.             $end $this->wiki->addToken(
  198.                 $this->rule
  199.                 array(
  200.                     'type' => $type '_item_end',
  201.                     'level' => $level,
  202.                     'count' => $itemcount[$level]
  203.                 )
  204.             );
  205.             
  206.             // add the starting token, list-item text, and ending token
  207.             // to the return.
  208.             $return .= $start $val[3$end;
  209.         }
  210.         
  211.         // the last list-item may have been indented.  go through the
  212.         // list-type stack and create end-list tokens until the stack
  213.         // is empty.
  214.         while (count($stack> 0{
  215.             $return .= $this->wiki->addToken(
  216.                 $this->rule
  217.                 array (
  218.                     'type' => array_pop($stack'_list_end',
  219.                     'level' => count($stack)
  220.                 )
  221.             );
  222.         }
  223.         
  224.         // we're done!  send back the replacement text.
  225.         return "\n" $return "\n\n";
  226.     }
  227. }
  228. ?>

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