/** * @since 2.2 */ public function getEditInfo(Title $title) { $this->page = new \WikiPage($title); if (class_exists('WikitextContent')) { $content = $this->page->getRevision()->getContent(); $format = $content->getContentHandler()->getDefaultFormat(); return $this->page->prepareContentForEdit($content, null, null, $format); } return $this->page->prepareTextForEdit($this->page->getRevision()->getRawText(), null, null); }
/** * @param WikiPage $page * @param ParserOptions $parserOptions ParserOptions to use for the parse * @param int $revid ID of the revision being parsed. * @param bool $useParserCache Whether to use the parser cache. * operation. * @param Content|string $content Content to parse or null to load it; may * also be given as a wikitext string, for BC. */ public function __construct(WikiPage $page, ParserOptions $parserOptions, $revid, $useParserCache, $content = null) { if (is_string($content)) { // BC: old style call $modelId = $page->getRevision()->getContentModel(); $format = $page->getRevision()->getContentFormat(); $content = ContentHandler::makeContent($content, $page->getTitle(), $modelId, $format); } $this->page = $page; $this->revid = $revid; $this->cacheable = $useParserCache; $this->parserOptions = $parserOptions; $this->content = $content; $this->cacheKey = ParserCache::singleton()->getKey($page, $parserOptions); $keyPrefix = $this->cacheKey ?: wfMemcKey('articleview', 'missingcachekey'); parent::__construct('ArticleView', $keyPrefix . ':revid:' . $revid); }
static function onPageContentSave(WikiPage &$wikiPage, User &$user, Content &$content, &$summary, $isMinor, $isWatch, $section, &$flags, Status &$status) { // get the current tags from the page ///////////////////////////////////// $CurrentReferences; preg_match_all(self::GetLabelsRegex, $wikiPage->getText(), $matches); // build it as a "set" foreach (array_merge($matches[2], $matches[3]) as $toAdd) { if ($toAdd != '') { $CurrentReferences[$toAdd] = 1; } } // get the old tags from the database ///////////////////////////////////// $OldReferences; if (($rev = $wikiPage->getRevision()) != null && ($prevRev = $rev->getPrevious()) != null) { preg_match_all(self::GetLabelsRegex, $prevRev->getText(), $matches); // build it as a "set" foreach (array_merge($matches[2], $matches[3]) as $toAdd) { if ($toAdd != '') { $OldReferences[$toAdd] = 1; } } } // Resolve differences ////////////////////// $DB = wfGetDB(DB_MASTER); $DB->begin(); // start a transaction // start with the newOnes and make sure that the database is compatable, and remove them foreach (array_keys($CurrentReferences) as $RefToMakeSureExists) { if (isset($OldReferences[$RefToMakeSureExists])) { // if it is already in the array, then we don't have to worry about it; delete it unset($OldReferences[$RefToMakeSureExists]); } else { // if it doesn't exist, we need to add it try { $DB->insert(ContentReferencerTableName, array('reference_name' => $RefToMakeSureExists, 'reference_page_name' => (string) $wikiPage->getTitle())); } catch (Exception $e) { die($e->getMessage()); } } } // now, anything left in $OldReferences has been deleted. Let's remove it from the database foreach (array_keys($OldReferences) as $RefToDelete) { try { $DB->delete(ContentReferencerTableName, "reference_name='{$RefToDelete}'"); } catch (Exception $e) { die($e->getMessage()); } } $DB->commit(); // end the transaction }
/** * Get text content object * Does *NOT* follow redirects. * TODO: when is this null? * * @note code that wants to retrieve page content from the database should use WikiPage::getContent(). * * @return Content|null|boolean false * * @since 1.21 */ protected function fetchContentObject() { if ( $this->mContentLoaded ) { return $this->mContentObject; } wfProfileIn( __METHOD__ ); $this->mContentLoaded = true; $this->mContent = null; $oldid = $this->getOldID(); # Pre-fill content with error message so that if something # fails we'll have something telling us what we intended. //XXX: this isn't page content but a UI message. horrible. $this->mContentObject = new MessageContent( 'missing-revision', array( $oldid ), array() ); if ( $oldid ) { # $this->mRevision might already be fetched by getOldIDFromRequest() if ( !$this->mRevision ) { $this->mRevision = Revision::newFromId( $oldid ); if ( !$this->mRevision ) { wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" ); wfProfileOut( __METHOD__ ); return false; } } } else { if ( !$this->mPage->getLatest() ) { wfDebug( __METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n" ); wfProfileOut( __METHOD__ ); return false; } $this->mRevision = $this->mPage->getRevision(); if ( !$this->mRevision ) { wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n" ); wfProfileOut( __METHOD__ ); return false; } } // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks. // We should instead work with the Revision object when we need it... $this->mContentObject = $this->mRevision->getContent( Revision::FOR_THIS_USER, $this->getContext()->getUser() ); // Loads if user is allowed $this->mRevIdFetched = $this->mRevision->getId(); wfRunHooks( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) ); wfProfileOut( __METHOD__ ); return $this->mContentObject; }
/** * Get text of an article from database * Does *NOT* follow redirects. * * @return mixed string containing article contents, or false if null */ function fetchContent() { if ($this->mContentLoaded) { return $this->mContent; } wfProfileIn(__METHOD__); $this->mContentLoaded = true; $oldid = $this->getOldID(); # Pre-fill content with error message so that if something # fails we'll have something telling us what we intended. $t = $this->getTitle()->getPrefixedText(); $d = $oldid ? wfMsgExt('missingarticle-rev', array('escape'), $oldid) : ''; $this->mContent = wfMsgNoTrans('missing-article', $t, $d); if ($oldid) { # $this->mRevision might already be fetched by getOldIDFromRequest() if (!$this->mRevision) { $this->mRevision = Revision::newFromId($oldid); if (!$this->mRevision) { wfDebug(__METHOD__ . " failed to retrieve specified revision, id {$oldid}\n"); Wikia::log(__METHOD__, 1, "failed to retrieve specified revision, title '{$t}', id {$oldid}", true); # Wikia change - @author macbre wfProfileOut(__METHOD__); return false; } } } else { if (!$this->mPage->getLatest()) { wfDebug(__METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n"); wfProfileOut(__METHOD__); return false; } $this->mRevision = $this->mPage->getRevision(); if (!$this->mRevision) { wfDebug(__METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n"); Wikia::log(__METHOD__, 3, "failed to retrieve current page, title '{$t}', rev_id " . $this->mPage->getLatest(), true); # Wikia change - @author macbre wfProfileOut(__METHOD__); return false; } } // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks. // We should instead work with the Revision object when we need it... $this->mContent = $this->mRevision->getText(Revision::FOR_THIS_USER); // Loads if user is allowed $this->mRevIdFetched = $this->mRevision->getId(); wfRunHooks('ArticleAfterFetchContent', array(&$this, &$this->mContent)); wfProfileOut(__METHOD__); return $this->mContent; }
/** * Get text of an article from database * Does *NOT* follow redirects. * * @param $oldid Int: 0 for whatever the latest revision is * @return mixed string containing article contents, or false if null */ function fetchContent($oldid = 0) { if ($this->mContentLoaded) { return $this->mContent; } # Pre-fill content with error message so that if something # fails we'll have something telling us what we intended. $t = $this->getTitle()->getPrefixedText(); $d = $oldid ? wfMsgExt('missingarticle-rev', array('escape'), $oldid) : ''; $this->mContent = wfMsgNoTrans('missing-article', $t, $d); if ($oldid) { $revision = Revision::newFromId($oldid); if (!$revision) { wfDebug(__METHOD__ . " failed to retrieve specified revision, id {$oldid}\n"); return false; } // Revision title doesn't match the page title given? if ($this->mPage->getID() != $revision->getPage()) { $function = array(get_class($this->mPage), 'newFromID'); $this->mPage = call_user_func($function, $revision->getPage()); if (!$this->mPage->getId()) { wfDebug(__METHOD__ . " failed to get page data linked to revision id {$oldid}\n"); return false; } } } else { if (!$this->mPage->getLatest()) { wfDebug(__METHOD__ . " failed to find page data for title " . $this->getTitle()->getPrefixedText() . "\n"); return false; } $revision = $this->mPage->getRevision(); if (!$revision) { wfDebug(__METHOD__ . " failed to retrieve current page, rev_id " . $this->mPage->getLatest() . "\n"); return false; } } // @todo FIXME: Horrible, horrible! This content-loading interface just plain sucks. // We should instead work with the Revision object when we need it... $this->mContent = $revision->getText(Revision::FOR_THIS_USER); // Loads if user is allowed $this->mRevIdFetched = $revision->getId(); $this->mContentLoaded = true; $this->mRevision =& $revision; wfRunHooks('ArticleAfterFetchContent', array(&$this, &$this->mContent)); return $this->mContent; }
/** * @param ParserOutput $parserOutput * @param WikiPage $page * @param ParserOptions $popts * @param string $cacheTime Time when the cache was generated * @param int $revId Revision ID that was parsed */ public function save($parserOutput, $page, $popts, $cacheTime = null, $revId = null) { $expire = $parserOutput->getCacheExpiry(); if ($expire > 0) { $cacheTime = $cacheTime ?: wfTimestampNow(); if (!$revId) { $revision = $page->getRevision(); $revId = $revision ? $revision->getId() : null; } $optionsKey = new CacheTime(); $optionsKey->mUsedOptions = $parserOutput->getUsedOptions(); $optionsKey->updateCacheExpiry($expire); $optionsKey->setCacheTime($cacheTime); $parserOutput->setCacheTime($cacheTime); $optionsKey->setCacheRevisionId($revId); $parserOutput->setCacheRevisionId($revId); $parserOutputKey = $this->getParserOutputKey($page, $popts->optionsHash($optionsKey->mUsedOptions, $page->getTitle())); // Save the timestamp so that we don't have to load the revision row on view $parserOutput->setTimestamp($page->getTimestamp()); $msg = "Saved in parser cache with key {$parserOutputKey}" . " and timestamp {$cacheTime}" . " and revision id {$revId}" . "\n"; $parserOutput->mText .= "\n<!-- {$msg} -->\n"; wfDebug($msg); // Save the parser output $this->mMemc->set($parserOutputKey, $parserOutput, $expire); // ...and its pointer $this->mMemc->set($this->getOptionsKey($page), $optionsKey, $expire); Hooks::run('ParserCacheSaveComplete', array($this, $parserOutput, $page->getTitle(), $popts, $revId)); } else { wfDebug("Parser output was marked as uncacheable and has not been saved.\n"); } }
/** * @covers WikiPage::doRollback */ public function testDoRollbackFailureSameContent() { $admin = new User(); $admin->setName("Admin"); $admin->addGroup("sysop"); #XXX: make the test user a sysop... $text = "one"; $page = $this->newPage("WikiPageTest_testDoRollback"); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "section one", EDIT_NEW, false, $admin); $rev1 = $page->getRevision(); $user1 = new User(); $user1->setName("127.0.1.11"); $user1->addGroup("sysop"); #XXX: make the test user a sysop... $text .= "\n\ntwo"; $page = new WikiPage($page->getTitle()); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "adding section two", 0, false, $user1); # now, do a the rollback from the same user was doing the edit before $resultDetails = array(); $token = $user1->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert same user", $token, false, $resultDetails, $admin); $this->assertEquals(array(), $errors, "Rollback failed same user"); # now, try the rollback $resultDetails = array(); $token = $admin->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert", $token, false, $resultDetails, $admin); $this->assertEquals(array(array('alreadyrolled', 'WikiPageTest testDoRollback', '127.0.1.11', 'Admin')), $errors, "Rollback not failed"); $page = new WikiPage($page->getTitle()); $this->assertEquals($rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision"); $this->assertEquals("one", $page->getContent()->getNativeData()); }
/** * Get the current content of the page. This is basically similar to * WikiPage::getContent( Revision::RAW ) except that when the page doesn't exist an empty * content object is returned instead of null. * * @since 1.21 * @return Content */ protected function getCurrentContent() { $rev = $this->page->getRevision(); $content = $rev ? $rev->getContent(Revision::RAW) : null; if ($content === false || $content === null) { 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->contentModel = $rev->getContentModel(); $this->contentFormat = $rev->getContentFormat(); return $content; } }
/** * Get the current content of the page. This is basically similar to * WikiPage::getContent( Revision::RAW ) except that when the page doesn't exist an empty * content object is returned instead of null. * * @since 1.21 * @return Content */ protected function getCurrentContent() { $rev = $this->page->getRevision(); $content = $rev ? $rev->getContent(Revision::RAW) : null; if ($content === false || $content === null) { if (!$this->contentModel) { $this->contentModel = $this->getTitle()->getContentModel(); } $handler = ContentHandler::getForModelID($this->contentModel); return $handler->makeEmptyContent(); } elseif (!$this->undidRev) { // Content models should always be the same since we error // out if they are different before this point (in ->edit()). // The exception being, during an undo, the current revision might // differ from the prior revision. $logger = LoggerFactory::getInstance('editpage'); if ($this->contentModel !== $rev->getContentModel()) { $logger->warning("Overriding content model from current edit {prev} to {new}", ['prev' => $this->contentModel, 'new' => $rev->getContentModel(), 'title' => $this->getTitle()->getPrefixedDBkey(), 'method' => __METHOD__]); $this->contentModel = $rev->getContentModel(); } // Given that the content models should match, the current selected // format should be supported. if (!$content->isSupportedFormat($this->contentFormat)) { $logger->warning("Current revision content format unsupported. Overriding {prev} to {new}", ['prev' => $this->contentFormat, 'new' => $rev->getContentFormat(), 'title' => $this->getTitle()->getPrefixedDBkey(), 'method' => __METHOD__]); $this->contentFormat = $rev->getContentFormat(); } } return $content; }
/** * Produce page output suitable for indexing. * * Specific content handlers may override it if they need different content handling. * * @param WikiPage $page * @param ParserCache $cache * @return ParserOutput */ public function getParserOutputForIndexing(WikiPage $page, ParserCache $cache = null) { $parserOptions = $page->makeParserOptions('canonical'); $revId = $page->getRevision()->getId(); if ($cache) { $parserOutput = $cache->get($page, $parserOptions); } if (empty($parserOutput)) { $parserOutput = $page->getContent()->getParserOutput($page->getTitle(), $revId, $parserOptions); if ($cache) { $cache->save($parserOutput, $page, $parserOptions); } } return $parserOutput; }
/** * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason. */ public function testDoRollback() { $admin = new User(); $admin->setName("Admin"); $text = "one"; $page = $this->newPage("WikiPageTest_testDoRollback"); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "section one", EDIT_NEW, false, $admin); $rev1 = $page->getRevision(); $user1 = new User(); $user1->setName("127.0.1.11"); $text .= "\n\ntwo"; $page = new WikiPage($page->getTitle()); $page->doEditContent(ContentHandler::makeContent($text, $page->getTitle(), CONTENT_MODEL_WIKITEXT), "adding section two", 0, false, $user1); # now, try the rollback $admin->addGroup("sysop"); #XXX: make the test user a sysop... $token = $admin->getEditToken(array($page->getTitle()->getPrefixedText(), $user1->getName()), null); $errors = $page->doRollback($user1->getName(), "testing revert", $token, false, $details, $admin); if ($errors) { $this->fail("Rollback failed:\n" . print_r($errors, true) . ";\n" . print_r($details, true)); } $page = new WikiPage($page->getTitle()); $this->assertEquals($rev1->getSha1(), $page->getRevision()->getSha1(), "rollback did not revert to the correct revision"); $this->assertEquals("one", $page->getContent()->getNativeData()); }