== Upgrading ==
1.21 has several database changes since 1.20, and will not work without schema
-updates.
+updates. Note that due to changes to some very large tables like the revision
+table, the schema update may take quite long (minutes on a medium sized site,
+many hours on a large site).
If upgrading from before 1.11, and you are using a wiki as a commons
repository, make sure that it is updated as well. Otherwise, errors may arise
* This function has side effects! Do not use this function if you
* only want the real revision text if any.
*
- * @deprecated in 1.21; use getContentObject() instead
+ * @deprecated in 1.21; use WikiPage::getContent() instead
*
* @return string Return the text of this revision
*/
* @return Content Return the content of this revision
*
* @since 1.21
- *
- * @todo: FIXME: this should really be protected, all callers should be changed to use WikiPage::getContent() instead.
*/
- public function getContentObject() {
- global $wgUser;
+ protected function getContentObject() {
wfProfileIn( __METHOD__ );
if ( $this->mPage->getID() === 0 ) {
$this->showCssOrJsPage();
$outputDone = true;
} elseif( !wfRunHooks( 'ArticleContentViewCustom',
- array( $this->fetchContentObject(), $this->getTitle(),
- $outputPage ) ) ) {
+ array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
# Allow extensions do their own custom view for certain pages
$outputDone = true;
} elseif( !ContentHandler::runLegacyHooks( 'ArticleViewCustom',
- array( $this->fetchContentObject(), $this->getTitle(),
- $outputPage ) ) ) {
+ array( $this->fetchContentObject(), $this->getTitle(), $outputPage ) ) ) {
# Allow extensions do their own custom view for certain pages
$outputDone = true;
# Viewing a redirect page (e.g. with parameter redirect=no)
$outputPage->addHTML( $this->viewRedirect( $rt ) );
# Parse just to get categories, displaytitle, etc.
- $this->mParserOutput = $content->getParserOutput( $this->getTitle(), $oldid,
- $parserOptions, false );
+ $this->mParserOutput = $content->getParserOutput( $this->getTitle(), $oldid, $parserOptions, false );
$outputPage->addParserOutputNoText( $this->mParserOutput );
$outputDone = true;
}
$rev = $this->getRevisionFetched();
if ( !$rev ) {
- $this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' )->text() );
+ $this->getContext()->getOutput()->setPageTitle( wfMessage( 'errorpagetitle' ) );
$this->getContext()->getOutput()->addWikiMsg( 'difference-missing-revision', $oldid, 1 );
return;
}
*
* This is hooked by SyntaxHighlight_GeSHi to do syntax highlighting of these
* page views.
+ *
+ * @param bool $showCacheHint whether to show a message telling the user to clear the browser cache (default: true).
*/
protected function showCssOrJsPage( $showCacheHint = true ) {
- global $wgOut;
-
if ( $showCacheHint ) {
$dir = $this->getContext()->getLanguage()->getDir();
$lang = $this->getContext()->getLanguage()->getCode();
- $wgOut->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
+ $outputPage = $this->getContext()->getOutput();
+ $outputPage->wrapWikiMsg( "<div id='mw-clearyourcache' lang='$lang' dir='$dir' class='mw-content-$dir'>\n$1\n</div>",
'clearyourcache' );
}
if ( !$reason ) {
try {
$reason = $this->generateReason( $hasHistory );
- } catch (MWException $e) {
+ } catch ( MWException $e ) {
# if a page is horribly broken, we still want to be able to delete it. so be lenient about errors here.
wfDebug("Error while building auto delete summary: $e");
$reason = '';
'ZipDirectoryReaderError' => 'includes/ZipDirectoryReader.php',
# content handler
- 'Content' => 'includes/content/Content.php',
'AbstractContent' => 'includes/content/AbstractContent.php',
'ContentHandler' => 'includes/content/ContentHandler.php',
- 'CssContent' => 'includes/content/CssContent.php',
- 'TextContentHandler' => 'includes/content/ContentHandler.php',
+ 'Content' => 'includes/content/Content.php',
'CssContentHandler' => 'includes/content/ContentHandler.php',
- 'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
+ 'CssContent' => 'includes/content/CssContent.php',
'JavaScriptContentHandler' => 'includes/content/ContentHandler.php',
+ 'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
'MessageContent' => 'includes/content/MessageContent.php',
+ 'TextContentHandler' => 'includes/content/ContentHandler.php',
'TextContent' => 'includes/content/TextContent.php',
- 'WikitextContent' => 'includes/content/WikitextContent.php',
'WikitextContentHandler' => 'includes/ContentHandler.php',
+ 'WikitextContent' => 'includes/content/WikitextContent.php',
# includes/actions
'CachedAction' => 'includes/actions/CachedAction.php',
'TestRecorder' => 'tests/testHelpers.inc',
# tests/phpunit
+ 'DummyContentHandlerForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
+ 'DummyContentForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
+ 'JavascriptContentTest' => 'tests/phpunit/includes/JavascriptContentTest.php',
'RevisionStorageTest' => 'tests/phpunit/includes/RevisionStorageTest.php',
'WikiPageTest' => 'tests/phpunit/includes/WikiPageTest.php',
'WikitextContentTest' => 'tests/phpunit/includes/WikitextContentTest.php',
- 'JavascriptContentTest' => 'tests/phpunit/includes/JavascriptContentTest.php',
- 'DummyContentHandlerForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
- 'DummyContentForTesting' => 'tests/phpunit/includes/ContentHandlerTest.php',
+
# tests/phpunit/includes
'GenericArrayObjectTest' => 'tests/phpunit/includes/libs/GenericArrayObjectTest.php',
/**
* Plugins for page content model handling.
- * Each entry in the array maps a model id to a class name
+ * Each entry in the array maps a model id to a class name.
+ *
+ * @since 1.21
*/
$wgContentHandlers = array(
CONTENT_MODEL_WIKITEXT => 'WikitextContentHandler', // the usual case
* Associative array mapping namespace IDs to the name of the content model pages in that namespace should have by
* default (use the CONTENT_MODEL_XXX constants). If no special content type is defined for a given namespace,
* pages in that namespace will use the CONTENT_MODEL_WIKITEXT (except for the special case of JS and CS pages).
+ *
+ * @since 1.21
*/
$wgNamespaceContentModels = array();
*
* * 'ignore': return null
* * 'fail': throw an MWException
- * * 'serializeContent': serializeContent to default format
+ * * 'serialize': serialize to default format
+ *
+ * @since 1.21
*/
$wgContentHandlerTextFallback = 'ignore';
/**
- * Compatibility switch for running ContentHandler code withoput a schema update.
* Set to false to disable use of the database fields introduced by the ContentHandler facility.
+ * This way, the ContentHandler facility can be used without any additional information in the database.
+ * A page's content model is then derived solely from the page's title. This however means that changing
+ * a page's default model (e.g. using $wgNamespaceContentModels) will break the page and/or make the content
+ * inaccessible. This also means that pages can not be moved to a title that would default to a different
+ * content model.
+ *
+ * Overall, with $wgContentHandlerUseDB = false, no database updates are needed, but content handling
+ * is less robust and less flexible.
*
- * @deprecated this is only here to allow code deployment without a database schema update on large sites.
- * get rid of it in the next version.
+ * @since 1.21
*/
$wgContentHandlerUseDB = true;
* These IDs will be exposed in the API and XML dumps.
*
* Extensions that define their own content model IDs should take
- * care to avoid conflicts. Using the extension name as a prefix is recommended.
+ * care to avoid conflicts. Using the extension name as a prefix is recommended,
+ * for example 'myextension-somecontent'.
*/
define( 'CONTENT_MODEL_WIKITEXT', 'wikitext' );
define( 'CONTENT_MODEL_JAVASCRIPT', 'javascript' );
*/
class DeprecatedGlobal extends StubObject {
- // The m's are to stay consistent with parent class.
+ // The m's are to stay consistent with parent class.
protected $mRealValue, $mVersion;
function __construct( $name, $realValue, $version = false ) {
var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false;
var $edittime = '', $section = '', $sectiontitle = '', $starttime = '';
var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true;
- var $content_model = null, $content_format = null;
+ var $contentModel = null, $contentFormat = null;
# Placeholders for text injection by hooks (must be HTML)
# extensions should take care to _append_ to the present value
$this->mArticle = $article;
$this->mTitle = $article->getTitle();
- $this->content_model = $this->mTitle->getContentModel();
+ $this->contentModel = $this->mTitle->getContentModel();
- $handler = ContentHandler::getForModelID( $this->content_model );
- $this->content_format = $handler->getDefaultFormat(); #NOTE: should be overridden by format of actual revision
+ $handler = ContentHandler::getForModelID( $this->contentModel );
+ $this->contentFormat = $handler->getDefaultFormat();
}
/**
wfProfileOut( __METHOD__ );
return;
}
-
- if ( !$this->mTitle->getArticleID() ) {
+ if ( !$this->mTitle->getArticleID() )
wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) );
- }
- else {
+ else
wfRunHooks( 'EditFormInitialText', array( $this ) );
- }
-
}
$this->showEditForm();
// modified by subclasses
wfProfileIn( get_class( $this ) . "::importContentFormData" );
$textbox1 = $this->importContentFormData( $request );
- if ( isset( $textbox1 ) ) {
+ if ( isset( $textbox1 ) )
$this->textbox1 = $textbox1;
- }
-
wfProfileOut( get_class( $this ) . "::importContentFormData" );
}
$this->nosummary = $request->getBool( 'nosummary' );
$content_handler = ContentHandler::getForTitle( $this->mTitle );
- $this->content_model = $request->getText( 'model', $content_handler->getModelID() ); #may be overridden by revision
- $this->content_format = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
+ $this->contentModel = $request->getText( 'model', $content_handler->getModelID() ); #may be overridden by revision
+ $this->contentFormat = $request->getText( 'format', $content_handler->getDefaultFormat() ); #may be overridden by revision
#TODO: check if the desired model is allowed in this namespace, and if a transition from the page's current model to the new model is allowed
#TODO: check if the desired content model supports the given content format!
* @return mixed string on success, $def_text for invalid sections
* @private
* @deprecated since 1.21
- * @todo: deprecated, replace usage everywhere
*/
function getContent( $def_text = false ) {
wfDeprecated( __METHOD__, '1.21' );
return $this->toEditText( $content );
}
- private function getContentObject( $def_content = null ) {
+ /**
+ * @param Content|false $def_content The default value to return
+ *
+ * @return mixed Content on success, $def_content for invalid sections
+ *
+ * @since 1.21
+ */
+ protected function getContentObject( $def_content = null ) {
global $wgOut, $wgRequest;
wfProfileIn( __METHOD__ );
}
$revision = $this->mArticle->getRevisionFetched();
if ( $revision === null ) {
- if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModel();
- $handler = ContentHandler::getForModelID( $this->content_model );
+ if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+ $handler = ContentHandler::getForModelID( $this->contentModel );
return $handler->makeEmptyContent();
}
* content object is returned instead of null.
*
* @since 1.21
- * @return string
+ * @return Content
*/
- private function getCurrentContent() {
+ protected function getCurrentContent() {
$rev = $this->mArticle->getRevision();
$content = $rev ? $rev->getContent( Revision::RAW ) : null;
if ( $content === false || $content === null ) {
- if ( !$this->content_model ) $this->content_model = $this->getTitle()->getContentModel();
- $handler = ContentHandler::getForModelID( $this->content_model );
+ if ( !$this->contentModel ) $this->contentModel = $this->getTitle()->getContentModel();
+ $handler = ContentHandler::getForModelID( $this->contentModel );
return $handler->makeEmptyContent();
} else {
# nasty side-effect, but needed for consistency
- $this->content_model = $rev->getContentModel();
- $this->content_format = $rev->getContentFormat();
+ $this->contentModel = $rev->getContentModel();
+ $this->contentFormat = $rev->getContentFormat();
return $content;
}
*
* @deprecated since 1.21, use getPreloadedContent() instead
*/
- protected function getPreloadedText( $preload ) { #NOTE: B/C only, replace usage!
+ protected function getPreloadedText( $preload ) {
wfDeprecated( __METHOD__, "1.21" );
$content = $this->getPreloadedContent( $preload );
*
* @since 1.21
*/
- protected function getPreloadedContent( $preload ) { #@todo: use this!
+ protected function getPreloadedContent( $preload ) {
global $wgUser;
if ( !empty( $this->mPreloadContent ) ) {
$title = Title::newFromText( $preload );
# Check for existence to avoid getting MediaWiki:Noarticletext
- if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+ if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
return $handler->makeEmptyContent();
}
if ( $page->isRedirect() ) {
$title = $page->getRedirectTarget();
# Same as before
- if ( $title === null || !$title->exists() || !$title->userCan( 'read', $wgUser ) ) {
+ if ( $title === null || !$title->exists() || !$title->userCan( 'read' ) ) {
return $handler->makeEmptyContent();
}
$page = WikiPage::factory( $title );
# Construct Content object
$textbox_content = $this->toEditContent( $this->textbox1 );
} catch (MWContentSerializationException $ex) {
- $status->fatal( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+ $status->fatal( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
$status->value = self::AS_PARSE_ERROR;
wfProfileOut( __METHOD__ );
return $status;
if ( $new ) {
// Late check for create permission, just in case *PARANOIA*
- if ( !$this->mTitle->userCan( 'create', $wgUser ) ) {
+ if ( !$this->mTitle->userCan( 'create' ) ) {
$status->fatal( 'nocreatetext' );
$status->value = self::AS_NO_CREATE_PERMISSION;
wfDebug( __METHOD__ . ": no create permission\n" );
// passed.
if ( $this->summary === '' ) {
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
- $this->summary = wfMessage( 'newsectionsummary' )
- ->rawParams( $cleanSectionTitle )->inContentLanguage()->text() ;
+ $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
+ ->inContentLanguage()->text() ;
}
} elseif ( $this->summary !== '' ) {
// Insert the section title above the content.
// Create a link to the new section from the edit summary.
$cleanSummary = $wgParser->stripSectionName( $this->summary );
- $this->summary = wfMessage( 'newsectionsummary' )
- ->rawParams( $cleanSummary )->inContentLanguage()->text();
+ $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
+ ->inContentLanguage()->text();
}
}
$this->isConflict = false;
wfDebug( __METHOD__ . ": conflict suppressed; new section\n" );
}
- } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER, $this->mTitle->getArticleID(), $wgUser->getId(), $this->edittime ) ) {
+ } elseif ( $this->section == '' && Revision::userWasLastToEdit( DB_MASTER, $this->mTitle->getArticleID(),
+ $wgUser->getId(), $this->edittime ) ) {
# Suppress edit conflict with self, except for section edits where merging is required.
wfDebug( __METHOD__ . ": Suppressing edit conflict, same user.\n" );
$this->isConflict = false;
wfDebug( __METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
. " (article time '{$timestamp}')\n" );
- $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content,
- $sectionTitle, $this->edittime );
+ $content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle, $this->edittime );
} else {
wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
$content = $this->mArticle->replaceSectionContent( $this->section, $textbox_content, $sectionTitle );
// passed.
if ( $this->summary === '' ) {
$cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle );
- $this->summary = wfMessage( 'newsectionsummary' )
- ->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
+ $this->summary = wfMessage( 'newsectionsummary', $cleanSectionTitle )
+ ->inContentLanguage()->text();
}
} elseif ( $this->summary !== '' ) {
$sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
# This is a new section, so create a link to the new section
# in the revision summary.
$cleanSummary = $wgParser->stripSectionName( $this->summary );
- $this->summary = wfMessage( 'newsectionsummary' )
- ->rawParams( $cleanSummary )->inContentLanguage()->text();
+ $this->summary = wfMessage( 'newsectionsummary', $cleanSummary )
+ ->inContentLanguage()->text();
}
} elseif ( $this->section != '' ) {
# Try to get a section anchor from the section source, redirect to edited section if header found
( $bot ? EDIT_FORCE_BOT : 0 );
$doEditStatus = $this->mArticle->doEditContent( $content, $this->summary, $flags,
- false, null, $this->content_format );
+ false, null, $this->contentFormat );
if ( $doEditStatus->isOK() ) {
- $result['redirect'] = $content->isRedirect();
- $this->updateWatchlist();
+ $result['redirect'] = $content->isRedirect();
+ $this->commitWatch();
wfProfileOut( __METHOD__ );
return $status;
} else {
}
/**
- * Register the change of watch status
+ * Commit the change of watch status
*/
- protected function updateWatchlist() {
+ protected function commitWatch() {
global $wgUser;
-
if ( $wgUser->isLoggedIn() && $this->watchthis != $wgUser->isWatched( $this->mTitle ) ) {
- $fname = __METHOD__;
- $title = $this->mTitle;
- $watch = $this->watchthis;
-
- // Do this in its own transaction to reduce contention...
$dbw = wfGetDB( DB_MASTER );
- $dbw->onTransactionIdle( function() use ( $dbw, $title, $watch, $wgUser, $fname ) {
- $dbw->begin( $fname );
- if ( $watch ) {
- WatchAction::doWatch( $title, $wgUser );
- } else {
- WatchAction::doUnwatch( $title, $wgUser );
- }
- $dbw->commit( $fname );
- } );
+ $dbw->begin( __METHOD__ );
+ if ( $this->watchthis ) {
+ WatchAction::doWatch( $this->mTitle, $wgUser );
+ } else {
+ WatchAction::doUnwatch( $this->mTitle, $wgUser );
+ }
+ $dbw->commit( __METHOD__ );
}
}
* @parma $editText string
*
* @return bool
- * @since since 1.21
+ * @since since 1.WD
*/
private function mergeChangesIntoContent( &$editContent ){
wfProfileIn( __METHOD__ );
$wgOut->addModules( 'mediawiki.action.edit' );
if ( $wgUser->getOption( 'uselivepreview', false ) ) {
- $wgOut->addModules( 'mediawiki.action.edit.preview' );
+ $wgOut->addModules( 'mediawiki.legacy.preview' );
}
// Bug #19334: textarea jumps when editing articles in IE8
$wgOut->addStyle( 'common/IE80Fixes.css', 'screen', 'IE 8' );
. ContentHandler::getLocalizedName( $content->getModel() ) );
}
- return $content->serialize( $this->content_format );
+ return $content->serialize( $this->contentFormat );
}
/**
*/
protected function toEditContent( $text ) {
$content = ContentHandler::makeContent( $text, $this->getTitle(),
- $this->content_model, $this->content_format );
+ $this->contentModel, $this->contentFormat );
if ( !$this->allowNonTextContent && !( $content instanceof TextContent ) ) {
throw new MWException( "This content model can not be edited as text: "
$wgOut->addHTML( Html::hidden( 'oldid', $this->oldid ) );
- $wgOut->addHTML( Html::hidden( 'format', $this->content_format ) );
- $wgOut->addHTML( Html::hidden( 'model', $this->content_model ) );
+ $wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
+ $wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
if ( $this->section == 'new' ) {
$this->showSummaryInput( true, $this->summary );
$this->showConflict();
} catch ( MWContentSerializationException $ex ) {
// this can't really happen, but be nice if it does.
- $msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+ $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
$wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
}
}
if ( $revision ) {
// Let sysop know that this will make private content public if saved
- if ( !$revision->userCan( Revision::DELETED_TEXT, $wgUser ) ) {
+ if ( !$revision->userCan( Revision::DELETED_TEXT ) ) {
$wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
} elseif ( $revision->isDeleted( Revision::DELETED_TEXT ) ) {
$wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
$wgOut->wrapWikiMsg( "<div class='error' id='mw-userinvalidcssjstitle'>\n$1\n</div>", array( 'userinvalidcssjstitle', $this->mTitle->getSkinFromCssJsSubpage() ) );
}
if ( $this->formtype !== 'preview' ) {
- if ( $this->isCssSubpage ) {
+ if ( $this->isCssSubpage )
$wgOut->wrapWikiMsg( "<div id='mw-usercssyoucanpreview'>\n$1\n</div>", array( 'usercssyoucanpreview' ) );
- }
-
- if ( $this->isJsSubpage ) {
+ if ( $this->isJsSubpage )
$wgOut->wrapWikiMsg( "<div id='mw-userjsyoucanpreview'>\n$1\n</div>", array( 'userjsyoucanpreview' ) );
- }
}
}
}
* @return String
*/
protected function getSummaryPreview( $isSubjectPreview, $summary = "" ) {
- if ( !$summary || ( !$this->preview && !$this->diff ) ) {
+ if ( !$summary || ( !$this->preview && !$this->diff ) )
return "";
- }
global $wgParser;
- if ( $isSubjectPreview ) {
+ if ( $isSubjectPreview )
$summary = wfMessage( 'newsectionsummary', $wgParser->stripSectionName( $summary ) )
->inContentLanguage()->text();
- }
$message = $isSubjectPreview ? 'subject-preview' : 'summary-preview';
HTML
);
- if ( !$this->checkUnicodeCompliantBrowser() ) {
+ if ( !$this->checkUnicodeCompliantBrowser() )
$wgOut->addHTML( Html::hidden( 'safemode', '1' ) );
- }
}
protected function showFormAfterText() {
protected function displayPreviewArea( $previewOutput, $isOnTop = false ) {
global $wgOut;
$classes = array();
- if ( $isOnTop ) {
+ if ( $isOnTop )
$classes[] = 'ontop';
- }
$attribs = array( 'id' => 'wikiPreview', 'class' => implode( ' ', $classes ) );
- if ( $this->formtype != 'preview' ) {
+ if ( $this->formtype != 'preview' )
$attribs['style'] = 'display: none;';
- }
$wgOut->addHTML( Xml::openElement( 'div', $attribs ) );
try {
$this->showDiff();
} catch ( MWContentSerializationException $ex ) {
- $msg = wfMessage( 'content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+ $msg = wfMessage( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
$wgOut->addWikiText( '<div class="error">' . $msg->text() . '</div>');
}
}
$textboxContent = $this->toEditContent( $this->textbox1 );
$newContent = $this->mArticle->replaceSectionContent(
- $this->section, $textboxContent,
- $this->summary, $this->edittime );
+ $this->section, $textboxContent,
+ $this->summary, $this->edittime );
ContentHandler::runLegacyHooks( 'EditPageGetDiffText', array( $this, &$newContent ) );
wfRunHooks( 'EditPageGetDiffContent', array( $this, &$newContent ) );
$content1 = $this->toEditContent( $this->textbox1 );
$content2 = $this->toEditContent( $this->textbox2 );
- $handler = ContentHandler::getForModelID( $this->content_model );
+ $handler = ContentHandler::getForModelID( $this->contentModel );
$de = $handler->createDifferenceEngine( $this->mArticle->getContext() );
$de->setContent( $content2, $content1 );
- $de->showDiff(
+ $de->showDiff(
wfMessage( 'yourtext' )->parse(),
wfMessage( 'storedversion' )->text()
);
);
// Quick paranoid permission checks...
if ( is_object( $data ) ) {
- if ( $data->log_deleted & LogPage::DELETED_USER ) {
+ if ( $data->log_deleted & LogPage::DELETED_USER )
$data->user_name = wfMessage( 'rev-deleted-user' )->escaped();
- }
-
- if ( $data->log_deleted & LogPage::DELETED_COMMENT ) {
+ if ( $data->log_deleted & LogPage::DELETED_COMMENT )
$data->log_comment = wfMessage( 'rev-deleted-comment' )->escaped();
- }
}
return $data;
}
$parserOptions = $this->mArticle->makeParserOptions( $this->mArticle->getContext() );
$parserOptions->setEditSection( false );
- $parserOptions->setTidy( true );
$parserOptions->setIsPreview( true );
$parserOptions->setIsSectionPreview( !is_null($this->section) && $this->section !== '' );
# If we're adding a comment, we need to show the
# summary as the headline
- if ( $this->section == "new" && $this->summary != "" ) {
+ if ( $this->section === "new" && $this->summary !== "" ) {
$content = $content->addSectionHeader( $this->summary );
}
$note .= "\n\n" . implode( "\n\n", $parserOutput->getWarnings() );
}
}
- } catch (MWContentSerializationException $ex) {
- $m = wfMessage('content-failed-to-parse', $this->content_model, $this->content_format, $ex->getMessage() );
+ } catch ( MWContentSerializationException $ex ) {
+ $m = wfMessage('content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage() );
$note .= "\n\n" . $m->parse();
$previewHTML = '';
}
$cgi = '';
foreach ( $array1 as $key => $value ) {
- if ( $value !== false ) {
+ if ( !is_null($value) && $value !== false ) {
if ( $cgi != '' ) {
$cgi .= '&';
}
} else {
if ( is_object( $value ) ) {
$value = $value->__toString();
- } elseif( !is_null( $value ) ) {
- $cgi .= urlencode( $key ) . '=' . urlencode( $value );
- } else {
- $cgi .= urlencode( $key );
}
+ $cgi .= urlencode( $key ) . '=' . urlencode( $value );
}
}
}
continue;
}
if ( strpos( $bit, '=' ) === false ) {
- // Pieces like &qwerty become 'qwerty' => null
- $key = urldecode( $bit );
- $value = null;
+ // Pieces like &qwerty become 'qwerty' => '' (at least this is what php does)
+ $key = $bit;
+ $value = '';
} else {
list( $key, $value ) = explode( '=', $bit );
- $key = urldecode( $key );
- $value = urldecode( $value );
}
-
+ $key = urldecode( $key );
+ $value = urldecode( $value );
if ( strpos( $key, '[' ) !== false ) {
$keys = array_reverse( explode( '[', $key ) );
$key = array_pop( $keys );
* Append a query string to an existing URL, which may or may not already
* have query string parameters already. If so, they will be combined.
*
- * @deprecated in 1.20. Use Uri class.
* @param $url String
* @param $query Mixed: string or associative array
* @return string
*/
function wfAppendQuery( $url, $query ) {
- $obj = new Uri( $url );
- $obj->extendQuery( $query );
- return $obj->toString();
+ if ( is_array( $query ) ) {
+ $query = wfArrayToCgi( $query );
+ }
+ if( $query != '' ) {
+ if( false === strpos( $url, '?' ) ) {
+ $url .= '?';
+ } else {
+ $url .= '&';
+ }
+ $url .= $query;
+ }
+ return $url;
}
/**
* @todo Need to integrate this into wfExpandUrl (bug 32168)
*
* @since 1.19
- * @deprecated
* @param $urlParts Array URL parts, as output from wfParseUrl
* @return string URL assembled from its component parts
*/
function wfAssembleUrl( $urlParts ) {
- $obj = new Uri( $urlParts );
- return $obj->toString();
+ $result = '';
+
+ if ( isset( $urlParts['delimiter'] ) ) {
+ if ( isset( $urlParts['scheme'] ) ) {
+ $result .= $urlParts['scheme'];
+ }
+
+ $result .= $urlParts['delimiter'];
+ }
+
+ if ( isset( $urlParts['host'] ) ) {
+ if ( isset( $urlParts['user'] ) ) {
+ $result .= $urlParts['user'];
+ if ( isset( $urlParts['pass'] ) ) {
+ $result .= ':' . $urlParts['pass'];
+ }
+ $result .= '@';
+ }
+
+ $result .= $urlParts['host'];
+
+ if ( isset( $urlParts['port'] ) ) {
+ $result .= ':' . $urlParts['port'];
+ }
+ }
+
+ if ( isset( $urlParts['path'] ) ) {
+ $result .= $urlParts['path'];
+ }
+
+ if ( isset( $urlParts['query'] ) ) {
+ $result .= '?' . $urlParts['query'];
+ }
+
+ if ( isset( $urlParts['fragment'] ) ) {
+ $result .= '#' . $urlParts['fragment'];
+ }
+
+ return $result;
}
/**
* 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly
* 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2))
*
- * @deprecated
* @param $url String: a URL to parse
* @return Array: bits of the URL in an associative array, per PHP docs
*/
} else {
$d = date_create( "now", $logDBErrorTimeZoneObject );
}
- $date = $d->format( 'D M j G:i:s T Y' );
$date = $d->format( 'D M j G:i:s T Y' );
/**
* Get a timestamp string in one of various formats
*
- * @deprecated
* @param $outputtype Mixed: A timestamp in one of the supported formats, the
* function will autodetect which format is supplied and act
* accordingly.
$this->mPage = $page;
- if ( !$page->getId() ) {
+ if ( !$page->exists() ) {
throw new MWException( "Page ID not known, perhaps the page doesn't exist?" );
}
}
$this->sendCacheControl();
- wfRunHooks( 'AfterFinalPageOutput', array( &$this ) );
-
ob_end_flush();
wfProfileOut( __METHOD__ );
'deleted' => $row->ar_deleted,
'len' => $row->ar_len,
'sha1' => isset( $row->ar_sha1 ) ? $row->ar_sha1 : null,
- 'content_model' => isset( $row->ar_content_model ) ? $row->ar_content_model : null,
+ 'content_model' => isset( $row->ar_content_model ) ? $row->ar_content_model : null,
'content_format' => isset( $row->ar_content_format ) ? $row->ar_content_format : null,
);
$this->mParentId = isset( $row['parent_id'] ) ? intval( $row['parent_id'] ) : null;
$this->mSha1 = isset( $row['sha1'] ) ? strval( $row['sha1'] ) : null;
- $this->mContentModel = isset( $row['content_model'] ) ? strval( $row['content_model'] ) : null;
- $this->mContentFormat = isset( $row['content_format'] ) ? strval( $row['content_format'] ) : null;
+ $this->mContentModel = isset( $row['content_model'] ) ? strval( $row['content_model'] ) : null;
+ $this->mContentFormat = isset( $row['content_format'] ) ? strval( $row['content_format'] ) : null;
// Enforce spacing trimming on supplied text
$this->mComment = isset( $row['comment'] ) ? trim( strval( $row['comment'] ) ) : null;
// if we have a Content object, override mText and mContentModel
if ( !empty( $row['content'] ) ) {
+ if ( !( $row['content'] instanceof Content ) ) {
+ throw new MWException( '`content` field must contain a Content object.' );
+ }
+
$handler = $this->getContentHandler();
$this->mContent = $row['content'];
*
* @since 1.20
*
- * @return string Formatted timestamp
+ * @return Message Formatted timestamp
*/
public function getHumanTimestamp() {
$then = $this->getTimestamp( TS_UNIX );
/**
* Convenience method for checking a title's content model name
*
- * @param int $id
+ * @param String $id The content model ID (use the CONTENT_MODEL_XXX constants).
* @return Boolean true if $this->getContentModel() == $id
*/
public function hasContentModel( $id ) {
+++ /dev/null
-<?php
-/**
- * Class for simple URI parsing and manipulation.
- * Intended to simplify things that were using wfParseUrl and
- * had to do manual concatenation for various needs.
- * Built to match our JS mw.Uri in naming patterns.
- * @file
- * @author Daniel Friesen
- * @since 1.20
- */
-
-class Uri {
-
- /**
- * The parsed components of the URI
- */
- protected $components;
-
- protected static $validComponents = array( 'scheme', 'delimiter', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment' );
- protected static $componentAliases = array( 'protocol' => 'scheme', 'password' => 'pass' );
-
- /**
- * parse_url() work-alike, but non-broken. Differences:
- *
- * 1) Does not raise warnings on bad URLs (just returns false)
- * 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly
- * 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2))
- *
- * @param $url String: a URL to parse
- * @return Array: bits of the URL in an associative array, per PHP docs
- */
- protected static function parseUri( $url ) {
- global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
-
- // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest
- // way to handle them is to just prepend 'http:' and strip the protocol out later
- $wasRelative = substr( $url, 0, 2 ) == '//';
- if ( $wasRelative ) {
- $url = "http:$url";
- }
- wfSuppressWarnings();
- $bits = parse_url( $url );
- wfRestoreWarnings();
- // parse_url() returns an array without scheme for some invalid URLs, e.g.
- // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
- if ( !$bits ||
- !isset( $bits['scheme'] ) && strpos( $url, "://" ) !== false ) {
- wfDebug( __METHOD__ . ": Invalid URL: $url" );
- return false;
- } else {
- $scheme = isset( $bits['scheme'] ) ? $bits['scheme'] : null;
- }
-
- // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
- if ( in_array( $scheme . '://', $wgUrlProtocols ) ) {
- $bits['delimiter'] = '://';
- } elseif ( !is_null( $scheme ) && !in_array( $scheme . ':', $wgUrlProtocols ) ) {
- wfDebug( __METHOD__ . ": Invalid scheme in URL: $scheme" );
- return false;
- } elseif( !is_null( $scheme ) ) {
- if( !in_array( $scheme . ':', $wgUrlProtocols ) ) {
- // For URLs that don't have a scheme, but do have a user:password, parse_url
- // detects the user as the scheme.
- unset( $bits['scheme'] );
- $bits['user'] = $scheme;
- } else {
- $bits['delimiter'] = ':';
- // parse_url detects for news: and mailto: the host part of an url as path
- // We have to correct this wrong detection
- if ( isset( $bits['path'] ) ) {
- $bits['host'] = $bits['path'];
- $bits['path'] = '';
- }
- }
- }
-
- /* Provide an empty host for eg. file:/// urls (see bug 28627) */
- if ( !isset( $bits['host'] ) && $scheme == "file" ) {
- $bits['host'] = '';
-
- /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
- if ( isset( $bits['path'] ) && substr( $bits['path'], 0, 1 ) !== '/' ) {
- $bits['path'] = '/' . $bits['path'];
- }
- }
-
- // If the URL was protocol-relative, fix scheme and delimiter
- if ( $wasRelative ) {
- $bits['scheme'] = '';
- $bits['delimiter'] = '//';
- }
- return $bits;
- }
-
- /**
- *
- * @param $uri mixed URI string or array
- */
- public function __construct( $uri ) {
- $this->components = array();
- $this->setUri( $uri );
- }
-
- /**
- * Set the Uri to the value of some other URI.
- *
- * @param $uri mixed URI string or array
- */
- public function setUri( $uri ) {
- if ( is_string( $uri ) ) {
- $parsed = self::parseUri( $uri );
- if( $parsed === false ) {
- return false;
- }
- $this->setComponents( $parsed );
- } elseif ( is_array( $uri ) ) {
- $this->setComponents( $uri );
- } elseif ( $uri instanceof Uri ) {
- $this->setComponents( $uri->getComponents() );
- } else {
- throw new MWException( __METHOD__ . ': $uri is not of a valid type.' );
- }
- }
-
- /**
- * Set the components of this array.
- * Will output warnings when invalid components or aliases are found.
- *
- * @param $components Array The components to set on this Uri.
- */
- public function setComponents( array $components ) {
- foreach ( $components as $name => $value ) {
- if ( isset( self::$componentAliases[$name] ) ) {
- $canonical = self::$componentAliases[$name];
- wfDebug( __METHOD__ . ": Converting alias $name to canonical $canonical." );
- $components[$canonical] = $value;
- unset( $components[$name] );
- } elseif ( !in_array( $name, self::$validComponents ) ) {
- throw new MWException( __METHOD__ . ": $name is not a valid component." );
- }
- }
-
- $this->components = $components;
- }
-
- /**
- * Return the components for this Uri
- * @return Array
- */
- public function getComponents() {
- return $this->components;
- }
-
- /**
- * Return the value of a specific component
- *
- * @param $name string The name of the component to return
- * @param string|null
- */
- public function getComponent( $name ) {
- if ( isset( self::$componentAliases[$name] ) ) {
- // Component is an alias. Get the actual name.
- $alias = $name;
- $name = self::$componentAliases[$name];
- wfDebug( __METHOD__ . ": Converting alias $alias to canonical $name." );
- }
-
- if( !in_array( $name, self::$validComponents ) ) {
- // Component is invalid
- throw new MWException( __METHOD__ . ": $name is not a valid component." );
- } elseif( !empty( $this->components[$name] ) ) {
- // Component is valid and has a value.
- return $this->components[$name];
- } else {
- // Component is empty
- return null;
- }
- }
-
- /**
- * Set a component for this Uri
- * @param $name string The name of the component to set
- * @param $value string|null The value to set
- */
- public function setComponent( $name, $value ) {
- if ( isset( self::$componentAliases[$name] ) ) {
- $alias = $name;
- $name = self::$componentAliases[$name];
- wfDebug( __METHOD__ . ": Converting alias $alias to canonical $name." );
- } elseif ( !in_array( $name, self::$validComponents ) ) {
- throw new MWException( __METHOD__ . ": $name is not a valid component." );
- }
- $this->components[$name] = $value;
- }
-
- public function getProtocol() { return $this->getComponent( 'scheme' ); }
- public function getUser() { return $this->getComponent( 'user' ); }
- public function getPassword() { return $this->getComponent( 'pass' ); }
- public function getHost() { return $this->getComponent( 'host' ); }
- public function getPort() { return $this->getComponent( 'port' ); }
- public function getPath() { return $this->getComponent( 'path' ); }
- public function getQueryString() { return $this->getComponent( 'query' ); }
- public function getFragment() { return $this->getComponent( 'fragment' ); }
-
- public function setProtocol( $scheme ) { $this->setComponent( 'scheme', $scheme ); }
- public function setUser( $user ) { $this->setComponent( 'user', $user ); }
- public function setPassword( $pass ) { $this->setComponent( 'pass', $pass ); }
- public function setHost( $host ) { $this->setComponent( 'host', $host ); }
- public function setPort( $port ) { $this->setComponent( 'port', $port ); }
- public function setPath( $path ) { $this->setComponent( 'path', $path ); }
- public function setFragment( $fragment ) { $this->setComponent( 'fragment', $fragment ); }
-
- /**
- * Gets the protocol-authority delimiter of a URI (:// or //).
- * @return string|null
- */
- public function getDelimiter() {
- $delimiter = $this->getComponent( 'delimiter' );
- if ( $delimiter ) {
- // A specific delimiter is set, so return it.
- return $delimiter;
- }
- if ( $this->getAuthority() && $this->getProtocol() ) {
- // If the URI has a protocol and a body (i.e., some sort of host, etc.)
- // the default delimiter is "://", e.g., "http://test.com".
- return '://';
- }
- return null;
- }
-
- /**
- * Gets query portion of a URI in array format.
- * @return string
- */
- public function getQuery() {
- return wfCgiToArray( $this->getQueryString() );
- }
-
- /**
- * Gets query portion of a URI.
- * @param string|array $query
- */
- public function setQuery( $query ) {
- if ( is_array( $query ) ) {
- $query = wfArrayToCGI( $query );
- }
- $this->setComponent( 'query', $query );
- }
-
- /**
- * Extend the query -- supply query parameters to override or add to ours
- * @param Array|string $parameters query parameters to override or add
- * @return Uri this URI object
- */
- public function extendQuery( $parameters ) {
- if ( !is_array( $parameters ) ) {
- $parameters = wfCgiToArray( $parameters );
- }
-
- $query = $this->getQuery();
- foreach( $parameters as $key => $value ) {
- $query[$key] = $value;
- }
-
- $this->setQuery( $query );
- return $this;
- }
-
- /**
- * Returns user and password portion of a URI.
- * @return string
- */
- public function getUserInfo() {
- $user = $this->getComponent( 'user' );
- $pass = $this->getComponent( 'pass' );
- return $pass ? "$user:$pass" : $user;
- }
-
- /**
- * Gets host and port portion of a URI.
- * @return string
- */
- public function getHostPort() {
- $host = $this->getComponent( 'host' );
- $port = $this->getComponent( 'port' );
- return $port ? "$host:$port" : $host;
- }
-
- /**
- * Returns the userInfo and host and port portion of the URI.
- * In most real-world URLs, this is simply the hostname, but it is more general.
- * @return string
- */
- public function getAuthority() {
- $userinfo = $this->getUserInfo();
- $hostinfo = $this->getHostPort();
- return $userinfo ? "$userinfo@$hostinfo" : $hostinfo;
- }
-
- /**
- * Returns everything after the authority section of the URI
- * @return String
- */
- public function getRelativePath() {
- $path = $this->getComponent( 'path' );
- $query = $this->getComponent( 'query' );
- $fragment = $this->getComponent( 'fragment' );
-
- $retval = $path;
- if( $query ) {
- $retval .= "?$query";
- }
- if( $fragment ) {
- $retval .= "#$fragment";
- }
- return $retval;
- }
-
- /**
- * Gets the entire URI string. May not be precisely the same as input due to order of query arguments.
- * @return String the URI string
- */
- public function toString() {
- return $this->getComponent( 'scheme' ) . $this->getDelimiter() . $this->getAuthority() . $this->getRelativePath();
- }
-
- /**
- * Gets the entire URI string. May not be precisely the same as input due to order of query arguments.
- * @return String the URI string
- */
- public function __toString() {
- return $this->toString();
- }
-
-}
return $ret;
}
- /**
- * Get the content that needs to be saved in order to undo all revisions
- * between $undo and $undoafter. Revisions must belong to the same page,
- * must exist and must not be deleted
- * @param $undo Revision
- * @param $undoafter Revision Must be an earlier revision than $undo
- * @return mixed string on success, false on failure
- * @since 1.21
- * Before we had the Content object, this was done in getUndoText
- */
- public function getUndoContent( Revision $undo, Revision $undoafter = null ) {
- $handler = $undo->getContentHandler();
- return $handler->getUndoContent( $this->getRevision(), $undo, $undoafter );
- }
+ /**
+ * Get the content that needs to be saved in order to undo all revisions
+ * between $undo and $undoafter. Revisions must belong to the same page,
+ * must exist and must not be deleted
+ * @param $undo Revision
+ * @param $undoafter Revision Must be an earlier revision than $undo
+ * @return mixed string on success, false on failure
+ * @since 1.21
+ * Before we had the Content object, this was done in getUndoText
+ */
+ public function getUndoContent( Revision $undo, Revision $undoafter = null ) {
+ $handler = $undo->getContentHandler();
+ return $handler->getUndoContent( $this->getRevision(), $undo, $undoafter );
+ }
/**
* Get the text that needs to be saved in order to undo all revisions
parent::show();
}
-}
\ No newline at end of file
+}
$this->content = $page->getContent( Revision::RAW ); //XXX: really raw?
if ( $this->section !== false ) {
- $this->content = $this->getSectionContent( $this->content, !is_null( $pageId )
- ? 'page id ' . $pageId : $page->getTitle()->getText() );
+ $this->content = $this->getSectionContent(
+ $this->content,
+ !is_null( $pageId ) ? 'page id ' . $pageId : $page->getTitle()->getText() );
// Not cached (save or load)
return $this->content->getParserOutput( $page->getTitle(), $popts );
global $wgEnableParserCache;
$popts = $page->makeParserOptions( 'canonical' );
- $popts->setTidy( true );
# Parse content; note that HTML generation is only needed if we want to cache the result.
$content = $page->getContent( Revision::RAW );
return array_merge( parent::getPossibleErrors(), array(
array( 'nosuchrevid', 'diffto' ),
array( 'code' => 'revids', 'info' => 'The revids= parameter may not be used with the list options '
- . '(limit, startid, endid, dirNewer, start, end).' ),
+ . '(limit, startid, endid, dirNewer, start, end).' ),
array( 'code' => 'multpages', 'info' => 'titles, pageids or a generator was used to supply multiple pages, '
- . ' but the limit, startid, endid, dirNewer, user, excludeuser, '
- . 'start and end parameters may only be used on a single page.' ),
+ . ' but the limit, startid, endid, dirNewer, user, excludeuser, '
+ . 'start and end parameters may only be used on a single page.' ),
array( 'code' => 'diffto', 'info' => 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"' ),
array( 'code' => 'badparams', 'info' => 'start and startid cannot be used together' ),
array( 'code' => 'badparams', 'info' => 'end and endid cannot be used together' ),
wfDebugLog( 'MessageCache', __METHOD__ . ": failed to load message page text for {$title} ($code)" );
$message = null; // no negative caching
} else {
- #XXX: Is this the right way to turn a Content object into a message?
+ // XXX: Is this the right way to turn a Content object into a message?
+ // NOTE: $content is typically either WikitextContent, JavaScriptContent or CssContent.
+ // MessageContent is *not* used for storing messages, it's only used for wrapping them when needed.
$message = $content->getWikitextForTransclusion();
if ( $message === false || $message === null ) {
wfDebugLog( 'MessageCache', __METHOD__ . ": message content doesn't provide wikitext "
- . "(content model: #" . $content->getContentHandler() . ")" );
+ . "(content model: " . $content->getContentHandler() . ")" );
$message = false; // negative caching
} else {
*/
protected function checkFormat( $format ) {
if ( !$this->isSupportedFormat( $format ) ) {
- throw new MWException( "Format $format is not supported for content model " .
+ throw new MWException( "Format $format is not supported for content model " .
$this->getModel() );
}
}
* @see Content::isEmpty()
*/
public function isEmpty() {
- return $this->getSize() == 0;
+ return $this->getSize() === 0;
}
/**
* string, a nested array structure, an object, a binary blob...
* anything, really.
*
- * @NOTE: review all calls carefully, caller must be aware of content model!
+ * @NOTE: Caller must be aware of content model!
*/
public function getNativeData( );
*
* - Will return false if $that is null.
* - Will return true if $that === $this.
- * - Will return false if $that->getModelName() != $this->getModel().
+ * - Will return false if $that->getModel() != $this->getModel().
* - Will return false if $that->getNativeData() is not equal to $this->getNativeData(),
* where the meaning of "equal" depends on the actual data model.
*
* - $original->equals( $copy )
*
* If and only if the Content object is immutable, the copy() method can and
- * should return $this. That is, $copy === $original may be true, but only
+ * should return $this. That is, $copy === $original may be true, but only
* for immutable content objects.
*
* @since 1.21
* find out.
* @return boolean
*/
- public function isCountable( $hasLinks = null ) ;
+ public function isCountable( $hasLinks = null );
/**
*
* There is usually no need to override the default behaviour, subclasses that
* want to implement redirects should override getRedirectTarget().
- *
+ *
* @since 1.21
*
* @return Title
public function matchMagicWord( MagicWord $word );
# TODO: ImagePage and CategoryPage interfere with per-content action handlers
- # TODO: make sure WikiSearch extension still works
- # TODO: make sure ReplaceTemplates extension still works
# TODO: nice&sane integration of GeSHi syntax highlighting
- # [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
+ # [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
# config to set the class which handles syntax highlighting
# [12:00] <vvv> And default it to a DummyHighlighter
}
\ No newline at end of file
return false;
}
- if ( $wgArticleCountMethod === 'any' ) {
+ if ( $wgArticleCountMethod === 'any' ) {
return true;
}
$text = $this->getNativeData();
$sect = $wgParser->getSection( $text, $section, false );
- return new WikitextContent( $sect );
+ return new WikitextContent( $sect );
}
/**
function generateContentDiffBody( Content $old, Content $new ) {
if ( !( $old instanceof TextContent ) ) {
throw new MWException( "Diff not implemented for " . get_class( $old ) . "; "
- . "override generateContentDiffBody to fix this." );
+ . "override generateContentDiffBody to fix this." );
}
if ( !( $new instanceof TextContent ) ) {
);
$page->doEditContent( $content,
- '',
- EDIT_NEW,
- false,
- User::newFromName( 'MediaWiki default' ) );
+ '',
+ EDIT_NEW,
+ false,
+ User::newFromName( 'MediaWiki default' ) );
} catch (MWException $e) {
//using raw, because $wgShowExceptionDetails can not be set yet
$status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
array( 'dropField', 'category', 'cat_hidden', 'patch-cat_hidden.sql' ),
// 1.21
- array( 'addField', 'revision', 'rev_content_format', 'patch-revision-rev_content_format.sql' ),
- array( 'addField', 'revision', 'rev_content_model', 'patch-revision-rev_content_model.sql' ),
- array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
- array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
- array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
- array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
+ array( 'addField', 'revision', 'rev_content_format', 'patch-revision-rev_content_format.sql' ),
+ array( 'addField', 'revision', 'rev_content_model', 'patch-revision-rev_content_model.sql' ),
+ array( 'addField', 'archive', 'ar_content_format', 'patch-archive-ar_content_format.sql' ),
+ array( 'addField', 'archive', 'ar_content_model', 'patch-archive-ar_content_model.sql' ),
+ array( 'addField', 'page', 'page_content_model', 'patch-page-page_content_model.sql' ),
+
+ array( 'dropField', 'site_stats', 'ss_admins', 'patch-drop-ss_admins.sql' ),
array( 'dropField', 'recentchanges', 'rc_moved_to_title', 'patch-rc_moved.sql' ),
);
}
if ( !count( $wgCopyUploadsDomains ) ) {
return true;
}
- $uri = new Uri( $url );
- $parsedDomain = $uri->getHost();
- if ( $parsedDomain === null ) {
+ $parsedUrl = wfParseUrl( $url );
+ if ( !$parsedUrl ) {
return false;
}
$valid = false;
'spamprotectionmatch' => 'Truicear ár scagaire dramhála ag an téacs seo a leanas: $1',
'spambot_username' => 'MediaWiki turscar glanadh',
-# Info page
-'pageinfo-subjectpage' => 'Leathanach',
-
# Skin names
'skinname-standard' => 'Clasaiceach',
'skinname-nostalgia' => 'Sean-nós',
'moveddeleted-notice' => 'Shown on top of a deleted page in normal view modus ([http://translatewiki.net/wiki/Test example]).',
'edit-conflict' => "An 'Edit conflict' happens when more than one edit is being made to a page at the same time. This would usually be caused by separate individuals working on the same page. However, if the system is slow, several edits from one individual could back up and attempt to apply simultaneously - causing the conflict.",
'defaultmessagetext' => 'Caption above the default message text shown on the left-hand side of a diff displayed after clicking “Show changes” when creating a new page in the MediaWiki: namespace',
-'invalid-content-data' => 'Error message indicating that the page\'s content can not be saved because it is invalid. This may occurr for some non-text content types.',
+'content-failed-to-parse' => "Error message indicating that the page\'s content can not be saved because it is syntactically invalid. This may occurr for content types using serialization or a strict markup syntax.",
+'invalid-content-data' => 'Error message indicating that the page\'s content can not be saved because it is invalid. This may occurr for content types with internal consistency constraints.',
'content-not-allowed-here' => 'Error message indicating that the desired content model is not supported in given localtion.
* $1 is the human readable name of the content model
* $1 is the title of the page in question.',
}
$this->output( "Importing $page\n" );
- $uri = new Uri( $baseUrl );
- $uri->extendQuery( array(
+ $url = wfAppendQuery( $baseUrl, array(
'action' => 'raw',
'title' => "MediaWiki:{$page}" ) );
- $url = $uri->toString();
-
$text = Http::get( $url );
$wikiPage = WikiPage::factory( $title );
$pages = array();
do {
- $uri = new Uri( $baseUrl );
- $uri->extendQuery( $data );
- $url = $uri->toString();
+ $url = wfAppendQuery( $baseUrl, $data );
$strResult = Http::get( $url );
//$result = FormatJson::decode( $strResult ); // Still broken
$result = unserialize( $strResult );
'addsection-preload',
'addsection-editintro',
'defaultmessagetext',
+ 'content-failed-to-parse',
+ 'invalid-content-data',
+ 'content-not-allowed-here',
+ ),
+ 'contentmodel' => array(
+ 'content-model-wikitext',
+ 'content-model-text',
+ 'content-model-javascript',
+ 'content-model-css',
),
'parserwarnings' => array(
'expensive-parserfunction-warning',
foreach ( $this->restoreGlobals as $var ) {
$v = $GLOBALS[ $var ];
- if ( is_object( $v ) || is_array( $v ) ) {
+ if ( is_object( $v ) ) {
$v = clone $v;
}
- $this->savedGlobals[ $var ] = $v;
+ $this->savedGlobals[$var] = $v;
}
}
* @return String a string representing the content in a way useful for building a full text search index.
* If no useful representation exists, this method returns an empty string.
*/
- public function getTextForSearchIndex()
- {
+ public function getTextForSearchIndex() {
return '';
}
* @return String the wikitext to include when another page includes this content, or false if the content is not
* includable in a wikitext page.
*/
- public function getWikitextForTransclusion()
- {
+ public function getWikitextForTransclusion() {
return false;
}
* @param int $maxlength maximum length of the summary text
* @return String the summary text
*/
- public function getTextForSummary( $maxlength = 250 )
- {
+ public function getTextForSummary( $maxlength = 250 ) {
return '';
}
*
* @return int
*/
- public function getSize()
- {
+ public function getSize() {
return strlen( $this->data );
}
*
* @return Content. A copy of this object
*/
- public function copy()
- {
+ public function copy() {
return $this;
}
* to avoid redundant parsing to find out.
* @return boolean
*/
- public function isCountable( $hasLinks = null )
- {
+ public function isCountable( $hasLinks = null ) {
return false;
}
*
* @return ParserOutput
*/
- public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true )
- {
+ public function getParserOutput( Title $title, $revId = null, ParserOptions $options = NULL, $generateHtml = true ) {
return new ParserOutput( $this->getNativeData() );
}
}
array( array( 'foo' => 1 ), 'foo=1' ), // number test
array( array( 'foo' => true ), 'foo=1' ), // true test
array( array( 'foo' => false ), '' ), // false test
- array( array( 'foo' => null ), 'foo' ), // null test
+ array( array( 'foo' => null ), '' ), // null test
array( array( 'foo' => 'A&B=5+6@!"\'' ), 'foo=A%26B%3D5%2B6%40%21%22%27' ), // urlencoding test
array( array( 'foo' => 'bar', 'baz' => 'is', 'asdf' => 'qwerty' ), 'foo=bar&baz=is&asdf=qwerty' ), // multi-item test
array( array( 'foo' => array( 'bar' => 'baz' ) ), 'foo%5Bbar%5D=baz' ),
protected function assertLinksUpdate( Title $title, ParserOutput $parserOutput, $table, $fields, $condition, array $expectedRows ) {
$update = new LinksUpdate( $title, $parserOutput );
+ //NOTE: make sure LinksUpdate does not generate warnings when called inside a transaction.
$update->beginTransaction();
$update->doUpdate();
$update->commitTransaction();
* Test human readable timestamp format.
*/
function testHumanOutput() {
- global $wgLang;
-
- $wgLang = Language::factory( 'es' );
- $timestamp = new MWTimestamp( time() - 3600 );
- $this->assertEquals( "hace una hora", $timestamp->getHumanTimestamp()->toString() );
-
- $wgLang = Language::factory( 'en' );
$timestamp = new MWTimestamp( time() - 3600 );
- $this->assertEquals( "1 hour ago", $timestamp->getHumanTimestamp()->toString() );
+ $this->assertEquals( "1 hour ago", $timestamp->getHumanTimestamp()->inLanguage( 'en' )->text() );
}
/**
+++ /dev/null
-<?php
-
-class UriTest extends MediaWikiTestCase {
-
- function setUp() {
- AutoLoader::loadClass( 'Uri' );
- }
-
- function dataUris() {
- return array(
- array(
- 'http://example.com/',
- array(
- 'scheme' => 'http',
- 'delimiter' => '://',
- 'user' => null,
- 'pass' => null,
- 'host' => 'example.com',
- 'port' => null,
- 'path' => '/',
- 'query' => null,
- 'fragment' => null,
- ),
- ),
- array(
- '//mediawiki.org/wiki/Main_Page',
- array(
- 'scheme' => null,
- 'delimiter' => '//',
- 'user' => null,
- 'pass' => null,
- 'host' => 'mediawiki.org',
- 'port' => null,
- 'path' => '/wiki/Main_Page',
- 'query' => null,
- 'fragment' => null,
- ),
- ),
- array(
- 'http://user:pass@example.com/',
- array(
- 'scheme' => 'http',
- 'delimiter' => '://',
- 'user' => 'user',
- 'pass' => 'pass',
- 'host' => 'example.com',
- 'port' => null,
- 'path' => '/',
- 'query' => null,
- 'fragment' => null,
- ),
- ),
- array(
- '/?asdf=asdf',
- array(
- 'scheme' => null,
- 'delimiter' => null,
- 'user' => null,
- 'pass' => null,
- 'host' => null,
- 'port' => null,
- 'path' => '/',
- 'query' => 'asdf=asdf',
- 'fragment' => null,
- ),
- ),
- array(
- '?asdf=asdf#asdf',
- array(
- 'scheme' => null,
- 'delimiter' => null,
- 'user' => null,
- 'pass' => null,
- 'host' => null,
- 'port' => null,
- 'path' => null,
- 'query' => 'asdf=asdf',
- 'fragment' => 'asdf',
- ),
- )
- );
- }
-
- /**
- * Ensure that get* methods properly match the appropriate getComponent( key ) value
- * @dataProvider dataUris
- */
- function testGetters( $uri ) {
- $uri = new Uri( $uri );
- $getterMap = array(
- 'getProtocol' => 'scheme',
- 'getUser' => 'user',
- 'getPassword' => 'pass',
- 'getHost' => 'host',
- 'getPort' => 'port',
- 'getPath' => 'path',
- 'getQueryString' => 'query',
- 'getFragment' => 'fragment',
- );
- foreach ( $getterMap as $fn => $c ) {
- $this->assertSame( $uri->{$fn}(), $uri->getComponent( $c ), "\$uri->{$fn}(); matches \$uri->getComponent( '$c' );" );
- }
- }
-
- /**
- * Ensure that Uri has the proper components for our example uris
- * @dataProvider dataUris
- */
- function testComponents( $uri, $components ) {
- $uri = new Uri( $uri );
-
- $this->assertSame( $components['scheme'], $uri->getProtocol(), 'Correct scheme' );
- $this->assertSame( $components['delimiter'], $uri->getDelimiter(), 'Correct delimiter' );
- $this->assertSame( $components['user'], $uri->getUser(), 'Correct user' );
- $this->assertSame( $components['pass'], $uri->getPassword(), 'Correct pass' );
- $this->assertSame( $components['host'], $uri->getHost(), 'Correct host' );
- $this->assertSame( $components['port'], $uri->getPort(), 'Correct port' );
- $this->assertSame( $components['path'], $uri->getPath(), 'Correct path' );
- $this->assertSame( $components['query'], $uri->getQueryString(), 'Correct query' );
- $this->assertSame( $components['fragment'], $uri->getFragment(), 'Correct fragment' );
- }
-
- /**
- * Ensure that the aliases work for various components.
- */
- function testAliases() {
- $url = "//myuser@test.com";
- $uri = new Uri( $url );
-
- // Set the aliases.
- $uri->setComponent( 'protocol', 'https' );
- $uri->setComponent( 'password', 'mypass' );
-
- // Now try getting them.
- $this->assertSame( 'https', $uri->getComponent( 'protocol' ), 'Correct protocol (alias for scheme)' );
- $this->assertSame( 'mypass', $uri->getComponent( 'password' ), 'Correct password (alias for pass)' );
-
- // Finally check their actual names.
- $this->assertSame( 'https', $uri->getProtocol(), 'Alias for scheme works' );
- $this->assertSame( 'mypass', $uri->getPassword(), 'Alias for pass works' );
- }
-
- /**
- * Ensure that Uri's helper methods return the correct data
- */
- function testHelpers() {
- $uri = new Uri( 'http://a:b@example.com:8080/path?query=value' );
-
- $this->assertSame( 'a:b', $uri->getUserInfo(), 'Correct getUserInfo' );
- $this->assertSame( 'example.com:8080', $uri->getHostPort(), 'Correct getHostPort' );
- $this->assertSame( 'a:b@example.com:8080', $uri->getAuthority(), 'Correct getAuthority' );
- $this->assertSame( '/path?query=value', $uri->getRelativePath(), 'Correct getRelativePath' );
- $this->assertSame( 'http://a:b@example.com:8080/path?query=value', $uri->toString(), 'Correct toString' );
- }
-
- /**
- * Ensure that Uri's extend method properly overrides keys
- */
- function testExtend() {
- $uri = new Uri( 'http://example.org/?a=b&hello=world' );
- $uri->extendQuery( 'a=c&foo=bar' );
- $this->assertSame( 'a=c&hello=world&foo=bar', $uri->getQueryString() );
- }
-}
function __construct( $name = null, array $data = array(), $dataName = '' ) {
parent::__construct( $name, $data, $dataName );
- $this->tablesUsed = array_merge ( $this->tablesUsed,
- array( 'page',
- 'revision',
- 'text',
+ $this->tablesUsed = array_merge (
+ $this->tablesUsed,
+ array( 'page',
+ 'revision',
+ 'text',
- 'recentchanges',
- 'logging',
+ 'recentchanges',
+ 'logging',
- 'page_props',
- 'pagelinks',
- 'categorylinks',
- 'langlinks',
- 'externallinks',
- 'imagelinks',
- 'templatelinks',
- 'iwlinks' ) );
+ 'page_props',
+ 'pagelinks',
+ 'categorylinks',
+ 'langlinks',
+ 'externallinks',
+ 'imagelinks',
+ 'templatelinks',
+ 'iwlinks' ) );
}
public function setUp() {
$page = $this->newPage( $title );
$content = ContentHandler::makeContent( "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
- . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
- $title, CONTENT_MODEL_WIKITEXT );
+ . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
+ $title, CONTENT_MODEL_WIKITEXT );
$page->doEditContent( $content, "[[testing]] 1" );
}
/**
- * @todo Text case required database!
+ * @todo Text case requires database, should be done by a test class in the Database group
*/
/*
public function testGetAutoDeleteReason( Title $title, &$hasHistory ) {
*/
/**
- * @todo Text case required database!
+ * @todo Text case requires database, should be done by a test class in the Database group
*/
/*
public function testGetUndoContent( Revision $current, Revision $undo, Revision $undoafter = null ) {
// make updates accessible by class name
foreach ( $updates as $update ) {
$class = get_class( $update );
- $updates[ $class ] = $update;
+ $updates[$class] = $update;
}
foreach ( $expectedStuff as $class => $fieldValues ) {
$this->assertArrayHasKey( $class, $updates, "missing an update of type $class" );
- $update = $updates[ $class ];
+ $update = $updates[$class];
foreach ( $fieldValues as $field => $value ) {
$v = $update->$field; #if the field doesn't exist, just crash and burn
$content = $this->newContent( $text );
$t = $content->getRedirectTarget( );
- if ( is_null( $expected ) ) $this->assertNull( $t, "text should not have generated a redirect target: $text" );
- else $this->assertEquals( $expected, $t->getPrefixedText() );
+ if ( is_null( $expected ) ) {
+ $this->assertNull( $t, "text should not have generated a redirect target: $text" );
+ } else {
+ $this->assertEquals( $expected, $t->getPrefixedText() );
+ }
}
/**
/**
- * @todo: test needs database!
+ * @todo: test needs database! Should be done by a test class in the Database group.
*/
/*
public function getRedirectChain() {
*/
/**
- * @todo: test needs database!
+ * @todo: test needs database! Should be done by a test class in the Database group.
*/
/*
public function getUltimateRedirectTarget() {
parent::setup();
- $wgExtraNamespaces[ 12312 ] = 'Dummy';
- $wgExtraNamespaces[ 12313 ] = 'Dummy_talk';
+ $wgExtraNamespaces[12312] = 'Dummy';
+ $wgExtraNamespaces[12313] = 'Dummy_talk';
- $wgNamespaceContentModels[ 12312 ] = "testing";
- $wgContentHandlers[ "testing" ] = 'DummyContentHandlerForTesting';
+ $wgNamespaceContentModels[12312] = "testing";
+ $wgContentHandlers["testing"] = 'DummyContentHandlerForTesting';
MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
$wgContLang->resetNamespaces(); # reset namespace cache
public function teardown() {
global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang;
- unset( $wgExtraNamespaces[ 12312 ] );
- unset( $wgExtraNamespaces[ 12313 ] );
+ unset( $wgExtraNamespaces[12312] );
+ unset( $wgExtraNamespaces[12313] );
- unset( $wgNamespaceContentModels[ 12312 ] );
- unset( $wgContentHandlers[ "testing" ] );
+ unset( $wgNamespaceContentModels[12312] );
+ unset( $wgContentHandlers["testing"] );
MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache
$wgContLang->resetNamespaces(); # reset namespace cache
<?php
/**
- * @group medium
- * ^---- causes phpunit to use a higher timeout threshold
- *
* @group FileRepo
* @group FileBackend
* @group medium
timeoutForSmallTests="2"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
- strict="false"
- verbose="false">
+ strict="true"
+ verbose="true">
<testsuites>
<testsuite name="includes">
<directory>includes</directory>
}
# Just get the URI path (REDIRECT_URL/REQUEST_URI is either a full URL or a path)
if ( substr( $uriPath, 0, 1 ) !== '/' ) {
- $uri = new Uri( $uriPath );
- $uriPath = $uri->getPath();
- if ( $uriPath === null ) {
+ $bits = wfParseUrl( $uriPath );
+ if ( $bits && isset( $bits['path'] ) ) {
+ $uriPath = $bits['path'];
+ } else {
wfThumbError( 404, 'The source file for the specified thumbnail does not exist.' );
return;
}