protected function performUpdate() { $applicationFactory = ApplicationFactory::getInstance(); $parserData = $applicationFactory->newParserData($this->wikiPage->getTitle(), $this->parserOutput); $pageInfoProvider = $applicationFactory->newMwCollaboratorFactory()->newPageInfoProvider($this->wikiPage, $this->revision, $this->user); $propertyAnnotator = $applicationFactory->newPropertyAnnotatorFactory()->newPredefinedPropertyAnnotator($parserData->getSemanticData(), $pageInfoProvider); $propertyAnnotator->addAnnotation(); $parserData->pushSemanticDataToParserOutput(); return true; }
/** * Protects a message entry in the PRAd namespace. * The protection lasts for infinity and acts for group * @ref $wgPromoterProtectGroup * * This really is intended only for use on the original source language * because those messages are set via the PR UI; not the translate UI. * * @param WikiPage $page Page containing the message to protect * @param User $user User doing the protection (ie: the last one to edit the page) */ protected function protectMessageInPrNamespaces($page, $user) { global $wgPromoterProtectGroup; if (!$page->getTitle()->getRestrictions('edit')) { $var = false; $page->doUpdateRestrictions(array('edit' => $wgPromoterProtectGroup, 'move' => $wgPromoterProtectGroup), array('edit' => 'infinity', 'move' => 'infinity'), $var, 'Auto protected by Promoter -- Only edit via Special:Promoter.', $user); } }
/** * Clears notification for parent pages if: * - User is NOT watching currently viewed subpage * - User is watching parent page * - User has 'watchlistsubpages' turned on * * @param $article WikiPage object ( subpage ) * * @author Jakub Kurcek <*****@*****.**> */ public static function ClearParentNotification(WikiPage $page) { global $wgUser; if ($wgUser->getBoolOption(self::PREFERENCES_ENTRY)) { if (!$page->getTitle()->userIsWatching()) { $tmpDBkey = $page->getTitle()->getDBkey(); $arrTitle = explode('/', $tmpDBkey); if (count($arrTitle > 1)) { $parentTitle = Title::newFromDBkey($arrTitle[0]); if ($parentTitle->userIsWatching()) { $wgUser->clearNotification($parentTitle); } } } } return true; }
/** * @covers WikiPage::getContentHandler */ public function testGetContentHandler() { $page = $this->createPage("WikiPageTest_testGetContentHandler", "some text", CONTENT_MODEL_JAVASCRIPT); // NOTE: since the content model is not recorded in the database, // we expect to get the default, namely CONTENT_MODEL_WIKITEXT $page = new WikiPage($page->getTitle()); $this->assertEquals('WikitextContentHandler', get_class($page->getContentHandler())); }
static function newFromTitle($title) { // see if we already have this as our main instance... if (self::$instance && self::$instance->mTitle == $title) { return self::$instance; } $wikiPage = new WikiPage($title); if (!$wikiPage) { return null; } $whow = new WikihowArticleEditor(); $whow->mTitleObj = $wikiPage->getTitle(); $whow->mWikiPage = $wikiPage; $whow->mTitle = $wikiPage->getTitle()->getText(); $text = ContentHandler::getContentText($wikiPage->getContent(Revision::RAW)); $whow->loadFromText($text); return $whow; }
/** * Delete $page */ protected function doDelete($page) { if ($page instanceof Title) { $page = new WikiPage($page); } if ($this->logActions) { print "Delete " . $page->getTitle() . " = " . $page->getId() . "\n"; } $page->doDeleteArticle('-'); }
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 }
/** * Hook: Clear cache (videos by category) when the category page is purged * @param WikiPage $page * @return true */ public static function onArticlePurge(WikiPage &$page) { wfProfileIn(__METHOD__); $title = $page->getTitle(); if ($title->getNamespace() == NS_CATEGORY) { $helper = new VideoPageToolHelper(); $helper->invalidateCacheVideosByCategory($title->getDBkey()); } wfProfileOut(__METHOD__); return true; }
protected function getParserOutput(WikiPage $wp, ParserOptions $parserOptions) { $params = $this->extractRequestParams(); if (!isset($params['text'])) { throw new Exception('Must specify page text'); } $parser = new Parser(); $po = $parser->parse($params['text'], $wp->getTitle(), $parserOptions); $po->setTOCEnabled(false); $po->setText(str_replace(array("\r", "\n"), '', $po->getText())); return $po; }
private function doExtendParserOutput($parserOutput) { $applicationFactory = ApplicationFactory::getInstance(); $title = $this->wikiPage->getTitle(); $parserData = $applicationFactory->newParserData($title, $parserOutput); $pageInfoProvider = $applicationFactory->newMwCollaboratorFactory()->newPageInfoProvider($this->wikiPage, $this->revision, $this->user); $propertyAnnotatorFactory = $applicationFactory->singleton('PropertyAnnotatorFactory'); $propertyAnnotator = $propertyAnnotatorFactory->newNullPropertyAnnotator($parserData->getSemanticData()); $propertyAnnotator = $propertyAnnotatorFactory->newPredefinedPropertyAnnotator($propertyAnnotator, $pageInfoProvider); $propertyAnnotator->addAnnotation(); $parserData->pushSemanticDataToParserOutput(); }
/** * @return bool */ public function doWork() { global $wgUseFileCache; // @todo several of the methods called on $this->page are not declared in Page, but present // in WikiPage and delegated by Article. $isCurrent = $this->revid === $this->page->getLatest(); if ($this->content !== null) { $content = $this->content; } elseif ($isCurrent) { // XXX: why use RAW audience here, and PUBLIC (default) below? $content = $this->page->getContent(Revision::RAW); } else { $rev = Revision::newFromTitle($this->page->getTitle(), $this->revid); if ($rev === null) { $content = null; } else { // XXX: why use PUBLIC audience here (default), and RAW above? $content = $rev->getContent(); } } if ($content === null) { return false; } // Reduce effects of race conditions for slow parses (bug 46014) $cacheTime = wfTimestampNow(); $time = -microtime(true); $this->parserOutput = $content->getParserOutput($this->page->getTitle(), $this->revid, $this->parserOptions); $time += microtime(true); // Timing hack if ($time > 3) { // TODO: Use Parser's logger (once it has one) $logger = MediaWiki\Logger\LoggerFactory::getInstance('slow-parse'); $logger->info('{time} {title}', ['time' => number_format($time, 2), 'title' => $this->page->getTitle()->getPrefixedDBkey(), 'trigger' => 'view']); } if ($this->cacheable && $this->parserOutput->isCacheable() && $isCurrent) { ParserCache::singleton()->save($this->parserOutput, $this->page, $this->parserOptions, $cacheTime, $this->revid); } // Make sure file cache is not used on uncacheable content. // Output that has magic words in it can still use the parser cache // (if enabled), though it will generally expire sooner. if (!$this->parserOutput->isCacheable()) { $wgUseFileCache = false; } if ($isCurrent) { $this->page->triggerOpportunisticLinksUpdate($this->parserOutput); } return true; }
/** * @param WikiPage $article * @param User $user * @param $content * @param $summary * @param Bool $isMinor * @param Bool $isWatch * @param $section * @param $flags * @param Revision $revision * @param $status * @param $baseRevId * * @return bool */ public static function onPageContentSaveComplete(WikiPage $article, User $user, $content, $summary, $isMinor, $isWatch, $section, $flags, $revision, $status, $baseRevId) { if (is_null($revision)) { // Ignore null edits return true; } $title = $article->getTitle(); $oldRevisionId = $revision->getParentId(); if ($oldRevisionId !== null && ApprovedRevs::isAssignedToProject($title) && ApprovedRevs::getApprovedRevID($title) === $oldRevisionId) { if ($user->isAllowed('auto-reapproval-on-save')) { ApprovedRevs::performAutoReapproval($title, $revision->getId()); } else { ApprovedRevs::logUnapprovedSave($title, $user, $revision->getId()); } } return true; }
/** * MediaWiki ArticleDelete hook. Prevent users from deleting stylometricanalysis pages they have not uploaded (except for sysops) */ public function onArticleDelete(WikiPage &$wikiPage, User &$user, &$reason, &$error) { try { $title = $wikiPage->getTitle(); if (!$this->isStylometricAnalysisNamespace($title)) { return true; } if (!$this->currentUserIsASysop($user)) { $error = '<br>' . $this->getMessage('collatehooks-nodeletepermission') . '.'; return false; } $deleter = ObjectRegistry::getInstance()->getManuscriptDeskDeleter(); $deleter->deleteStylometricAnalysisData($title->getPrefixedURL()); } catch (Exception $e) { return true; } return true; }
/** * Purge RelatedVideos namespace article after an edit * * @param WikiPage $article */ public static function onArticleSaveComplete(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId) { wfProfileIn(__METHOD__); $title = $article->getTitle(); if (!empty($title)) { switch ($title->getNamespace()) { case NS_RELATED_VIDEOS: $relatedVideosNSData = RelatedVideosNamespaceData::newFromTitle($title); $relatedVideosNSData->purge(); break; case NS_MEDIAWIKI: if (empty(F::app()->wg->relatedVideosPartialRelease)) { if ($title->getText() == RelatedVideosNamespaceData::GLOBAL_RV_LIST) { $relatedVideosNSData = RelatedVideosNamespaceData::newFromTitle($title); $relatedVideosNSData->purge(); } } break; } } wfProfileOut(__METHOD__); return true; }
function savePage(WikiPage $p) { $db = new DatabaseConnection(); // Read values $ns = $p->getNs(); $uri = $p->getUri(); $title = $p->getTitle(); $content = $p->getContent(); $author = User::getActiveUserId(); // Update try { // pull the latest revision of the page $rs = $db->getSingleRow('SELECT MAX(revision) AS latest FROM wiki WHERE ns=\'%s\' AND uri=\'%s\'', $ns, $uri); $currev = $rs ? $rs['latest'] : 0; // set to 0 if no record returned // bump revision (if no record, 0 becomes 1) $currev++; // and insert the new data $db->updateRow("INSERT INTO wiki SET content='%s',revision='%d',title='%s',ns='%s',uri='%s',lastedit=NOW(),author='%d'", $content, $currev, $title, $ns, $uri, $author); } catch (DBXException $e) { throw $e; } }
public function getDataForSearchIndex(WikiPage $page, ParserOutput $parserOutput, SearchEngine $engine) { $fields = []; $title = $page->getTitle(); if (NS_FILE != $title->getNamespace()) { return []; } $file = wfLocalFile($title); if (!$file || !$file->exists()) { return []; } $handler = $file->getHandler(); if ($handler) { $fields['file_text'] = $handler->getEntireText($file); } $fields['file_media_type'] = $file->getMediaType(); $fields['file_mime'] = $file->getMimeType(); $fields['file_size'] = $file->getSize(); $fields['file_width'] = $file->getWidth(); $fields['file_height'] = $file->getHeight(); $fields['file_bits'] = $file->getBitDepth(); $fields['file_resolution'] = (int) floor(sqrt($fields['file_width'] * $fields['file_height'])); return $fields; }
/** * @param $hasHistory bool * @return mixed */ public function generateReason(&$hasHistory) { $title = $this->mPage->getTitle(); $handler = ContentHandler::getForTitle($title); return $handler->getAutoDeleteReason($title, $hasHistory); }
/** * Create an Article object of the appropriate class for the given page. * * @param WikiPage $page * @param IContextSource $context * @return Article */ public static function newFromWikiPage(WikiPage $page, IContextSource $context) { $article = self::newFromTitle($page->getTitle(), $context); $article->mPage = $page; // override to keep process cached vars return $article; }
/** * hook handler * update timestamp of newest message * * @param WikiPage $article * * @author Maciej Błaszkowski <marooned at wikia-inc.com> */ static function onArticleSaveComplete(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId) { global $wgMemc; $title = $article->getTitle(); if ($title->getNamespace() == NS_MEDIAWIKI && strtolower($title->getText()) == 'community-corner' && !$minoredit) { $revision = Revision::newFromTitle($title); if ($revision) { $wgMemc->set(wfMemcKey('CommunityMessagesTimestamp'), wfTimestamp(TS_UNIX, $revision->getTimestamp()), 86400); } } return true; }
/** * Get the content for the given page and the requested section. * * @param WikiPage $page * @param int $pageId * @return Content */ private function getContent(WikiPage $page, $pageId = null) { $content = $page->getContent(Revision::RAW); // XXX: really raw? if ($this->section !== false && $content !== null) { $content = $this->getSectionContent($content, !is_null($pageId) ? 'page id ' . $pageId : $page->getTitle()->getPrefixedText()); } return $content; }
/** * This method is called after an article has been saved. * This is the server side of IntraACL protection toolbar, * allowing to modify page SD together with article save. * * No modifications are made if either: * - Page namespace is ACL * - User is anonymous * - Users don't have the right to modify page SD * - 'haloacl_protect_with' request value is invalid * (valid are 'unprotected', or ID/name of predefined right or THIS page SD) * * @param WikiPage $article The article which was saved * @param User $user The user who saved the article * @param string $text The content of the article * * @return true */ public static function articleSaveComplete_SaveSD($article, User $user, $text) { global $wgUser, $wgRequest, $haclgContLang; if ($user->isAnon()) { // Don't handle protection toolbar for anonymous users return true; } if ($article->getTitle()->getNamespace() == HACL_NS_ACL) { // Don't use protection toolbar for articles in the namespace ACL. // Note that embedded content protection toolbar is handled nevertheless. return true; } // Obtain user selection // hacl_protected_with == '<peType>:<peID>' or 'unprotected' $selectedSD = $wgRequest->getVal('hacl_protected_with'); if ($selectedSD && $selectedSD != 'unprotected') { // Some SD is selected by the user // Ignore selection of invalid SDs $selectedSD = array_map('intval', explode('-', $selectedSD, 2)); if (count($selectedSD) != 2) { $selectedSD = NULL; } } if (!$selectedSD) { return true; } if ($selectedSD == 'unprotected') { $selectedSD = NULL; } // Check if current SD must be modified if ($article->exists()) { $pageSD = IACLDefinition::getSDForPE(IACL::PE_PAGE, $article->getId()); if ($pageSD && $selectedSD) { // Check if page's SD ID passed as selected if ($pageSD['pe_type'] == $selectedSD[0] && $pageSD['pe_id'] == $selectedSD[1]) { return true; } // Check if page's SD is single inclusion and it is passed as selected if ($pageSD['single_child'] == $selectedSD) { return true; } } } // Check if no protection selected and no protection exists if (!$selectedSD && !$pageSD) { return true; } // Check if other SD is a predefined right // FIXME Allow selecting non-PE_RIGHTs in quick acl toolbar? if ($selectedSD && $selectedSD[0] != IACL::PE_RIGHT) { return true; } // Check SD modification rights $pageSDName = IACLDefinition::nameOfSD(IACL::PE_PAGE, $article->getTitle()); $etc = haclfDisableTitlePatch(); $pageSDTitle = Title::newFromText($pageSDName); haclfRestoreTitlePatch($etc); if (!$pageSDTitle->userCan('edit')) { return true; } $newSDArticle = new WikiPage($pageSDTitle); if ($selectedSD) { // Create/modify page SD $selectedSDTitle = IACLDefinition::getSDTitle($selectedSD); $content = '{{#predefined right: ' . $selectedSDTitle->getText() . "}}\n" . '{{#manage rights: assigned to = User:'******'hacl_comment_protect_with', $selectedSDTitle->getFullText())); } else { // Remove page SD $newSDArticle->doDeleteArticle(wfMsg('hacl_comment_unprotect')); } // Continue hook processing return true; }
/** * It's like Article::prepareTextForEdit, but not for editing (old wikitext usually) * * * @param string $wikitext * @param WikiPage $article * * @return object */ function parseNonEditWikitext($wikitext, $article) { static $cache = array(); $cacheKey = md5($wikitext) . ':' . $article->getTitle()->getPrefixedText(); if (isset($cache[$cacheKey])) { return $cache[$cacheKey]; } global $wgParser; $edit = (object) array(); $options = new ParserOptions(); $options->setTidy(true); $edit->output = $wgParser->parse($wikitext, $article->getTitle(), $options); $cache[$cacheKey] = $edit; return $edit; }
/** * Hook to refresh the cache of conversion tables when * MediaWiki:Conversiontable* is updated. * @private * * @param WikiPage $page * @param User $user User object for the current user * @param Content $content New page content * @param string $summary Edit summary of the edit * @param bool $isMinor Was the edit marked as minor? * @param null $isWatch Unused. * @param null $section Unused. * @param int $flags Bitfield * @param Revision|null $revision New Revision object or null * @return bool True */ function OnPageContentSaveComplete($page, $user, $content, $summary, $isMinor, $isWatch, $section, $flags, $revision) { $titleobj = $page->getTitle(); if ($titleobj->getNamespace() == NS_MEDIAWIKI) { $title = $titleobj->getDBkey(); $t = explode('/', $title, 3); $c = count($t); if ($c > 1 && $t[0] == 'Conversiontable') { if ($this->validateVariant($t[1])) { $this->reloadTables(); } } } return true; }
/** * Invalidates cache for authors * @param WikiPage $wikiPage * @param User $user * @param Content $content * @param type $summary * @param type $isMinor * @param type $isWatch * @param type $section * @param type $flags * @param Status $status * @return boolean */ public static function onPageContentSave($wikiPage, $user, $content, $summary, $isMinor, $isWatch, $section, $flags, $status) { BsCacheHelper::invalidateCache(BsCacheHelper::getCacheKey('BlueSpice', 'Authors', $wikiPage->getTitle()->getArticleID())); return true; }
protected function createPage($page, $text, $model = null) { if (is_string($page)) { if (!preg_match('/:/', $page) && ($model === null || $model === CONTENT_MODEL_WIKITEXT)) { $ns = $this->getDefaultWikitextNS(); $page = MWNamespace::getCanonicalName($ns) . ':' . $page; } $page = Title::newFromText($page); } if ($page instanceof Title) { $page = new WikiPage($page); } if ($page->exists()) { $page->doDeleteArticle("done"); } $content = ContentHandler::makeContent($text, $page->getTitle(), $model); $page->doEditContent($content, "testing", EDIT_NEW); return $page; }
/** * @param WikiPage $page * @param Revision $newRev * @throws MWException */ protected function notifyUpdatesForRevision(WikiPage $page, Revision $newRev) { $config = RequestContext::getMain()->getConfig(); $title = $page->getTitle(); // Get the new revision if (!$newRev->getContent()) { return; // deleted? } // Get the prior revision (the same for null edits) if ($newRev->getParentId()) { $oldRev = Revision::newFromId($newRev->getParentId(), Revision::READ_LATEST); if (!$oldRev->getContent()) { return; // deleted? } } else { $oldRev = null; } // Parse the new revision and get the categories $categoryChanges = $this->getExplicitCategoriesChanges($title, $newRev, $oldRev); list($categoryInserts, $categoryDeletes) = $categoryChanges; if (!$categoryInserts && !$categoryDeletes) { return; // nothing to do } $dbw = wfGetDB(DB_MASTER); $catMembChange = new CategoryMembershipChange($title, $newRev); $catMembChange->checkTemplateLinks(); $batchSize = $config->get('UpdateRowsPerQuery'); $insertCount = 0; foreach ($categoryInserts as $categoryName) { $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName); $catMembChange->triggerCategoryAddedNotification($categoryTitle); if ($insertCount++ && $insertCount % $batchSize == 0) { $dbw->commit(__METHOD__, 'flush'); wfGetLBFactory()->waitForReplication(); } } foreach ($categoryDeletes as $categoryName) { $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName); $catMembChange->triggerCategoryRemovedNotification($categoryTitle); if ($insertCount++ && $insertCount++ % $batchSize == 0) { $dbw->commit(__METHOD__, 'flush'); wfGetLBFactory()->waitForReplication(); } } }
/** * Shortcut to get the Title object from the page * @return Title */ final public function getTitle() { return $this->page->getTitle(); }
/** * @desc Purges cache once a post within category is requested for deletion * * @param WikiPage $page * @param User $user * @param String $reason * @param $error * * @return boolean true because it's a hook */ public static function onArticleDelete(&$page, &$user, &$reason, &$error) { $app = F::app(); if (in_array($app->wg->DBname, $app->wg->CssUpdatesLangMap)) { $title = $page->getTitle(); static::purgeCacheDependingOnCats($title, 'because a post within the category was deleted'); } return true; }
/** * @param $page WikiPage * @param $popts ParserOptions * @param $pageId Int * @param $getWikitext Bool * @return ParserOutput */ private function getParsedContent(WikiPage $page, $popts, $pageId = null, $getWikitext = false) { $this->content = $page->getContent(Revision::RAW); //XXX: really raw? if ($this->section !== false && $this->content !== null) { $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(), null, $popts); } else { // Try the parser cache first // getParserOutput will save to Parser cache if able $pout = $page->getParserOutput($popts); if (!$pout) { $this->dieUsage("There is no revision ID {$page->getLatest()}", 'missingrev'); } if ($getWikitext) { $this->content = $page->getContent(Revision::RAW); } return $pout; } }
/** * Set the WikiPage object * * @since 1.19 * @param WikiPage $p */ public function setWikiPage(WikiPage $p) { $pageTitle = $p->getTitle(); if (!$this->hasTitle() || !$pageTitle->equals($this->getTitle())) { $this->setTitle($pageTitle); } // Defer this to the end since setTitle sets it to null. $this->wikipage = $p; }