From af08d4a2577550e411505a0da2af31204550d2c8 Mon Sep 17 00:00:00 2001 From: Vitaly _Vi Shukela Date: Sun, 10 Jun 2012 21:41:16 +0300 Subject: [PATCH] Make MediaWiki 1.20-gb7ed02 be able to fetch from alternative locations like HTTP Set $wgAlternativeSourceObtainerUri to some http://127.0.0.1:9876/ and when you open wiki/Qqq it downloads: http://127.0.0.1:9876/Qqq http://127.0.0.1:9876/Template:Whatever http://127.0.0.1:9876/Eee (for rendering link) instead of fetching content from database. Limitations: * No editing * No history * Still requires "stub" database * No images * Lots of calls to the backend (for each link, to render it red/blue) for rendering one page * Not tested enough * Not secure (especially if wgAlternativeSourceObtainerUri is filesystem dir) --- includes/AlternativeSourceObtainerBackend.php | 41 +++++++++++++++++++++ includes/Article.php | 11 ++++++ includes/AutoLoader.php | 1 + includes/DefaultSettings.php | 10 +++++ includes/EditPage.php | 49 +++++++++++++++++-------- includes/Title.php | 37 +++++++++++++++++++ includes/WikiPage.php | 45 +++++++++++++++++++++++ includes/parser/Parser.php | 6 +++ 8 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 includes/AlternativeSourceObtainerBackend.php diff --git a/includes/AlternativeSourceObtainerBackend.php b/includes/AlternativeSourceObtainerBackend.php new file mode 100644 index 0000000..2fe23b4 --- /dev/null +++ b/includes/AlternativeSourceObtainerBackend.php @@ -0,0 +1,41 @@ +getPage()->getTitle()->getSourceObtainedFromAlternativeBackend(); + if ($contentFromAltSource) { + wfDebug("Article fetchContent hack\n"); + + $this->mContent = $contentFromAltSource; + $this->mRevIdFetched = -1; + $this->mContentLoaded = true; + + return $this->mContent; + } + if ( $this->mContentLoaded ) { return $this->mContent; } diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 78ed450..23e1c2d 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -33,6 +33,7 @@ $wgAutoloadLocalClasses = array( 'AjaxDispatcher' => 'includes/AjaxDispatcher.php', 'AjaxResponse' => 'includes/AjaxResponse.php', 'AlphabeticPager' => 'includes/Pager.php', + 'AlternativeSourceObtainerBackend' => 'includes/AlternativeSourceObtainerBackend.php', 'Article' => 'includes/Article.php', 'AtomFeed' => 'includes/Feed.php', 'AuthPlugin' => 'includes/AuthPlugin.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 0a3d4ad..0d44b7c 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -5854,6 +5854,16 @@ $wgDBtestuser = ''; //db user that has permission to create and drop the test da $wgDBtestpassword = ''; /** + * URL for alternative source of page/template sources. + * Expected something like "http://127.0.0.1:7977/" or "/path/to/directory/" + * AlternativeSourceObtainerBackend appends url-encoded prefixed page title to it + * and calls PHP's file_get_contents. + * Note MediaWiki may use this more than 300 times for rendering one page, so it should be fast and/or cached. + */ +$wgAlternativeSourceObtainerUri = false; + + +/** * For really cool vim folding this needs to be at the end: * vim: foldmarker=@{,@} foldmethod=marker * @} diff --git a/includes/EditPage.php b/includes/EditPage.php index 9e337fd..96917fa 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -357,17 +357,28 @@ class EditPage { wfProfileIn( __METHOD__ . "-business-end" ); - $this->isConflict = false; - // css / js subpages of user pages get a special treatment - $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage(); - $this->isCssSubpage = $this->mTitle->isCssSubpage(); - $this->isJsSubpage = $this->mTitle->isJsSubpage(); - $this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage(); - $this->isNew = !$this->mTitle->exists() || $this->section == 'new'; - - # Show applicable editing introductions - if ( $this->formtype == 'initial' || $this->firsttime ) { - $this->showIntro(); + if ($this->getArticle()->getPage()->getTitle()->getSourceObtainedFromAlternativeBackend()) { + $this->isConflict = false; + // css / js subpages of user pages get a special treatment + $this->isCssJsSubpage = false; + $this->isCssSubpage = false; + $this->isJsSubpage = false; + $this->isWrongCaseCssJsPage = false; + $this->isNew = false; + + } else { + $this->isConflict = false; + // css / js subpages of user pages get a special treatment + $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage(); + $this->isCssSubpage = $this->mTitle->isCssSubpage(); + $this->isJsSubpage = $this->mTitle->isJsSubpage(); + $this->isWrongCaseCssJsPage = $this->isWrongCaseCssJsPage(); + $this->isNew = !$this->mTitle->exists() || $this->section == 'new'; + + # Show applicable editing introductions + if ( $this->formtype == 'initial' || $this->firsttime ) { + $this->showIntro(); + } } # Attempt submission here. This will check for edit conflicts, @@ -392,10 +403,14 @@ class EditPage { wfProfileOut( __METHOD__ ); return; } - if ( !$this->mTitle->getArticleID() ) - wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) ); - else - wfRunHooks( 'EditFormInitialText', array( $this ) ); + if ($this->getArticle()->getPage()->getTitle()->getSourceObtainedFromAlternativeBackend()) { + wfDebug("EditPage: getSourceObtainedFromAlternativeBackend hack\n"); + } else { + if ( !$this->mTitle->getArticleID() ) + wfRunHooks( 'EditFormPreloadText', array( &$this->textbox1, &$this->mTitle ) ); + else + wfRunHooks( 'EditFormInitialText', array( $this ) ); + } } $this->showEditForm(); @@ -886,6 +901,10 @@ class EditPage { if ( $this->section == 'new' ) { return $this->getCurrentText(); } + $altSource = $this->mArticle->getPage()->getTitle()->getSourceObtainedFromAlternativeBackend(); + if ($altSource) { + return $altSource; + } $revision = $this->mArticle->getRevisionFetched(); if ( $revision === null ) { return ''; diff --git a/includes/Title.php b/includes/Title.php index 481f480..a48f750 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -88,6 +88,13 @@ class Title { var $mHasSubpage; // /< Whether a page has any subpages // @} + /** + * @var string|false|"none"; + * false - uninitialized + * "none" - checked, but not found + * string other than "none" - use this source instead of querying the database + */ + protected $sourceObtainedFromAlternativeBackend = false; /** * Constructor @@ -4131,6 +4138,30 @@ class Title { && strpos( $this->getDBkey(), $title->getDBkey() . '/' ) === 0; } + /** + * @return string|false + * Check the alternative backend for presence of this page. + * Cache the answer in $this->sourceObtainedFromAlternativeBackend and return the source or false. + */ + public function getSourceObtainedFromAlternativeBackend () { + if (! $this->sourceObtainedFromAlternativeBackend ) { + $pn = $this->getPrefixedText(); + $str = AlternativeSourceObtainerBackend::obtainPageSource($pn); + + if ($str) { + $this->sourceObtainedFromAlternativeBackend = $str; + } else { + $this->sourceObtainedFromAlternativeBackend = "none"; + } + } + + if ($this->sourceObtainedFromAlternativeBackend == "none") { + return false; + } else { + return $this->sourceObtainedFromAlternativeBackend; + } + } + /** * Check if page exists. For historical reasons, this function simply * checks for the existence of the title in the page table, and will @@ -4141,6 +4172,9 @@ class Title { * @return Bool */ public function exists() { + if ($this->getSourceObtainedFromAlternativeBackend()) { + return true; + } return $this->getArticleID() != 0; } @@ -4161,6 +4195,9 @@ class Title { * @return Bool */ public function isAlwaysKnown() { + if ($this->getSourceObtainedFromAlternativeBackend()) { + return true; + } $isKnown = null; /** diff --git a/includes/WikiPage.php b/includes/WikiPage.php index b5f4c1d..14653b4 100644 --- a/includes/WikiPage.php +++ b/includes/WikiPage.php @@ -299,6 +299,7 @@ class WikiPage extends Page { return $row; } + /** * Fetch a page record matching the Title object's namespace and title * using a sanitized title string @@ -309,6 +310,33 @@ class WikiPage extends Page { * @return mixed Database result resource, or false on failure */ public function pageDataFromTitle( $dbr, $title, $options = array() ) { + + if ($this->getTitle()->getSourceObtainedFromAlternativeBackend()) { + wfDebug("WikiPage pageDataFromTitle hack\n"); + + $fakerow= new stdClass(); + + $arr = array( + 'page_id' => -1, + 'page_namespace' => $title->getNamespace(), + 'page_title' => $title->getDBkey(), + 'page_restrictions' => '', + 'page_counter' => 1, + 'page_is_redirect' => false, + 'page_is_new' => false, + 'page_random' => false, + 'page_touched' => false, + 'page_latest' => true, + 'page_len' => -1, + ); + + foreach ($arr as $k=> $v) { + $fakerow->{$k} = $v; + } + + return $fakerow; + } + return $this->pageData( $dbr, array( 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey() ), $options ); @@ -538,6 +566,23 @@ class WikiPage extends Page { * This isn't necessary for all uses, so it's only done if needed. */ protected function loadLastEdit() { + + if ( $this->getTitle()->getSourceObtainedFromAlternativeBackend() ) { + wfDebug("WikiPage loadLastEdit hack\n"); + $revision = new Revision( array( + 'page' => -1, + 'comment' => "fake revision", + 'minor_edit' => false, + 'text_id' => -1, + 'parent_id' => -1, + 'len' => -1, + 'sha1' => null, + ) ); + + $this->setLastEdit ($revision); + return; + } + if ( $this->mLastRevision !== null ) { return; // already loaded } diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index f881455..73e8a2e 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -3477,6 +3477,12 @@ class Parser { * @return Array ( string or false, Title ) */ function fetchTemplateAndTitle( $title ) { + $altSource = AlternativeSourceObtainerBackend::obtainPageSource($title); + if ($altSource) { + return array ($altSource, $title); + } + + $templateCb = $this->mOptions->getTemplateCallback(); # Defaults to Parser::statelessFetchTemplate() $stuff = call_user_func( $templateCb, $title, $this ); $text = $stuff['text']; -- 1.7.8.5