[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/mod/wiki/parser/ -> parser.php (source)

   1  <?php
   2  
   3  /**
   4   * Generic parser implementation
   5   *
   6   * @author Josep ArĂºs
   7   *
   8   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
   9   * @package mod_wiki
  10   */
  11  
  12  class wiki_parser_proxy {
  13      private static $parsers = array();
  14      private static $basepath = "";
  15  
  16      public static function parse(&$string, $type, $options = array()) {
  17  
  18          if(empty(self::$basepath)) {
  19              global $CFG;
  20              self::$basepath = $CFG->dirroot.'/mod/wiki/parser/';
  21          }
  22  
  23          $type = strtolower($type);
  24          self::$parsers[$type] = null; // Reset the current parser because it may have other options.
  25          if(self::create_parser_instance($type)) {
  26              return self::$parsers[$type]->parse($string, $options);
  27          }
  28          else {
  29              return false;
  30          }
  31      }
  32  
  33      public static function get_token($name, $type) {
  34          if(self::create_parser_instance($type)) {
  35              return self::$parsers[$type]->get_token($name);
  36          }
  37          else {
  38              return false;
  39          }
  40      }
  41      
  42      public static function get_section(&$string, $type, $section, $all_content = false) {
  43          if(self::create_parser_instance($type)) {
  44              $content = self::$parsers[$type]->get_section($section, $string, true);
  45              
  46              if($all_content) {
  47                  return $content;
  48              }
  49              else {
  50                  return $content[1];
  51              }
  52          }
  53          else {
  54              return false;
  55          }
  56      }
  57  
  58      private static function create_parser_instance($type) {
  59          if(empty(self::$parsers[$type])) {
  60              include_once(self::$basepath."markups/$type.php");
  61              $class = strtolower($type)."_parser";
  62              if(class_exists($class)) {
  63                  self::$parsers[$type] = new $class;
  64                  return true;
  65              }
  66              else {
  67                  return false;
  68              }
  69          }
  70          else {
  71              return true;
  72          }
  73      }
  74  }
  75  
  76  require_once ('utils.php');
  77  
  78  abstract class generic_parser {
  79      protected $string;
  80  
  81      protected $blockrules = array();
  82      protected $tagrules = array();
  83  
  84      private $rulestack = array();
  85  
  86      protected $parser_status = 'Before';
  87      
  88      /**
  89       * Dynamic return values
  90       */
  91       
  92      protected $returnvalues = array();
  93  
  94      private $nowikiindex = array();
  95  
  96      protected $nowikitoken = "%!";
  97      
  98      public function __construct() {}
  99  
 100      /**
 101       * Parse function
 102       */
 103  
 104      public function parse(&$string, $options = array()) {
 105          if(!is_string($string)) {
 106              return false;
 107          }
 108  
 109          $this->string =& $string;
 110  
 111          $this->set_options(is_array($options) ? $options : array());
 112  
 113          $this->initialize_nowiki_index();
 114  
 115          if(method_exists($this, 'before_parsing')) {
 116              $this->before_parsing();
 117          }
 118          
 119          $this->parser_status = 'Parsing';
 120  
 121          foreach($this->blockrules as $name => $block) {
 122              $this->process_block_rule($name, $block);
 123          }
 124  
 125          $this->commit_nowiki_index();
 126  
 127          $this->parser_status = 'After';
 128  
 129          if(method_exists($this, 'after_parsing')) {
 130              $this->after_parsing();
 131          }
 132          
 133          return array('parsed_text' => $this->string) + $this->returnvalues;
 134      }
 135  
 136      /**
 137       * Initialize options
 138       */
 139  
 140      protected function set_options($options) {}
 141  
 142      /**
 143       * Block processing function & callbacks
 144       */
 145  
 146      protected function process_block_rule($name, $block) {
 147          $this->rulestack[] = array('callback' => method_exists($this, $name."_block_rule") ? $name."_block_rule" : null, 'rule' => $block);
 148  
 149          $this->string = preg_replace_callback($block['expression'], array($this, 'block_callback'), $this->string);
 150  
 151          array_pop($this->rulestack);
 152      }
 153  
 154      private function block_callback($match) {
 155          $rule = end($this->rulestack);
 156          if(!empty($rule['callback'])) {
 157              $stuff = $this->{$rule['callback']}($match);
 158          }
 159          else {
 160              $stuff = $match[1];
 161          }
 162  
 163          if(is_array($stuff) && $rule['rule']['tag']) {
 164              $this->rules($stuff[0], $rule['rule']['tags']);
 165              $stuff = "\n".parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1])."\n";
 166          }
 167          else {
 168              if(!isset($rule['rule']['tags'])) {
 169                  $rule['rule']['tags'] = null;
 170              }
 171              $this->rules($stuff, $rule['rule']['tags']);
 172              if(isset($rule['rule']['tag']) && is_string($rule['rule']['tag'])) {
 173                  $stuff = "\n".parser_utils::h($rule['rule']['tag'], $stuff)."\n";
 174              }
 175          }
 176  
 177          return $stuff;
 178      }
 179  
 180      /**
 181       * Rules processing function & callback
 182       */
 183  
 184      protected final function rules(&$text, $rules = null) {
 185          if($rules === null) {
 186              $rules = array('except' => array());
 187          }
 188          else if(is_array($rules) && count($rules) > 1) {
 189              $rules = array('only' => $rules);
 190          }
 191  
 192          if(isset($rules['only']) && is_array($rules['only'])) {
 193              $rules = $rules['only'];
 194              foreach($rules as $r) {
 195                  if(!empty($this->tagrules[$r])) {
 196                      $this->process_tag_rule($r, $this->tagrules[$r], $text);
 197                  }
 198              }
 199          }
 200          else if(isset($rules['except']) && is_array($rules['except'])) {
 201              $rules = $rules['except'];
 202              foreach($this->tagrules as $r => $tr) {
 203                  if(!in_array($r, $rules)) {
 204                      $this->process_tag_rule($r, $tr, $text);
 205                  }
 206              }
 207          }
 208      }
 209  
 210      private function process_tag_rule($name, $rule, &$text) {
 211          if(method_exists($this, $name."_tag_rule")) {
 212              $this->rulestack[] = array('callback' => $name."_tag_rule", 'rule' => $rule);
 213              $text = preg_replace_callback($rule['expression'], array($this, 'tag_callback'), $text);
 214              array_pop($this->rulestack);
 215          }
 216          else {
 217              if(isset($rule['simple'])) {
 218                  $replace = "<{$rule['tag']} />";
 219              }
 220              else {
 221                  $replace = parser_utils::h($rule['tag'], "$1");
 222              }
 223              
 224              $text = preg_replace($rule['expression'], $replace, $text);
 225          }
 226      }
 227  
 228      private function tag_callback($match) {
 229          $rule = end($this->rulestack);
 230          $stuff = $this->{$rule['callback']}($match);
 231  
 232          if(is_array($stuff)) {
 233              return parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1]);
 234          }
 235          else {
 236              return $stuff;
 237          }
 238      }
 239  
 240      /**
 241       * Special nowiki parser index
 242       */
 243  
 244      private function initialize_nowiki_index() {
 245          $token = "\Q".$this->nowikitoken."\E";
 246          $this->string = preg_replace_callback("/".$token."\d+".$token."/", array($this, "initialize_nowiki_index_callback"), $this->string);
 247      }
 248  
 249      private function initialize_nowiki_index_callback($match) {
 250          return $this->protect($match[0]);
 251      }
 252  
 253      protected function protect($text) {
 254          $this->nowikiindex[] = $text;
 255  
 256          return $this->nowikitoken.(count($this->nowikiindex)-1).$this->nowikitoken;
 257      }
 258  
 259      private function commit_nowiki_index() {
 260          $token = "\Q".$this->nowikitoken."\E";
 261          $this->string = preg_replace_callback("/".$token."(\d+)".$token."/", array($this, "commit_nowiki_index_callback"), $this->string);
 262      }
 263  
 264      private function commit_nowiki_index_callback($match) {
 265          return $this->nowikiindex[intval($match[1])];
 266      }
 267  
 268      /**
 269       * Get token of the parsable element $name.
 270       */
 271  
 272       public function get_token($name) {
 273           foreach(array_merge($this->blockrules, $this->tagrules) as $n => $v) {
 274               if($name == $n && isset($v['token'])) {
 275                  return $v['token'] ? $v['token'] : false;
 276               }
 277           }
 278  
 279           return false;
 280       }     
 281  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1