XOOPS RMCommon Utilities  2.1.8.91RC
 All Classes Namespaces Files Functions Variables
customcode.php
Go to the documentation of this file.
1 <?php
9 {
13  private $custom_codes = array();
14 
15  static function get(){
16  static $instance;
17 
18  if (isset($instance))
19  return $instance;
20 
21  $instance = new RMCustomCode();
22  return $instance;
23  }
24 
73  function add($tag, $func) {
74 
75  if ( is_callable($func) )
76  $this->custom_codes[$tag] = $func;
77 
78  }
79 
88  function remove($tag) {
89 
90  unset($this->custom_codes[$tag]);
91  }
92 
103  function removeAll() {
104 
105  $this->custom_codes = array();
106 
107  }
108 
123  function doCode($content) {
124 
125  if (empty($this->custom_codes) || !is_array($this->custom_codes))
126  return $content;
127 
128  $pattern = $this->getRegex();
129  return preg_replace_callback( "/$pattern/s", array($this, 'doTag'), $content );
130  }
131 
152  function getRegex() {
153 
154  $tagnames = array_keys($this->custom_codes);
155  $tagregexp = join( '|', array_map('preg_quote', $tagnames) );
156 
157  // WARNING! Do not change this regex without changing do_customcode_tag() and strip_customcode_tag()
158  // Also, see customcode_unautop() and customcode.js.
159  return
160  '\\[' // Opening bracket
161  . '(\\[?)' // 1: Optional second opening bracket for escaping customcodes: [[tag]]
162  . "($tagregexp)" // 2: customcode name
163  . '(?![\\w-])' // Not followed by word character or hyphen
164  . '(' // 3: Unroll the loop: Inside the opening customcode tag
165  . '[^\\]\\/]*' // Not a closing bracket or forward slash
166  . '(?:'
167  . '\\/(?!\\])' // A forward slash not followed by a closing bracket
168  . '[^\\]\\/]*' // Not a closing bracket or forward slash
169  . ')*?'
170  . ')'
171  . '(?:'
172  . '(\\/)' // 4: Self closing tag ...
173  . '\\]' // ... and closing bracket
174  . '|'
175  . '\\]' // Closing bracket
176  . '(?:'
177  . '(' // 5: Unroll the loop: Optionally, anything between the opening and closing customcode tags
178  . '[^\\[]*+' // Not an opening bracket
179  . '(?:'
180  . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing customcode tag
181  . '[^\\[]*+' // Not an opening bracket
182  . ')*+'
183  . ')'
184  . '\\[\\/\\2\\]' // Closing customcode tag
185  . ')?'
186  . ')'
187  . '(\\]?)'; // 6: Optional second closing brocket for escaping customcodes: [[tag]]
188  }
189 
201  function doTag( $m ) {
202 
203  // allow [[foo]] syntax for escaping a tag
204  if ( $m[1] == '[' && $m[6] == ']' ) {
205  return substr($m[0], 1, -1);
206  }
207 
208  $tag = $m[2];
209  $attr = $this->parseAtts( $m[3] );
210 
211  if ( isset( $m[5] ) ) {
212  // enclosing tag - extra parameter
213  return $m[1] . call_user_func( $this->custom_codes[$tag], $attr, $m[5], $tag ) . $m[6];
214  } else {
215  // self-closing tag
216  return $m[1] . call_user_func( $this->custom_codes[$tag], $attr, null, $tag ) . $m[6];
217  }
218  }
219 
232  function parseAtts($text) {
233  $atts = array();
234  $pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
235  $text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text);
236  if ( preg_match_all($pattern, $text, $match, PREG_SET_ORDER) ) {
237  foreach ($match as $m) {
238  if (!empty($m[1]))
239  $atts[strtolower($m[1])] = stripcslashes($m[2]);
240  elseif (!empty($m[3]))
241  $atts[strtolower($m[3])] = stripcslashes($m[4]);
242  elseif (!empty($m[5]))
243  $atts[strtolower($m[5])] = stripcslashes($m[6]);
244  elseif (isset($m[7]) and strlen($m[7]))
245  $atts[] = stripcslashes($m[7]);
246  elseif (isset($m[8]))
247  $atts[] = stripcslashes($m[8]);
248  }
249  } else {
250  $atts = ltrim($text);
251  }
252  return $atts;
253  }
254 
271  function atts($pairs, $atts) {
272  $atts = (array)$atts;
273  $out = array();
274  foreach($pairs as $name => $default) {
275  if ( array_key_exists($name, $atts) )
276  $out[$name] = $atts[$name];
277  else
278  $out[$name] = $default;
279  }
280  return $out;
281  }
282 
292  function strip( $content ) {
293 
294  if (empty($this->custom_codes) || !is_array($this->custom_codes))
295  return $content;
296 
297  $pattern = $this->getRegex();
298 
299  return preg_replace_callback( "/$pattern/s", array($this, 'strip'), $content );
300  }
301 
302  function stripTag( $m ) {
303  // allow [[foo]] syntax for escaping a tag
304  if ( $m[1] == '[' && $m[6] == ']' ) {
305  return substr($m[0], 1, -1);
306  }
307 
308  return $m[1] . $m[6];
309  }
310 
311 }
312