Page MenuHomePhabricator
Authored By
bzimport
Nov 21 2014, 9:19 PM
Size
20 KB
Referenced Files
None
Subscribers
None

6271.txt

This document is not UTF8. It was detected as Shift JIS and converted to UTF8 for display.
--- Cite.php (revision 14725)
+++ Cite.php (working copy)
@@ -35,13 +35,15 @@
'CITE_ERROR_STR_INVALID',
'CITE_ERROR_KEY_INVALID_1',
'CITE_ERROR_KEY_INVALID_2',
+ 'CITE_ERROR_GROUP_INVALID_1',
'CITE_ERROR_STACK_INVALID_INPUT'
),
'user' => array(
'CITE_ERROR_REF_NUMERIC_KEY',
'CITE_ERROR_REF_NO_KEY',
- 'CITE_ERROR_REF_TOO_MANY_KEYS',
+ 'CITE_ERROR_REF_BAD_ARGS',
'CITE_ERROR_REF_NO_INPUT',
+ 'CITE_ERROR_REF_BAD_GROUP',
'CITE_ERROR_REFERENCES_INVALID_INPUT',
'CITE_ERROR_REFERENCES_INVALID_PARAMETERS',
'CITE_ERROR_REFERENCES_NO_BACKLINK_LABEL'
@@ -63,45 +65,47 @@
/*
Debug & errors
*/
// Internal errors
'cite_croak' => 'Cite croaked; $1: $2',
'cite_error_' . CITE_ERROR_STR_INVALID => 'Internal error; invalid $str',
'cite_error_' . CITE_ERROR_KEY_INVALID_1 => 'Internal error; invalid key',
'cite_error_' . CITE_ERROR_KEY_INVALID_2 => 'Internal error; invalid key',
+ 'cite_error_' . CITE_ERROR_GROUP_INVALID_1 => 'Internal error; invalid group',
'cite_error_' . CITE_ERROR_STACK_INVALID_INPUT => 'Internal error; invalid stack key',
// User errors
'cite_error' => 'Cite error $1; $2',
- 'cite_error_' . CITE_ERROR_REF_NUMERIC_KEY => 'Invalid call; expecting a non-integer key',
+ 'cite_error_' . CITE_ERROR_REF_NUMERIC_KEY => 'Invalid key defined for <ref> (keys cannot be integers)',
- 'cite_error_' . CITE_ERROR_REF_NO_KEY => 'Invalid call; no key specified',
+ 'cite_error_' . CITE_ERROR_REF_NO_KEY => 'No key defined for <ref>',
- 'cite_error_' . CITE_ERROR_REF_TOO_MANY_KEYS => 'Invalid call; invalid keys, e.g. too many or wrong key specified',
+ 'cite_error_' . CITE_ERROR_REF_BAD_ARGS => 'Invalid arguments defined for <ref>: exactly one name and/or one group are allowed',
- 'cite_error_' . CITE_ERROR_REF_NO_INPUT => 'Invalid call; no input specified',
+ 'cite_error_' . CITE_ERROR_REF_NO_INPUT => 'No input specified for <ref>',
+ 'cite_error_' . CITE_ERROR_REF_BAD_GROUP => "Invalid group label defined for <ref>: 'ungrouped' is reserved",
- 'cite_error_' . CITE_ERROR_REFERENCES_INVALID_INPUT => 'Invalid input; expecting none',
+ 'cite_error_' . CITE_ERROR_REFERENCES_INVALID_INPUT => 'Invalid input to <references>: expecting none, use <references />',
- 'cite_error_' . CITE_ERROR_REFERENCES_INVALID_PARAMETERS => 'Invalid parameters; expecting none',
+ 'cite_error_' . CITE_ERROR_REFERENCES_INVALID_PARAMETERS => 'Invalid parameters defined for <references>: only "group" is valid',
'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",
/*
Output formatting
*/
'cite_reference_link_key_with_num' => '$1_$2',
// Ids produced by <ref>
- 'cite_reference_link_prefix' => '_ref-',
+ 'cite_ref_link_prefix' => '_ref-',
- 'cite_reference_link_suffix' => '',
+ 'cite_ref_link_suffix' => '',
// Ids produced by <references>
'cite_references_link_prefix' => '_note-',
'cite_references_link_suffix' => '',
- 'cite_reference_link' => '<sup id="$1" class="reference">[[#$2|<nowiki>[</nowiki>$3<nowiki>]</nowiki>]]</sup>',
+ 'cite_ref_link' => '<sup id="$1" class="reference">[[#$2|<nowiki>[</nowiki>$3<nowiki>]</nowiki>]]</sup>',
'cite_references_link_one' => '<li id="$1">[[#$2|G褂]] $3</li>',
'cite_references_link_many' => '<li id="$1">G褂 $2 $3</li>',
'cite_references_link_many_format' => '[[#$1|<sup>$2</sup>]]',
// An item from this set is passed as $3 in the message above
'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',
'cite_references_link_many_sep' => "\xc2\xa0", // &nbsp;
- 'cite_references_link_many_and' => "\xc2\xa0", // &nbps;
+ 'cite_references_link_many_and' => "\xc2\xa0", // &nbsp;
// Although I could just use # instead of <li> above and nothing here that
// will break on input that contains linebreaks
@@ -109,36 +113,43 @@
'cite_references_suffix' => '</ol>',
)
);
class Cite {
/**#@+
* @access private
*/
+
+
/**
* Datastructure representing <ref> input, in the format of:
* <code>
* array(
+ * 'ungrouped' => array(
- * 'user supplied' => array(
+ * 'user supplied' => array(
- * 'text' => 'user supplied reference & key',
+ * 'text' => 'user supplied reference & key',
- * 'count' => 1, // occurs twice
+ * 'count' => 1, // occurs twice
- * 'number' => 1, // The first reference, we want
+ * 'number' => 1, // The first reference, we want
- * // all occourances of it to
+ * // all occurrences of it to
- * // use the same number
+ * // all occurrences of it to
- * ),
+ * ),
- * 0 => 'Anonymous reference',
+ * 0 => 'Anonymous reference',
- * 1 => 'Another anonymous reference',
+ * 1 => 'Another anonymous reference',
- * 'some key' => array(
+ * 'some key' => array(
- * 'text' => 'this one occurs once'
+ * 'text' => 'this one occurs once'
- * 'count' => 0,
+ * 'count' => 0,
- * 'number' => 4
+ * 'number' => 4
- * ),
+ * ),
- * 3 => 'more stuff'
+ * 3 => 'more stuff'
+ * ),
+ * 'custom_group' => array(
+ * ...
+ * )
* );
* </code>
*
* This works because:
- * * PHP's datastructures are guarenteed to be returned in the
+ * * PHP's datastructures are guaranteed to be returned in the
* order that things are inserted into them (unless you mess
* with that)
* * User supplied keys can't be integers, therefore avoiding
@@ -147,22 +158,23 @@
* @var array
**/
var $mRefs = array();
/**
* Count for user displayed output (ref[1], ref[2], ...)
+ * Broken up into pieces for different groups, default is 'ungrouped'
*
* @var int
*/
- var $mOutCnt = 0;
+ var $mOutCnt = array();
/**
- * Internal counter for anonymous references, seperate from
+ * Internal counter for anonymous references, separate from
* $mOutCnt because anonymous references won't increment it,
* but will incremement $mOutCnt
*
* @var int
*/
- var $mInCnt = 0;
+ var $mInCnt = array();
/**
* The backlinks, in order, to pass as $3 to
@@ -215,42 +227,48 @@
return $ret;
}
}
function guardedRef( $str, $argv, $parser ) {
- $this->mParser = $parser;
+ $this->mParser = $parser;
- $key = $this->refArg( $argv );
+ $args = $this->refArg( $argv );
+ $key = $args['name'];
+ $group = $args['group'];
- if ( $str !== null ) {
+ if ( $str !== null ) { // <ref>s have some content--not <ref ... />
- if ( $str === '' )
+ if ( $str === '' ) // <ref ...></ref>
return $this->error( CITE_ERROR_REF_NO_INPUT );
- if ( is_string( $key ) )
+ elseif ( is_string( $key ) || $key === null )
// I don't want keys in the form of /^[0-9]+$/ because they would
// conflict with the php datastructure I'm using, besides, why specify
// a manual key if it's just going to be any old integer?
if ( sprintf( '%d', $key ) === (string)$key )
return $this->error( CITE_ERROR_REF_NUMERIC_KEY );
- else
+ elseif ($group === false) // $group === 'ungrouped'
+ $this->error( CITE_ERROR_REF_BAD_GROUP );
+ elseif ( !is_string( $group ) && $group !== null )
+ $this->croak( CITE_ERROR_GROUP_INVALID_1, serialize( $group ) );
+ else // $key is valid, $group is valid: hopefully we end up here
- return $this->stack( $str, $key);
+ return $this->stack( $str, $key, $group );
- else if ( $key === null )
- return $this->stack( $str );
- else if ( $key === false )
+ elseif ( $key === false ) // refArg determined $key is bad
- return $this->error( CITE_ERROR_REF_TOO_MANY_KEYS );
+ return $this->error( CITE_ERROR_REF_BAD_ARGS );
else
$this->croak( CITE_ERROR_KEY_INVALID_1,serialize( $key ) );
- } else if ( $str === null ) {
+ } elseif ( $str === null ) { // <ref ... />
if ( is_string( $key ) )
if ( sprintf( '%d', $key ) === (string)$key )
return $this->error( CITE_ERROR_REF_NUMERIC_KEY );
- else
+ elseif ($group === false) // $group === 'ungrouped'
+ $this->error( CITE_ERROR_REF_BAD_GROUP );
+ else // $key is valid, $group is valid: hopefully we end up here
- return $this->stack( $str, $key);
+ return $this->stack( $str, $key, $group );
- else if ( $key === false )
+ elseif ( $key === false )
- return $this->error( CITE_ERROR_REF_TOO_MANY_KEYS );
+ return $this->error( CITE_ERROR_REF_BAD_ARGS );
- else if ( $key === null )
+ elseif ( $key === null )
return $this->error( CITE_ERROR_REF_NO_KEY );
else
$this->croak( CITE_ERROR_KEY_INVALID_2,serialize( $key ) );
- } else
+ } else // If we reach here, something is seriously wrong.
$this->croak( CITE_ERROR_STR_INVALID, serialize( $str ) );
}
@@ -260,28 +278,41 @@
* @static
*
* @param array $argv The argument vector
- * @return mixed false on invalid input, a string on valid
- * input and null on no input
+ * @return array: each element is false on invalid input, a string on
+ * valid input and null on no input (or 'ungrouped' for
+ * groups, since that's less confusing as an array key)
*/
function refArg( $argv ) {
$cnt = count( $argv );
- if ( $cnt > 1 )
+ if ( $cnt > 2 )
- // There should only be one key
+ // There should never be more than two arguments
- return false;
+ return array('name' => false, 'group' => false);
- else if ( $cnt == 1 )
+ elseif ( $cnt == 1 )
if ( isset( $argv['name'] ) )
// Key given.
- return $this->validateName( array_shift( $argv ) );
+ return array('name' => $this->validateName($argv['name']),
+ 'group' => 'ungrouped' );
+ elseif ( isset( $argv['group'] ) )
+ // Group given.
+ return array('name' => null,
+ 'group' => $this->validateGroup($argv['group']) );
else
- // Invalid key
+ // Invalid arg
- return false;
+ return array('name' => false, 'group' => false);
+ elseif ( $cnt == 2 )
+ if ( isset( $argv['name'] ) && isset( $argv['group'] ) )
+ // Key and group given.
+ return array('name' => $this->validateName($argv['name']),
+ 'group' => $this->validateGroup($argv['group']) );
+ else
+ // Invalid arg(s)
+ return array('name' => false, 'group' => false);
else
- // No key
+ // No key or group
- return null;
+ return array('name' => null, 'group' => 'ungrouped');
}
/**
* Since the key name is used in an XHTML id attribute, it must
* conform to the validity rules. The restriction to begin with
@@ -292,7 +323,7 @@
* @return string if valid, false if invalid
*/
function validateName( $name ) {
- if( preg_match( '/^[A-Za-z0-9:_.-]*$/i', $name ) ) {
+ if( preg_match( '/^[A-Za-z0-9:_.-]*$/', $name ) ) {
return $name;
} else {
// WARNING: CRAPPY CUT AND PASTE MAKES BABY JESUS CRY
@@ -309,44 +340,67 @@
}
+
+ /**
+ * Since the group name is used as an array key, make sure it's not
+ * screwy. NUL, \, ', ", and $ are all probably Bad.
+ *
+ * @return string
+ */
+ function validateGroup( $group ) {
+ if( $group === 'ungrouped' )
+ return false;
+ elseif( !get_magic_quotes_gpc() )
+ return addcslashes($group,'\0\\\'"$');
+ else
+ return $group;
+ }
/**
* Populate $this->mRefs based on input and arguments to <ref>
*
* @param string $str Input from the <ref> tag
- * @param mixed $key Argument to the <ref> tag as returned by $this->refArg()
+ * @param mixed $key Key for the <ref> tag as returned by $this->refArg()
+ * (either a string or null)
+ * @param mixed $group Which grouping of references this is part of
- * @return string
+ * @return string
*/
- function stack( $str, $key = null ) {
+ function stack( $str, $key = null, $group = 'ungrouped' ) {
+ if ($this->mInCnt[$group] === null)
+ $this->mInCnt[$group] = 0;
+ if ($this->mOutCnt[$group] === null)
+ $this->mOutCnt[$group] = 0;
if ( $key === null ) {
// No key
- $this->mRefs[] = $str;
+ $this->mRefs[$group][] = $str;
- return $this->linkRef( $this->mInCnt++ );
+ return $this->linkRef( $this->mInCnt[$group]++,$group );
- } else if ( is_string( $key ) )
+ } elseif ( is_string( $key ) ) {
// Valid key
- if ( ! @is_array( $this->mRefs[$key] ) ) {
+ if ( ! @is_array( $this->mRefs[$group][$key] ) ) {
- // First occourance
+ // First occurrence
- $this->mRefs[$key] = array(
+ $this->mRefs[$group][$key] = array(
'text' => $str,
'count' => 0,
- 'number' => ++$this->mOutCnt
+ 'number' => ++$this->mOutCnt[$group]
);
return
$this->linkRef(
$key,
+ $group,
- $this->mRefs[$key]['count'],
+ $this->mRefs[$group][$key]['count'],
- $this->mRefs[$key]['number']
+ $this->mRefs[$group][$key]['number']
);
} else
// We've been here before
return
$this->linkRef(
$key,
+ $group,
- ++$this->mRefs[$key]['count'],
+ ++$this->mRefs[$group][$key]['count'],
- $this->mRefs[$key]['number']
+ $this->mRefs[$group][$key]['number']
);
- else
+ } else
$this->croak( CITE_ERROR_STACK_INVALID_INPUT, serialize( array( $key, $str ) ) );
}
/**
* Callback function for <references>
*
@@ -368,64 +422,99 @@
return $ret;
}
}
function guardedReferences( $str, $argv, $parser ) {
$this->mParser = $parser;
+ $group = $this->referencesArg( $argv );
+
if ( $str !== null )
return $this->error( CITE_ERROR_REFERENCES_INVALID_INPUT );
- else if ( count( $argv ) )
+ elseif ( $group === false )
return $this->error( CITE_ERROR_REFERENCES_INVALID_PARAMETERS );
else
- return $this->referencesFormat();
+ return $this->referencesFormat( $group );
}
+
+ /**
+ * Parse the arguments to the <references> tag
+ *
+ * @static
+ *
+ * @param array $argv The argument vector
+ * @return mixed false on invalid input, a string on valid
+ * or no input
+ */
+ function referencesArg( $argv ) {
+ $cnt = count( $argv );
+
+ if ( $cnt > 1 )
+ // There should never be more than one argument
+ return false;
+ elseif ( $cnt == 1 ) {
+ if ( isset( $argv['group'] ) )
+ // Group given.
+ return $this->validateGroup( $argv['group'] );
+ else
+ // Not a group
+ return false;
+ } else
+ // No group
+ return 'ungrouped';
+ }
/**
* Make output to be returned from the references() function
*
+ * @param string $group The group of <references />
* @return string XHTML ready for output
*/
- function referencesFormat() {
+ function referencesFormat( $group = 'ungrouped' ) {
$ent = array();
- foreach ( $this->mRefs as $k => $v )
+ foreach ( $this->mRefs[$group] as $k => $v )
+ // $k: name of a named ref, number of an anon
+ // $v: contents of the ref
- $ent[] = $this->referencesFormatEntry( $k, $v );
+ $ent[] = $this->referencesFormatEntry( $k, $v, $group );
$prefix = wfMsgForContentNoTrans( 'cite_references_prefix' );
$suffix = wfMsgForContentNoTrans( 'cite_references_suffix' );
$content = implode( "\n", $ent );
// Live hack: parse() adds two newlines on WM, can't reproduce it locally -+ェvar
return rtrim( $this->parse( $prefix . $content . $suffix ), "\n" );
}
/**
* Format a single entry for the referencesFormat() function
*
- * @param string $key The key of the reference
+ * @param string $key The key (name/number) of the reference
- * @param mixed $val The value of the reference, string for anonymous
+ * @param mixed $val The value of the reference (string for anonymous
- * references, array for user-suppplied
+ * references, array for user-supplied)
+ * @param string $group The group that this whole <references> belongs
+ * to
* @return string Wikitext
*/
- function referencesFormatEntry( $key, $val ) {
+ function referencesFormatEntry( $key, $val, $group = 'ungrouped' ) {
// Anonymous reference
if ( ! is_array( $val ) )
return
wfMsgForContentNoTrans(
'cite_references_link_one',
- $this->referencesKey( $key ),
+ $this->referencesKey( $key, $group ),
- $this->refKey( $key ),
+ $this->refKey( $key, $group ),
$val
);
// Standalone named reference, I want to format this like an
// anonymous reference because displaying "1. 1.1 Ref text" is
// overkill and users frequently use named references when they
// don't need them for convenience
- else if ( $val['count'] === 0 )
+ elseif ( $val['count'] === 0 )
return
wfMsgForContentNoTrans(
'cite_references_link_one',
- $this->referencesKey( $key ),
+ $this->referencesKey( $key, $group ),
- $this->refKey( $key, $val['count'] ),
+ $this->refKey( $key, $group, $val['count'] ),
$val['text']
);
// Named references with >1 occurrences
@@ -435,7 +524,7 @@
for ( $i = 0; $i <= $val['count']; ++$i ) {
$links[] = wfMsgForContentNoTrans(
'cite_references_link_many_format',
- $this->refKey( $key, $i),
+ $this->refKey( $key, $group, $i ),
$this->referencesFormatEntryNumericBacklinkLabel( $val['number'], $i, $val['count'] ),
$this->referencesFormatEntryAlternateBacklinkLabel( $i )
);
@@ -445,7 +534,7 @@
return
wfMsgForContentNoTrans( 'cite_references_link_many',
- $this->referencesKey( $key ),
+ $this->referencesKey( $key, $group ),
$list,
$val['text']
);
@@ -500,14 +589,17 @@
*
* @param string $key The key
* @param int $num The number of the key
+ * @param string $group The group
* @return string A key for use in wikitext
*/
- function refKey( $key, $num = null ) {
+ function refKey( $key, $group = 'ungrouped', $num = null ) {
- $prefix = wfMsgForContent( 'cite_reference_link_prefix');
+ $prefix = wfMsgForContent( 'cite_ref_link_prefix' );
- $suffix = wfMsgForContent( 'cite_reference_link_suffix');
+ $suffix = wfMsgForContent( 'cite_ref_link_suffix' );
+ if ( $group !== 'ungrouped' )
+ $key .= '-'.$group;
if ( isset( $num ) )
$key = wfMsgForContentNoTrans( 'cite_reference_link_key_with_num', $key, $num );
return $prefix . $key . $suffix;
}
@@ -522,12 +614,14 @@
* @param int $num The number of the key
* @return string A key for use in wikitext
*/
- function referencesKey( $key, $num = null ) {
+ function referencesKey( $key, $group = 'ungrouped', $num = null ) {
$prefix = wfMsgForContent( 'cite_references_link_prefix' );
$suffix = wfMsgForContent( 'cite_references_link_suffix' );
+ if ( $group !== 'ungrouped' )
+ $key .= '-'.$group;
if ( isset( $num ) )
$key = wfMsgForContentNoTrans( 'cite_reference_link_key_with_num', $key, $num );
return $prefix . $key . $suffix;
}
@@ -537,22 +631,24 @@
*
* @param string $key The key for the link
* @param int $count The # of the key, used for distinguishing
- * multiple occourances of the same key
+ * multiple occurrences of the same key
* @param int $label The label to use for the link, I want to
- * use the same label for all occourances of
+ * use the same label for all occurrences of
* the same named reference.
+ * @param string $group The link's group (affects numbering and
+ * link name)
* @return string
*/
- function linkRef( $key, $count = null, $label = null ) {
+ function linkRef( $key, $group = 'ungrouped', $count = null, $label = null ) {
global $wgContLang;
return
$this->parse(
wfMsgForContentNoTrans(
- 'cite_reference_link',
+ 'cite_ref_link',
- $this->refKey( $key, $count ),
+ $this->refKey( $key, $group, $count ),
- $this->referencesKey( $key ),
+ $this->referencesKey( $key, $group ),
- $wgContLang->formatNum( is_null( $label ) ? ++$this->mOutCnt : $label )
+ $wgContLang->formatNum( is_null( $label ) ? ++$this->mOutCnt[$group] : $label )
)
);
}
@@ -647,7 +743,7 @@
* want the counts to transcend pages and other instances
*/
function clearState() {
- $this->mOutCnt = $this->mInCnt = 0;
+ $this->mOutCnt = $this->mInCnt = array();
$this->mRefs = array();
return true;
id, wfMsgForContent( "cite_error_$id" ) ) .
'</strong>'
);
- else if ( $id < 0 )
+ elseif ( $id < 0 )
return wfMsgforContent( 'cite_error', $id );
}

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2591
Default Alt Text
6271.txt (20 KB)

Event Timeline