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

« back to all changes in this revision

Viewing changes to extensions/Cite.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
 
if ( ! defined( 'MEDIAWIKI' ) )
3
 
        die();
4
 
/**#@+
5
 
 * A parser extension that adds two tags, <ref> and <references> for adding
6
 
 * citations to pages
7
 
 *
8
 
 * @package MediaWiki
9
 
 * @subpackage Extensions
10
 
 *
11
 
 * @link http://meta.wikimedia.org/wiki/Cite/Cite.php Documentation
12
 
 * @link http://www.w3.org/TR/html4/struct/text.html#edef-CITE <cite> definition in HTML
13
 
 * @link http://www.w3.org/TR/2005/WD-xhtml2-20050527/mod-text.html#edef_text_cite <cite> definition in XHTML 2.0
14
 
 *
15
 
 * @bug 4579
16
 
 *
17
 
 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
18
 
 * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
19
 
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
20
 
 */
21
 
 
22
 
$wgExtensionFunctions[] = 'wfCite';
23
 
$wgExtensionCredits['parserhook'][] = array(
24
 
        'name' => 'Cite',
25
 
        'author' => 'Ævar Arnfjörð Bjarmason',
26
 
        'description' => 'adds <nowiki><ref[ name=id]></nowiki> and <nowiki><references/></nowiki> tags, for citations',
27
 
        'url' => 'http://meta.wikimedia.org/wiki/Cite/Cite.php'
28
 
);
29
 
 
30
 
/**
31
 
 * Error codes, first array = internal errors; second array = user errors
32
 
 */
33
 
$wgCiteErrors = array(
34
 
        'system' => array(
35
 
                'CITE_ERROR_STR_INVALID',
36
 
                'CITE_ERROR_KEY_INVALID_1',
37
 
                'CITE_ERROR_KEY_INVALID_2',
38
 
                'CITE_ERROR_STACK_INVALID_INPUT'
39
 
        ),
40
 
        'user' => array(
41
 
                'CITE_ERROR_REF_NUMERIC_KEY',
42
 
                'CITE_ERROR_REF_NO_KEY',
43
 
                'CITE_ERROR_REF_TOO_MANY_KEYS',
44
 
                'CITE_ERROR_REF_NO_INPUT',
45
 
                'CITE_ERROR_REFERENCES_INVALID_INPUT',
46
 
                'CITE_ERROR_REFERENCES_INVALID_PARAMETERS',
47
 
                'CITE_ERROR_REFERENCES_NO_BACKLINK_LABEL'
48
 
        )
49
 
);
50
 
 
51
 
for ( $i = 0; $i < count( $wgCiteErrors['system'] ); ++$i )
52
 
        // System errors are negative integers
53
 
        define( $wgCiteErrors['system'][$i], -($i + 1) );
54
 
for ( $i = 0; $i < count( $wgCiteErrors['user'] ); ++$i )
55
 
        // User errors are positive integers
56
 
        define( $wgCiteErrors['user'][$i], $i + 1 );
57
 
 
58
 
function wfCite() {
59
 
        global $wgMessageCache;
60
 
        $wgMessageCache->addMessages(
61
 
                array(
62
 
                        /*
63
 
                           Debug & errors
64
 
                        */
65
 
                        
66
 
                        // Internal errors
67
 
                        'cite_croak' => 'Cite croaked; $1: $2',
68
 
 
69
 
                        'cite_error_' . CITE_ERROR_STR_INVALID => 'Internal error; invalid $str',
70
 
                        'cite_error_' . CITE_ERROR_KEY_INVALID_1 => 'Internal error; invalid key',
71
 
                        'cite_error_' . CITE_ERROR_KEY_INVALID_2 => 'Internal error; invalid key',
72
 
                        'cite_error_' . CITE_ERROR_STACK_INVALID_INPUT => 'Internal error; invalid stack key',
73
 
 
74
 
                        // User errors
75
 
                        'cite_error' => 'Cite error $1; $2',
76
 
                        
77
 
                        'cite_error_' . CITE_ERROR_REF_NUMERIC_KEY => 'Invalid call; expecting a non-integer key',
78
 
                        'cite_error_' . CITE_ERROR_REF_NO_KEY => 'Invalid call; no key specified',
79
 
                        'cite_error_' . CITE_ERROR_REF_TOO_MANY_KEYS => 'Invalid call; invalid keys, e.g. too many or wrong key specified',
80
 
                        'cite_error_' . CITE_ERROR_REF_NO_INPUT => 'Invalid call; no input specified',
81
 
                        'cite_error_' . CITE_ERROR_REFERENCES_INVALID_INPUT => 'Invalid input; expecting none',
82
 
                        'cite_error_' . CITE_ERROR_REFERENCES_INVALID_PARAMETERS => 'Invalid parameters; expecting none',
83
 
                        'cite_error_' . CITE_ERROR_REFERENCES_NO_BACKLINK_LABEL => "Ran out of custom backlink labels, define more in the \"''cite_references_link_many_format_backlink_labels''\" message",
84
 
 
85
 
                        /*
86
 
                           Output formatting
87
 
                        */
88
 
                        'cite_reference_link_key_with_num' => '$1_$2',
89
 
                        // Ids produced by <ref>
90
 
                        'cite_reference_link_prefix' => '_ref-',
91
 
                        'cite_reference_link_suffix' => '',
92
 
                        // Ids produced by <references>
93
 
                        'cite_references_link_prefix' => '_note-',
94
 
                        'cite_references_link_suffix' => '',
95
 
 
96
 
                        'cite_reference_link' => '<sup id="$1" class="reference">[[#$2|<nowiki>[</nowiki>$3<nowiki>]</nowiki>]]</sup>',
97
 
                        'cite_references_link_one' => '<li id="$1">[[#$2|↑]] $3</li>',
98
 
                        'cite_references_link_many' => '<li id="$1">↑ $2 $3</li>',
99
 
                        'cite_references_link_many_format' => '[[#$1|<sup>$2</sup>]]',
100
 
                        // An item from this set is passed as $3 in the message above
101
 
                        'cite_references_link_many_format_backlink_labels' => 'a b c d e f g h i j k l m n o p q r s t u v w x y z',
102
 
                        'cite_references_link_many_sep' => "\xc2\xa0", // &nbsp;
103
 
                        'cite_references_link_many_and' => "\xc2\xa0", // &nbps;
104
 
 
105
 
                        // Although I could just use # instead of <li> above and nothing here that
106
 
                        // will break on input that contains linebreaks
107
 
                        'cite_references_prefix' => '<ol class="references">',
108
 
                        'cite_references_suffix' => '</ol>',
109
 
                )
110
 
        );
111
 
        
112
 
        class Cite {
113
 
                /**#@+
114
 
                 * @access private
115
 
                 */
116
 
                
117
 
                /**
118
 
                 * Datastructure representing <ref> input, in the format of:
119
 
                 * <code>
120
 
                 * array(
121
 
                 *      'user supplied' => array(
122
 
                 *              'text' => 'user supplied reference & key',
123
 
                 *              'count' => 1, // occurs twice
124
 
                 *              'number' => 1, // The first reference, we want
125
 
                 *                             // all occourances of it to
126
 
                 *                             // use the same number
127
 
                 *      ),
128
 
                 *      0 => 'Anonymous reference',
129
 
                 *      1 => 'Another anonymous reference',
130
 
                 *      'some key' => array(
131
 
                 *              'text' => 'this one occurs once'
132
 
                 *              'count' => 0,
133
 
                 *              'number' => 4
134
 
                 *      ),
135
 
                 *      3 => 'more stuff'
136
 
                 * );
137
 
                 * </code>
138
 
                 *
139
 
                 * This works because:
140
 
                 * * PHP's datastructures are guarenteed to be returned in the
141
 
                 *   order that things are inserted into them (unless you mess
142
 
                 *   with that)
143
 
                 * * User supplied keys can't be integers, therefore avoiding
144
 
                 *   conflict with anonymous keys
145
 
                 *
146
 
                 * @var array
147
 
                 **/
148
 
                var $mRefs = array();
149
 
                
150
 
                /**
151
 
                 * Count for user displayed output (ref[1], ref[2], ...)
152
 
                 *
153
 
                 * @var int
154
 
                 */
155
 
                var $mOutCnt = 0;
156
 
 
157
 
                /**
158
 
                 * Internal counter for anonymous references, seperate from
159
 
                 * $mOutCnt because anonymous references won't increment it,
160
 
                 * but will incremement $mOutCnt
161
 
                 *
162
 
                 * @var int
163
 
                 */
164
 
                var $mInCnt = 0;
165
 
 
166
 
                /**
167
 
                 * The backlinks, in order, to pass as $3 to
168
 
                 * 'cite_references_link_many_format', defined in
169
 
                 * 'cite_references_link_many_format_backlink_labels
170
 
                 *
171
 
                 * @var array
172
 
                 */
173
 
                var $mBacklinkLabels;
174
 
                
175
 
                /**
176
 
                 * @var object
177
 
                 */
178
 
                var $mParser;
179
 
                
180
 
                /**
181
 
                 * True when a <ref> or <references> tag is being processed.
182
 
                 * Used to avoid infinite recursion
183
 
                 * 
184
 
                 * @var boolean
185
 
                 */
186
 
                var $mInCite = false;
187
 
                
188
 
                /**#@-*/
189
 
 
190
 
                /**
191
 
                 * Constructor
192
 
                 */
193
 
                function Cite() {
194
 
                        $this->setHooks();
195
 
                }
196
 
 
197
 
                /**#@+ @access private */
198
 
 
199
 
                /**
200
 
                 * Callback function for <ref>
201
 
                 *
202
 
                 * @param string $str Input
203
 
                 * @param array $argv Arguments
204
 
                 * @return string
205
 
                 */
206
 
                function ref( $str, $argv, $parser ) {
207
 
                        if ( $this->mInCite ) {
208
 
                                return htmlspecialchars( "<ref>$str</ref>" );
209
 
                        } else {
210
 
                                $this->mInCite = true;
211
 
                                $ret = $this->guardedRef( $str, $argv, $parser );
212
 
                                $this->mInCite = false;
213
 
                                return $ret;
214
 
                        }
215
 
                }
216
 
                
217
 
                function guardedRef( $str, $argv, $parser ) {
218
 
                        $this->mParser = $parser;
219
 
                        $key = $this->refArg( $argv );
220
 
                        
221
 
                        if ( $str !== null ) {
222
 
                                if ( $str === '' )
223
 
                                        return $this->error( CITE_ERROR_REF_NO_INPUT );
224
 
                                if ( is_string( $key ) )
225
 
                                        // I don't want keys in the form of /^[0-9]+$/ because they would
226
 
                                        // conflict with the php datastructure I'm using, besides, why specify
227
 
                                        // a manual key if it's just going to be any old integer?
228
 
                                        if ( sprintf( '%d', $key ) === (string)$key )
229
 
                                                return $this->error( CITE_ERROR_REF_NUMERIC_KEY );
230
 
                                        else
231
 
                                                return $this->stack( $str, $key );
232
 
                                else if ( $key === null )
233
 
                                        return $this->stack( $str );
234
 
                                else if ( $key === false )
235
 
                                        return $this->error( CITE_ERROR_REF_TOO_MANY_KEYS );
236
 
                                else
237
 
                                        $this->croak( CITE_ERROR_KEY_INVALID_1, serialize( $key ) );
238
 
                        } else if ( $str === null ) {
239
 
                                if ( is_string( $key ) )
240
 
                                        if ( sprintf( '%d', $key ) === (string)$key )
241
 
                                                return $this->error( CITE_ERROR_REF_NUMERIC_KEY );
242
 
                                        else
243
 
                                                return $this->stack( $str, $key );
244
 
                                else if ( $key === false )
245
 
                                        return $this->error( CITE_ERROR_REF_TOO_MANY_KEYS );
246
 
                                else if ( $key === null )
247
 
                                        return $this->error( CITE_ERROR_REF_NO_KEY );
248
 
                                else
249
 
                                        $this->croak( CITE_ERROR_KEY_INVALID_2, serialize( $key ) );
250
 
                                        
251
 
                        } else
252
 
                                $this->croak( CITE_ERROR_STR_INVALID, serialize( $str ) );
253
 
                }
254
 
 
255
 
                /**
256
 
                 * Parse the arguments to the <ref> tag
257
 
                 *
258
 
                 * @static
259
 
                 *
260
 
                 * @param array $argv The argument vector
261
 
                 * @return mixed false on invalid input, a string on valid
262
 
                 *               input and null on no input
263
 
                 */
264
 
                function refArg( $argv ) {
265
 
 
266
 
                        $cnt = count( $argv );
267
 
                        
268
 
                        if ( $cnt > 1 )
269
 
                                // There should only be one key
270
 
                                return false;
271
 
                        else if ( $cnt == 1 )
272
 
                                if ( isset( $argv['name'] ) )
273
 
                                        // Key given.
274
 
                                        return $this->validateName( array_shift( $argv ) );
275
 
                                else
276
 
                                        // Invalid key
277
 
                                        return false;
278
 
                        else
279
 
                                // No key
280
 
                                return null;
281
 
                }
282
 
                
283
 
                /**
284
 
                 * Since the key name is used in an XHTML id attribute, it must
285
 
                 * conform to the validity rules. The restriction to begin with
286
 
                 * a letter is lifted since references have their own prefix.
287
 
                 *
288
 
                 * @fixme merge this code with the various section name transformations
289
 
                 * @fixme double-check for complete validity
290
 
                 * @return string if valid, false if invalid
291
 
                 */
292
 
                function validateName( $name ) {
293
 
                        if( preg_match( '/^[A-Za-z0-9:_.-]*$/i', $name ) ) {
294
 
                                return $name;
295
 
                        } else {
296
 
                                // WARNING: CRAPPY CUT AND PASTE MAKES BABY JESUS CRY
297
 
                                $text = urlencode( str_replace( ' ', '_', $name ) );
298
 
                                $replacearray = array(
299
 
                                        '%3A' => ':',
300
 
                                        '%' => '.'
301
 
                                );
302
 
                                return str_replace(
303
 
                                        array_keys( $replacearray ),
304
 
                                        array_values( $replacearray ),
305
 
                                        $text );
306
 
                        }
307
 
                }
308
 
 
309
 
                /**
310
 
                 * Populate $this->mRefs based on input and arguments to <ref>
311
 
                 *
312
 
                 * @param string $str Input from the <ref> tag
313
 
                 * @param mixed $key Argument to the <ref> tag as returned by $this->refArg()
314
 
                 * @return string 
315
 
                 */
316
 
                function stack( $str, $key = null ) {
317
 
                        if ( $key === null ) {
318
 
                                // No key
319
 
                                $this->mRefs[] = $str;
320
 
                                return $this->linkRef( $this->mInCnt++ );
321
 
                        } else if ( is_string( $key ) )
322
 
                                // Valid key
323
 
                                if ( ! @is_array( $this->mRefs[$key] ) ) {
324
 
                                        // First occourance
325
 
                                        $this->mRefs[$key] = array(
326
 
                                                'text' => $str,
327
 
                                                'count' => 0,
328
 
                                                'number' => ++$this->mOutCnt
329
 
                                        );
330
 
                                        return
331
 
                                                $this->linkRef(
332
 
                                                        $key,
333
 
                                                        $this->mRefs[$key]['count'],
334
 
                                                        $this->mRefs[$key]['number']
335
 
                                                );
336
 
                                } else
337
 
                                        // We've been here before
338
 
                                        return 
339
 
                                                $this->linkRef(
340
 
                                                        $key,
341
 
                                                        ++$this->mRefs[$key]['count'],
342
 
                                                        $this->mRefs[$key]['number']
343
 
                                                );
344
 
                        else
345
 
                                $this->croak( CITE_ERROR_STACK_INVALID_INPUT, serialize( array( $key, $str ) ) );
346
 
                }
347
 
                
348
 
                /**
349
 
                 * Callback function for <references>
350
 
                 *
351
 
                 * @param string $str Input
352
 
                 * @param array $argv Arguments
353
 
                 * @return string
354
 
                 */
355
 
                function references( $str, $argv, $parser ) {
356
 
                        if ( $this->mInCite ) {
357
 
                                if ( is_null( $str ) ) {
358
 
                                        return htmlspecialchars( "<references/>" );
359
 
                                } else {
360
 
                                        return htmlspecialchars( "<references>$str</references>" );
361
 
                                }
362
 
                        } else {
363
 
                                $this->mInCite = true;
364
 
                                $ret = $this->guardedReferences( $str, $argv, $parser );
365
 
                                $this->mInCite = false;
366
 
                                return $ret;
367
 
                        }
368
 
                }
369
 
                
370
 
                function guardedReferences( $str, $argv, $parser ) {
371
 
                        $this->mParser = $parser;
372
 
                        if ( $str !== null )
373
 
                                return $this->error( CITE_ERROR_REFERENCES_INVALID_INPUT );
374
 
                        else if ( count( $argv ) )
375
 
                                return $this->error( CITE_ERROR_REFERENCES_INVALID_PARAMETERS );
376
 
                        else
377
 
                                return $this->referencesFormat();
378
 
                }
379
 
 
380
 
                /**
381
 
                 * Make output to be returned from the references() function
382
 
                 *
383
 
                 * @return string XHTML ready for output
384
 
                 */
385
 
                function referencesFormat() {
386
 
                        $ent = array();
387
 
                        
388
 
                        foreach ( $this->mRefs as $k => $v )
389
 
                                $ent[] = $this->referencesFormatEntry( $k, $v );
390
 
                        
391
 
                        $prefix = wfMsgForContentNoTrans( 'cite_references_prefix' );
392
 
                        $suffix = wfMsgForContentNoTrans( 'cite_references_suffix' );
393
 
                        $content = implode( "\n", $ent );
394
 
                        
395
 
                        // Live hack: parse() adds two newlines on WM, can't reproduce it locally -ævar
396
 
                        return rtrim( $this->parse( $prefix . $content . $suffix ), "\n" );
397
 
                }
398
 
 
399
 
                /**
400
 
                 * Format a single entry for the referencesFormat() function
401
 
                 *
402
 
                 * @param string $key The key of the reference
403
 
                 * @param mixed $val The value of the reference, string for anonymous
404
 
                 *                   references, array for user-suppplied
405
 
                 * @return string Wikitext
406
 
                 */
407
 
                function referencesFormatEntry( $key, $val ) {
408
 
                        // Anonymous reference
409
 
                        if ( ! is_array( $val ) )
410
 
                                return
411
 
                                        wfMsgForContentNoTrans(
412
 
                                                'cite_references_link_one',
413
 
                                                $this->referencesKey( $key ),
414
 
                                                $this->refKey( $key ),
415
 
                                                $val
416
 
                                        );
417
 
                        // Standalone named reference, I want to format this like an
418
 
                        // anonymous reference because displaying "1. 1.1 Ref text" is
419
 
                        // overkill and users frequently use named references when they
420
 
                        // don't need them for convenience
421
 
                        else if ( $val['count'] === 0 )
422
 
                                return
423
 
                                        wfMsgForContentNoTrans(
424
 
                                                'cite_references_link_one',
425
 
                                                $this->referencesKey( $key ),
426
 
                                                $this->refKey( $key, $val['count'] ),
427
 
                                                $val['text']
428
 
                                        );
429
 
                        // Named references with >1 occurrences
430
 
                        else {
431
 
                                $links = array();
432
 
 
433
 
                                for ( $i = 0; $i <= $val['count']; ++$i ) {
434
 
                                        $links[] = wfMsgForContentNoTrans(
435
 
                                                        'cite_references_link_many_format',
436
 
                                                        $this->refKey( $key, $i ),
437
 
                                                        $this->referencesFormatEntryNumericBacklinkLabel( $val['number'], $i, $val['count'] ),
438
 
                                                        $this->referencesFormatEntryAlternateBacklinkLabel( $i )
439
 
                                        );
440
 
                                }
441
 
 
442
 
                                $list = $this->listToText( $links );
443
 
 
444
 
                                return
445
 
                                        wfMsgForContentNoTrans( 'cite_references_link_many',
446
 
                                                $this->referencesKey( $key ),
447
 
                                                $list,
448
 
                                                $val['text']
449
 
                                        );
450
 
                        }
451
 
                }
452
 
 
453
 
                /**
454
 
                 * Generate a numeric backlink given a base number and an
455
 
                 * offset, e.g. $base = 1, $offset = 2; = 1.2
456
 
                 * Since bug #5525, it correctly does 1.9 -> 1.10 as well as 1.099 -> 1.100
457
 
                 *
458
 
                 * @static
459
 
                 *
460
 
                 * @param int $base The base
461
 
                 * @param int $offset The offset
462
 
                 * @param int $max Maximum value expected.
463
 
                 * @return string
464
 
                 */
465
 
                function referencesFormatEntryNumericBacklinkLabel( $base, $offset, $max ) {
466
 
                        global $wgContLang;
467
 
                        $scope = strlen( $max );
468
 
                        $ret = $wgContLang->formatNum(
469
 
                                sprintf("%s.%0{$scope}s", $base, $offset)
470
 
                        );
471
 
                        return $ret;
472
 
                }
473
 
 
474
 
                /**
475
 
                 * Generate a custom format backlink given an offset, e.g.
476
 
                 * $offset = 2; = c if $this->mBacklinkLabels = array( 'a',
477
 
                 * 'b', 'c', ...). Return an error if the offset > the # of
478
 
                 * array items
479
 
                 *
480
 
                 * @param int $offset The offset
481
 
                 *
482
 
                 * @return string
483
 
                 */
484
 
                function referencesFormatEntryAlternateBacklinkLabel( $offset ) {
485
 
                        if ( !isset( $this->mBacklinkLabels ) ) {
486
 
                                $this->genBacklinkLabels();
487
 
                        }
488
 
                        if ( isset( $this->mBacklinkLabels[$offset] ) ) {
489
 
                                return $this->mBacklinkLabels[$offset];
490
 
                        } else {
491
 
                                // Feed me!
492
 
                                return $this->error( CITE_ERROR_REFERENCES_NO_BACKLINK_LABEL );
493
 
                        }
494
 
                }
495
 
 
496
 
                /**
497
 
                 * Return an id for use in wikitext output based on a key and
498
 
                 * optionally the # of it, used in <references>, not <ref>
499
 
                 * (since otherwise it would link to itself)
500
 
                 *
501
 
                 * @static
502
 
                 *
503
 
                 * @param string $key The key
504
 
                 * @param int $num The number of the key
505
 
                 * @return string A key for use in wikitext
506
 
                 */
507
 
                function refKey( $key, $num = null ) {
508
 
                        $prefix = wfMsgForContent( 'cite_reference_link_prefix' );
509
 
                        $suffix = wfMsgForContent( 'cite_reference_link_suffix' );
510
 
                        if ( isset( $num ) )
511
 
                                $key = wfMsgForContentNoTrans( 'cite_reference_link_key_with_num', $key, $num );
512
 
                        
513
 
                        return $prefix . $key . $suffix;
514
 
                }
515
 
 
516
 
                /**
517
 
                 * Return an id for use in wikitext output based on a key and
518
 
                 * optionally the # of it, used in <ref>, not <references>
519
 
                 * (since otherwise it would link to itself)
520
 
                 *
521
 
                 * @static
522
 
                 *
523
 
                 * @param string $key The key
524
 
                 * @param int $num The number of the key
525
 
                 * @return string A key for use in wikitext
526
 
                 */
527
 
                function referencesKey( $key, $num = null ) {
528
 
                        $prefix = wfMsgForContent( 'cite_references_link_prefix' );
529
 
                        $suffix = wfMsgForContent( 'cite_references_link_suffix' );
530
 
                        if ( isset( $num ) )
531
 
                                $key = wfMsgForContentNoTrans( 'cite_reference_link_key_with_num', $key, $num );
532
 
                        
533
 
                        return $prefix . $key . $suffix;
534
 
                }
535
 
 
536
 
                /**
537
 
                 * Generate a link (<sup ...) for the <ref> element from a key
538
 
                 * and return XHTML ready for output
539
 
                 *
540
 
                 * @param string $key The key for the link
541
 
                 * @param int $count The # of the key, used for distinguishing
542
 
                 *                   multiple occourances of the same key
543
 
                 * @param int $label The label to use for the link, I want to
544
 
                 *                   use the same label for all occourances of
545
 
                 *                   the same named reference.
546
 
                 * @return string
547
 
                 */
548
 
                function linkRef( $key, $count = null, $label = null ) {
549
 
                        global $wgContLang;
550
 
 
551
 
                        return
552
 
                                $this->parse(
553
 
                                        wfMsgForContentNoTrans(
554
 
                                                'cite_reference_link',
555
 
                                                $this->refKey( $key, $count ),
556
 
                                                $this->referencesKey( $key ),
557
 
                                                $wgContLang->formatNum( is_null( $label ) ? ++$this->mOutCnt : $label )
558
 
                                        )
559
 
                                );
560
 
                }
561
 
 
562
 
                /**
563
 
                 * This does approximately the same thing as
564
 
                 * Langauge::listToText() but due to this being used for a
565
 
                 * slightly different purpose (people might not want , as the
566
 
                 * first seperator and not 'and' as the second, and this has to
567
 
                 * use messages from the content language) I'm rolling my own.
568
 
                 *
569
 
                 * @static
570
 
                 *
571
 
                 * @param array $arr The array to format
572
 
                 * @return string
573
 
                 */
574
 
                function listToText( $arr ) {
575
 
                        $cnt = count( $arr );
576
 
 
577
 
                        $sep = wfMsgForContentNoTrans( 'cite_references_link_many_sep' );
578
 
                        $and = wfMsgForContentNoTrans( 'cite_references_link_many_and' );
579
 
 
580
 
                        if ( $cnt == 1 )
581
 
                                // Enforce always returning a string
582
 
                                return (string)$arr[0];
583
 
                        else {
584
 
                                $t = array_slice( $arr, 0, $cnt - 1 );
585
 
                                return implode( $sep, $t ) . $and . $arr[$cnt - 1];
586
 
                        }
587
 
                }
588
 
 
589
 
                /**
590
 
                 * Parse a given fragment and fix up Tidy's trail of blood on
591
 
                 * it...
592
 
                 *
593
 
                 * @param string $in The text to parse
594
 
                 * @return string The parsed text
595
 
                 */
596
 
                function parse( $in ) {
597
 
                        $ret = $this->mParser->parse(
598
 
                                $in,
599
 
                                $this->mParser->mTitle,
600
 
                                $this->mParser->mOptions,
601
 
                                // Avoid whitespace buildup
602
 
                                false,
603
 
                                // Important, otherwise $this->clearState()
604
 
                                // would get run every time <ref> or
605
 
                                // <references> is called, fucking the whole
606
 
                                // thing up.
607
 
                                false
608
 
                        );
609
 
                        $text = $ret->getText();
610
 
                        
611
 
                        return $this->fixTidy( $text );
612
 
                }
613
 
 
614
 
                /**
615
 
                 * Tidy treats all input as a block, it will e.g. wrap most
616
 
                 * input in <p> if it isn't already, fix that and return the fixed text
617
 
                 *
618
 
                 * @static
619
 
                 *
620
 
                 * @param string $text The text to fix
621
 
                 * @return string The fixed text
622
 
                 */
623
 
                function fixTidy( $text ) {
624
 
                        global $wgUseTidy;
625
 
 
626
 
                        if ( ! $wgUseTidy )
627
 
                                return $text;
628
 
                        else {
629
 
                                $text = preg_replace( '~^<p>\s*~', '', $text );
630
 
                                $text = preg_replace( '~\s*</p>\s*~', '', $text );
631
 
                                $text = preg_replace( '~\n$~', '', $text );
632
 
                                
633
 
                                return $text;
634
 
                        }
635
 
                }
636
 
 
637
 
                /**
638
 
                 * Generate the labels to pass to the
639
 
                 * 'cite_references_link_many_format' message, the format is an
640
 
                 * arbitary number of tokens seperated by [\t\n ]
641
 
                 */
642
 
                function genBacklinkLabels() {
643
 
                        wfProfileIn( __METHOD__ );
644
 
                        $text = wfMsgForContentNoTrans( 'cite_references_link_many_format_backlink_labels' );
645
 
                        $this->mBacklinkLabels = preg_split( '#[\n\t ]#', $text );
646
 
                        wfProfileOut( __METHOD__ );
647
 
                }
648
 
 
649
 
                /**
650
 
                 * Gets run when Parser::clearState() gets run, since we don't
651
 
                 * want the counts to transcend pages and other instances
652
 
                 */
653
 
                function clearState() {
654
 
                        $this->mOutCnt = $this->mInCnt = 0;
655
 
                        $this->mRefs = array();
656
 
 
657
 
                        return true;
658
 
                }
659
 
 
660
 
                /**
661
 
                 * Initialize the parser hooks
662
 
                 */
663
 
                function setHooks() {
664
 
                        global $wgParser, $wgHooks;
665
 
                        
666
 
                        $wgParser->setHook( 'ref' , array( &$this, 'ref' ) );
667
 
                        $wgParser->setHook( 'references' , array( &$this, 'references' ) );
668
 
 
669
 
                        $wgHooks['ParserClearState'][] = array( &$this, 'clearState' );
670
 
                }
671
 
 
672
 
                /**
673
 
                 * Return an error message based on an error ID
674
 
                 *
675
 
                 * @param int $id ID for the error
676
 
                 * @return string XHTML ready for output
677
 
                 */
678
 
                function error( $id ) {
679
 
                        if ( $id > 0 )
680
 
                                // User errors are positive
681
 
                                return 
682
 
                                        $this->parse(
683
 
                                                '<strong class="error">' .
684
 
                                                wfMsgforContent( 'cite_error', $id, wfMsgForContent( "cite_error_$id" ) ) .
685
 
                                                '</strong>'
686
 
                                        );
687
 
                        else if ( $id < 0 )
688
 
                                return wfMsgforContent( 'cite_error', $id );
689
 
                }
690
 
 
691
 
                /**
692
 
                 * Die with a backtrace if something happens in the code which
693
 
                 * shouldn't have
694
 
                 *
695
 
                 * @param int $error  ID for the error
696
 
                 * @param string $data Serialized error data
697
 
                 */
698
 
                function croak( $error, $data ) {
699
 
                        wfDebugDieBacktrace( wfMsgForContent( 'cite_croak', $this->error( $error ), $data ) );
700
 
                }
701
 
 
702
 
                /**#@-*/
703
 
        }
704
 
 
705
 
        new Cite;
706
 
}
707
 
 
708
 
/**#@-*/
709
 
?>