MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / mod / wiki / ewiki / fragments / wiki_format.inc
blob0c09749b5bb2b46c2f0fdbbc56f3a1736756e635
1 <?php
3 /* 
4  * Wiki-Engine from "ErfurtWiki", Mario Salzer <milky@erphesfurt.de>
5  * Adapted by Frank Luithle <sigi@fsinfo.cs.uni-sb.de>
6  *
7  * WikiLinks and binary already stripped off -> just the rendering core
8  */
10 // URL prefixes
11 $ewiki_idf_url = array( "http://",
12                         "mailto:",
13                         "ftp://",
14                         "irc://",
15                         "telnet://",
16                         "news://",
17                         "internal://",
18                         "chrome://",
19                         "file://" );
21 // allowed wikinames
22 //define( "EWIKI_CHARS_L", "a-z����_��$" );
23 //define( "EWIKI_CHARS_U", "A-Z���" );
25 function wiki_format( $wiki_source,
26                       $strip_slashes = true,
27                       $safe_html_allowed = true,
28                       $table_html_allowed = false ) {
30   if ( $strip_slashes ) {
31     $wiki_source = stripslashes( $wiki_source );
32   }
34   // formatted output
35   $o = "<p>\n";
37   // state vars
38   $li_o = "";
39   $tbl_o = 0;
40   $post = "";
42   $wm_whole_line = array( "!!!" => "h2",
43                           "!!"  => "h3",
44                           "!"   => "h4",
45                           " "   => "tt",
46                           ";:"  => 'div style="left-margin:10pt;"' );
48   $table_defaults = 'cellpadding="2" border="1" cellspacing="0"';
50   // these tags will be preserved if the $safe_html_allowed argument
51   // is set to 'true'
52   $rescue_html = array( "tt", "b", "i", "strong", "em", "s", "kbd", "var",
53                         "xmp", "sup", "sub", "pre", "q", "h2", "h3", "h4",
54                         "h5", "h6", "cite", "code", "u" );
56   $syn_htmlentities = array( "&" => "&amp;",
57                              ">" => "&gt;",
58                              "<" => "&lt;",
59                              "%%%" => "<br/>" );
61   $wm_list = array( "-" => array('ul type="square"', "", "li"),
62                     "*" => array('ul type="circle"', "", "li"),
63                     "#" => array("ol", "", "li"),
64                     ":" => array("dl", "dt", "dd") );
66   $wm_text_style = array( "'''" => array("''__", "__''"),
67                           "___" => array("''__", "__''"),
68                           "''" => array("<em>", "</em>"),
69                           "__" => array("<strong>", "</strong>"),
70                           // "^^" => array("<sup>", "</sup>"),
71                           // "***" => array("<b><i>", "</i></b>"),
72                           // "###" => array("<big><b>", "</b></big>"),
73                           "**" => array("<b>", "</b>"),
74                           "##" => array("<big>", "</big>"),
75                           "��" => array("<small>", "</small>") );
77   $link_regex = "#(!?\[[^[\]\n]+\])|((?:!?[a-z]{2,6}://|mailto:)[^\s\[\]\'\"\)\,<]+)#";
79   #$link_regex = "#(!?\[[^[\]\n]+\])|((?:!?[".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L.
80   #  ":]+){2}[\w\d]*)|((?:!?[a-z]{2,6}://|mailto:)[^\s\[\]\'\"\)\,<]+)#";
82   // eliminate html
83   foreach ( $syn_htmlentities as $find => $replace ) {
84     $wiki_source = str_replace( $find, $replace, $wiki_source );
85   }
86   array_pop( $syn_htmlentities );
88   // unescape allowed html
89   if ( $safe_html_allowed ) {
90     foreach ( $rescue_html as $tag ) {
91       foreach( array( $tag, "/$tag", ( $tag = strtoupper($tag) ), "/$tag" )
92                as $tag ) {
93         $wiki_source = str_replace( '&lt;' . $tag . '&gt;',
94                                     "<" . $tag . ">",
95                                     $wiki_source );
96       }
97     }
98   }
100   $wiki_source = trim( $wiki_source ) . "\n";
102   foreach ( explode( "\n", $wiki_source ) as $line ) {
103     $line = rtrim( $line );
104     $post = "";
106     // paragraphs
107     if ( empty($line) ) {
108       $post .= "</p>\n\n<p>";
109     } elseif ( strpos( $line, "----" ) === 0 ) {
110       $o .= "<hr>\n";
111       continue;
112     } elseif ( strpos( $line, "&lt;!--" ) === 0 ) {
113       $o .= "<!-- " . s( str_replace( "--", "__", substr($line, 7) ) ) . " -->\n";
114       continue;
115     }
117     // unescape html markup || tables wiki markup
118     if ( strlen( $line ) && ( $line[0] == "|" ) ) {
119       if ( strlen( $line ) >
120            strlen( trim( $line, "|" ) ) + 1 ) {
121         $line = substr( $line, 1, strlen( $line ) - 2 );
122         if ( !$tbl_o ) {
123           $o .= "<table " . $table_defaults . ">\n";
124         }
125         $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
126         $tbl_o = 1;
127       } elseif ( $table_html_allowed ) {
128         $line = ltrim( substr( $line, 1 ) );
129         foreach ( array_flip( $syn_htmlentities ) as $find => $replace ) {
130           $line = str_replace( $find, $replace, $line );
131         }
132       }
133     } elseif ($tbl_o) {
134       $o .= "</table>\n";
135       $tbl_o = 0;
136     }
138     // whole-line wikimarkup
139     foreach ( $wm_whole_line as $find => $replace ) {
140       if ( substr( $line, 0, strlen($find) ) == $find ) {
141         $line = ltrim( substr( $line, strlen($find) ) );
142         $o .= "<$replace>";
143         $post = "</" . strtok( $replace, " " ) . ">" . $post;
144       }
145     }
147     // wiki list markup
148     if ( strlen( $li_o ) ||
149          strlen( $line ) && isset( $wm_list[@$line[0]] ) ) {
150       $n = 0;
151       $li = "";
152       // count differences to previous list wikimarkup
153       while ( strlen( $line ) && ( $li0 = $line[0] ) && isset( $wm_list[$li0] ) ) {
154         $li .= $li0;
155         $n++;
156         $line = substr($line, 1);
157       }
158       $line = ltrim($line);
160       // fetch list definition
161       if ( strlen( $li ) && ( $last_list_i = $li[strlen($li)-1] ) )
162         list( $list_tag, $list_dt0, $list_entry_tag ) = $wm_list[$last_list_i];
164       // output <ul> until new list wikimarkup rule matched
165       while ( strlen($li_o) < strlen($li) ) {
166         $add = $li[ strlen($li_o) ];
167         $o .= "<" . $wm_list[ $add ][ 0 ] . ">\n";
168         $li_o .= $add;
169       }
171       // close </ul> lists until "$li_o" == "$li" (list wikimarkup state var)
172       while ( strlen($li_o) > strlen($li) ) {
173         $del = $li_o[ strlen($li_o) - 1 ];
174         $o .= "</" . strtok( $wm_list[$del][0], " " ) . ">\n";
175         $li_o = substr( $li_o, 0, strlen($li_o) - 1 );
176       }
178       // more work for <dl> lists
179       if ( !empty($list_dt0) ) {
180         list( $line_dt, $line ) = explode( $last_list_i, $line, 2 );
181         $o .= "<$list_dt0>$line_dt</$list_dt0>";
182         $list_dt0 = $last_list_i = false;
183       }
185       // finally enclose current line in <li>...</li>
186       if ( !empty($line) ) {
187         $o .=  "<$list_entry_tag>";
188         $post = "</$list_entry_tag>" . $post;
189       }
191       $li_o = $li;
192     }
194     // link-regex here??
195     // (was formerly, may be faster if applied to the whole formatted
196     // page, but this could also introduce some rendering bugs)
198     // text style triggers
199     foreach ( $wm_text_style as $find => $replace ) {
200       $n = strlen( $find );
201       $loop = 20;
202       while( ( $loop-- ) &&
203              ( ($l = strpos($line, $find)) !== false ) &&
204              ( $r = strpos($line, $find, $l + $n) ) ) {
205         $line = substr( $line, 0, $l ) . $replace[0] .
206           substr( $line, $l + strlen($find), $r - $l - $n ) .
207           $replace[1] . substr( $line, $r + $n );
208       }
209     }
211     // add formatted line to page-output
212     $o .= $line . $post . "\n";
214   }
216   // close last line
217   $o .= "</p>\n";
219   // finally the link-detection-regex
220   // (impossible to do with simple string arithmetics)
221   $o = preg_replace_callback( $link_regex, "wiki_link_regex_callback", $o );
223   return( $o );
227 function wiki_link_regex_callback( $uu ) {
229    global $ewiki_idf_url;
231    $str = $uu[0];
233    // link bracket '[' escaped with '!'
234    if ( $str[0] == "!" ) {
235      return(substr($str, 1));
236    } elseif ( $str[0] == "[" ) {
237      $str = substr( $str, 1, strlen($str) - 2 );
238    }
240    // explicit title given via [ foo | bar ]
241    $href = $title = strtok( $str, "|" );
242    if ( $uu = strtok("|") ) {
243       $href = $uu;
244    }
246    // title and href swapped: swap back
247    if ( strpos( "://", $title ) ||
248         strpos( $title, ":" ) && !strpos( $href, ":" ) ) {
249      $uu = $title;
250      $title = $href;
251      $href = $uu;
252    }
254    $title = trim($title);
255    $href = trim($href);
257    /* create _no_ WikiLinks */
258    if ( false ){
259      // interwiki links
260      if ( strpos($href, ":") &&
261           !strpos($href, "//") &&
262           ($p1 = @$ewiki_interwiki[strtok($href, ":")]) ) {
263        while ($p1_alias = @$ewiki_interwiki[$p1]) {
264          $p1 = $p1_alias;
265        }
266        $href = $p1 . strtok("\000");
267      } elseif (($ewiki_links === true) ||
268                @$ewiki_links[$href] ||
269                @$ewiki_internal_pages[$href]) {
270        // ordinary internal WikiLinks
271       $str = '<a href="' . EWIKI_SCRIPT .
272         urlencode($href) . '">' . $title . '</a>';
273      } else {
274        $str = '<b>' . $title . '</b><a href="' .
275          EWIKI_SCRIPT . urlencode($href) /*.EWIKI_ADDPARAMDELIM.'edit'*/ .
276          ' ">?</a>';
277      }
278    }
280    // convert normal URLs
281    foreach ( $ewiki_idf_url as $find ) {
282      if ( strpos( $href, $find ) === 0 ) {
283       $str = '<a href="' . $href . '">' . $title . '</a>';
284       break;
285      }
286    }
288    return($str);