/** * Same as addWatch, only the opposite. * @return bool */ public function removeWatch() { $success = false; $dbw = wfGetDB(DB_MASTER); $dbw->delete('watchlist', array('wl_user' => $this->id, 'wl_namespace' => MWNamespace::getSubject($this->ns), 'wl_title' => $this->ti), __METHOD__); if ($dbw->affectedRows()) { $success = true; } # the following code compensates the new behaviour, introduced by the # enotif patch, that every single watched page needs now to be listed # in watchlist namespace:page and namespace_talk:page had separate # entries: clear them $dbw->delete('watchlist', array('wl_user' => $this->id, 'wl_namespace' => MWNamespace::getTalk($this->ns), 'wl_title' => $this->ti), __METHOD__); if ($dbw->affectedRows()) { $success = true; } return $success; }
function register() { global $wgContLang, $wgNamespaceAliases, $wgNonincludableNamespaces; $lib = array('loadSiteStats' => array($this, 'loadSiteStats'), 'getNsIndex' => array($this, 'getNsIndex'), 'pagesInCategory' => array($this, 'pagesInCategory'), 'pagesInNamespace' => array($this, 'pagesInNamespace'), 'usersInGroup' => array($this, 'usersInGroup')); $info = array('siteName' => $GLOBALS['wgSitename'], 'server' => $GLOBALS['wgServer'], 'scriptPath' => $GLOBALS['wgScriptPath'], 'stylePath' => $GLOBALS['wgStylePath'], 'currentVersion' => SpecialVersion::getVersion()); if (!self::$namespacesCache) { $namespaces = array(); $namespacesByName = array(); foreach ($wgContLang->getFormattedNamespaces() as $ns => $title) { $canonical = MWNamespace::getCanonicalName($ns); $namespaces[$ns] = array('id' => $ns, 'name' => $title, 'canonicalName' => strtr($canonical, '_', ' '), 'hasSubpages' => MWNamespace::hasSubpages($ns), 'hasGenderDistinction' => MWNamespace::hasGenderDistinction($ns), 'isCapitalized' => MWNamespace::isCapitalized($ns), 'isContent' => MWNamespace::isContent($ns), 'isIncludable' => !($wgNonincludableNamespaces && in_array($ns, $wgNonincludableNamespaces)), 'isMovable' => MWNamespace::isMovable($ns), 'isSubject' => MWNamespace::isSubject($ns), 'isTalk' => MWNamespace::isTalk($ns), 'aliases' => array()); if ($ns >= NS_MAIN) { $namespaces[$ns]['subject'] = MWNamespace::getSubject($ns); $namespaces[$ns]['talk'] = MWNamespace::getTalk($ns); $namespaces[$ns]['associated'] = MWNamespace::getAssociated($ns); } else { $namespaces[$ns]['subject'] = $ns; } $namespacesByName[strtr($title, ' ', '_')] = $ns; if ($canonical) { $namespacesByName[$canonical] = $ns; } } $aliases = array_merge($wgNamespaceAliases, $wgContLang->getNamespaceAliases()); foreach ($aliases as $title => $ns) { if (!isset($namespacesByName[$title])) { $ct = count($namespaces[$ns]['aliases']); $namespaces[$ns]['aliases'][$ct + 1] = $title; $namespacesByName[$title] = $ns; } } $namespaces[NS_MAIN]['displayName'] = wfMessage('blanknamespace')->text(); self::$namespacesCache = $namespaces; } $info['namespaces'] = self::$namespacesCache; if (self::$siteStatsLoaded) { $stats = $this->loadSiteStats(); $info['stats'] = $stats[0]; } $this->getEngine()->registerInterface('mw.site.lua', $lib, $info); }
function register() { global $wgContLang, $wgNamespaceAliases, $wgDisableCounters; $lib = array('getNsIndex' => array($this, 'getNsIndex'), 'pagesInCategory' => array($this, 'pagesInCategory'), 'pagesInNamespace' => array($this, 'pagesInNamespace'), 'usersInGroup' => array($this, 'usersInGroup'), 'interwikiMap' => array($this, 'interwikiMap')); $info = array('siteName' => $GLOBALS['wgSitename'], 'server' => $GLOBALS['wgServer'], 'scriptPath' => $GLOBALS['wgScriptPath'], 'stylePath' => $GLOBALS['wgStylePath'], 'currentVersion' => SpecialVersion::getVersion()); if (!self::$namespacesCache || self::$namespacesCacheLang !== $wgContLang->getCode()) { $namespaces = array(); $namespacesByName = array(); foreach ($wgContLang->getFormattedNamespaces() as $ns => $title) { $canonical = MWNamespace::getCanonicalName($ns); $namespaces[$ns] = array('id' => $ns, 'name' => $title, 'canonicalName' => strtr($canonical, '_', ' '), 'hasSubpages' => MWNamespace::hasSubpages($ns), 'hasGenderDistinction' => MWNamespace::hasGenderDistinction($ns), 'isCapitalized' => MWNamespace::isCapitalized($ns), 'isContent' => MWNamespace::isContent($ns), 'isIncludable' => !MWNamespace::isNonincludable($ns), 'isMovable' => MWNamespace::isMovable($ns), 'isSubject' => MWNamespace::isSubject($ns), 'isTalk' => MWNamespace::isTalk($ns), 'defaultContentModel' => MWNamespace::getNamespaceContentModel($ns), 'aliases' => array()); if ($ns >= NS_MAIN) { $namespaces[$ns]['subject'] = MWNamespace::getSubject($ns); $namespaces[$ns]['talk'] = MWNamespace::getTalk($ns); $namespaces[$ns]['associated'] = MWNamespace::getAssociated($ns); } else { $namespaces[$ns]['subject'] = $ns; } $namespacesByName[strtr($title, ' ', '_')] = $ns; if ($canonical) { $namespacesByName[$canonical] = $ns; } } $aliases = array_merge($wgNamespaceAliases, $wgContLang->getNamespaceAliases()); foreach ($aliases as $title => $ns) { if (!isset($namespacesByName[$title]) && isset($namespaces[$ns])) { $ct = count($namespaces[$ns]['aliases']); $namespaces[$ns]['aliases'][$ct + 1] = $title; $namespacesByName[$title] = $ns; } } $namespaces[NS_MAIN]['displayName'] = wfMessage('blanknamespace')->inContentLanguage()->text(); self::$namespacesCache = $namespaces; self::$namespacesCacheLang = $wgContLang->getCode(); } $info['namespaces'] = self::$namespacesCache; $info['stats'] = array('pages' => (int) SiteStats::pages(), 'articles' => (int) SiteStats::articles(), 'files' => (int) SiteStats::images(), 'edits' => (int) SiteStats::edits(), 'views' => $wgDisableCounters ? null : (int) SiteStats::views(), 'users' => (int) SiteStats::users(), 'activeUsers' => (int) SiteStats::activeUsers(), 'admins' => (int) SiteStats::numberingroup('sysop')); return $this->getEngine()->registerInterface('mw.site.lua', $lib, $info); }
/** * Get the preferred destination title for a given target page. * @param integer $ns The destination namespace ID * @param string $name The conflicting prefix * @param integer $sourceNs The source namespace * @param integer $sourceDbk The source DB key (i.e. page_title) * @param array $options Associative array of validated command-line options * @return Title|false */ private function getDestinationTitle($ns, $name, $sourceNs, $sourceDbk, $options) { $dbk = substr($sourceDbk, strlen("{$name}:")); if ($ns == 0) { // An interwiki; try an alternate encoding with '-' for ':' $dbk = "{$name}-" . $dbk; } $destNS = $ns; if ($sourceNs == NS_TALK && MWNamespace::isSubject($ns)) { // This is an associated talk page moved with the --move-talk feature. $destNS = MWNamespace::getTalk($destNS); } $newTitle = Title::makeTitleSafe($destNS, $dbk); if (!$newTitle || !$newTitle->canExist()) { return false; } return $newTitle; }
/** * move one comment * * @access public * @static * * @param $oCommentTitle Title * @param $oNewTitle title */ private static function moveComment($oCommentTitle, &$oNewTitle, $reason = '') { global $wgUser; wfProfileIn(__METHOD__); if (!is_object($oCommentTitle)) { wfProfileOut(__METHOD__); return array('invalid title'); } $currentUser = $wgUser; $wgUser = User::newFromName(self::MOVE_USER); $parts = self::explode($oCommentTitle->getDBkey()); $commentTitleText = implode('/', $parts['partsOriginal']); $newCommentTitle = Title::newFromText(sprintf('%s/%s', $oNewTitle->getText(), $commentTitleText), MWNamespace::getTalk($oNewTitle->getNamespace())); $error = $oCommentTitle->moveTo($newCommentTitle, false, $reason, false); $wgUser = $currentUser; wfProfileOut(__METHOD__); return $error; }
public function onAfterLanguageGetNamespaces(&$namespaces) { wfProfileIn(__METHOD__); $app = F::App(); $title = $app->wg->Title; if (empty($title) || !$title->isSpecial('Allpages')) { wfProfileOut(__METHOD__); return true; } foreach ($app->wg->WallNS as $val) { $ns = MWNamespace::getTalk($val); if (!empty($namespaces[$ns])) { unset($namespaces[$ns]); } } wfProfileOut(__METHOD__); return true; }
/** * Get a Title object associated with the talk page of this article * * @return Title The object for the talk page */ public function getTalkPage() { return Title::makeTitle(MWNamespace::getTalk($this->getNamespace()), $this->getDBkey()); }
/** * Get talk page IDs (if requested) and subject page IDs (if requested) * and put them in $talkids and $subjectids */ private function getTSIDs() { $getTitles = $this->talkids = $this->subjectids = array(); $db = $this->getDB(); foreach ($this->everything as $t) { if (MWNamespace::isTalk($t->getNamespace())) { if ($this->fld_subjectid) { $getTitles[] = $t->getSubjectPage(); } } else { if ($this->fld_talkid) { $getTitles[] = $t->getTalkPage(); } } } if (!count($getTitles)) { return; } // Construct a custom WHERE clause that matches // all titles in $getTitles $lb = new LinkBatch($getTitles); $this->resetQueryParams(); $this->addTables('page'); $this->addFields(array('page_title', 'page_namespace', 'page_id')); $this->addWhere($lb->constructSet('page', $db)); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { if (MWNamespace::isTalk($row->page_namespace)) { $this->talkids[MWNamespace::getSubject($row->page_namespace)][$row->page_title] = intval($row->page_id); } else { $this->subjectids[MWNamespace::getTalk($row->page_namespace)][$row->page_title] = intval($row->page_id); } } }
/** * Same as addWatch, only the opposite. * @return bool */ public function removeWatch() { // Only loggedin user can have a watchlist if (wfReadOnly() || $this->mUser->isAnon()) { return false; } $success = false; $dbw = wfGetDB(DB_MASTER); $dbw->delete('watchlist', array('wl_user' => $this->userID, 'wl_namespace' => MWNamespace::getSubject($this->nameSpace), 'wl_title' => $this->databaseKey), __METHOD__); if ($dbw->affectedRows()) { $success = true; } # the following code compensates the new behaviour, introduced by the # enotif patch, that every single watched page needs now to be listed # in watchlist namespace:page and namespace_talk:page had separate # entries: clear them $dbw->delete('watchlist', array('wl_user' => $this->userID, 'wl_namespace' => MWNamespace::getTalk($this->nameSpace), 'wl_title' => $this->databaseKey), __METHOD__); // No errors, update the global_watchlist table. if ($dbw->affectedRows()) { wfRunHooks('WatchedItem::updateWatch', array($this, $this->userID)); } return $success; }
private function loadThreadListFromDB($master = true) { wfProfileIn(__METHOD__); // get list of threads (article IDs) on Message Wall $dbr = wfGetDB($master ? DB_MASTER : DB_SLAVE); $query = ''; // page_latest condition is for BugId:22821 $query = "\n\t\t\tselect page.page_id, page.page_title from page\n\t\t\tleft join page_wikia_props\n\t\t\ton page.page_id = page_wikia_props.page_id\n\t\t\tand (page_wikia_props.propname = " . WPP_WALL_ADMINDELETE . "\n\t\t\t or page_wikia_props.propname = " . WPP_WALL_REMOVE . "\n\t\t\t or page_wikia_props.propname = " . WPP_WALL_ARCHIVE . ")\n\t\t\twhere page_wikia_props.page_id is null\n\t\t\tand page.page_title" . $dbr->buildLike(sprintf("%s/%s", $this->mTitle->getDBkey(), ARTICLECOMMENT_PREFIX), $dbr->anyString()) . " \n\t\t\tand page.page_title NOT " . $dbr->buildLike(sprintf("%s/%s%%/%s", $this->mTitle->getDBkey(), ARTICLECOMMENT_PREFIX, ARTICLECOMMENT_PREFIX), $dbr->anyString()) . "\n\t\t\tand page.page_title not like '%@%@%'\n\t\t\tand page.page_namespace = " . MWNamespace::getTalk($this->mTitle->getNamespace()) . "\n\t\t\tand page.page_latest > 0\n\t\t\torder by page.page_id desc"; $res = $dbr->query($query); $this->mThreadMapping = array(); $this->mThreadMappingRev = array(); while ($row = $dbr->fetchObject($res)) { $this->mThreadMapping[$row->page_title] = $row->page_id; $this->mThreadMappingRev[$row->page_id] = $row->page_title; } wfProfileOut(__METHOD__); }
/** * Returns comment article title. */ public function getCommentArticleTitle() { if ( $this->mCommentTitle ) { return $this->mCommentTitle; } elseif ( $this->mCommentPage ) { return Title::newFromID( $this->mCommentPage, Title::GAID_FOR_UPDATE ); } else { $it = $this->mItem->mTitle; return Title::makeTitle( MWNamespace::getTalk( $it->getNamespace() ), $it->getText() . '/c' . self::padID( $this->mID ) ); } }
/** * Hook function calls when watch was removed from database * @param $oWatchItem WatchedItem: object * @param $success Boolean: removed successfully * @return bool (always true) */ public static function removeGlobalWatch($oWatchItem, $success) { global $wgEnableScribeReport, $wgCityId; wfProfileIn(__METHOD__); if (empty($wgEnableScribeReport)) { wfProfileOut(__METHOD__); return true; } if (!$oWatchItem instanceof WatchedItem) { wfProfileOut(__METHOD__); return true; } if (!$success) { /* some errors when update in local watchlist table */ wfProfileOut(__METHOD__); return true; } if ($oWatchItem->id == 0) { wfProfileOut(__METHOD__); return true; } foreach (array(MWNamespace::getSubject($oWatchItem->ns), MWNamespace::getTalk($oWatchItem->ns)) as $ns) { $params = array('wl_user' => $oWatchItem->id, 'wl_namespace' => $ns, 'wl_title' => $oWatchItem->ti, 'wl_wikia' => $wgCityId); try { $message = array('method' => 'removeWatch', 'params' => $params); $data = json_encode($message); WScribeClient::singleton('trigger')->send($data); } catch (Exception $e) { Wikia::log(__METHOD__, 'scribeClient exception', $e->getMessage()); } } wfProfileOut(__METHOD__); return true; }
/** * Constructor. * @param $title Title object. */ function __construct( $title ) { $origns = $title->getNamespace(); $this->mIsTalk = MWNamespace::isTalk( $origns ); $ns = MWNamespace::getSubject( $origns ); $tns = MWNamespace::getTalk( $origns ); if ( strpos( $title->getText(), '/' ) !== false ) { # If title contains a '/', treat as a wikilog article title. list( $this->mWikilogName, $this->mItemName ) = explode( '/', $title->getText(), 2 ); if ( strpos( $this->mItemName, '/' ) !== false ) { list( $this->mItemName, $this->mTrailing ) = explode( '/', $this->mItemName, 2 ); } $rawtitle = "{$this->mWikilogName}/{$this->mItemName}"; $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); $this->mItemTitle = Title::makeTitle( $ns, $rawtitle ); $this->mItemTalkTitle = Title::makeTitle( $tns, $rawtitle ); } else { # Title doesn't contain a '/', treat as a wikilog name. $this->mWikilogName = $title->getText(); $this->mWikilogTitle = Title::makeTitle( $ns, $this->mWikilogName ); $this->mItemName = null; $this->mItemTitle = null; $this->mItemTalkTitle = null; } }
protected function getWatchlist($name, $titleDbkey, $ns = NS_USER_WALL) { //TODO: add some caching $userTitle = Title::newFromText($name, MWNamespace::getSubject($ns)); $dbw = $this->getLocalDB(true); $res = $dbw->select(array('watchlist'), array('wl_user'), array('wl_title' => array($titleDbkey, $userTitle->getDBkey()), 'wl_namespace' => array(MWNamespace::getSubject($ns), MWNamespace::getTalk($ns)), "((wl_wikia_addedtimestamp > '2012-01-31' and wl_namespace = " . MWNamespace::getSubject($ns) . ") or ( wl_namespace = " . MWNamespace::getTalk($ns) . " ))"), __METHOD__); $users = array(); while ($row = $dbw->fetchObject($res)) { $userId = intval($row->wl_user); $users[$userId] = $userId; } return $users; }
function upgradeWatchlist() { $chunksize = 100; list($watchlist, $watchlist_temp) = $this->dbw->tableNamesN('watchlist', 'watchlist_temp'); $this->log('Migrating watchlist table to watchlist_temp...'); $this->dbw->query("CREATE TABLE {$watchlist_temp} (\n -- Key to user_id\n wl_user int(5) unsigned NOT NULL,\n\n -- Key to page_namespace/page_title\n -- Note that users may watch patches which do not exist yet,\n -- or existed in the past but have been deleted.\n wl_namespace int NOT NULL default '0',\n wl_title varchar(255) binary NOT NULL default '',\n\n -- Timestamp when user was last sent a notification e-mail;\n -- cleared when the user visits the page.\n -- FIXME: add proper null support etc\n wl_notificationtimestamp varchar(14) binary NOT NULL default '0',\n\n UNIQUE KEY (wl_user, wl_namespace, wl_title),\n KEY namespace_title (wl_namespace,wl_title)\n\n) TYPE=InnoDB;", __METHOD__); // Fix encoding for Latin-1 upgrades, add some fields, // and double article to article+talk pairs $numwatched = $this->dbw->selectField('watchlist', 'count(*)', '', __METHOD__); $this->setChunkScale($chunksize, $numwatched * 2, 'watchlist_temp', __METHOD__); $result = $this->dbr->select('watchlist', array('wl_user', 'wl_namespace', 'wl_title'), '', __METHOD__); $add = array(); foreach ($result as $row) { $add[] = array('wl_user' => $row->wl_user, 'wl_namespace' => MWNamespace::getSubject($row->wl_namespace), 'wl_title' => $this->conv($row->wl_title), 'wl_notificationtimestamp' => '0'); $this->addChunk($add); $add[] = array('wl_user' => $row->wl_user, 'wl_namespace' => MWNamespace::getTalk($row->wl_namespace), 'wl_title' => $this->conv($row->wl_title), 'wl_notificationtimestamp' => '0'); $this->addChunk($add); } $this->lastChunk($add); $this->log('Done converting watchlist.'); $this->cleanupSwaps[] = 'watchlist'; }
/** * Exceptions with getTalk() * NS_SPECIAL does not have talk pages. MediaWiki raise an exception for them. * @expectedException MWException */ public function testGetTalkExceptionsForNsSpecial() { $this->assertNull(MWNamespace::getTalk(NS_SPECIAL)); }
private function loadReplyIdsFromDB($master = false) { // this is a direct way to get IDs // the other one is in Wall.class done in a grouped way // (fetch for many threads at once, set with ->setReplies) $title = Title::newFromId($this->mThreadId); if (empty($title)) { $title = Title::newFromId($this->mThreadId, Title::GAID_FOR_UPDATE); } if (empty($title)) { return; } $dbr = wfGetDB($master ? DB_MASTER : DB_SLAVE); $table = array('page'); $vars = array('page_id'); $conds[] = "page_title" . $dbr->buildLike(sprintf("%s/%s", $title->getDBkey(), ARTICLECOMMENT_PREFIX), $dbr->anyString()); $conds[] = "page_latest > 0"; // BugId:22821 $conds['page_namespace'] = MWNamespace::getTalk($title->getNamespace()); $options = array('ORDER BY' => 'page_id ASC'); $res = $dbr->select($table, $vars, $conds, __METHOD__, $options); $list = array(); while ($row = $dbr->fetchObject($res)) { array_push($list, $row->page_id); } $this->setReplies($list); }
/** * Same as addWatch, only the opposite. * @return bool */ public function removeWatch() { wfProfileIn(__METHOD__); // Only loggedin user can have a watchlist if (wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed('editmywatchlist')) { wfProfileOut(__METHOD__); return false; } $success = false; $dbw = wfGetDB(DB_MASTER); $dbw->delete('watchlist', array('wl_user' => $this->getUserId(), 'wl_namespace' => MWNamespace::getSubject($this->getTitleNs()), 'wl_title' => $this->getTitleDBkey()), __METHOD__); if ($dbw->affectedRows()) { $success = true; } # the following code compensates the new behavior, introduced by the # enotif patch, that every single watched page needs now to be listed # in watchlist namespace:page and namespace_talk:page had separate # entries: clear them $dbw->delete('watchlist', array('wl_user' => $this->getUserId(), 'wl_namespace' => MWNamespace::getTalk($this->getTitleNs()), 'wl_title' => $this->getTitleDBkey()), __METHOD__); if ($dbw->affectedRows()) { $success = true; } $this->watched = false; wfProfileOut(__METHOD__); return $success; }
private function getRemovedCommentPages($oTitle) { wfProfileIn(__METHOD__); $pages = array(); if ($oTitle instanceof Title) { $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select(array('archive'), array('ar_page_id', 'ar_title'), array('ar_namespace' => MWNamespace::getTalk($this->getTitle()->getNamespace()), "ar_title" . $dbr->buildLike(sprintf("%s/%s", $oTitle->getDBkey(), ARTICLECOMMENT_PREFIX), $dbr->anyString())), __METHOD__, array('ORDER BY' => 'ar_page_id ASC')); while ($row = $dbr->fetchObject($res)) { $pages[$row->ar_page_id] = array('title' => $row->ar_title, 'nspace' => MWNamespace::getTalk($this->getTitle()->getNamespace())); } $dbr->freeResult($res); } wfProfileOut(__METHOD__); return $pages; }
/** * Remove a list of titles from a user's watchlist * * $titles can be an array of strings or Title objects; the former * is preferred, since Titles are very memory-heavy * * @param array $titles Array of strings, or Title objects */ private function unwatchTitles($titles) { $dbw = wfGetDB(DB_MASTER); foreach ($titles as $title) { if (!$title instanceof Title) { $title = Title::newFromText($title); } if ($title instanceof Title) { $dbw->delete('watchlist', array('wl_user' => $this->getUser()->getId(), 'wl_namespace' => MWNamespace::getSubject($title->getNamespace()), 'wl_title' => $title->getDBkey()), __METHOD__); $dbw->delete('watchlist', array('wl_user' => $this->getUser()->getId(), 'wl_namespace' => MWNamespace::getTalk($title->getNamespace()), 'wl_title' => $title->getDBkey()), __METHOD__); $page = WikiPage::factory($title); Hooks::run('UnwatchArticleComplete', array($this->getUser(), &$page)); } } }
/** * Add a list of targets to a user's watchlist * * @param string[]|LinkTarget[] $targets */ private function watchTitles($targets) { $expandedTargets = []; foreach ($targets as $target) { if (!$target instanceof LinkTarget) { try { $target = $this->titleParser->parseTitle($target, NS_MAIN); } catch (MalformedTitleException $e) { continue; } } $ns = $target->getNamespace(); $dbKey = $target->getDBkey(); $expandedTargets[] = new TitleValue(MWNamespace::getSubject($ns), $dbKey); $expandedTargets[] = new TitleValue(MWNamespace::getTalk($ns), $dbKey); } MediaWikiServices::getInstance()->getWatchedItemStore()->addWatchBatchForUser($this->getUser(), $expandedTargets); }
/** * Get a Title object associated with the talk page of this article * * @return Title the object for the talk page */ public function getTalkPage() { // begin wikia change // VOLDEV-66 $talkPageTitle = Title::makeTitle(MWNamespace::getTalk($this->getNamespace()), $this->getDBkey()); wfRunHooks('GetTalkPage', [$this, &$talkPageTitle]); return $talkPageTitle; // end wikia change }
public function execute() { global $wgUser; $params = $this->extractRequestParams(); $fld_protection = $fld_talkid = $fld_subjectid = $fld_url = $fld_readable = false; if (!is_null($params['prop'])) { $prop = array_flip($params['prop']); $fld_protection = isset($prop['protection']); $fld_talkid = isset($prop['talkid']); $fld_subjectid = isset($prop['subjectid']); $fld_url = isset($prop['url']); $fld_readable = isset($prop['readable']); } $pageSet = $this->getPageSet(); $titles = $pageSet->getGoodTitles(); $missing = $pageSet->getMissingTitles(); $result = $this->getResult(); $pageRestrictions = $pageSet->getCustomField('page_restrictions'); $pageIsRedir = $pageSet->getCustomField('page_is_redirect'); $pageIsNew = $pageSet->getCustomField('page_is_new'); $pageCounter = $pageSet->getCustomField('page_counter'); $pageTouched = $pageSet->getCustomField('page_touched'); $pageLatest = $pageSet->getCustomField('page_latest'); $pageLength = $pageSet->getCustomField('page_len'); $db = $this->getDB(); if ($fld_protection && count($titles)) { $this->addTables('page_restrictions'); $this->addFields(array('pr_page', 'pr_type', 'pr_level', 'pr_expiry', 'pr_cascade')); $this->addWhereFld('pr_page', array_keys($titles)); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { $a = array('type' => $row->pr_type, 'level' => $row->pr_level, 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601)); if ($row->pr_cascade) { $a['cascade'] = ''; } $protections[$row->pr_page][] = $a; # Also check old restrictions if ($pageRestrictions[$row->pr_page]) { foreach (explode(':', trim($pageRestrictions[$pageid])) as $restrict) { $temp = explode('=', trim($restrict)); if (count($temp) == 1) { // old old format should be treated as edit/move restriction $restriction = trim($temp[0]); if ($restriction == '') { continue; } $protections[$row->pr_page][] = array('type' => 'edit', 'level' => $restriction, 'expiry' => 'infinity'); $protections[$row->pr_page][] = array('type' => 'move', 'level' => $restriction, 'expiry' => 'infinity'); } else { $restriction = trim($temp[1]); if ($restriction == '') { continue; } $protections[$row->pr_page][] = array('type' => $temp[0], 'level' => $restriction, 'expiry' => 'infinity'); } } } } $db->freeResult($res); $imageIds = array(); foreach ($titles as $id => $title) { if ($title->getNamespace() == NS_FILE) { $imageIds[] = $id; } } // To avoid code duplication $cascadeTypes = array(array('prefix' => 'tl', 'table' => 'templatelinks', 'ns' => 'tl_namespace', 'title' => 'tl_title', 'ids' => array_diff(array_keys($titles), $imageIds)), array('prefix' => 'il', 'table' => 'imagelinks', 'ns' => NS_FILE, 'title' => 'il_to', 'ids' => $imageIds)); foreach ($cascadeTypes as $type) { if (count($type['ids']) != 0) { $this->resetQueryParams(); $this->addTables(array('page_restrictions', $type['table'])); $this->addTables('page', 'page_source'); $this->addTables('page', 'page_target'); $this->addFields(array('pr_type', 'pr_level', 'pr_expiry', 'page_target.page_id AS page_target_id', 'page_source.page_namespace AS page_source_namespace', 'page_source.page_title AS page_source_title')); $this->addWhere(array("{$type['prefix']}_from = pr_page", 'page_target.page_namespace = ' . $type['ns'], 'page_target.page_title = ' . $type['title'], 'page_source.page_id = pr_page')); $this->addWhereFld('pr_cascade', 1); $this->addWhereFld('page_target.page_id', $type['ids']); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { $source = Title::makeTitle($row->page_source_namespace, $row->page_source_title); $a = array('type' => $row->pr_type, 'level' => $row->pr_level, 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601), 'source' => $source->getPrefixedText()); $protections[$row->page_target_id][] = $a; } $db->freeResult($res); } } } // We don't need to check for pt stuff if there are no nonexistent titles if ($fld_protection && count($missing)) { $this->resetQueryParams(); // Construct a custom WHERE clause that matches all titles in $missing $lb = new LinkBatch($missing); $this->addTables('protected_titles'); $this->addFields(array('pt_title', 'pt_namespace', 'pt_create_perm', 'pt_expiry')); $this->addWhere($lb->constructSet('pt', $db)); $res = $this->select(__METHOD__); $prottitles = array(); while ($row = $db->fetchObject($res)) { $prottitles[$row->pt_namespace][$row->pt_title][] = array('type' => 'create', 'level' => $row->pt_create_perm, 'expiry' => Block::decodeExpiry($row->pt_expiry, TS_ISO_8601)); } $db->freeResult($res); $images = array(); $others = array(); foreach ($missing as $title) { if ($title->getNamespace() == NS_FILE) { $images[] = $title->getDBKey(); } else { $others[] = $title; } } if (count($others) != 0) { $lb = new LinkBatch($others); $this->resetQueryParams(); $this->addTables(array('page_restrictions', 'page', 'templatelinks')); $this->addFields(array('pr_type', 'pr_level', 'pr_expiry', 'page_title', 'page_namespace', 'tl_title', 'tl_namespace')); $this->addWhere($lb->constructSet('tl', $db)); $this->addWhere('pr_page = page_id'); $this->addWhere('pr_page = tl_from'); $this->addWhereFld('pr_cascade', 1); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { $source = Title::makeTitle($row->page_namespace, $row->page_title); $a = array('type' => $row->pr_type, 'level' => $row->pr_level, 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601), 'source' => $source->getPrefixedText()); $prottitles[$row->tl_namespace][$row->tl_title][] = $a; } $db->freeResult($res); } if (count($images) != 0) { $this->resetQueryParams(); $this->addTables(array('page_restrictions', 'page', 'imagelinks')); $this->addFields(array('pr_type', 'pr_level', 'pr_expiry', 'page_title', 'page_namespace', 'il_to')); $this->addWhere('pr_page = page_id'); $this->addWhere('pr_page = il_from'); $this->addWhereFld('pr_cascade', 1); $this->addWhereFld('il_to', $images); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { $source = Title::makeTitle($row->page_namespace, $row->page_title); $a = array('type' => $row->pr_type, 'level' => $row->pr_level, 'expiry' => Block::decodeExpiry($row->pr_expiry, TS_ISO_8601), 'source' => $source->getPrefixedText()); $prottitles[NS_FILE][$row->il_to][] = $a; } $db->freeResult($res); } } // Run the talkid/subjectid query if ($fld_talkid || $fld_subjectid) { $talktitles = $subjecttitles = $talkids = $subjectids = array(); $everything = array_merge($titles, $missing); foreach ($everything as $t) { if (MWNamespace::isTalk($t->getNamespace())) { if ($fld_subjectid) { $subjecttitles[] = $t->getSubjectPage(); } } else { if ($fld_talkid) { $talktitles[] = $t->getTalkPage(); } } } if (count($talktitles) || count($subjecttitles)) { // Construct a custom WHERE clause that matches // all titles in $talktitles and $subjecttitles $lb = new LinkBatch(array_merge($talktitles, $subjecttitles)); $this->resetQueryParams(); $this->addTables('page'); $this->addFields(array('page_title', 'page_namespace', 'page_id')); $this->addWhere($lb->constructSet('page', $db)); $res = $this->select(__METHOD__); while ($row = $db->fetchObject($res)) { if (MWNamespace::isTalk($row->page_namespace)) { $talkids[MWNamespace::getSubject($row->page_namespace)][$row->page_title] = $row->page_id; } else { $subjectids[MWNamespace::getTalk($row->page_namespace)][$row->page_title] = $row->page_id; } } } } foreach ($titles as $pageid => $title) { $pageInfo = array('touched' => wfTimestamp(TS_ISO_8601, $pageTouched[$pageid]), 'lastrevid' => intval($pageLatest[$pageid]), 'counter' => intval($pageCounter[$pageid]), 'length' => intval($pageLength[$pageid])); if ($pageIsRedir[$pageid]) { $pageInfo['redirect'] = ''; } if ($pageIsNew[$pageid]) { $pageInfo['new'] = ''; } if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); $pageInfo['starttimestamp'] = wfTimestamp(TS_ISO_8601, time()); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $pageid, $title); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $pageInfo[$t . 'token'] = $val; } } } if ($fld_protection) { $pageInfo['protection'] = array(); if (isset($protections[$pageid])) { $pageInfo['protection'] = $protections[$pageid]; $result->setIndexedTagName($pageInfo['protection'], 'pr'); } } if ($fld_talkid && isset($talkids[$title->getNamespace()][$title->getDBKey()])) { $pageInfo['talkid'] = $talkids[$title->getNamespace()][$title->getDBKey()]; } if ($fld_subjectid && isset($subjectids[$title->getNamespace()][$title->getDBKey()])) { $pageInfo['subjectid'] = $subjectids[$title->getNamespace()][$title->getDBKey()]; } if ($fld_url) { $pageInfo['fullurl'] = $title->getFullURL(); $pageInfo['editurl'] = $title->getFullURL('action=edit'); } if ($fld_readable) { if ($title->userCanRead()) { $pageInfo['readable'] = ''; } } $result->addValue(array('query', 'pages'), $pageid, $pageInfo); } // Get properties for missing titles if requested if (!is_null($params['token']) || $fld_protection || $fld_talkid || $fld_subjectid || $fld_url || $fld_readable) { $res =& $result->getData(); foreach ($missing as $pageid => $title) { if (!is_null($params['token'])) { $tokenFunctions = $this->getTokenFunctions(); $res['query']['pages'][$pageid]['starttimestamp'] = wfTimestamp(TS_ISO_8601, time()); foreach ($params['token'] as $t) { $val = call_user_func($tokenFunctions[$t], $pageid, $title); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $res['query']['pages'][$pageid][$t . 'token'] = $val; } } } if ($fld_protection) { // Apparently the XML formatting code doesn't like array(null) // This is painful to fix, so we'll just work around it if (isset($prottitles[$title->getNamespace()][$title->getDBkey()])) { $res['query']['pages'][$pageid]['protection'] = $prottitles[$title->getNamespace()][$title->getDBkey()]; } else { $res['query']['pages'][$pageid]['protection'] = array(); } $result->setIndexedTagName($res['query']['pages'][$pageid]['protection'], 'pr'); } if ($fld_talkid && isset($talkids[$title->getNamespace()][$title->getDBKey()])) { $res['query']['pages'][$pageid]['talkid'] = $talkids[$title->getNamespace()][$title->getDBKey()]; } if ($fld_subjectid && isset($subjectids[$title->getNamespace()][$title->getDBKey()])) { $res['query']['pages'][$pageid]['subjectid'] = $subjectids[$title->getNamespace()][$title->getDBKey()]; } if ($fld_url) { $res['query']['pages'][$pageid]['fullurl'] = $title->getFullURL(); $res['query']['pages'][$pageid]['editurl'] = $title->getFullURL('action=edit'); } if ($fld_readable) { if ($title->userCanRead()) { $res['query']['pages'][$pageid]['readable'] = ''; } } } } }