~ubuntu-branches/ubuntu/saucy/mediawiki-extensions/saucy

« back to all changes in this revision

Viewing changes to dist/mediawiki-extensions-fckeditor/usr/share/mediawiki-extensions/fckeditor/FCKeditorParser.body.php

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis
  • Date: 2010-05-04 15:13:35 UTC
  • mfrom: (0.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20100504151335-54qeucg3ec108q28
Tags: 2.2
* Added Replaces:/Conflicts: to allow a proper upgrade.
Closes: #580066
* Fixed package descriptions.
Closes: #579667
* Patched mediawiki-extensions-fckeditor to make it work with
  php 5.3. The fix may not be perfect but at least it work.
  Not closing the bug (#579822) for now..

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
class FCKeditorParser extends FCKeditorParserWrapper
 
4
{
 
5
        public static $fkc_mw_makeImage_options;
 
6
        protected $fck_mw_strtr_span;
 
7
        protected $fck_mw_strtr_span_counter=1;
 
8
        protected $fck_mw_taghook;
 
9
        protected $fck_internal_parse_text;
 
10
        protected $fck_matches = array();
 
11
 
 
12
        private $FCKeditorMagicWords = array(
 
13
        '__NOTOC__',
 
14
        '__FORCETOC__',
 
15
        '__NOEDITSECTION__',
 
16
        '__START__',
 
17
        '__NOTITLECONVERT__',
 
18
        '__NOCONTENTCONVERT__',
 
19
        '__END__',
 
20
        '__TOC__',
 
21
        '__NOTC__',
 
22
        '__NOCC__',
 
23
        "__FORCETOC__",
 
24
        "__NEWSECTIONLINK__",
 
25
        "__NOGALLERY__",
 
26
        );
 
27
 
 
28
        /**
 
29
         * Add special string (that would be changed by Parser) to array and return simple unique string
 
30
         * that will remain unchanged during whole parsing operation.
 
31
         * At the end we'll replace all this unique strings with original content
 
32
         *
 
33
         * @param string $text
 
34
         * @return string
 
35
         */
 
36
        private function fck_addToStrtr($text, $replaceLineBreaks = true) {
 
37
                $key = 'Fckmw'.$this->fck_mw_strtr_span_counter.'fckmw';
 
38
                $this->fck_mw_strtr_span_counter++;
 
39
                if ($replaceLineBreaks) {
 
40
                        $this->fck_mw_strtr_span[$key] = str_replace(array("\r\n", "\n", "\r"),"fckLR",$text);
 
41
                }
 
42
                else {
 
43
                        $this->fck_mw_strtr_span[$key] = $text;
 
44
                }
 
45
                return $key;
 
46
        }
 
47
 
 
48
        /**
 
49
         * Handle link to subpage if necessary
 
50
         * @param string $target the source of the link
 
51
         * @param string &$text the link text, modified as necessary
 
52
         * @return string the full name of the link
 
53
         * @private
 
54
         */
 
55
        function maybeDoSubpageLink($target, &$text) {
 
56
                return $target;
 
57
        }
 
58
 
 
59
        /**
 
60
         * DO NOT Replace special strings like "ISBN xxx" and "RFC xxx" with
 
61
         * magic external links.
 
62
         *
 
63
         * DML
 
64
         * @private
 
65
         */
 
66
        function doMagicLinks( $text ) {
 
67
                return $text;
 
68
        }
 
69
 
 
70
        /**
 
71
        * Callback function for custom tags: feed, ref, references etc.
 
72
        *
 
73
        * @param string $str Input
 
74
        * @param array $argv Arguments
 
75
        * @return string
 
76
        */
 
77
        function fck_genericTagHook( $str, $argv, $parser ) {
 
78
                if (in_array($this->fck_mw_taghook, array("ref", "math", "references", "source"))) {
 
79
                        $class = $this->fck_mw_taghook;
 
80
                }
 
81
                else {
 
82
                        $class = "special";
 
83
                }
 
84
 
 
85
                if (empty($argv)) {
 
86
                        $ret = "<span class=\"fck_mw_".$class."\" _fck_mw_customtag=\"true\" _fck_mw_tagname=\"".$this->fck_mw_taghook."\">";
 
87
                }
 
88
                else {
 
89
                        $ret = "<span class=\"fck_mw_".$class."\" _fck_mw_customtag=\"true\" _fck_mw_tagname=\"".$this->fck_mw_taghook."\"";
 
90
                        foreach ($argv as $key=>$value) {
 
91
                                $ret .= " ".$key."=\"".$value."\"";
 
92
                        }
 
93
                        $ret .=">";
 
94
                }
 
95
                if (is_null($str)) {
 
96
                        $ret = substr($ret, 0, -1) . " />";
 
97
                }
 
98
                else {
 
99
                        $ret .= htmlspecialchars($str);
 
100
                        $ret .= "</span>";
 
101
                }
 
102
 
 
103
                $replacement = $this->fck_addToStrtr($ret);
 
104
                return $replacement;
 
105
        }
 
106
 
 
107
        /**
 
108
        * Callback function for wiki tags: nowiki, includeonly, noinclude
 
109
        *
 
110
        * @param string $tagName tag name, eg. nowiki, math
 
111
        * @param string $str Input
 
112
        * @param array $argv Arguments
 
113
        * @return string
 
114
        */
 
115
        function fck_wikiTag( $tagName, $str, $argv = array()) {
 
116
                if (empty($argv)) {
 
117
                        $ret = "<span class=\"fck_mw_".$tagName."\" _fck_mw_customtag=\"true\" _fck_mw_tagname=\"".$tagName."\">";
 
118
                }
 
119
                else {
 
120
                        $ret = "<span class=\"fck_mw_".$tagName."\" _fck_mw_customtag=\"true\" _fck_mw_tagname=\"".$tagName."\"";
 
121
                        foreach ($argv as $key=>$value) {
 
122
                                $ret .= " ".$key."=\"".$value."\"";
 
123
                        }
 
124
                        $ret .=">";
 
125
                }
 
126
                if (is_null($str)) {
 
127
                        $ret = substr($ret, 0, -1) . " />";
 
128
                }
 
129
                else {
 
130
                        $ret .= htmlspecialchars($str);
 
131
                        $ret .= "</span>";
 
132
                }
 
133
 
 
134
                $replacement = $this->fck_addToStrtr($ret);
 
135
 
 
136
                return $replacement;
 
137
        }
 
138
 
 
139
        /**
 
140
         * Strips and renders nowiki, pre, math, hiero
 
141
         * If $render is set, performs necessary rendering operations on plugins
 
142
         * Returns the text, and fills an array with data needed in unstrip()
 
143
         *
 
144
         * @param StripState $state
 
145
         *
 
146
         * @param bool $stripcomments when set, HTML comments <!-- like this -->
 
147
         *  will be stripped in addition to other tags. This is important
 
148
         *  for section editing, where these comments cause confusion when
 
149
         *  counting the sections in the wikisource
 
150
         *
 
151
         * @param array dontstrip contains tags which should not be stripped;
 
152
         *  used to prevent stipping of <gallery> when saving (fixes bug 2700)
 
153
         *
 
154
         * @private
 
155
         */
 
156
        function strip( $text, $state, $stripcomments = false , $dontstrip = array () ) {
 
157
                global $wgContLang, $wgUseTeX, $wgScriptPath, $wgVersion, $wgHooks, $wgExtensionFunctions;
 
158
 
 
159
                wfProfileIn( __METHOD__ );
 
160
                $render = ($this->mOutputType == OT_HTML);
 
161
 
 
162
                $uniq_prefix = $this->mUniqPrefix;
 
163
                $commentState = new ReplacementArray;
 
164
                $nowikiItems = array();
 
165
                $generalItems = array();
 
166
 
 
167
                $elements = array_merge( array( 'nowiki', 'gallery', 'math' ), array_keys( $this->mTagHooks ) );
 
168
                if ( (isset($wgHooks['ParserFirstCallInit']) && in_array('efSyntaxHighlight_GeSHiSetup', $wgHooks['ParserFirstCallInit']))
 
169
                        || (isset($wgExtensionFunctions) && in_array('efSyntaxHighlight_GeSHiSetup', $wgExtensionFunctions)) ) {
 
170
                        $elements = array_merge( $elements, array( 'source' ) );
 
171
                }
 
172
                if ( (isset($wgHooks['ParserFirstCallInit']) && in_array('wfCite', $wgHooks['ParserFirstCallInit']))
 
173
                        || (isset($wgExtensionFunctions) && in_array('wfCite', $wgExtensionFunctions)) ) {
 
174
                        $elements = array_merge( $elements, array( 'ref', 'references' ) );
 
175
                }
 
176
                global $wgRawHtml;
 
177
                if( $wgRawHtml ) {
 
178
                        $elements[] = 'html';
 
179
                }
 
180
 
 
181
                # Removing $dontstrip tags from $elements list (currently only 'gallery', fixing bug 2700)
 
182
                foreach ( $elements AS $k => $v ) {
 
183
                        if ( !in_array ( $v , $dontstrip ) ) continue;
 
184
                        unset ( $elements[$k] );
 
185
                }
 
186
 
 
187
                $elements = array_unique($elements);
 
188
                $matches = array();
 
189
                if (version_compare("1.12", $wgVersion, ">")) {
 
190
                        $text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
 
191
                }
 
192
                else {
 
193
                        $text = self::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
 
194
                }
 
195
 
 
196
                foreach( $matches as $marker => $data ) {
 
197
                        list( $element, $content, $params, $tag ) = $data;
 
198
                        if( $render ) {
 
199
                                $tagName = strtolower( $element );
 
200
                                wfProfileIn( __METHOD__."-render-$tagName" );
 
201
                                switch( $tagName ) {
 
202
                                        case '!--':
 
203
                                                // Comment
 
204
                                                if( substr( $tag, -3 ) == '-->' ) {
 
205
                                                        $output = $tag;
 
206
                                                } else {
 
207
                                                        // Unclosed comment in input.
 
208
                                                        // Close it so later stripping can remove it
 
209
                                                        $output = "$tag-->";
 
210
                                                }
 
211
                                                break;
 
212
                                        case 'references':
 
213
                                                $output = $this->fck_wikiTag('references', $content, $params);
 
214
                                                break;
 
215
                                        case 'ref':
 
216
                                                $output = $this->fck_wikiTag('ref', $content, $params);
 
217
                                                break;
 
218
                                        case 'source':
 
219
                                                $output = $this->fck_wikiTag('source', $content, $params);
 
220
                                                break;
 
221
                                        case 'html':
 
222
                                                if( $wgRawHtml ) {
 
223
                                                        $output = $this->fck_wikiTag('html', $content, $params);
 
224
                                                }
 
225
                                                break;
 
226
                                        case 'nowiki':
 
227
                                                $output = $this->fck_wikiTag('nowiki', $content, $params); //required by FCKeditor
 
228
                                                break;
 
229
                                        case 'math':
 
230
                                                if($wgUseTeX){          //normal render
 
231
                                                        $output = $wgContLang->armourMath( MathRenderer::renderMath( $content ) );
 
232
                                                }else                           //show fakeimage
 
233
                                                        $output = '<img _fckfakelement="true" class="FCK__MWMath" _fck_mw_math="'.$content.'" src="'.$wgScriptPath.'/skins/common/images/button_math.png" />';
 
234
                                                break;
 
235
                                        case 'gallery':
 
236
                                                $output = $this->fck_wikiTag('gallery', $content, $params); //required by FCKeditor
 
237
                                                //$output = $this->renderImageGallery( $content, $params );
 
238
                                                break;
 
239
                                        default:
 
240
                                                if( isset( $this->mTagHooks[$tagName] ) ) {
 
241
                                                        $this->fck_mw_taghook = $tagName; //required by FCKeditor
 
242
                                                        $output = call_user_func_array( $this->mTagHooks[$tagName],
 
243
                                                        array( $content, $params, $this ) );
 
244
                                                } else {
 
245
                                                        throw new MWException( "Invalid call hook $element" );
 
246
                                                }
 
247
                                }
 
248
                                wfProfileOut( __METHOD__."-render-$tagName" );
 
249
                        } else {
 
250
                                // Just stripping tags; keep the source
 
251
                                $output = $tag;
 
252
                        }
 
253
 
 
254
                        // Unstrip the output, to support recursive strip() calls
 
255
                        $output = $state->unstripBoth( $output );
 
256
 
 
257
                        if( !$stripcomments && $element == '!--' ) {
 
258
                                $commentState->setPair( $marker, $output );
 
259
                        } elseif ( $element == 'html' || $element == 'nowiki' ) {
 
260
                                $nowikiItems[$marker] = $output;
 
261
                        } else {
 
262
                                $generalItems[$marker] = $output;
 
263
                        }
 
264
                }
 
265
                # Add the new items to the state
 
266
                # We do this after the loop instead of during it to avoid slowing
 
267
                # down the recursive unstrip
 
268
                $state->nowiki->mergeArray( $nowikiItems );
 
269
                $state->general->mergeArray( $generalItems );
 
270
 
 
271
                # Unstrip comments unless explicitly told otherwise.
 
272
                # (The comments are always stripped prior to this point, so as to
 
273
                # not invoke any extension tags / parser hooks contained within
 
274
                # a comment.)
 
275
                if ( !$stripcomments ) {
 
276
                        // Put them all back and forget them
 
277
                        $text = $commentState->replace( $text );
 
278
                }
 
279
 
 
280
                $this->fck_matches = $matches;
 
281
                wfProfileOut( __METHOD__ );
 
282
                return $text;
 
283
        }
 
284
 
 
285
        /** Replace HTML comments with unique text using fck_addToStrtr function
 
286
         *
 
287
         * @private
 
288
         * @param string $text
 
289
         * @return string
 
290
         */
 
291
        private function fck_replaceHTMLcomments( $text ) {
 
292
                wfProfileIn( __METHOD__ );
 
293
                while (($start = strpos($text, '<!--')) !== false) {
 
294
                        $end = strpos($text, '-->', $start + 4);
 
295
                        if ($end === false) {
 
296
                                # Unterminated comment; bail out
 
297
                                break;
 
298
                        }
 
299
 
 
300
                        $end += 3;
 
301
 
 
302
                        # Trim space and newline if the comment is both
 
303
                        # preceded and followed by a newline
 
304
                        $spaceStart = max($start - 1, 0);
 
305
                        $spaceLen = $end - $spaceStart;
 
306
                        while (substr($text, $spaceStart, 1) === ' ' && $spaceStart > 0) {
 
307
                                $spaceStart--;
 
308
                                $spaceLen++;
 
309
                        }
 
310
                        while (substr($text, $spaceStart + $spaceLen, 1) === ' ')
 
311
                        $spaceLen++;
 
312
                        if (substr($text, $spaceStart, 1) === "\n" and substr($text, $spaceStart + $spaceLen, 1) === "\n") {
 
313
                                # Remove the comment, leading and trailing
 
314
                                # spaces, and leave only one newline.
 
315
                                $replacement = $this->fck_addToStrtr(substr($text, $spaceStart, $spaceLen+1), false);
 
316
                                $text = substr_replace($text, $replacement."\n", $spaceStart, $spaceLen + 1);
 
317
                        }
 
318
                        else {
 
319
                                # Remove just the comment.
 
320
                                $replacement = $this->fck_addToStrtr(substr($text, $start, $end - $start), false);
 
321
                                $text = substr_replace($text, $replacement, $start, $end - $start);
 
322
                        }
 
323
                }
 
324
                wfProfileOut( __METHOD__ );
 
325
 
 
326
                return $text;
 
327
        }
 
328
 
 
329
        function replaceInternalLinks( $text ) {
 
330
                $text = preg_replace("/\[\[([^|\[\]]*?)\]\]/", "[[$1|RTENOTITLE]]", $text);     //#2223: [[()]] =>      [[%1|RTENOTITLE]]
 
331
                $text = preg_replace("/\[\[:(.*?)\]\]/", "[[RTECOLON$1]]", $text);      //change ':' => 'RTECOLON' in links
 
332
                $text = parent::replaceInternalLinks($text);
 
333
                $text = preg_replace("/\|RTENOTITLE\]\]/", "]]", $text);                                // remove unused RTENOTITLE
 
334
 
 
335
                return $text;
 
336
        }
 
337
 
 
338
        function makeImage( $nt, $options ) {
 
339
                FCKeditorParser::$fkc_mw_makeImage_options = $options;
 
340
                return parent::makeImage( $nt, $options );
 
341
        }
 
342
 
 
343
        /**
 
344
         * Replace templates with unique text to preserve them from parsing
 
345
         *
 
346
         * @todo if {{template}} is inside string that also must be returned unparsed,
 
347
         * e.g. <noinclude>{{template}}</noinclude>
 
348
         * {{template}} replaced with Fckmw[n]fckmw which is wrong...
 
349
         *
 
350
         * @param string $text
 
351
         * @return string
 
352
         */
 
353
        private function fck_replaceTemplates( $text ) {
 
354
 
 
355
                $callback = array('{' =>
 
356
                array(
 
357
                'end'=>'}',
 
358
                'cb' => array(
 
359
                2=>array('FCKeditorParser', 'fck_leaveTemplatesAlone'),
 
360
                3=>array('FCKeditorParser', 'fck_leaveTemplatesAlone'),
 
361
                ),
 
362
                'min' =>2,
 
363
                'max' =>3,
 
364
                )
 
365
                );
 
366
 
 
367
                $text = $this->replace_callback($text, $callback);
 
368
 
 
369
                $tags = array();
 
370
                $offset=0;
 
371
                $textTmp = $text;
 
372
                while (false !== ($pos = strpos($textTmp, "<!--FCK_SKIP_START-->")))
 
373
                {
 
374
                        $tags[abs($pos + $offset)] = 1;
 
375
                        $textTmp = substr($textTmp, $pos+21);
 
376
                        $offset += $pos + 21;
 
377
                }
 
378
 
 
379
                $offset=0;
 
380
                $textTmp = $text;
 
381
                while (false !== ($pos = strpos($textTmp, "<!--FCK_SKIP_END-->")))
 
382
                {
 
383
                        $tags[abs($pos + $offset)] = -1;
 
384
                        $textTmp = substr($textTmp, $pos+19);
 
385
                        $offset += $pos + 19;
 
386
                }
 
387
 
 
388
                if (!empty($tags)) {
 
389
                        ksort($tags);
 
390
 
 
391
                        $strtr = array("<!--FCK_SKIP_START-->" => "", "<!--FCK_SKIP_END-->" => "");
 
392
 
 
393
                        $sum=0;
 
394
                        $lastSum=0;
 
395
                        $finalString = "";
 
396
                        $stringToParse = "";
 
397
                        $startingPos = 0;
 
398
                        $inner = "";
 
399
                        $strtr_span = array();
 
400
                        foreach ($tags as $pos=>$type) {
 
401
                                $sum += $type;
 
402
                                if (!$pos) {
 
403
                                        $opened = 0;
 
404
                                        $closed = 0;
 
405
                                }
 
406
                                else {
 
407
                                        $opened = substr_count($text, '[', 0, $pos);                    //count [
 
408
                                        $closed = substr_count($text, ']', 0, $pos);                    //count ]
 
409
                                }
 
410
                                if ($sum == 1 && $lastSum == 0) {
 
411
                                        $stringToParse .= strtr(substr($text, $startingPos, $pos - $startingPos), $strtr);
 
412
                                        $startingPos = $pos;
 
413
                                }
 
414
                                else if ($sum == 0) {
 
415
                                        $stringToParse .= 'Fckmw'.$this->fck_mw_strtr_span_counter.'fckmw';
 
416
                                        $inner = htmlspecialchars(strtr(substr($text, $startingPos, $pos - $startingPos + 19), $strtr));
 
417
                                        $this->fck_mw_strtr_span['href="Fckmw'.$this->fck_mw_strtr_span_counter.'fckmw"'] = 'href="'.$inner.'"';
 
418
                                        if($opened <= $closed) {                                                // {{template}} is NOT in [] or [[]]
 
419
                                                $this->fck_mw_strtr_span['Fckmw'.$this->fck_mw_strtr_span_counter.'fckmw'] = '<span class="fck_mw_template">'.str_replace(array("\r\n", "\n", "\r"),"fckLR",$inner).'</span>';
 
420
                                        }else{
 
421
                                                $this->fck_mw_strtr_span['Fckmw'.$this->fck_mw_strtr_span_counter.'fckmw'] = str_replace(array("\r\n", "\n", "\r"),"fckLR",$inner);
 
422
                                        }
 
423
                                        $startingPos = $pos + 19;
 
424
                                        $this->fck_mw_strtr_span_counter++;
 
425
                                }
 
426
                                $lastSum = $sum;
 
427
                        }
 
428
                        $stringToParse .= substr($text, $startingPos);
 
429
                        $text = &$stringToParse;
 
430
                }
 
431
 
 
432
                return $text;
 
433
        }
 
434
 
 
435
        function internalParse ( $text ) {
 
436
 
 
437
                $this->fck_internal_parse_text =& $text;
 
438
 
 
439
                //these three tags should remain unchanged
 
440
                $text = StringUtils::delimiterReplaceCallback( '<includeonly>', '</includeonly>', array($this, 'fck_includeonly'), $text );
 
441
                $text = StringUtils::delimiterReplaceCallback( '<noinclude>', '</noinclude>', array($this, 'fck_noinclude'), $text );
 
442
                $text = StringUtils::delimiterReplaceCallback( '<onlyinclude>', '</onlyinclude>', array($this, 'fck_onlyinclude'), $text );
 
443
 
 
444
                //html comments shouldn't be stripped
 
445
                $text = $this->fck_replaceHTMLcomments( $text );
 
446
                //as well as templates
 
447
                $text = $this->fck_replaceTemplates( $text );
 
448
 
 
449
                $finalString = parent::internalParse($text);
 
450
 
 
451
                return $finalString;
 
452
        }
 
453
        function fck_includeonly( $matches ) {
 
454
                return $this->fck_wikiTag('includeonly', $matches[1]);
 
455
        }
 
456
        function fck_noinclude( $matches ) {
 
457
                return $this->fck_wikiTag('noinclude', $matches[1]);
 
458
        }
 
459
        function fck_onlyinclude( $matches ) {
 
460
                return $this->fck_wikiTag('onlyinclude', $matches[1]);
 
461
        }
 
462
        function fck_leaveTemplatesAlone( $matches ) {
 
463
                return "<!--FCK_SKIP_START-->".$matches['text']."<!--FCK_SKIP_END-->";
 
464
        }
 
465
        function formatHeadings( $text, $isMain=true ) {
 
466
                return $text;
 
467
        }
 
468
        function replaceFreeExternalLinks( $text ) { return $text; }
 
469
        function stripNoGallery(&$text) {}
 
470
        function stripToc( $text ) {
 
471
                //$prefix = '<span class="fck_mw_magic">';
 
472
                //$suffix = '</span>';
 
473
                $prefix = '';
 
474
                $suffix = '';
 
475
 
 
476
                $strtr = array();
 
477
                foreach ($this->FCKeditorMagicWords as $word) {
 
478
                        $strtr[$word] = $prefix . $word . $suffix;
 
479
                }
 
480
 
 
481
                return strtr( $text, $strtr );
 
482
        }
 
483
 
 
484
        function doDoubleUnderscore( $text ) {
 
485
                return $text;
 
486
        }
 
487
 
 
488
        function parse( $text, &$title, $options, $linestart = true, $clearState = true, $revid = null ) {
 
489
                $text = preg_replace("/^#REDIRECT/", "<!--FCK_REDIRECT-->", $text);
 
490
                $parserOutput = parent::parse($text, $title, $options, $linestart , $clearState , $revid );
 
491
 
 
492
                $categories = $parserOutput->getCategories();
 
493
                if ($categories) {
 
494
                        $appendString = "";
 
495
                        foreach ($categories as $cat=>$val) {
 
496
                                $args = '';
 
497
                                if( $val == 'RTENOTITLE' ){
 
498
                                                $args .= '_fcknotitle="true" ';
 
499
                                        $val = $cat;
 
500
                                }
 
501
                                if ($val != $title->mTextform) {
 
502
                                        $appendString .= "<a ".$args."href=\"Category:" . $cat ."\">" . $val ."</a> ";
 
503
                                }
 
504
                                else {
 
505
                                        $appendString .= "<a ".$args."href=\"Category:" . $cat ."\">Category:" . $cat ."</a> ";
 
506
                                }
 
507
                        }
 
508
                        $parserOutput->setText($parserOutput->getText() . $appendString);
 
509
                }
 
510
 
 
511
                if (!empty($this->fck_mw_strtr_span)) {
 
512
                        global $leaveRawTemplates;
 
513
                        if (!empty($leaveRawTemplates)) {
 
514
                                foreach ($leaveRawTemplates as $l) {
 
515
                                        $this->fck_mw_strtr_span[$l] = substr($this->fck_mw_strtr_span[$l], 30, -7);
 
516
                                }
 
517
                        }
 
518
                        $text = strtr($parserOutput->getText(), $this->fck_mw_strtr_span);
 
519
                        $parserOutput->setText(strtr($text, $this->fck_mw_strtr_span));
 
520
                }
 
521
                if (!empty($this->fck_matches)) {
 
522
                        $text = $parserOutput->getText() ;
 
523
                        foreach ($this->fck_matches as $key => $m) {
 
524
                                $text = str_replace( $key, $m[3], $text);
 
525
                        }
 
526
                        $parserOutput->setText($text);
 
527
                }
 
528
 
 
529
                if (!empty($parserOutput->mLanguageLinks)) {
 
530
                        foreach ($parserOutput->mLanguageLinks as $l) {
 
531
                                $parserOutput->setText($parserOutput->getText() . "\n" . "<a href=\"".$l."\">".$l."</a>") ;
 
532
                        }
 
533
                }
 
534
 
 
535
                $parserOutput->setText(str_replace("<!--FCK_REDIRECT-->", "#REDIRECT", $parserOutput->getText()));
 
536
 
 
537
                return $parserOutput;
 
538
        }
 
539
 
 
540
        /**
 
541
         * Make lists from lines starting with ':', '*', '#', etc.
 
542
         *
 
543
         * @private
 
544
         * @return string the lists rendered as HTML
 
545
         */
 
546
        function doBlockLevels( $text, $linestart ) {
 
547
                $fname = 'Parser::doBlockLevels';
 
548
                wfProfileIn( $fname );
 
549
 
 
550
                # Parsing through the text line by line.  The main thing
 
551
                # happening here is handling of block-level elements p, pre,
 
552
                # and making lists from lines starting with * # : etc.
 
553
                #
 
554
                $textLines = explode( "\n", $text );
 
555
 
 
556
                $lastPrefix = $output = '';
 
557
                $this->mDTopen = $inBlockElem = false;
 
558
                $prefixLength = 0;
 
559
                $paragraphStack = false;
 
560
 
 
561
                if ( !$linestart ) {
 
562
                        $output .= array_shift( $textLines );
 
563
                }
 
564
                foreach ( $textLines as $oLine ) {
 
565
                        $lastPrefixLength = strlen( $lastPrefix );
 
566
                        $preCloseMatch = preg_match('/<\\/pre/i', $oLine );
 
567
                        $preOpenMatch = preg_match('/<pre/i', $oLine );
 
568
                        if ( !$this->mInPre ) {
 
569
                                # Multiple prefixes may abut each other for nested lists.
 
570
                                $prefixLength = strspn( $oLine, '*#:;' );
 
571
                                $pref = substr( $oLine, 0, $prefixLength );
 
572
 
 
573
                                # eh?
 
574
                                $pref2 = str_replace( ';', ':', $pref );
 
575
                                $t = substr( $oLine, $prefixLength );
 
576
                                $this->mInPre = !empty($preOpenMatch);
 
577
                        } else {
 
578
                                # Don't interpret any other prefixes in preformatted text
 
579
                                $prefixLength = 0;
 
580
                                $pref = $pref2 = '';
 
581
                                $t = $oLine;
 
582
                        }
 
583
 
 
584
                        # List generation
 
585
                        if( $prefixLength && 0 == strcmp( $lastPrefix, $pref2 ) ) {
 
586
                                # Same as the last item, so no need to deal with nesting or opening stuff
 
587
                                $output .= $this->nextItem( substr( $pref, -1 ) );
 
588
                                $paragraphStack = false;
 
589
 
 
590
                                if ( substr( $pref, -1 ) == ';') {
 
591
                                        # The one nasty exception: definition lists work like this:
 
592
                                        # ; title : definition text
 
593
                                        # So we check for : in the remainder text to split up the
 
594
                                        # title and definition, without b0rking links.
 
595
                                        $term = $t2 = '';
 
596
                                        if ($this->findColonNoLinks($t, $term, $t2) !== false) {
 
597
                                                $t = $t2;
 
598
                                                $output .= $term . $this->nextItem( ':' );
 
599
                                        }
 
600
                                }
 
601
                        } elseif( $prefixLength || $lastPrefixLength ) {
 
602
                                # Either open or close a level...
 
603
                                $commonPrefixLength = $this->getCommon( $pref, $lastPrefix );
 
604
                                $paragraphStack = false;
 
605
 
 
606
                                while( $commonPrefixLength < $lastPrefixLength ) {
 
607
                                        $output .= $this->closeList( $lastPrefix{$lastPrefixLength-1} );
 
608
                                        --$lastPrefixLength;
 
609
                                }
 
610
                                if ( $prefixLength <= $commonPrefixLength && $commonPrefixLength > 0 ) {
 
611
                                        $output .= $this->nextItem( $pref{$commonPrefixLength-1} );
 
612
                                }
 
613
                                while ( $prefixLength > $commonPrefixLength ) {
 
614
                                        $char = substr( $pref, $commonPrefixLength, 1 );
 
615
                                        $output .= $this->openList( $char );
 
616
 
 
617
                                        if ( ';' == $char ) {
 
618
                                                # FIXME: This is dupe of code above
 
619
                                                if ($this->findColonNoLinks($t, $term, $t2) !== false) {
 
620
                                                        $t = $t2;
 
621
                                                        $output .= $term . $this->nextItem( ':' );
 
622
                                                }
 
623
                                        }
 
624
                                        ++$commonPrefixLength;
 
625
                                }
 
626
                                $lastPrefix = $pref2;
 
627
                        }
 
628
                        if( 0 == $prefixLength ) {
 
629
                                wfProfileIn( "$fname-paragraph" );
 
630
                                # No prefix (not in list)--go to paragraph mode
 
631
                                // XXX: use a stack for nestable elements like span, table and div
 
632
                                $openmatch = preg_match('/(?:<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
 
633
                                $closematch = preg_match(
 
634
                                '/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
 
635
                                '<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
 
636
                                if ( $openmatch or $closematch ) {
 
637
                                        $paragraphStack = false;
 
638
                                        # TODO bug 5718: paragraph closed
 
639
                                        $output .= $this->closeParagraph();
 
640
                                        if ( $preOpenMatch and !$preCloseMatch ) {
 
641
                                                $this->mInPre = true;
 
642
                                        }
 
643
                                        if ( $closematch ) {
 
644
                                                $inBlockElem = false;
 
645
                                        } else {
 
646
                                                $inBlockElem = true;
 
647
                                        }
 
648
                                } else if ( !$inBlockElem && !$this->mInPre ) {
 
649
                                        if ( ' ' == $t{0} and ( $this->mLastSection == 'pre' or trim($t) != '' ) ) {
 
650
                                                // pre
 
651
                                                if ($this->mLastSection != 'pre') {
 
652
                                                        $paragraphStack = false;
 
653
                                                        $output .= $this->closeParagraph().'<pre class="_fck_mw_lspace">';
 
654
                                                        $this->mLastSection = 'pre';
 
655
                                                }
 
656
                                                $t = substr( $t, 1 );
 
657
                                        } else {
 
658
                                                // paragraph
 
659
                                                if ( '' == trim($t) ) {
 
660
                                                        if ( $paragraphStack ) {
 
661
                                                                $output .= $paragraphStack.'<br />';
 
662
                                                                $paragraphStack = false;
 
663
                                                                $this->mLastSection = 'p';
 
664
                                                        } else {
 
665
                                                                if ($this->mLastSection != 'p' ) {
 
666
                                                                        $output .= $this->closeParagraph();
 
667
                                                                        $this->mLastSection = '';
 
668
                                                                        $paragraphStack = '<p>';
 
669
                                                                } else {
 
670
                                                                        $paragraphStack = '</p><p>';
 
671
                                                                }
 
672
                                                        }
 
673
                                                } else {
 
674
                                                        if ( $paragraphStack ) {
 
675
                                                                $output .= $paragraphStack;
 
676
                                                                $paragraphStack = false;
 
677
                                                                $this->mLastSection = 'p';
 
678
                                                        } else if ($this->mLastSection != 'p') {
 
679
                                                                $output .= $this->closeParagraph().'<p>';
 
680
                                                                $this->mLastSection = 'p';
 
681
                                                        }
 
682
                                                }
 
683
                                        }
 
684
                                }
 
685
                                wfProfileOut( "$fname-paragraph" );
 
686
                        }
 
687
                        // somewhere above we forget to get out of pre block (bug 785)
 
688
                        if($preCloseMatch && $this->mInPre) {
 
689
                                $this->mInPre = false;
 
690
                        }
 
691
                        if ($paragraphStack === false) {
 
692
                                $output .= $t."\n";
 
693
                        }
 
694
                }
 
695
                while ( $prefixLength ) {
 
696
                        $output .= $this->closeList( $pref2{$prefixLength-1} );
 
697
                        --$prefixLength;
 
698
                }
 
699
                if ( '' != $this->mLastSection ) {
 
700
                        $output .= '</' . $this->mLastSection . '>';
 
701
                        $this->mLastSection = '';
 
702
                }
 
703
 
 
704
                wfProfileOut( $fname );
 
705
                return $output;
 
706
        }
 
707
}