|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00012 class wiki_parser_proxy { 00013 private static $parsers = array(); 00014 private static $basepath = ""; 00015 00016 public static function parse(&$string, $type, $options = array()) { 00017 00018 if(empty(self::$basepath)) { 00019 global $CFG; 00020 self::$basepath = $CFG->dirroot.'/mod/wiki/parser/'; 00021 } 00022 00023 $type = strtolower($type); 00024 if(self::create_parser_instance($type)) { 00025 return self::$parsers[$type]->parse($string, $options); 00026 } 00027 else { 00028 return false; 00029 } 00030 } 00031 00032 public static function get_token($name, $type) { 00033 if(self::create_parser_instance($type)) { 00034 return self::$parsers[$type]->get_token($name); 00035 } 00036 else { 00037 return false; 00038 } 00039 } 00040 00041 public static function get_section(&$string, $type, $section, $all_content = false) { 00042 if(self::create_parser_instance($type)) { 00043 $content = self::$parsers[$type]->get_section($section, $string, true); 00044 00045 if($all_content) { 00046 return $content; 00047 } 00048 else { 00049 return $content[1]; 00050 } 00051 } 00052 else { 00053 return false; 00054 } 00055 } 00056 00057 private static function create_parser_instance($type) { 00058 if(empty(self::$parsers[$type])) { 00059 if(include(self::$basepath."markups/$type.php")) { 00060 $class = strtolower($type)."_parser"; 00061 if(class_exists($class)) { 00062 self::$parsers[$type] = new $class; 00063 return true; 00064 } 00065 else { 00066 return false; 00067 } 00068 } 00069 else { 00070 return false; 00071 } 00072 } 00073 else { 00074 return true; 00075 } 00076 } 00077 } 00078 00079 require_once('utils.php'); 00080 00081 abstract class generic_parser { 00082 protected $string; 00083 00084 protected $blockrules = array(); 00085 protected $tagrules = array(); 00086 00087 private $rulestack = array(); 00088 00089 protected $parser_status = 'Before'; 00090 00095 protected $returnvalues = array(); 00096 00097 private $nowikiindex = array(); 00098 00099 protected $nowikitoken = "%!"; 00100 00101 public function __construct() {} 00102 00107 public function parse(&$string, $options = array()) { 00108 if(!is_string($string)) { 00109 return false; 00110 } 00111 00112 $this->string =& $string; 00113 00114 $this->set_options(is_array($options) ? $options : array()); 00115 00116 $this->initialize_nowiki_index(); 00117 00118 if(method_exists($this, 'before_parsing')) { 00119 $this->before_parsing(); 00120 } 00121 00122 $this->parser_status = 'Parsing'; 00123 00124 foreach($this->blockrules as $name => $block) { 00125 $this->process_block_rule($name, $block); 00126 } 00127 00128 $this->commit_nowiki_index(); 00129 00130 $this->parser_status = 'After'; 00131 00132 if(method_exists($this, 'after_parsing')) { 00133 $this->after_parsing(); 00134 } 00135 00136 return array('parsed_text' => $this->string) + $this->returnvalues; 00137 } 00138 00143 protected function set_options($options) {} 00144 00149 protected function process_block_rule($name, $block) { 00150 $this->rulestack[] = array('callback' => method_exists($this, $name."_block_rule") ? $name."_block_rule" : null, 'rule' => $block); 00151 00152 $this->string = preg_replace_callback($block['expression'], array($this, 'block_callback'), $this->string); 00153 00154 array_pop($this->rulestack); 00155 } 00156 00157 private function block_callback($match) { 00158 $rule = end($this->rulestack); 00159 if(!empty($rule['callback'])) { 00160 $stuff = $this->{$rule['callback']}($match); 00161 } 00162 else { 00163 $stuff = $match[1]; 00164 } 00165 00166 if(is_array($stuff) && $rule['rule']['tag']) { 00167 $this->rules($stuff[0], $rule['rule']['tags']); 00168 $stuff = "\n".parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1])."\n"; 00169 } 00170 else { 00171 if(!isset($rule['rule']['tags'])) { 00172 $rule['rule']['tags'] = null; 00173 } 00174 $this->rules($stuff, $rule['rule']['tags']); 00175 if(isset($rule['rule']['tag']) && is_string($rule['rule']['tag'])) { 00176 $stuff = "\n".parser_utils::h($rule['rule']['tag'], $stuff)."\n"; 00177 } 00178 } 00179 00180 return $stuff; 00181 } 00182 00187 protected final function rules(&$text, $rules = null) { 00188 if($rules === null) { 00189 $rules = array('except' => array()); 00190 } 00191 else if(is_array($rules) && count($rules) > 1) { 00192 $rules = array('only' => $rules); 00193 } 00194 00195 if(isset($rules['only']) && is_array($rules['only'])) { 00196 $rules = $rules['only']; 00197 foreach($rules as $r) { 00198 if(!empty($this->tagrules[$r])) { 00199 $this->process_tag_rule($r, $this->tagrules[$r], $text); 00200 } 00201 } 00202 } 00203 else if(isset($rules['except']) && is_array($rules['except'])) { 00204 $rules = $rules['except']; 00205 foreach($this->tagrules as $r => $tr) { 00206 if(!in_array($r, $rules)) { 00207 $this->process_tag_rule($r, $tr, $text); 00208 } 00209 } 00210 } 00211 } 00212 00213 private function process_tag_rule($name, $rule, &$text) { 00214 if(method_exists($this, $name."_tag_rule")) { 00215 $this->rulestack[] = array('callback' => $name."_tag_rule", 'rule' => $rule); 00216 $text = preg_replace_callback($rule['expression'], array($this, 'tag_callback'), $text); 00217 array_pop($this->rulestack); 00218 } 00219 else { 00220 if(isset($rule['simple'])) { 00221 $replace = "<{$rule['tag']} />"; 00222 } 00223 else { 00224 $replace = parser_utils::h($rule['tag'], "$1"); 00225 } 00226 00227 $text = preg_replace($rule['expression'], $replace, $text); 00228 } 00229 } 00230 00231 private function tag_callback($match) { 00232 $rule = end($this->rulestack); 00233 $stuff = $this->{$rule['callback']}($match); 00234 00235 if(is_array($stuff)) { 00236 return parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1]); 00237 } 00238 else { 00239 return $stuff; 00240 } 00241 } 00242 00247 private function initialize_nowiki_index() { 00248 $token = "\Q".$this->nowikitoken."\E"; 00249 $this->string = preg_replace_callback("/".$token."\d+".$token."/", array($this, "initialize_nowiki_index_callback"), $this->string); 00250 } 00251 00252 private function initialize_nowiki_index_callback($match) { 00253 return $this->protect($match[0]); 00254 } 00255 00256 protected function protect($text) { 00257 $this->nowikiindex[] = $text; 00258 00259 return $this->nowikitoken.(count($this->nowikiindex)-1).$this->nowikitoken; 00260 } 00261 00262 private function commit_nowiki_index() { 00263 $token = "\Q".$this->nowikitoken."\E"; 00264 $this->string = preg_replace_callback("/".$token."(\d+)".$token."/", array($this, "commit_nowiki_index_callback"), $this->string); 00265 } 00266 00267 private function commit_nowiki_index_callback($match) { 00268 return $this->nowikiindex[intval($match[1])]; 00269 } 00270 00275 public function get_token($name) { 00276 foreach(array_merge($this->blockrules, $this->tagrules) as $n => $v) { 00277 if($name == $n && isset($v['token'])) { 00278 return $v['token'] ? $v['token'] : false; 00279 } 00280 } 00281 00282 return false; 00283 } 00284 }