$this->firstCallInit();
}
$this->mOutput = new ParserOutput;
- $this->mOptions->registerWatcher( array( $this->mOutput, 'recordOption' ) );
+ if( $this->mOptions ) {
+ $this->mOptions->registerWatcher( array( $this->mOutput, 'recordOption' ) );
+ }
$this->mAutonumber = 0;
$this->mLastSection = '';
$this->mDTopen = false;
$has_opened_tr = array(); # Did this table open a <tr> element?
$indent_level = 0; # indent level of the table
- # Keep pulling lines off the front of the array until they're all gone.
- # we want to be able to push lines back on to the front of the stream,
- # but StringUtils::explode() returns funky optimised Iterators which don't
- # support insertion. So maintain a separate buffer and draw on that first if
- # there's anything in it
- $extraLines = array();
- $lines->rewind();
- do {
- if( $extraLines ){
- $outLine = array_shift( $extraLines );
- } elseif( $lines->valid() ) {
- $outLine = $lines->current();
- $lines->next();
- } else {
- break;
- }
+ foreach ( $lines as $outLine ) {
$line = trim( $outLine );
if ( $line === '' ) { # empty line, go to next line
} elseif ( $first_character === '|' || $first_character === '!' || substr( $line , 0 , 2 ) === '|+' ) {
# This might be cell elements, td, th or captions
if ( substr( $line , 0 , 2 ) === '|+' ) {
- $first_character = '|+';
+ $first_character = '+';
+ $line = substr( $line , 1 );
}
- $line = substr( $line , strlen( $first_character ) );
+ $line = substr( $line , 1 );
if ( $first_character === '!' ) {
$line = str_replace( '!!' , '||' , $line );
# by earlier parser steps, but should avoid splitting up eg
# attribute values containing literal "||".
$cells = StringUtils::explodeMarkup( '||' , $line );
- $cell = array_shift( $cells );
-
- # Inject cells back into the stream to be dealt with later
- # TODO: really we should do the whole thing as a stream...
- # but that would be too much like a sensible implementation :P
- if( count( $cells ) ){
- foreach( array_reverse( $cells ) as $extraCell ){
- array_unshift( $extraLines, $first_character . $extraCell );
- }
- }
$outLine = '';
- $previous = '';
- if ( $first_character !== '|+' ) {
- $tr_after = array_pop( $tr_attributes );
- if ( !array_pop( $tr_history ) ) {
- $previous = "<tr{$tr_after}>\n";
+ # Loop through each table cell
+ foreach ( $cells as $cell ) {
+ $previous = '';
+ if ( $first_character !== '+' ) {
+ $tr_after = array_pop( $tr_attributes );
+ if ( !array_pop( $tr_history ) ) {
+ $previous = "<tr{$tr_after}>\n";
+ }
+ array_push( $tr_history , true );
+ array_push( $tr_attributes , '' );
+ array_pop( $has_opened_tr );
+ array_push( $has_opened_tr , true );
}
- array_push( $tr_history , true );
- array_push( $tr_attributes , '' );
- array_pop( $has_opened_tr );
- array_push( $has_opened_tr , true );
- }
- $last_tag = array_pop( $last_tag_history );
+ $last_tag = array_pop( $last_tag_history );
- if ( array_pop( $td_history ) ) {
- $previous = "</{$last_tag}>\n{$previous}";
- }
+ if ( array_pop( $td_history ) ) {
+ $previous = "</{$last_tag}>\n{$previous}";
+ }
- if ( $first_character === '|' ) {
- $last_tag = 'td';
- } elseif ( $first_character === '!' ) {
- $last_tag = 'th';
- } elseif ( $first_character === '|+' ) {
- $last_tag = 'caption';
- } else {
- $last_tag = '';
- }
+ if ( $first_character === '|' ) {
+ $last_tag = 'td';
+ } elseif ( $first_character === '!' ) {
+ $last_tag = 'th';
+ } elseif ( $first_character === '+' ) {
+ $last_tag = 'caption';
+ } else {
+ $last_tag = '';
+ }
- array_push( $last_tag_history , $last_tag );
-
- # A cell could contain both parameters and data... but the pipe could
- # also be the start of a nested table, or a raw pipe inside an invalid
- # link (bug 553).
- $cell_data = preg_split( '/(?<!\{)\|/', $cell, 2 );
-
- # Bug 553: a '|' inside an invalid link should not
- # be mistaken as delimiting cell parameters
- if ( strpos( $cell_data[0], '[[' ) !== false ) {
- $data = $cell;
- $cell = "{$previous}<{$last_tag}>";
- } elseif ( count( $cell_data ) == 1 ) {
- $cell = "{$previous}<{$last_tag}>";
- $data = $cell_data[0];
- } else {
- $attributes = $this->mStripState->unstripBoth( $cell_data[0] );
- $attributes = Sanitizer::fixTagAttributes( $attributes , $last_tag );
- $cell = "{$previous}<{$last_tag}{$attributes}>";
- $data = $cell_data[1];
- }
+ array_push( $last_tag_history , $last_tag );
- # Bug 529: the start of a table cell should be a linestart context for
- # processing other block markup, including nested tables. The original
- # implementation of this was to add a newline before every brace construct,
- # which broke all manner of other things. Instead, push the contents
- # of the cell back into the stream and come back to it later. But don't
- # do that if the first line is empty, or you may get extra whitespace
- if( $data ){
- array_unshift( $extraLines, trim( $data ) );
- }
+ # A cell could contain both parameters and data
+ $cell_data = explode( '|' , $cell , 2 );
+
+ # Bug 553: Note that a '|' inside an invalid link should not
+ # be mistaken as delimiting cell parameters
+ if ( strpos( $cell_data[0], '[[' ) !== false ) {
+ $cell = "{$previous}<{$last_tag}>{$cell}";
+ } elseif ( count( $cell_data ) == 1 ) {
+ $cell = "{$previous}<{$last_tag}>{$cell_data[0]}";
+ } else {
+ $attributes = $this->mStripState->unstripBoth( $cell_data[0] );
+ $attributes = Sanitizer::fixTagAttributes( $attributes , $last_tag );
+ $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}";
+ }
- $outLine .= $cell;
- array_push( $td_history , true );
+ $outLine .= $cell;
+ array_push( $td_history , true );
+ }
}
$out .= $outLine . "\n";
- } while( $lines->valid() || count( $extraLines ) );
+ }
# Closing open td, tr && table
while ( count( $td_history ) > 0 ) {
throw new MWException( __METHOD__.': unrecognised match type "' .
substr( $m[0], 0, 20 ) . '"' );
}
- $url = wfMsgForContent( $urlmsg, $id);
+ $url = wfMsgForContent( $urlmsg, $id );
$sk = $this->mOptions->getSkin( $this->mTitle );
- $la = $sk->getExternalLinkAttributes( "external $CssClass" );
- return "<a href=\"{$url}\"{$la}>{$keyword} {$id}</a>";
+ return $sk->makeExternalLink( $url, "{$keyword} {$id}", true, $CssClass );
} elseif ( isset( $m[5] ) && $m[5] !== '' ) {
# ISBN
$isbn = $m[5];
'/(?:<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
'<td|<th|<\\/?div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t );
if ( $openmatch or $closematch ) {
-
$paragraphStack = false;
# TODO bug 5718: paragraph closed
$output .= $this->closeParagraph();
$text = wfEscapeWikiText( $text );
} elseif ( is_string( $text )
&& !$piece['lineStart']
- && preg_match( '/^{\\|/', $text ) )
+ && preg_match( '/^(?:{\\||:|;|#|\*)/', $text ) )
{
- # Bug 529: if the template begins with a table, it should be treated as
- # beginning a new line. This previously handled other block-level elements
- # such as #, :, etc, but these have many false-positives (bug 12974).
+ # Bug 529: if the template begins with a table or block-level
+ # element, it should be treated as beginning a new line.
+ # This behaviour is somewhat controversial.
$text = "\n" . $text;
}
if ( !$title->equals( $cacheTitle ) ) {
$this->mTplRedirCache[$cacheTitle->getPrefixedDBkey()] =
- array( $title->getNamespace(), $title->getDBkey() );
+ array( $title->getNamespace(), $cdb = $title->getDBkey() );
}
return array( $dom, $title );
// We use a page and section attribute to stop the language converter from converting these important bits
// of data, but put the headline hint inside a content block because the language converter is supposed to
// be able to convert that piece of data.
- $editlink = '<editsection page="' . htmlspecialchars($editlinkArgs[0]);
+ $editlink = '<mw:editsection page="' . htmlspecialchars($editlinkArgs[0]);
$editlink .= '" section="' . htmlspecialchars($editlinkArgs[1]) .'"';
if ( isset($editlinkArgs[2]) ) {
- $editlink .= '>' . $editlinkArgs[2] . '</editsection>';
+ $editlink .= '>' . $editlinkArgs[2] . '</mw:editsection>';
} else {
$editlink .= '/>';
}
# Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags
$text = $this->replaceVariables( $text );
+ # This works almost by chance, as the replaceVariables are done before the getUserSig(),
+ # which may corrupt this parser instance via its wfMsgExt( parsemag ) call-
+
# Signatures
$sigText = $this->getUserSig( $user );
$text = strtr( $text, array(
* validated, ready-to-insert wikitext.
* If you have pre-fetched the nickname or the fancySig option, you can
* specify them here to save a database query.
+ * Do not reuse this parser instance after calling getUserSig(),
+ * as it may have changed if it's the $wgParser.
*
* @param $user User
* @param $nickname String: nickname to use or false to use user's default nickname
* Set up some variables which are usually set up in parse()
* so that an external function can call some class members with confidence
*/
- public function startExternalParse( Title $title, ParserOptions $options, $outputType, $clearState = true ) {
+ public function startExternalParse( Title $title = null, ParserOptions $options, $outputType, $clearState = true ) {
$this->setTitle( $title );
$this->mOptions = $options;
$this->setOutputType( $outputType );
$executing = true;
wfProfileIn( __METHOD__ );
- $text = $this->preprocess( $text, $wgTitle, $options );
+ $title = $wgTitle;
+ if ( !$title ) {
+ # It's not uncommon having a null $wgTitle in scripts. See r80898
+ # Create a ghost title in such case
+ $title = Title::newFromText( 'Dwimmerlaik' );
+ }
+ $text = $this->preprocess( $text, $title, $options );
$executing = false;
wfProfileOut( __METHOD__ );
/**
* Accessor for $mDefaultSort
- * Will use the title/prefixed title if none is set
+ * Will use the empty string if none is set.
+ *
+ * This value is treated as a prefix, so the
+ * empty string is equivalent to sorting by
+ * page name.
*
* @return string
*/
if ( $this->mDefaultSort !== false ) {
return $this->mDefaultSort;
} else {
- return $this->mTitle->getCategorySortkey();
+ return '';
}
}