geparster Text:
1 .<?php
2
/**
3  * BBParser
4  * parst Code auf konfigurierbare BBCode-Tags
5  * 
6  * @author Johannes Schlichenmaier
7  * @version 01.03.2006
8  * @package core_util
9  */
10  
11  
class core_util_BBParser {
12      private 
$tags = array('search' => array(), 'replace' => array(), 'plc' => array(), 'allowed_in' => array(), 'allowed_within' => array());
13      
14      
/**
15       * core_util_BBParser::construct($custom = false)
16       * Erstellt auf Wunsch häufige BBCode-Tags automatisch. Wenn nicht erwünscht, einfach mit "true" als Parameter aufrufen.
17       * 
18       * @param boolean $custom     Wenn "true" gesetzt, werden b, i , u, und zwei Varianten von Links (link - [url=...]...[/url] - 
19       *                             und url - [url]...[/url]- ) nicht erstellt.
20       */
21      
public function __construct($custom false) {
22          if (
$custom === false) {
23              
$this->add_Tag('b''[b]%b[/b]''<b>%b</b>');
24              
$this->add_Tag('i''[i]%i[/i]''<i>%i</i>');
25              
$this->add_Tag('u''[u]%u[/u]''<u>%u</u>');
26              
$this->add_Tag('link''[url=%s]%l[/url]''<a href="%s">%l</a>');
27              
$this->add_Tag('url''[url]%s[/url]''<a href="%s">%s</a>');    
28          }
29      }
30      
31      
32      
/**
33       * core_util_BBParser::prepare_Pattern($string)
34       * wandelt einen BBCode zu einem Regulären Ausdruck um
35       * 
36       * @param String $string    umzuwandelnder String
37       */
38      
private function prepare_Pattern($string$modifiers) {
39          
$string addcslashes($string,'\'\\/,^$.[]|()?*+{}');
40          
$string preg_replace("/%[a-z]/""(.*)"$string);
41          
$string '/'.$string.'/'.$modifiers;
42          return 
$string;
43      }
44      
45      
46      
/**
47       * core_util_BBParser::prepare_html_Output($string, $placeholders)
48       * bereitet den übergebenen HTML-Code mit den Platzhaltern für die Verwendung in preg_replace vor
49       * 
50       * @param String $string    umzuwandelnder HTML-Code
51       * @param Array $placeholders    Array mit in dem BBCode gefundenen Platzhaltern in der Reihenfolge ihres Auftretens
52       */
53      
private function prepare_html_Output($string$placeholders) {
54          
$i 0;
55          
$return = array("", array());
56          
$return[0] = str_replace(array("'""%\'"), array("\'""'"), $string);
57          
$return[0] = "'".$return[0]."'";
58          foreach (
$placeholders as $index => $plc) {
59              
$return[1][] = $index;
60              if (
$plc !== null) {
61              
$return[0] = str_replace($index"'.".$plc."(str_replace('\\"', '"','\$".($i+1)."')).'"$return[0]);
62              }
63              else {
64              
$return[0] = str_replace($index"'.str_replace('\\"', '"', '\$".($i+1)."').'"$return[0]);
65              }
66              
$i++;
67          }
68          return 
$return;
69      }
70      
71      
72      
/**
73       * core_util_BBParser::is_valid_function_array(&$name)
74       * Überprüft, ob ein übergebenes Array mit Platzhaltern gültige Funktionen/Methoden enthält
75       * 
76       * @param &Array $name     Array mit Platzhaltern (und zusätzlichen Informationen)
77       */
78      
private function is_valid_function_array(&$name) {
79          
$all_valid true;
80          foreach (
$name as $plc => $function) {
81              
$valid true;
82              if (
preg_match("/^%[a-z]/"$plc)) {
83                  if (
stristr($function'$this->') !== false) {
84                      
$function_array explode('->'$function);
85                      if (!
is_callable(array($this$function_array[1]))) $valid false;    
86                  } 
87                  elseif (
strstr($function'::') !== false) {
88                      
$function_array explode('::'$function);
89                      if (!
is_callable(array("$function_array[0]"$function_array[1]))) $valid false;
90                  }
91                  else {
92                      if (!
function_exists($function)) $valid false;
93                  }
94                  if (!
$valid) {
95                      
$all_valid false;
96                      
$name[$plc] = $name[$plc].' - ERROR: method/function is not callable';
97                  }
98              }
99          }
100          
101          return 
$all_valid;
102      }
103      
104      
105      
/**
106       * core_util_BBParser::add_Tag($name, $bbcode, $htmlcode, $options = array())
107       * Fügt einen weiteren BBCode-Tag zum Suchalgorithmus hinzu
108       * 
109       * Platzhalter: ein % mit anschließendem a-z.
110       * Besondere Platzhalter:     %s : Darin gefundene Strings werden nicht weiter geparst - NOCH NICHT IMPLEMENTIERT
111       *                             %' : Wird im preg_replace später zu einem unescapten ' . Nützlich, um einzelne Platzhalter direkt durch Funktionen oder Methoden zu schicken.
112       * 
113       * @param String $name    Identifier des neuen Tags
114       * @param String $bbcode    BBCode mit Platzhaltern
115       * @param String $htmlcode    HTML-Code mit Platzhaltern - 
116       *                             nur %' wird später zu ' so können auch direkt Funktionen auf einzelne Platzhalter übergeben werden
117       * @param Array $options    Enthält Informationen zum Tag und für einzelne Platzhalter Funktionen 'Platzhalter' => Funktion/Methode
118       */
119      
public function add_Tag($name$bbcode$htmlcode$options = array()) {
120          
$placeholders = array();
121          
$place_holders = array();
122          if (
count($options) > && !$this->is_valid_function_array($options))
123              throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler in Funktionsarray für Tag "".$name."": ".print_r($optionstrue));
124          
125          
$pattern $this->prepare_Pattern($bbcode, (isset($options['modifier'])) ? $options['modifier'] : 'isUe');
126          
$search array_flip($this->tags['search']);
127          
128          if (
in_array($pattern$this->tags['search']) && $search[$pattern] != $name) {
129              throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler bei Erstellen von BB-Tag "".$name."": "".$search[$pattern]."" hat gleiches BBCode-Pattern");
130          }
131          
132          if (
$name == 'erde') {
133              throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler bei Erstellen von BB-Tag: Name 'erde' ist reserviert!");
134          }
135          
136          
preg_match_all("/%[a-z]/"$bbcode$place_holders);
137          foreach (
$place_holders[0] as $plc) {
138              
$placeholders[$plc]    = (isset($options[$plc])) ? $options[$plc] : null;
139          }
140          
141          
$html_array $this->prepare_html_Output($htmlcode$placeholders);
142          
143          
$this->tags['search'][$name]  = $pattern;
144          
$this->tags['replace'][$name] = $html_array[0];
145          
$this->tags['plc'][$name] = $html_array[1];
146          
$this->tags['allowed_in'][$name] = (isset($options['allowed_in'])) ? explode(';'$options['allowed_in']) : array();
147          
$this->tags['allowed_within'][$name] = (isset($options['allowed_within'])) ? explode(';'$options['allowed_within']) : array();
148      }
149      
150      
151      
152      
/**
153       * core_util_BBParser::find_first_occurent($string, $search)
154       * Testet einen String auf mehrere reguläre Ausdrücke und gibt den zurück, der als erster greift
155       * 
156       * @param String $string zu untersuchender String
157       * @param Array $search Array mit Regulären Ausdrücken
158       */
159      
private function find_first_occurent($string$search) {
160          
$found = array();
161          
$first = array('ID' => null'StrPos' => null'Str' => array(nullnullnull));
162          
163          foreach (
$search as $id => $pattern) {
164              
preg_match($pattern$string$found);
165              if (
count($found) > 0) {
166                  
$strpos strpos($string$found[0]);
167                  if (!isset(
$first['StrPos']) || $strpos $first['StrPos']) {
168                      
$split explode($found[0], $string2);
169                      
170                      if (
count($split) == 1) {
171                           
$split[0] = "";
172                           
$split[1] = "";
173                      }
174                      elseif (
count($split) == 1) {
175                          if  (
$strpos == 0) {
176                              
$split[1] = $split[0];
177                               
$split[0] = "";
178                          }
179                          else {
180                              
$split[1] = "";
181                          }
182                      }
183                          
184                  
185                      
$first['ID'] = $id;
186                      
$first['StrPos'] = $strpos;
187                      
$first['Str'][0] = $split[0];
188                      
$first['Str'][1] = $found[0];
189                      
$first['Str'][2] = $split[1];
190                      if (
$strpos === 0) break;
191                  }
192              }
193          }
194          
195          return 
$first;
196      }
197      
198      
/*
199      private function get_allowed_pattern(&$IDs) {
200          $search = array();
201          $cache = 'erde';
202          $cached_IDs = $IDs;
203          $cached2_IDs = array();
204          if (count($IDs) == 0) {
205              return $this->tags['search'];
206          }
207          else {
208             echo "\n\n\n";
209              foreach ($IDs as $index => $id) {
210                  if (count($this->tags['allowed_within'][$IDs[$index]]) == 0 || in_array($cache, $this->tags['allowed_within'][$IDs[$index]])) {
211                      
212                      $cached2_IDs = $cached_IDs;
213                      print_r($cached_IDs);
214                      foreach($cached_IDs as $index2 => $cached_id) {
215                          if (!in_array($cached_id, $this->tags['allowed_in'][$IDs[$index]])) {
216                              unset($cached2_IDs[$index2]);
217                          }
218                      }
219                      
220                      $cached_IDs = $cached2_IDs;
221                      $cache = $id;
222                  }
223                  else {
224                      unset($cached_IDs[$index]);
225                  }
226              }
227              $IDs = $cached_IDs;
228              foreach ($IDs as $id) {
229                  $search[$id] = $this->tags['search'][$id];
230              }
231              var_dump($search);
232              return $search;
233          }
234      }
235      */
236      
237      
private function get_allowed_pattern($IDs) {
238          
$search = array();
239          if (
count($IDs) == 0) {
240              
$search $this->tags['search'];
241          }
242          else {
243              if (
count($this->tags['allowed_in'][$IDs[0]]) == 0) {
244                  
$search $this->tags['search'];
245              }
246              else {
247                  foreach(
$this->tags['allowed_in'][$IDs[0]] as $pattern) {
248                      
$search[$pattern] = $this->tags['search'][$pattern];
249                  }
250              }            
251          }
252              
253          
$cache_search $search;
254          foreach (
$cache_search as $id => $pattern) {
255              if (!
count($this->tags['allowed_within'][$id]) == && !in_array((isset($IDs[0])) ? $IDs[0] : 'erde'$this->tags['allowed_within'][$id])) {
256                  unset(
$search[$id]);
257              }
258          }
259          return 
$search;
260      }
261      
262      
/**
263       * core_util_BBParser::parse_rek($string, $name = null)
264       * ominöse Funktion, die rekursiv einen String parst. ^^
265       * 
266       * @param String $string zu parsender String
267       * @param String $name ID des Strings
268       */
269      
private function parse_rek($string$IDs = array()) {
270          if (
strlen(trim($string)) == 0) {
271              return 
$string;
272          }
273          
274          
$search = array();
275          
$first = array();
276          
277          
//$strpos = 0;
278          
$split = array();
279          
280          
//var_dump($string);
281          
$search $this->get_allowed_pattern($IDs);
282          
283          
$first $this->find_first_occurent($string$search);
284          if (
strlen($first['Str'][1]) > 0) {
285              
$inner_strings = array();
286              
287              
preg_match_all($this->tags['search'][$first['ID']], $first['Str'][1], $inner_strings);
288              
array_shift($inner_strings);
289              
array_unshift($IDs$first['ID']);
290              
291              foreach (
$inner_strings as $index => $plc) {
292                  if (
$this->tags['plc'][$first['ID']][$index] != "%s") {
293                      
$first['Str'][1] = str_replace($plc[0], $this->parse_rek($inner_strings[$index][0], $IDs), $first['Str'][1]);
294                  }
295                  else {
296                      
str_replace($plc[$index], $inner_strings[$index][0], $first['Str'][1]);
297                  }
298              }
299              
300              
$first['Str'][2] = $this->parse_rek($first['Str'][2]);
301              
$first['Str'][1] = preg_replace(str_replace("/isUe""/ise"$this->tags['search'][$first['ID']]), $this->tags['replace'][$first['ID']], $first['Str'][1]);
302              return 
$first['Str'][0].$first['Str'][1].$first['Str'][2];
303          }
304          else {
305              return 
$string;
306          }
307      }
308      
309      
310      
311      
/**
312       * core_util_BBParser::parse($code)
313       * Parst übergebenen Code nach den vorher definierten Tags
314       * 
315       * @param String $code zu parsender Code
316       */
317      
public function parse($code) {
318          
//print_r($this->tags);
319          //return preg_replace($this->tags['search'], $this->tags['replace'], $code);
320          
return $this->parse_rek($code);
321      }
322  }
323
?>.




Datei: Test.php:
<?
function __autoload($classname) {
    global 
$config;
      
$classname str_replace('_''/'$classname);
    
$require = require_once('src/' $classname '.php');
    if (!
$require) echo 'File '.dirname($_SERVER['SCRIPT_FILENAME']).'/src/' $classname '.php not found!';
}


function 
highlight($str) {
    
$rows = array();
    
$str highlight_string($strtrue);
    
$str_array explode("<br />"$str);
    
$i 1;
    foreach (
$str_array as $row) {
        
$rows[] = '<font color="#808080">'.$i."</font>\t".$row;
        
$i++;
    }
    
$str implode("<br />"$rows);
    return 
$str;
}

$fp fopen(dirname($_SERVER['SCRIPT_FILENAME']).'/src/core/util/BBParser.php'"r");
$string fread($fpfilesize(dirname($_SERVER['SCRIPT_FILENAME']).'/src/core/util/BBParser.php'));
fclose($fp);

echo 
'<html><body>';
try {
    
$parser = new core_util_BBParser(); // )
    
$parser->add_Tag('php''[php]%s[/php]''<div class="php">%\'.highlight(str_replace(%\'\"%\', %\'"%\', %\'.%s.%\')).%\'</div>');
    
//$parser->add_Tag('php', '[php]%s[/php]', '<div class="php">%s</div>', array('%s' => 'highlight'));
    
$parser->add_Tag('php2''[php2]%s[/php2]''<div class="php2">%s</div>');
    echo 
'geparster Text:<br />';
    echo 
$parser->parse('[php]'.$string.'[/php]');
    echo 
'<br /><br /><br /><br />Datei: Test.php:<br />';
    
highlight_file(__FILE__);
    echo 
'<br /><br /><br /><br />Datei: BBParser.php:<br />';
    
highlight_file(dirname($_SERVER['SCRIPT_FILENAME']).'/src/core/util/BBParser.php');
    echo 
'<br /><br /><br /><br />Text normal geparst<br />';
    echo 
highlight($string);
}
catch (
Exception $e) {
    echo 
'Error: '.$e->getMessage();
}
echo 
'</body></html>';
?>




Datei: BBParser.php:
<?php
/**
 * BBParser
 * parst Code auf konfigurierbare BBCode-Tags
 * 
 * @author Johannes Schlichenmaier
 * @version 01.03.2006
 * @package core_util
 */
 
 
class core_util_BBParser {
     private 
$tags = array('search' => array(), 'replace' => array(), 'plc' => array(), 'allowed_in' => array(), 'allowed_within' => array());
     
     
/**
      * core_util_BBParser::construct($custom = false)
      * Erstellt auf Wunsch häufige BBCode-Tags automatisch. Wenn nicht erwünscht, einfach mit "true" als Parameter aufrufen.
      * 
      * @param boolean $custom     Wenn "true" gesetzt, werden b, i , u, und zwei Varianten von Links (link - [url=...]...[/url] - 
      *                             und url - [url]...[/url]- ) nicht erstellt.
      */
     
public function __construct($custom false) {
         if (
$custom === false) {
             
$this->add_Tag('b''[b]%b[/b]''<b>%b</b>');
             
$this->add_Tag('i''[i]%i[/i]''<i>%i</i>');
             
$this->add_Tag('u''[u]%u[/u]''<u>%u</u>');
             
$this->add_Tag('link''[url=%s]%l[/url]''<a href="%s">%l</a>');
             
$this->add_Tag('url''[url]%s[/url]''<a href="%s">%s</a>');    
         }
     }
     
     
     
/**
      * core_util_BBParser::prepare_Pattern($string)
      * wandelt einen BBCode zu einem Regulären Ausdruck um
      * 
      * @param String $string    umzuwandelnder String
      */
     
private function prepare_Pattern($string$modifiers) {
         
$string addcslashes($string,'\'\\/,^$.[]|()?*+{}');
         
$string preg_replace("/%[a-z]/""(.*)"$string);
         
$string '/'.$string.'/'.$modifiers;
         return 
$string;
     }
     
     
     
/**
      * core_util_BBParser::prepare_html_Output($string, $placeholders)
      * bereitet den übergebenen HTML-Code mit den Platzhaltern für die Verwendung in preg_replace vor
      * 
      * @param String $string    umzuwandelnder HTML-Code
      * @param Array $placeholders    Array mit in dem BBCode gefundenen Platzhaltern in der Reihenfolge ihres Auftretens
      */
     
private function prepare_html_Output($string$placeholders) {
         
$i 0;
         
$return = array("", array());
         
$return[0] = str_replace(array("'""%\'"), array("\'""'"), $string);
         
$return[0] = "'".$return[0]."'";
         foreach (
$placeholders as $index => $plc) {
             
$return[1][] = $index;
             if (
$plc !== null) {
             
$return[0] = str_replace($index"'.".$plc."(str_replace('\\\"', '\"','\$".($i+1)."')).'"$return[0]);
             }
             else {
             
$return[0] = str_replace($index"'.str_replace('\\\"', '\"', '\$".($i+1)."').'"$return[0]);
             }
             
$i++;
         }
         return 
$return;
     }
     
     
     
/**
      * core_util_BBParser::is_valid_function_array(&$name)
      * Überprüft, ob ein übergebenes Array mit Platzhaltern gültige Funktionen/Methoden enthält
      * 
      * @param &Array $name     Array mit Platzhaltern (und zusätzlichen Informationen)
      */
     
private function is_valid_function_array(&$name) {
         
$all_valid true;
         foreach (
$name as $plc => $function) {
             
$valid true;
             if (
preg_match("/^%[a-z]/"$plc)) {
                 if (
stristr($function'$this->') !== false) {
                     
$function_array explode('->'$function);
                     if (!
is_callable(array($this$function_array[1]))) $valid false;    
                 } 
                 elseif (
strstr($function'::') !== false) {
                     
$function_array explode('::'$function);
                     if (!
is_callable(array("$function_array[0]"$function_array[1]))) $valid false;
                 }
                 else {
                     if (!
function_exists($function)) $valid false;
                 }
                 if (!
$valid) {
                     
$all_valid false;
                     
$name[$plc] = $name[$plc].' - ERROR: method/function is not callable';
                 }
             }
         }
         
         return 
$all_valid;
     }
     
     
     
/**
      * core_util_BBParser::add_Tag($name, $bbcode, $htmlcode, $options = array())
      * Fügt einen weiteren BBCode-Tag zum Suchalgorithmus hinzu
      * 
      * Platzhalter: ein % mit anschließendem a-z.
      * Besondere Platzhalter:     %s : Darin gefundene Strings werden nicht weiter geparst - NOCH NICHT IMPLEMENTIERT
      *                             %' : Wird im preg_replace später zu einem unescapten ' . Nützlich, um einzelne Platzhalter direkt durch Funktionen oder Methoden zu schicken.
      * 
      * @param String $name    Identifier des neuen Tags
      * @param String $bbcode    BBCode mit Platzhaltern
      * @param String $htmlcode    HTML-Code mit Platzhaltern - 
      *                             nur %' wird später zu ' so können auch direkt Funktionen auf einzelne Platzhalter übergeben werden
      * @param Array $options    Enthält Informationen zum Tag und für einzelne Platzhalter Funktionen 'Platzhalter' => Funktion/Methode
      */
     
public function add_Tag($name$bbcode$htmlcode$options = array()) {
         
$placeholders = array();
         
$place_holders = array();
         if (
count($options) > && !$this->is_valid_function_array($options))
             throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler in Funktionsarray für Tag \"".$name."\": ".print_r($optionstrue));
         
         
$pattern $this->prepare_Pattern($bbcode, (isset($options['modifier'])) ? $options['modifier'] : 'isUe');
         
$search array_flip($this->tags['search']);
         
         if (
in_array($pattern$this->tags['search']) && $search[$pattern] != $name) {
             throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler bei Erstellen von BB-Tag \"".$name."\": \"".$search[$pattern]."\" hat gleiches BBCode-Pattern");
         }
         
         if (
$name == 'erde') {
             throw new 
Exception (__FILE__."; Zeile ".__LINE__."  :  Fehler bei Erstellen von BB-Tag: Name 'erde' ist reserviert!");
         }
         
         
preg_match_all("/%[a-z]/"$bbcode, <