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

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