public function testBatchAddWatch()
 {
     $itemOne = new WatchedItem($this->getMockUser(1), new TitleValue(0, 'Title1'), null);
     $itemTwo = new WatchedItem($this->getMockUser(3), Title::newFromText('Title2'), '20150101010101');
     $store = $this->getMockWatchedItemStore();
     $store->expects($this->exactly(2))->method('addWatchBatchForUser');
     $store->expects($this->at(0))->method('addWatchBatchForUser')->with($itemOne->getUser(), [$itemOne->getTitle()->getSubjectPage(), $itemOne->getTitle()->getTalkPage()]);
     $store->expects($this->at(1))->method('addWatchBatchForUser')->with($itemTwo->getUser(), [$itemTwo->getTitle()->getSubjectPage(), $itemTwo->getTitle()->getTalkPage()]);
     $this->setService('WatchedItemStore', $store);
     WatchedItem::batchAddWatch([$itemOne, $itemTwo]);
 }
 /**
  * Adds users to watchlist if:
  * - User is watching parent page
  * - User has 'watchlistsubpages' turned on
  *
  * @param $watchers array of user ID
  * @param $title Title object
  * @param $editor User object
  * @param $notificationTimeoutSql string timeout to the watchlist
  *
  * @author Jakub Kurcek <*****@*****.**>
  */
 public static function NotifyOnSubPageChange($watchers, $title, $editor, $notificationTimeoutSql)
 {
     wfProfileIn(__METHOD__);
     // Gets parent data
     $arrTitle = explode('/', $title->getDBkey());
     if (empty($arrTitle)) {
         wfProfileOut(__METHOD__);
         return true;
     }
     // make Title
     $t = reset($arrTitle);
     $newTitle = Title::newFromDBkey($t);
     if (!$newTitle instanceof Title) {
         return true;
     }
     $dbw = wfGetDB(DB_MASTER);
     /** @var $dbw Database */
     $res = $dbw->select(array('watchlist'), array('wl_user'), array('wl_title' => $newTitle->getDBkey(), 'wl_namespace' => $newTitle->getNamespace(), 'wl_user != ' . intval($editor->getID()), $notificationTimeoutSql), __METHOD__);
     // Gets user settings
     $parentpageWatchers = array();
     while ($row = $dbw->fetchObject($res)) {
         $userId = intval($row->wl_user);
         $tmpUser = User::newFromId($userId);
         if ($tmpUser->getBoolOption(self::PREFERENCES_ENTRY)) {
             $parentpageWatchers[] = $userId;
         }
         unset($tmpUser);
     }
     // Updates parent watchlist timestamp for $parentOnlyWatchers.
     $parentOnlyWatchers = array_diff($parentpageWatchers, $watchers);
     $wl = WatchedItem::fromUserTitle($editor, $newTitle);
     $wl->updateWatch($parentOnlyWatchers);
     wfProfileOut(__METHOD__);
     return true;
 }
Esempio n. 3
0
 /**
  * Get the timestamp when this page was updated since the user last saw it.
  *
  * @param User $user
  * @return string|null
  */
 public function getNotificationTimestamp($user = null)
 {
     global $wgUser;
     // Assume current user if none given
     if (!$user) {
         $user = $wgUser;
     }
     // Check cache first
     $uid = $user->getId();
     if (!$uid) {
         return false;
     }
     // avoid isset here, as it'll return false for null entries
     if (array_key_exists($uid, $this->mNotificationTimestamp)) {
         return $this->mNotificationTimestamp[$uid];
     }
     // Don't cache too much!
     if (count($this->mNotificationTimestamp) >= self::CACHE_MAX) {
         $this->mNotificationTimestamp = array();
     }
     $watchedItem = WatchedItem::fromUserTitle($user, $this);
     $this->mNotificationTimestamp[$uid] = $watchedItem->getNotificationTimestamp();
     return $this->mNotificationTimestamp[$uid];
 }
Esempio n. 4
0
 /**
  * Move a title to a new location
  *
  * @param $nt Title the new title
  * @param $auth Bool indicates whether $wgUser's permissions
  *  should be checked
  * @param $reason String the reason for the move
  * @param $createRedirect Bool Whether to create a redirect from the old title to the new title.
  *  Ignored if the user doesn't have the suppressredirect right.
  * @return Mixed true on success, getUserPermissionsErrors()-like array on failure
  */
 public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true)
 {
     global $wgUser;
     $err = $this->isValidMoveOperation($nt, $auth, $reason);
     if (is_array($err)) {
         // Auto-block user's IP if the account was "hard" blocked
         $wgUser->spreadAnyEditBlock();
         return $err;
     }
     // If it is a file, move it first. It is done before all other moving stuff is
     // done because it's hard to revert
     $dbw = wfGetDB(DB_MASTER);
     if ($this->getNamespace() == NS_FILE) {
         $file = wfLocalFile($this);
         if ($file->exists()) {
             $status = $file->move($nt);
             if (!$status->isOk()) {
                 return $status->getErrorsArray();
             }
         }
     }
     $dbw->begin();
     # If $file was a LocalFile, its transaction would have closed our own.
     $pageid = $this->getArticleID(self::GAID_FOR_UPDATE);
     $protected = $this->isProtected();
     $pageCountChange = ($createRedirect ? 1 : 0) - ($nt->exists() ? 1 : 0);
     // Do the actual move
     $err = $this->moveToInternal($nt, $reason, $createRedirect);
     if (is_array($err)) {
         # @todo FIXME: What about the File we have already moved?
         $dbw->rollback();
         return $err;
     }
     $redirid = $this->getArticleID();
     // Refresh the sortkey for this row.  Be careful to avoid resetting
     // cl_timestamp, which may disturb time-based lists on some sites.
     $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__);
     foreach ($prefixes as $prefixRow) {
         $prefix = $prefixRow->cl_sortkey_prefix;
         $catTo = $prefixRow->cl_to;
         $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($nt->getCategorySortkey($prefix)), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__);
     }
     if ($protected) {
         # Protect the redirect title as the title used to be...
         $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE'));
         # Update the protection log
         $log = new LogPage('protect');
         $comment = wfMsgForContent('prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText());
         if ($reason) {
             $comment .= wfMsgForContent('colon-separator') . $reason;
         }
         // @todo FIXME: $params?
         $log->addEntry('move_prot', $nt, $comment, array($this->getPrefixedText()));
     }
     # Update watchlists
     $oldnamespace = $this->getNamespace() & ~1;
     $newnamespace = $nt->getNamespace() & ~1;
     $oldtitle = $this->getDBkey();
     $newtitle = $nt->getDBkey();
     if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this, $nt);
     }
     # Update search engine
     $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey());
     $u->doUpdate();
     $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), '');
     $u->doUpdate();
     $dbw->commit();
     # Update site_stats
     if ($this->isContentPage() && !$nt->isContentPage()) {
         # No longer a content page
         # Not viewed, edited, removing
         $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange);
     } elseif (!$this->isContentPage() && $nt->isContentPage()) {
         # Now a content page
         # Not viewed, edited, adding
         $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange);
     } elseif ($pageCountChange) {
         # Redirect added
         $u = new SiteStatsUpdate(0, 0, 0, 1);
     } else {
         # Nothing special
         $u = false;
     }
     if ($u) {
         $u->doUpdate();
     }
     # Update message cache for interface messages
     if ($this->getNamespace() == NS_MEDIAWIKI) {
         # @bug 17860: old article can be deleted, if this the case,
         # delete it from message cache
         if ($this->getArticleID() === 0) {
             MessageCache::singleton()->replace($this->getDBkey(), false);
         } else {
             $oldarticle = new Article($this);
             MessageCache::singleton()->replace($this->getDBkey(), $oldarticle->getContent());
         }
     }
     if ($nt->getNamespace() == NS_MEDIAWIKI) {
         $newarticle = new Article($nt);
         MessageCache::singleton()->replace($nt->getDBkey(), $newarticle->getContent());
     }
     global $wgUser;
     wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid));
     return true;
 }
Esempio n. 5
0
 /**
  * Get a WatchedItem for this user and $title.
  *
  * @since 1.22 $checkRights parameter added
  * @param Title $title
  * @param int $checkRights Whether to check 'viewmywatchlist'/'editmywatchlist' rights.
  *     Pass WatchedItem::CHECK_USER_RIGHTS or WatchedItem::IGNORE_USER_RIGHTS.
  * @return WatchedItem
  */
 public function getWatchedItem($title, $checkRights = WatchedItem::CHECK_USER_RIGHTS)
 {
     $key = $checkRights . ':' . $title->getNamespace() . ':' . $title->getDBkey();
     if (isset($this->mWatchedItems[$key])) {
         return $this->mWatchedItems[$key];
     }
     if (count($this->mWatchedItems) >= self::MAX_WATCHED_ITEMS_CACHE) {
         $this->mWatchedItems = array();
     }
     $this->mWatchedItems[$key] = WatchedItem::fromUserTitle($this, $title, $checkRights);
     return $this->mWatchedItems[$key];
 }
Esempio n. 6
0
/**
 * Allow the user to clear their watchlist
 *
 * @param $out Output object
 * @param $request Request object
 * @param $par Parameters passed to the watchlist page
 * @return bool True if it's been taken care of; false indicates the watchlist
 * 				code needs to do something further
 */
function wlHandleClear(&$out, &$request, $par)
{
    # Check this function has something to do
    if ($request->getText('action') == 'clear' || $par == 'clear') {
        global $wgUser;
        $out->setPageTitle(wfMsgHtml('clearwatchlist'));
        $count = wlCountItems($wgUser);
        if ($count > 0) {
            # See if we're clearing or confirming
            if ($request->wasPosted() && $wgUser->matchEditToken($request->getText('token'), 'clearwatchlist')) {
                # Clearing, so do it and report the result
                $dbw =& wfGetDB(DB_MASTER);
                // WERELATE - don't remove pages in your trees; call WatchedItem::removeWatch
                // $dbw->delete( 'watchlist', array( 'wl_user' => $wgUser->mId ), 'wlHandleClear' );
                $sql = 'SELECT wl_namespace, wl_title FROM watchlist where wl_user='******' AND NOT EXISTS (SELECT fp_tree_id FROM familytree_page WHERE fp_namespace=(wl_namespace & ~1) AND fp_title=wl_title AND fp_user_id=wl_user)';
                $rows = $dbw->query($sql, 'wlHandleClear');
                while ($row = $dbw->fetchObject($rows)) {
                    $title = Title::makeTitle($row->wl_namespace, $row->wl_title);
                    if ($title) {
                        $wl = WatchedItem::fromUserTitle($wgUser, $title);
                        $wl->removeWatch();
                    }
                }
                $dbw->freeResult($rows);
                $out->addWikiText(wfMsg('watchlistcleardone', $count));
                $out->returnToMain();
            } else {
                # Confirming, so show a form
                $wlTitle = Title::makeTitle(NS_SPECIAL, 'Watchlist');
                $out->addHTML(wfElement('form', array('method' => 'post', 'action' => $wlTitle->getLocalUrl('action=clear')), NULL));
                $out->addWikiText(wfMsg('watchlistcount', $count));
                $out->addWikiText(wfMsg('watchlistcleartext'));
                $out->addHTML(wfElement('input', array('type' => 'hidden', 'name' => 'token', 'value' => $wgUser->editToken('clearwatchlist')), ''));
                $out->addHTML(wfElement('input', array('type' => 'submit', 'name' => 'submit', 'value' => wfMsgHtml('watchlistclearbutton')), ''));
                $out->addHTML(wfCloseElement('form'));
            }
            return true;
        } else {
            # Nothing on the watchlist; nothing to do here
            $out->addWikiText(wfMsg('nowatchlist'));
            $out->returnToMain();
            return true;
        }
    } else {
        return false;
    }
}
Esempio n. 7
0
 /**
  * Clear the user's notification timestamp for the given title.
  * If e-notif e-mails are on, they will receive notification mails on
  * the next change of the page if it's watched etc.
  * @param $title Title of the article to look at
  */
 public function clearNotification(&$title)
 {
     global $wgUseEnotif, $wgShowUpdatedMarker;
     # Do nothing if the database is locked to writes
     if (wfReadOnly()) {
         return;
     }
     if ($title->getNamespace() == NS_USER_TALK && $title->getText() == $this->getName()) {
         if (!wfRunHooks('UserClearNewTalkNotification', array(&$this))) {
             return;
         }
         $this->setNewtalk(false);
     }
     if (!$wgUseEnotif && !$wgShowUpdatedMarker) {
         return;
     }
     if ($this->isAnon()) {
         // Nothing else to do...
         return;
     }
     // Only update the timestamp if the page is being watched.
     // The query to find out if it is watched is cached both in memcached and per-invocation,
     // and when it does have to be executed, it can be on a slave
     // If this is the user's newtalk page, we always update the timestamp
     if ($title->getNamespace() == NS_USER_TALK && $title->getText() == $this->getName()) {
         $watched = true;
     } else {
         $watched = $this->isWatched($title);
     }
     // If the page is watched by the user (or may be watched), update the timestamp on any
     // any matching rows
     if ($watched) {
         $wl = WatchedItem::fromUserTitle($this, $title);
         $wl->clearWatch();
     }
 }
Esempio n. 8
0
 private function extractOutputData(WatchedItem $watchedItem, array $recentChangeInfo)
 {
     /* Determine the title of the page that has been changed. */
     $title = Title::makeTitle($watchedItem->getLinkTarget()->getNamespace(), $watchedItem->getLinkTarget()->getDBkey());
     $user = $this->getUser();
     /* Our output data. */
     $vals = [];
     $type = intval($recentChangeInfo['rc_type']);
     $vals['type'] = RecentChange::parseFromRCType($type);
     $anyHidden = false;
     /* Create a new entry in the result for the title. */
     if ($this->fld_title || $this->fld_ids) {
         // These should already have been filtered out of the query, but just in case.
         if ($type === RC_LOG && $recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION) {
             $vals['actionhidden'] = true;
             $anyHidden = true;
         }
         if ($type !== RC_LOG || LogEventsList::userCanBitfield($recentChangeInfo['rc_deleted'], LogPage::DELETED_ACTION, $user)) {
             if ($this->fld_title) {
                 ApiQueryBase::addTitleInfo($vals, $title);
             }
             if ($this->fld_ids) {
                 $vals['pageid'] = intval($recentChangeInfo['rc_cur_id']);
                 $vals['revid'] = intval($recentChangeInfo['rc_this_oldid']);
                 $vals['old_revid'] = intval($recentChangeInfo['rc_last_oldid']);
             }
         }
     }
     /* Add user data and 'anon' flag, if user is anonymous. */
     if ($this->fld_user || $this->fld_userid) {
         if ($recentChangeInfo['rc_deleted'] & Revision::DELETED_USER) {
             $vals['userhidden'] = true;
             $anyHidden = true;
         }
         if (Revision::userCanBitfield($recentChangeInfo['rc_deleted'], Revision::DELETED_USER, $user)) {
             if ($this->fld_userid) {
                 $vals['userid'] = (int) $recentChangeInfo['rc_user'];
                 // for backwards compatibility
                 $vals['user'] = (int) $recentChangeInfo['rc_user'];
             }
             if ($this->fld_user) {
                 $vals['user'] = $recentChangeInfo['rc_user_text'];
             }
             if (!$recentChangeInfo['rc_user']) {
                 $vals['anon'] = true;
             }
         }
     }
     /* Add flags, such as new, minor, bot. */
     if ($this->fld_flags) {
         $vals['bot'] = (bool) $recentChangeInfo['rc_bot'];
         $vals['new'] = $recentChangeInfo['rc_type'] == RC_NEW;
         $vals['minor'] = (bool) $recentChangeInfo['rc_minor'];
     }
     /* Add sizes of each revision. (Only available on 1.10+) */
     if ($this->fld_sizes) {
         $vals['oldlen'] = intval($recentChangeInfo['rc_old_len']);
         $vals['newlen'] = intval($recentChangeInfo['rc_new_len']);
     }
     /* Add the timestamp. */
     if ($this->fld_timestamp) {
         $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $recentChangeInfo['rc_timestamp']);
     }
     if ($this->fld_notificationtimestamp) {
         $vals['notificationtimestamp'] = $watchedItem->getNotificationTimestamp() == null ? '' : wfTimestamp(TS_ISO_8601, $watchedItem->getNotificationTimestamp());
     }
     /* Add edit summary / log summary. */
     if ($this->fld_comment || $this->fld_parsedcomment) {
         if ($recentChangeInfo['rc_deleted'] & Revision::DELETED_COMMENT) {
             $vals['commenthidden'] = true;
             $anyHidden = true;
         }
         if (Revision::userCanBitfield($recentChangeInfo['rc_deleted'], Revision::DELETED_COMMENT, $user)) {
             if ($this->fld_comment && isset($recentChangeInfo['rc_comment'])) {
                 $vals['comment'] = $recentChangeInfo['rc_comment'];
             }
             if ($this->fld_parsedcomment && isset($recentChangeInfo['rc_comment'])) {
                 $vals['parsedcomment'] = Linker::formatComment($recentChangeInfo['rc_comment'], $title);
             }
         }
     }
     /* Add the patrolled flag */
     if ($this->fld_patrol) {
         $vals['patrolled'] = $recentChangeInfo['rc_patrolled'] == 1;
         $vals['unpatrolled'] = ChangesList::isUnpatrolled((object) $recentChangeInfo, $user);
     }
     if ($this->fld_loginfo && $recentChangeInfo['rc_type'] == RC_LOG) {
         if ($recentChangeInfo['rc_deleted'] & LogPage::DELETED_ACTION) {
             $vals['actionhidden'] = true;
             $anyHidden = true;
         }
         if (LogEventsList::userCanBitfield($recentChangeInfo['rc_deleted'], LogPage::DELETED_ACTION, $user)) {
             $vals['logid'] = intval($recentChangeInfo['rc_logid']);
             $vals['logtype'] = $recentChangeInfo['rc_log_type'];
             $vals['logaction'] = $recentChangeInfo['rc_log_action'];
             $vals['logparams'] = LogFormatter::newFromRow($recentChangeInfo)->formatParametersForApi();
         }
     }
     if ($anyHidden && $recentChangeInfo['rc_deleted'] & Revision::DELETED_RESTRICTED) {
         $vals['suppressed'] = true;
     }
     return $vals;
 }
Esempio n. 9
0
 private function cache(WatchedItem $item)
 {
     $user = $item->getUser();
     $target = $item->getLinkTarget();
     $key = $this->getCacheKey($user, $target);
     $this->cache->set($key, $item);
     $this->cacheIndex[$target->getNamespace()][$target->getDBkey()][$user->getId()] = $key;
     $this->stats->increment('WatchedItemStore.cache');
 }
Esempio n. 10
0
function wrArticleSave(&$article, &$user, $text)
{
    $newTitle = Title::newFromRedirect($text);
    // can't use $article->content or SD:getRedirectToTitle because they return the wrong results
    if ($newTitle != null) {
        // if this article is a redirect
        $newTitle = StructuredData::getRedirectToTitle($newTitle, true);
        // get final redirect; unreliable on the article title for some reason
        $newRevision = StructuredData::getRevision($newTitle, false, true);
        $newText = $newRevision ? $newRevision->getText() : '';
        $summary = StructuredData::getWatchlistSummary($newTitle, $newText);
        WatchedItem::duplicateEntries($article->getTitle(), $newTitle, $summary);
        StructuredData::purgeTitle($newTitle, +1);
        StructuredData::requestIndex($newTitle);
        // remove watchers from redirected titles
        StructuredData::removeAllWatchers($article->getTitle());
    }
    return true;
}
Esempio n. 11
0
 /**
  * Check if the given title already is watched by the user, and if so
  * add watches on a new title. To be used for page renames and such.
  *
  * @param Title $ot Page title to duplicate entries from, if present
  * @param Title $nt Page title to add watches on
  * @static
  */
 function duplicateEntries($ot, $nt, $summary = null)
 {
     //WERELATE - add optional $summary parameter
     WatchedItem::doDuplicateEntries($ot->getSubjectPage(), $nt->getSubjectPage(), $summary);
     WatchedItem::doDuplicateEntries($ot->getTalkPage(), $nt->getTalkPage());
 }
Esempio n. 12
0
 public function testDuplicateEntries()
 {
     $oldTitle = Title::newFromText('OldTitle');
     $newTitle = Title::newFromText('NewTitle');
     $store = $this->getMockWatchedItemStore();
     $store->expects($this->once())->method('duplicateAllAssociatedEntries')->with($oldTitle, $newTitle);
     $this->setService('WatchedItemStore', $store);
     WatchedItem::duplicateEntries($oldTitle, $newTitle);
 }
Esempio n. 13
0
 /**
  * Send emails corresponding to the user $editor editing the page $title.
  * Also updates wl_notificationtimestamp.
  *
  * May be deferred via the job queue.
  *
  * @param $editor User object
  * @param $title Title object
  * @param $timestamp
  * @param $summary
  * @param $minorEdit
  * @param $oldid (default: false)
  * @param $action(Wikia)
  * @param $otherParam(Wikia)
  */
 public function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false, $action = '', $otherParam = array())
 {
     global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker, $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
     if ($title->getNamespace() < 0) {
         return;
     }
     # <Wikia>
     if (!wfRunHooks('AllowNotifyOnPageChange', array($editor, $title))) {
         return false;
     }
     if (!empty($otherParam['watchers'])) {
         $watchers = $otherParam['watchers'];
     }
     # </Wikia>
     // Build a list of users to notfiy
     $watchers = array();
     if ($wgEnotifWatchlist || $wgShowUpdatedMarker) {
         /* Wikia change begin - @author: wladek & tomek */
         /* RT#55604: Add a timeout to the watchlist email block */
         global $wgEnableWatchlistNotificationTimeout, $wgWatchlistNotificationTimeout;
         if (!empty($otherParam['notisnull'])) {
             $notificationTimeoutSql = "1";
         } elseif (!empty($wgEnableWatchlistNotificationTimeout) && isset($wgWatchlistNotificationTimeout)) {
             $blockTimeout = wfTimestamp(TS_MW, wfTimestamp(TS_UNIX, $timestamp) - intval($wgWatchlistNotificationTimeout));
             $notificationTimeoutSql = "wl_notificationtimestamp IS NULL OR wl_notificationtimestamp < '{$blockTimeout}'";
         } else {
             $notificationTimeoutSql = 'wl_notificationtimestamp IS NULL';
         }
         /* Wikia change end */
         $dbw = wfGetDB(DB_MASTER);
         $res = $dbw->select(array('watchlist'), array('wl_user'), array('wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace(), 'wl_user != ' . intval($editor->getID()), $notificationTimeoutSql), __METHOD__);
         foreach ($res as $row) {
             $watchers[] = intval($row->wl_user);
         }
         if ($watchers) {
             // Update wl_notificationtimestamp for all watching users except
             // the editor
             $wl = WatchedItem::fromUserTitle($editor, $title);
             $wl->updateWatch($watchers, $timestamp);
         }
         /* Wikia change begin - @author: Jakub Kurcek */
         wfRunHooks('NotifyOnSubPageChange', array($watchers, $title, $editor, $notificationTimeoutSql));
         /* Wikia change end */
     }
     $sendEmail = true;
     // If nobody is watching the page, and there are no users notified on all changes
     // don't bother creating a job/trying to send emails
     // $watchers deals with $wgEnotifWatchlist
     if (!count($watchers) && !count($wgUsersNotifiedOnAllChanges)) {
         $sendEmail = false;
         // Only send notification for non minor edits, unless $wgEnotifMinorEdits
         if (!$minorEdit || $wgEnotifMinorEdits && !$editor->isAllowed('nominornewtalk')) {
             $isUserTalkPage = $title->getNamespace() == NS_USER_TALK;
             if ($wgEnotifUserTalk && $isUserTalkPage && $this->canSendUserTalkEmail($editor, $title, $minorEdit)) {
                 $sendEmail = true;
             }
         }
     }
     if (!$sendEmail) {
         return;
     }
     if ($wgEnotifUseJobQ) {
         $params = array('editor' => $editor->getName(), 'editorID' => $editor->getID(), 'timestamp' => $timestamp, 'summary' => $summary, 'minorEdit' => $minorEdit, 'oldid' => $oldid, 'watchers' => $watchers, 'action' => $action, 'otherParam' => $othersParam);
         $job = new EnotifNotifyJob($title, $params);
         $job->insert();
     } else {
         $this->actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers, $action, $otherParam);
     }
 }
Esempio n. 14
0
 function duplicateEntries($ot, $nt)
 {
     # duplicate watchlist entries for the target page
     # When using ENotif, talkpages have distinct watchlist entries
     # existing talkpage entries in the watchlist will be moved, too
     WatchedItem::duplicateEntriesNs($ot, $nt, false);
     WatchedItem::duplicateEntriesNs($ot, $nt, true);
 }
Esempio n. 15
0
 /**
  * Back-end article deletion
  * Deletes the article with database consistency, writes logs, purges caches
  * Returns success
  */
 function doDeleteArticle($reason, $rc = true)
 {
     global $wgUseSquid, $wgDeferredUpdateList;
     global $wgPostCommitUpdateList, $wgUseTrackbacks;
     wfDebug(__METHOD__ . "\n");
     $dbw =& wfGetDB(DB_MASTER);
     $ns = $this->mTitle->getNamespace();
     $t = $this->mTitle->getDBkey();
     $id = $this->mTitle->getArticleID();
     if ($t == '' || $id == 0) {
         return false;
     }
     $u = new SiteStatsUpdate(0, 1, -(int) $this->isCountable($this->getContent()), -1);
     array_push($wgDeferredUpdateList, $u);
     // For now, shunt the revision data into the archive table.
     // Text is *not* removed from the text table; bulk storage
     // is left intact to avoid breaking block-compression or
     // immutable storage schemes.
     //
     // For backwards compatibility, note that some older archive
     // table entries will have ar_text and ar_flags fields still.
     //
     // In the future, we may keep revisions and mark them with
     // the rev_deleted field, which is reserved for this purpose.
     $dbw->insertSelect('archive', array('page', 'revision'), array('ar_namespace' => 'page_namespace', 'ar_title' => 'page_title', 'ar_comment' => 'rev_comment', 'ar_user' => 'rev_user', 'ar_user_text' => 'rev_user_text', 'ar_timestamp' => 'rev_timestamp', 'ar_minor_edit' => 'rev_minor_edit', 'ar_rev_id' => 'rev_id', 'ar_text_id' => 'rev_text_id'), array('page_id' => $id, 'page_id = rev_page'), __METHOD__);
     # Now that it's safely backed up, delete it
     $dbw->delete('revision', array('rev_page' => $id), __METHOD__);
     $dbw->delete('page', array('page_id' => $id), __METHOD__);
     if ($wgUseTrackbacks) {
         $dbw->delete('trackbacks', array('tb_page' => $id), __METHOD__);
     }
     # Clean up recentchanges entries...
     $dbw->delete('recentchanges', array('rc_namespace' => $ns, 'rc_title' => $t), __METHOD__);
     // WERELATE: remove from watchlists on delete
     if (Namespac::isMain($ns)) {
         $rows = $dbw->select(array('watchlist', 'user'), array('user_name'), array('wl_user=user_id', 'wl_namespace' => $ns, 'wl_title' => $t));
         while ($row = $dbw->fetchObject($rows)) {
             $user = User::newFromName($row->user_name, false);
             $wl = WatchedItem::fromUserTitle($user, $this->mTitle);
             $wl->removeWatch();
         }
         $dbw->freeResult($rows);
     }
     # Finally, clean up the link tables
     $t = $this->mTitle->getPrefixedDBkey();
     # Clear caches
     Article::onArticleDelete($this->mTitle);
     # Delete outgoing links
     $dbw->delete('pagelinks', array('pl_from' => $id));
     $dbw->delete('imagelinks', array('il_from' => $id));
     $dbw->delete('categorylinks', array('cl_from' => $id));
     $dbw->delete('templatelinks', array('tl_from' => $id));
     $dbw->delete('externallinks', array('el_from' => $id));
     $dbw->delete('langlinks', array('ll_from' => $id));
     # Log the deletion
     $log = new LogPage('delete', $rc);
     // WERELATE - add id as a log param
     $log->addEntry('delete', $this->mTitle, $reason, array($id));
     # Clear the cached article id so the interface doesn't act like we exist
     $this->mTitle->resetArticleID(0);
     $this->mTitle->mArticleID = 0;
     return true;
 }
Esempio n. 16
0
 /**
  * Move a title to a new location
  * @param &$nt \type{Title} the new title
  * @param $auth \type{\bool} indicates whether $wgUser's permissions
  *  should be checked
  * @param $reason \type{\string} The reason for the move
  * @param $createRedirect \type{\bool} Whether to create a redirect from the old title to the new title.
  *  Ignored if the user doesn't have the suppressredirect right.
  * @return \type{\mixed} true on success, getUserPermissionsErrors()-like array on failure
  */
 public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true)
 {
     $err = $this->isValidMoveOperation($nt, $auth, $reason);
     if (is_array($err)) {
         return $err;
     }
     // If it is a file, move it first. It is done before all other moving stuff is done because it's hard to revert
     $dbw = wfGetDB(DB_MASTER);
     if ($this->getNamespace() == NS_FILE) {
         $file = wfLocalFile($this);
         if ($file->exists()) {
             $status = $file->move($nt);
             if (!$status->isOk()) {
                 return $status->getErrorsArray();
             }
         }
     }
     $pageid = $this->getArticleID();
     $protected = $this->isProtected();
     if ($nt->exists()) {
         $err = $this->moveOverExistingRedirect($nt, $reason, $createRedirect);
         $pageCountChange = $createRedirect ? 0 : -1;
     } else {
         # Target didn't exist, do normal move.
         $err = $this->moveToNewTitle($nt, $reason, $createRedirect);
         $pageCountChange = $createRedirect ? 1 : 0;
     }
     if (is_array($err)) {
         return $err;
     }
     $redirid = $this->getArticleID();
     // Category memberships include a sort key which may be customized.
     // If it's left as the default (the page title), we need to update
     // the sort key to match the new title.
     //
     // Be careful to avoid resetting cl_timestamp, which may disturb
     // time-based lists on some sites.
     //
     // Warning -- if the sort key is *explicitly* set to the old title,
     // we can't actually distinguish it from a default here, and it'll
     // be set to the new title even though it really shouldn't.
     // It'll get corrected on the next edit, but resetting cl_timestamp.
     $dbw->update('categorylinks', array('cl_sortkey' => $nt->getPrefixedText(), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_sortkey' => $this->getPrefixedText()), __METHOD__);
     if ($protected) {
         # Protect the redirect title as the title used to be...
         $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE'));
         # Update the protection log
         $log = new LogPage('protect');
         $comment = wfMsgForContent('prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText());
         if ($reason) {
             $comment .= wfMsgForContent('colon-separator') . $reason;
         }
         $log->addEntry('move_prot', $nt, $comment, array($this->getPrefixedText()));
         // FIXME: $params?
     }
     # Update watchlists
     $oldnamespace = $this->getNamespace() & ~1;
     $newnamespace = $nt->getNamespace() & ~1;
     $oldtitle = $this->getDBkey();
     $newtitle = $nt->getDBkey();
     if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this, $nt);
     }
     # Update search engine
     $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey());
     $u->doUpdate();
     $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), '');
     $u->doUpdate();
     # Update site_stats
     if ($this->isContentPage() && !$nt->isContentPage()) {
         # No longer a content page
         # Not viewed, edited, removing
         $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange);
     } elseif (!$this->isContentPage() && $nt->isContentPage()) {
         # Now a content page
         # Not viewed, edited, adding
         $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange);
     } elseif ($pageCountChange) {
         # Redirect added
         $u = new SiteStatsUpdate(0, 0, 0, 1);
     } else {
         # Nothing special
         $u = false;
     }
     if ($u) {
         $u->doUpdate();
     }
     # Update message cache for interface messages
     if ($nt->getNamespace() == NS_MEDIAWIKI) {
         global $wgMessageCache;
         # @bug 17860: old article can be deleted, if this the case,
         # delete it from message cache
         if ($this->getArticleID() === 0) {
             $wgMessageCache->replace($this->getDBkey(), false);
         } else {
             $oldarticle = new Article($this);
             $wgMessageCache->replace($this->getDBkey(), $oldarticle->getContent());
         }
         $newarticle = new Article($nt);
         $wgMessageCache->replace($nt->getDBkey(), $newarticle->getContent());
     }
     global $wgUser;
     wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid));
     return true;
 }
Esempio n. 17
0
 private function processActionOnWatchlist($user, $followedUserName, $action)
 {
     wfProfileIn(__METHOD__);
     $watchTitle = Title::newFromText($followedUserName, NS_USER);
     if ($watchTitle instanceof Title) {
         $wl = new WatchedItem();
         $wl->mTitle = $watchTitle;
         $wl->id = $user->getId();
         $wl->ns = $watchTitle->getNamespace();
         $wl->ti = $watchTitle->getDBkey();
         if ($action === 'add') {
             $wl->addWatch();
         } elseif ($action === 'remove') {
             $wl->removeWatch();
         }
     } else {
         //just-in-case -- it shouldn't happen but if it does we want to know about it
         Wikia::log(__METHOD__, false, 'WALL_HOOK_ERROR: No title instance while syncing follows. User name: ' . $followedUserName);
     }
     wfProfileOut(__METHOD__);
 }
Esempio n. 18
0
<?php

require_once "commandLine.inc";
require_once "{$IP}/extensions/structuredNamespaces/StructuredData.php";
require_once "{$IP}/extensions/familytree/FamilyTreePropagator.php";
require_once "{$IP}/includes/Title.php";
$db =& wfGetDB(DB_MASTER);
$rows = $db->query("select page_namespace, page_title from page where page_is_redirect > 0 and (page_namespace = 108 or page_namespace = 110)");
while ($row = $db->fetchObject($rows)) {
    $title = Title::makeTitle($row->page_namespace, $row->page_title);
    $newTitle = StructuredData::getRedirectToTitle($title);
    if ($title->getPrefixedText() != $newTitle->getPrefixedText()) {
        //		print "title=" . $title->getPrefixedText() . " newTitle=" . $newTitle->getPrefixedText() . "\n";
        // from wrArticleSave
        WatchedItem::duplicateEntries($title, $newTitle);
    }
}
$db->freeResult($rows);
Esempio n. 19
0
 /**
  * Move a title to a new location
  *
  * @param Title $nt The new title
  * @param bool $auth Indicates whether $wgUser's permissions
  *  should be checked
  * @param string $reason The reason for the move
  * @param bool $createRedirect Whether to create a redirect from the old title to the new title.
  *  Ignored if the user doesn't have the suppressredirect right.
  * @return array|bool True on success, getUserPermissionsErrors()-like array on failure
  */
 public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true)
 {
     global $wgUser;
     $err = $this->isValidMoveOperation($nt, $auth, $reason);
     if (is_array($err)) {
         // Auto-block user's IP if the account was "hard" blocked
         $wgUser->spreadAnyEditBlock();
         return $err;
     }
     // Check suppressredirect permission
     if ($auth && !$wgUser->isAllowed('suppressredirect')) {
         $createRedirect = true;
     }
     wfRunHooks('TitleMove', array($this, $nt, $wgUser));
     // If it is a file, move it first.
     // It is done before all other moving stuff is done because it's hard to revert.
     $dbw = wfGetDB(DB_MASTER);
     if ($this->getNamespace() == NS_FILE) {
         $file = wfLocalFile($this);
         if ($file->exists()) {
             $status = $file->move($nt);
             if (!$status->isOk()) {
                 return $status->getErrorsArray();
             }
         }
         // Clear RepoGroup process cache
         RepoGroup::singleton()->clearCache($this);
         RepoGroup::singleton()->clearCache($nt);
         # clear false negative cache
     }
     $dbw->begin(__METHOD__);
     # If $file was a LocalFile, its transaction would have closed our own.
     $pageid = $this->getArticleID(self::GAID_FOR_UPDATE);
     $protected = $this->isProtected();
     // Do the actual move
     $this->moveToInternal($nt, $reason, $createRedirect);
     // Refresh the sortkey for this row.  Be careful to avoid resetting
     // cl_timestamp, which may disturb time-based lists on some sites.
     $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__);
     foreach ($prefixes as $prefixRow) {
         $prefix = $prefixRow->cl_sortkey_prefix;
         $catTo = $prefixRow->cl_to;
         $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($nt->getCategorySortkey($prefix)), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__);
     }
     $redirid = $this->getArticleID();
     if ($protected) {
         # Protect the redirect title as the title used to be...
         $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE'));
         # Update the protection log
         $log = new LogPage('protect');
         $comment = wfMessage('prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText())->inContentLanguage()->text();
         if ($reason) {
             $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason;
         }
         // @todo FIXME: $params?
         $logId = $log->addEntry('move_prot', $nt, $comment, array($this->getPrefixedText()), $wgUser);
         // reread inserted pr_ids for log relation
         $insertedPrIds = $dbw->select('page_restrictions', 'pr_id', array('pr_page' => $redirid), __METHOD__);
         $logRelationsValues = array();
         foreach ($insertedPrIds as $prid) {
             $logRelationsValues[] = $prid->pr_id;
         }
         $log->addRelations('pr_id', $logRelationsValues, $logId);
     }
     // Update *_from_namespace fields as needed
     if ($this->getNamespace() != $nt->getNamespace()) {
         $dbw->update('pagelinks', array('pl_from_namespace' => $nt->getNamespace()), array('pl_from' => $pageid), __METHOD__);
         $dbw->update('templatelinks', array('tl_from_namespace' => $nt->getNamespace()), array('tl_from' => $pageid), __METHOD__);
         $dbw->update('imagelinks', array('il_from_namespace' => $nt->getNamespace()), array('il_from' => $pageid), __METHOD__);
     }
     # Update watchlists
     $oldtitle = $this->getDBkey();
     $newtitle = $nt->getDBkey();
     $oldsnamespace = MWNamespace::getSubject($this->getNamespace());
     $newsnamespace = MWNamespace::getSubject($nt->getNamespace());
     if ($oldsnamespace != $newsnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this, $nt);
     }
     $dbw->commit(__METHOD__);
     wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid, $reason));
     return true;
 }
 /**
  * Creates or changes a review for a page. Called by remote handler.
  * @return bool Allow other hooked methods to be executed. Always true.
  */
 public static function doEditReview()
 {
     if (BsCore::checkAccessAdmission('workflowedit') === false) {
         return true;
     }
     $aAnswer = array('success' => true, 'errors' => array(), 'messages' => array());
     $oUser = BsCore::loadCurrentUser();
     $oReview = BsExtensionManager::getExtension('Review');
     $userIsSysop = in_array('sysop', $oUser->getGroups());
     //TODO: getEffectiveGroups()?
     if (!$userIsSysop && !$oUser->isAllowed('workflowedit')) {
         $aAnswer['success'] = false;
         $aAnswer['messages'][] = wfMessage('bs-review-save-norights')->plain();
         return json_encode($aAnswer);
     }
     global $wgRequest;
     $paramRvPid = $wgRequest->getInt('pid', -1);
     // Check for id 0 prevents special pages to be put on a review
     if (empty($paramRvPid)) {
         $aAnswer['success'] = false;
         $aAnswer['messages'][] = wfMessage('bs-review-save-noid')->plain();
         return json_encode($aAnswer);
     }
     $oReviewProcess = BsReviewProcess::newFromPid($paramRvPid);
     $bIsEdit = false;
     if (is_object($oReviewProcess) && $oReviewProcess->hasSteps()) {
         $bIsEdit = true;
     }
     if (!$userIsSysop && $oReviewProcess && BsConfig::get('MW::Review::CheckOwner') && $oReviewProcess->owner != $oUser->getID()) {
         $aAnswer['success'] = false;
         $aAnswer['messages'][] = wfMessage('bs-review-save-norights')->plain();
         return json_encode($aAnswer);
     }
     $paramCmd = $wgRequest->getVal('cmd', '');
     $paramSaveTmpl = $wgRequest->getInt('save_tmpl', 0);
     if (!($paramCmd === false)) {
         switch ($paramCmd) {
             case 'insert':
                 $aErrors = array();
                 $review = BsReviewProcess::newFromJSON($wgRequest->getVal('review', ''), $aErrors);
                 if (is_array($aErrors) && count($aErrors) > 0) {
                     $aAnswer['success'] = false;
                     foreach ($aErrors as $sError) {
                         $aAnswer['messages'][] = wfMessage('bs-review-' . $sError)->plain();
                     }
                     return json_encode($aAnswer);
                 }
                 $review->setOwner($oUser->getID());
                 $oOldReview = BsReviewProcess::newFromPid($paramRvPid);
                 $update = is_object($oOldReview) ? $oOldReview->getPid() : false;
                 BsReviewProcess::removeReviewSteps($paramRvPid);
                 if ($paramSaveTmpl == 1) {
                     $paramTmplChoice = $wgRequest->getInt('tmpl_choice', -1);
                     $paramTmplName = $wgRequest->getVal('tmpl_name', '');
                     $review->asTemplate($paramTmplChoice, $paramTmplName);
                 }
                 if (!is_array($review->steps)) {
                     $aAnswer['success'] = false;
                     $aAnswer['messages'][] = wfMessage('bs-review-save-nosteps')->plain();
                     return json_encode($aAnswer);
                 }
                 if ($review->store($update)) {
                     $oTitle = Title::newFromID($paramRvPid);
                     $oTitle->invalidateCache();
                     $oWatchlist = WatchedItem::fromUserTitle($oUser, $oTitle);
                     if (!$oWatchlist->isWatched()) {
                         $oWatchlist->addWatch();
                     }
                     $aParams = array('action' => $bIsEdit ? 'modify' : 'create', 'target' => $oTitle, 'comment' => '', 'params' => null, 'doer' => $oUser);
                     $oReview->oLogger->addEntry($aParams['action'], $aParams['target'], $aParams['comment'], $aParams['params'], $aParams['doer']);
                     $aAnswer['messages'][] = wfMessage('bs-review-save-success')->plain();
                     // Identify owner
                     $oReviewProcess = BsReviewProcess::newFromPid($paramRvPid);
                     $oReview->emailNotifyNextUsers($oReviewProcess);
                     return json_encode($aAnswer);
                 } else {
                     $aAnswer['success'] = false;
                     $aAnswer['messages'][] = wfMessage('bs-review-save-error')->plain();
                     return json_encode($aAnswer);
                 }
                 break;
                 // 22.08.13 STM: WTF?
             // 22.08.13 STM: WTF?
             case 'delete':
                 BsReviewProcess::removeReviews($paramRvPid);
                 $oTitle = Title::newFromID($paramRvPid);
                 $oTitle->invalidateCache();
                 $oWatchlist = WatchedItem::fromUserTitle($oUser, $oTitle);
                 if ($oWatchlist->isWatched()) {
                     $oWatchlist->removeWatch();
                 }
                 $aParams = array('action' => 'delete', 'target' => $oTitle, 'comment' => '', 'params' => null, 'doer' => $oUser);
                 $oReview->oLogger->addEntry($aParams['action'], $aParams['target'], $aParams['comment'], $aParams['params'], $aParams['doer']);
                 $aAnswer['messages'][] = wfMessage('bs-review-save-removed')->plain();
                 return json_encode($aAnswer);
                 break;
         }
     }
     return true;
 }
Esempio n. 21
0
 /**
  * Move a title to a new location
  * @param Title &$nt the new title
  * @param bool $auth indicates whether $wgUser's permissions
  * 	should be checked
  * @param string $reason The reason for the move
  * @param bool $createRedirect Whether to create a redirect from the old title to the new title.
  *  Ignored if the user doesn't have the suppressredirect right.
  * @return mixed true on success, message name on failure
  */
 public function moveTo(&$nt, $auth = true, $reason = '', $createRedirect = true)
 {
     $err = $this->isValidMoveOperation($nt, $auth);
     if (is_string($err)) {
         return $err;
     }
     $pageid = $this->getArticleID();
     if ($nt->exists()) {
         $this->moveOverExistingRedirect($nt, $reason, $createRedirect);
         $pageCountChange = $createRedirect ? 0 : -1;
     } else {
         # Target didn't exist, do normal move.
         $this->moveToNewTitle($nt, $reason, $createRedirect);
         $pageCountChange = $createRedirect ? 1 : 0;
     }
     $redirid = $this->getArticleID();
     // Category memberships include a sort key which may be customized.
     // If it's left as the default (the page title), we need to update
     // the sort key to match the new title.
     //
     // Be careful to avoid resetting cl_timestamp, which may disturb
     // time-based lists on some sites.
     //
     // Warning -- if the sort key is *explicitly* set to the old title,
     // we can't actually distinguish it from a default here, and it'll
     // be set to the new title even though it really shouldn't.
     // It'll get corrected on the next edit, but resetting cl_timestamp.
     $dbw = wfGetDB(DB_MASTER);
     $dbw->update('categorylinks', array('cl_sortkey' => $nt->getPrefixedText(), 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_sortkey' => $this->getPrefixedText()), __METHOD__);
     # Update watchlists
     $oldnamespace = $this->getNamespace() & ~1;
     $newnamespace = $nt->getNamespace() & ~1;
     $oldtitle = $this->getDBkey();
     $newtitle = $nt->getDBkey();
     if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this, $nt);
     }
     # Update search engine
     $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey());
     $u->doUpdate();
     $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), '');
     $u->doUpdate();
     # Update site_stats
     if ($this->isContentPage() && !$nt->isContentPage()) {
         # No longer a content page
         # Not viewed, edited, removing
         $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange);
     } elseif (!$this->isContentPage() && $nt->isContentPage()) {
         # Now a content page
         # Not viewed, edited, adding
         $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange);
     } elseif ($pageCountChange) {
         # Redirect added
         $u = new SiteStatsUpdate(0, 0, 0, 1);
     } else {
         # Nothing special
         $u = false;
     }
     if ($u) {
         $u->doUpdate();
     }
     # Update message cache for interface messages
     if ($nt->getNamespace() == NS_MEDIAWIKI) {
         global $wgMessageCache;
         $oldarticle = new Article($this);
         $wgMessageCache->replace($this->getDBkey(), $oldarticle->getContent());
         $newarticle = new Article($nt);
         $wgMessageCache->replace($nt->getDBkey(), $newarticle->getContent());
     }
     global $wgUser;
     wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid));
     return true;
 }
Esempio n. 22
0
 /**
  * auto-unwatch all comments if blog post was unwatched
  *
  * @access public
  * @static
  */
 public static function UnwatchBlogComments($oUser, $oArticle)
 {
     wfProfileIn(__METHOD__);
     if (wfReadOnly()) {
         wfProfileOut(__METHOD__);
         return true;
     }
     /* @var $oUser User */
     if (!$oUser instanceof User) {
         wfProfileOut(__METHOD__);
         return true;
     }
     /* @var $oArticle WikiPage */
     if (!$oArticle instanceof Article) {
         wfProfileOut(__METHOD__);
         return true;
     }
     /* @var $oTitle Title */
     $oTitle = $oArticle->getTitle();
     if (!$oTitle instanceof Title) {
         wfProfileOut(__METHOD__);
         return true;
     }
     $list = array();
     $dbr = wfGetDB(DB_SLAVE);
     $like = $dbr->buildLike(sprintf("%s/", $oTitle->getDBkey()), $dbr->anyString());
     $res = $dbr->select('watchlist', '*', array('wl_user' => $oUser->getId(), 'wl_namespace' => NS_BLOG_ARTICLE_TALK, "wl_title {$like}"), __METHOD__);
     if ($res->numRows() > 0) {
         while ($row = $res->fetchObject()) {
             $oCommentTitle = Title::makeTitleSafe($row->wl_namespace, $row->wl_title);
             if ($oCommentTitle instanceof Title) {
                 $list[] = $oCommentTitle;
             }
         }
         $dbr->freeResult($res);
     }
     if (!empty($list)) {
         foreach ($list as $oCommentTitle) {
             $oWItem = WatchedItem::fromUserTitle($oUser, $oCommentTitle);
             $oWItem->removeWatch();
         }
         $oUser->invalidateCache();
     }
     wfProfileOut(__METHOD__);
     return true;
 }
 public function testGetNotificationTimestamp_falseOnNotWatched()
 {
     $user = $this->getUser();
     $title = Title::newFromText('WatchedItemIntegrationTestPage');
     WatchedItem::fromUserTitle($user, $title)->removeWatch();
     $this->assertFalse(WatchedItem::fromUserTitle($user, $title)->isWatched());
     $this->assertFalse(WatchedItem::fromUserTitle($user, $title)->getNotificationTimestamp());
 }
Esempio n. 24
0
 /**
  * update local watchlist 
  */
 private function updateLocalWatchlistForUser($iUserId, $sTitle, $iNamespace)
 {
     $dbw = wfGetDB(DB_MASTER);
     $oUser = User::newFromId($iUserId);
     if (!is_object($oUser)) {
         return false;
     }
     $oTitle = Title::makeTitle($iNamespace, $sTitle);
     if (!is_object($oTitle)) {
         return false;
     }
     $wl = WatchedItem::fromUserTitle($oUser, $oTitle);
     $wl->clearWatch();
     return true;
 }
Esempio n. 25
0
 /**
  * Move a title to a new location
  * @param Title &$nt the new title
  * @param bool $auth indicates whether $wgUser's permissions
  * 	should be checked
  * @return mixed true on success, message name on failure
  */
 public function moveTo(&$nt, $auth = true, $reason = '')
 {
     $err = $this->isValidMoveOperation($nt, $auth);
     if (is_string($err)) {
         return $err;
     }
     $pageid = $this->getArticleID();
     if ($nt->exists()) {
         $this->moveOverExistingRedirect($nt, $reason);
         $pageCountChange = 0;
     } else {
         # Target didn't exist, do normal move.
         $this->moveToNewTitle($nt, $reason);
         $pageCountChange = 1;
     }
     $redirid = $this->getArticleID();
     # Fixing category links (those without piped 'alternate' names) to be sorted under the new title
     $dbw = wfGetDB(DB_MASTER);
     $categorylinks = $dbw->tableName('categorylinks');
     $sql = "UPDATE {$categorylinks} SET cl_sortkey=" . $dbw->addQuotes($nt->getPrefixedText()) . " WHERE cl_from=" . $dbw->addQuotes($pageid) . " AND cl_sortkey=" . $dbw->addQuotes($this->getPrefixedText());
     $dbw->query($sql, 'SpecialMovepage::doSubmit');
     # Update watchlists
     $oldnamespace = $this->getNamespace() & ~1;
     $newnamespace = $nt->getNamespace() & ~1;
     $oldtitle = $this->getDBkey();
     $newtitle = $nt->getDBkey();
     if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this, $nt);
     }
     # Update search engine
     $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey());
     $u->doUpdate();
     $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), '');
     $u->doUpdate();
     # Update site_stats
     if ($this->isContentPage() && !$nt->isContentPage()) {
         # No longer a content page
         # Not viewed, edited, removing
         $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange);
     } elseif (!$this->isContentPage() && $nt->isContentPage()) {
         # Now a content page
         # Not viewed, edited, adding
         $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange);
     } elseif ($pageCountChange) {
         # Redirect added
         $u = new SiteStatsUpdate(0, 0, 0, 1);
     } else {
         # Nothing special
         $u = false;
     }
     if ($u) {
         $u->doUpdate();
     }
     global $wgUser;
     wfRunHooks('TitleMoveComplete', array(&$this, &$nt, &$wgUser, $pageid, $redirid));
     return true;
 }
Esempio n. 26
0
 /**
  * Update wl_notificationtimestamp for all watching users except the editor
  */
 private function updateWatchedItem(array $watchers)
 {
     $wl = WatchedItem::fromUserTitle($this->editor, $this->title);
     $wl->updateWatch($watchers, $this->timestamp);
 }
Esempio n. 27
0
 /**
  * Stop watching an article
  */
 function removeWatch($title)
 {
     $wl = WatchedItem::fromUserTitle($this, $title);
     $wl->removeWatch();
     $this->invalidateCache();
 }
Esempio n. 28
0
 /**
  * @param User $user
  * @param string $reason
  * @param bool $createRedirect
  * @return Status
  */
 public function move(User $user, $reason, $createRedirect)
 {
     global $wgCategoryCollation;
     Hooks::run('TitleMove', array($this->oldTitle, $this->newTitle, $user));
     // If it is a file, move it first.
     // It is done before all other moving stuff is done because it's hard to revert.
     $dbw = wfGetDB(DB_MASTER);
     if ($this->oldTitle->getNamespace() == NS_FILE) {
         $file = wfLocalFile($this->oldTitle);
         $file->load(File::READ_LATEST);
         if ($file->exists()) {
             $status = $file->move($this->newTitle);
             if (!$status->isOk()) {
                 return $status;
             }
         }
         // Clear RepoGroup process cache
         RepoGroup::singleton()->clearCache($this->oldTitle);
         RepoGroup::singleton()->clearCache($this->newTitle);
         # clear false negative cache
     }
     $dbw->begin(__METHOD__);
     # If $file was a LocalFile, its transaction would have closed our own.
     $pageid = $this->oldTitle->getArticleID(Title::GAID_FOR_UPDATE);
     $protected = $this->oldTitle->isProtected();
     // Do the actual move
     $this->moveToInternal($user, $this->newTitle, $reason, $createRedirect);
     // Refresh the sortkey for this row.  Be careful to avoid resetting
     // cl_timestamp, which may disturb time-based lists on some sites.
     // @todo This block should be killed, it's duplicating code
     // from LinksUpdate::getCategoryInsertions() and friends.
     $prefixes = $dbw->select('categorylinks', array('cl_sortkey_prefix', 'cl_to'), array('cl_from' => $pageid), __METHOD__);
     if ($this->newTitle->getNamespace() == NS_CATEGORY) {
         $type = 'subcat';
     } elseif ($this->newTitle->getNamespace() == NS_FILE) {
         $type = 'file';
     } else {
         $type = 'page';
     }
     foreach ($prefixes as $prefixRow) {
         $prefix = $prefixRow->cl_sortkey_prefix;
         $catTo = $prefixRow->cl_to;
         $dbw->update('categorylinks', array('cl_sortkey' => Collation::singleton()->getSortKey($this->newTitle->getCategorySortkey($prefix)), 'cl_collation' => $wgCategoryCollation, 'cl_type' => $type, 'cl_timestamp=cl_timestamp'), array('cl_from' => $pageid, 'cl_to' => $catTo), __METHOD__);
     }
     $redirid = $this->oldTitle->getArticleID();
     if ($protected) {
         # Protect the redirect title as the title used to be...
         $dbw->insertSelect('page_restrictions', 'page_restrictions', array('pr_page' => $redirid, 'pr_type' => 'pr_type', 'pr_level' => 'pr_level', 'pr_cascade' => 'pr_cascade', 'pr_user' => 'pr_user', 'pr_expiry' => 'pr_expiry'), array('pr_page' => $pageid), __METHOD__, array('IGNORE'));
         // Build comment for log
         $comment = wfMessage('prot_1movedto2', $this->oldTitle->getPrefixedText(), $this->newTitle->getPrefixedText())->inContentLanguage()->text();
         if ($reason) {
             $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason;
         }
         // reread inserted pr_ids for log relation
         $insertedPrIds = $dbw->select('page_restrictions', 'pr_id', array('pr_page' => $redirid), __METHOD__);
         $logRelationsValues = array();
         foreach ($insertedPrIds as $prid) {
             $logRelationsValues[] = $prid->pr_id;
         }
         // Update the protection log
         $logEntry = new ManualLogEntry('protect', 'move_prot');
         $logEntry->setTarget($this->newTitle);
         $logEntry->setComment($comment);
         $logEntry->setPerformer($user);
         $logEntry->setParameters(array('4::oldtitle' => $this->oldTitle->getPrefixedText()));
         $logEntry->setRelations(array('pr_id' => $logRelationsValues));
         $logId = $logEntry->insert();
         $logEntry->publish($logId);
     }
     // Update *_from_namespace fields as needed
     if ($this->oldTitle->getNamespace() != $this->newTitle->getNamespace()) {
         $dbw->update('pagelinks', array('pl_from_namespace' => $this->newTitle->getNamespace()), array('pl_from' => $pageid), __METHOD__);
         $dbw->update('templatelinks', array('tl_from_namespace' => $this->newTitle->getNamespace()), array('tl_from' => $pageid), __METHOD__);
         $dbw->update('imagelinks', array('il_from_namespace' => $this->newTitle->getNamespace()), array('il_from' => $pageid), __METHOD__);
     }
     # Update watchlists
     $oldtitle = $this->oldTitle->getDBkey();
     $newtitle = $this->newTitle->getDBkey();
     $oldsnamespace = MWNamespace::getSubject($this->oldTitle->getNamespace());
     $newsnamespace = MWNamespace::getSubject($this->newTitle->getNamespace());
     if ($oldsnamespace != $newsnamespace || $oldtitle != $newtitle) {
         WatchedItem::duplicateEntries($this->oldTitle, $this->newTitle);
     }
     $dbw->commit(__METHOD__);
     Hooks::run('TitleMoveComplete', array(&$this->oldTitle, &$this->newTitle, &$user, $pageid, $redirid, $reason));
     return Status::newGood();
 }
Esempio n. 29
0
 /**
  * Check if the given title already is watched by the user, and if so
  * add watches on a new title. To be used for page renames and such.
  *
  * @param $ot Title: page title to duplicate entries from, if present
  * @param $nt Title: page title to add watches on
  */
 public static function duplicateEntries($ot, $nt)
 {
     WatchedItem::doDuplicateEntries($ot->getSubjectPage(), $nt->getSubjectPage());
     WatchedItem::doDuplicateEntries($ot->getTalkPage(), $nt->getTalkPage());
 }
Esempio n. 30
0
 /**
  * Do the rename operation
  */
 function rename()
 {
     global $wgMemc, $wgDBname, $wgAuth;
     $fname = 'RenameuserSQL::rename';
     wfProfileIn($fname);
     $dbw =& wfGetDB(DB_MASTER);
     foreach ($this->tables as $table => $field) {
         $dbw->update($table, array($field => $this->new), array($field => $this->old), $fname);
     }
     $fields = array('user_touched' => $dbw->timestamp());
     // WERELATE: added isVandal
     if ($this->isVandal) {
         $fields = $fields + array('user_password' => '12345678901234567890123456789012', 'user_email' => '');
     }
     $dbw->update('user', $fields, array('user_name' => $this->new), $fname);
     // Clear the user cache
     $wgMemc->delete("{$wgDBname}:user:id:{$this->uid}");
     //WERELATE - newFromId doesn't exist
     //		$user = User::newFromId( $this->uid );
     $user = User::newFromName($this->new, false);
     $user->setID($this->uid);
     // WERELATE: added isVandal
     if ($this->isVandal) {
         // delete watchlist
         $rows = $dbw->select('watchlist', array('wl_namespace', 'wl_title'), array('wl_user' => $this->uid));
         while ($row = $dbw->fetchObject($rows)) {
             $title = Title::makeTitle($row->wl_namespace, $row->wl_title);
             if ($title && !$title->isTalkPage()) {
                 $wl = WatchedItem::fromUserTitle($user, $title);
                 $wl->removeWatch();
             }
         }
         $dbw->freeResult($rows);
     }
     // Inform authentication plugin of the change
     $wgAuth->updateExternalDB($user);
     wfProfileOut($fname);
 }