public function execute($par)
 {
     global $wgRequest, $wgLang;
     $shownavigation = is_object($this->specialPage) && !$this->specialPage->including();
     $defaults = array('hideliu' => false, 'hidepatrolled' => false, 'hidebots' => false, 'namespace' => "0", 'username' => '', 'offset' => 0, 'limit' => 50);
     $options = $defaults;
     if ($par) {
         $bits = preg_split('/\\s*,\\s*/', trim($par));
         foreach ($bits as $bit) {
             if ('shownav' == $bit) {
                 $shownavigation = true;
             }
             if ('hideliu' === $bit) {
                 $options['hideliu'] = true;
             }
             if ('hidepatrolled' == $bit) {
                 $options['hidepatrolled'] = true;
             }
             if ('hidebots' == $bit) {
                 $options['hidebots'] = true;
             }
             if (is_numeric($bit)) {
                 $options['limit'] = intval($bit);
             }
             $m = array();
             if (preg_match('/^limit=(\\d+)$/', $bit, $m)) {
                 $options['limit'] = intval($m[1]);
             }
             if (preg_match('/^offset=(\\d+)$/', $bit, $m)) {
                 $options['offset'] = intval($m[1]);
             }
             if (preg_match('/^namespace=(.*)$/', $bit, $m)) {
                 $ns = $wgLang->getNsIndex($m[1]);
                 if ($ns !== false) {
                     $options['namespace'] = $ns;
                 }
             }
         }
     }
     // Override all values from requests, if specified
     foreach ($defaults as $v => $t) {
         if (is_bool($t)) {
             $options[$v] = $wgRequest->getBool($v, $options[$v]);
         } elseif (is_int($t)) {
             $options[$v] = $wgRequest->getInt($v, $options[$v]);
         } elseif (is_string($t)) {
             $options[$v] = $wgRequest->getText($v, $options[$v]);
         }
     }
     // Validate limit and offset params
     if ($options['limit'] <= 0) {
         $options['limit'] = $defaults['limit'];
     }
     if ($options['offset'] < 0) {
         $options['offset'] = $defaults['offset'];
     }
     $nondefaults = array();
     foreach ($options as $v => $t) {
         if ($v === 'offset') {
             continue;
         }
         # Reset offset if parameters change
         wfAppendToArrayIfNotDefault($v, $t, $defaults, $nondefaults);
     }
     # bind to class
     $this->options = $options;
     $this->nondefaults = $nondefaults;
     if (!$this->doFeed($wgRequest->getVal('feed'), $options['limit'])) {
         $this->doQuery($options['offset'], $options['limit'], $shownavigation);
     }
 }
Exemple #2
0
/**
 * Constructor
 * @todo Document $par parameter.
 * @param $par String: FIXME
 */
function wfSpecialWatchlist($par)
{
    global $wgUser, $wgOut, $wgLang, $wgMemc, $wgRequest, $wgContLang;
    global $wgUseWatchlistCache, $wgWLCacheTimeout, $wgDBname;
    global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
    global $wgEnotifWatchlist;
    $fname = 'wfSpecialWatchlist';
    $skin =& $wgUser->getSkin();
    $specialTitle = Title::makeTitle(NS_SPECIAL, 'Watchlist');
    $wgOut->setRobotPolicy('noindex,nofollow');
    # Anons don't get a watchlist
    if ($wgUser->isAnon()) {
        $wgOut->setPageTitle(wfMsg('watchnologin'));
        $llink = $skin->makeKnownLinkObj(Title::makeTitle(NS_SPECIAL, 'Userlogin'), wfMsgHtml('loginreqlink'), 'returnto=' . $specialTitle->getPrefixedUrl());
        $wgOut->addHtml(wfMsgWikiHtml('watchlistanontext', $llink));
        return;
    } else {
        $wgOut->setPageTitle(wfMsg('watchlist'));
        $wgOut->setSubtitle(wfMsgWikiHtml('watchlistfor', htmlspecialchars($wgUser->getName())));
    }
    if (wlHandleClear($wgOut, $wgRequest, $par)) {
        return;
    }
    $defaults = array('days' => floatval($wgUser->getOption('watchlistdays')), 'hideOwn' => (int) $wgUser->getBoolOption('watchlisthideown'), 'hideBots' => (int) $wgUser->getBoolOption('watchlisthidebots'), 'namespace' => 'all');
    extract($defaults);
    # Extract variables from the request, falling back to user preferences or
    # other default values if these don't exist
    $prefs['days'] = floatval($wgUser->getOption('watchlistdays'));
    $prefs['hideown'] = $wgUser->getBoolOption('watchlisthideown');
    $prefs['hidebots'] = $wgUser->getBoolOption('watchlisthidebots');
    # Get query variables
    $days = $wgRequest->getVal('days', $prefs['days']);
    $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
    $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
    # Get namespace value, if supplied, and prepare a WHERE fragment
    $nameSpace = $wgRequest->getIntOrNull('namespace');
    if (!is_null($nameSpace)) {
        $nameSpace = intval($nameSpace);
        $nameSpaceClause = " AND rc_namespace = {$nameSpace}";
    } else {
        $nameSpace = '';
        $nameSpaceClause = '';
    }
    # Watchlist editing
    $action = $wgRequest->getVal('action');
    $remove = $wgRequest->getVal('remove');
    $id = $wgRequest->getArray('id');
    $uid = $wgUser->getID();
    if ($wgEnotifWatchlist && $wgRequest->getVal('reset') && $wgRequest->wasPosted()) {
        $wgUser->clearAllNotifications($uid);
    }
    # Deleting items from watchlist
    if ($action == 'submit' && isset($remove) && is_array($id)) {
        $wgOut->addWikiText(wfMsg('removingchecked'));
        $wgOut->addHTML('<p>');
        foreach ($id as $one) {
            $t = Title::newFromURL($one);
            if (!is_null($t)) {
                // WERELATE - run UnwatchArticle hooks; fix UnwatchArticle hook below to UnwatchArticleComplete
                $article = new Article($t);
                if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$article))) {
                    $wl = WatchedItem::fromUserTitle($wgUser, $t);
                    if ($wl->removeWatch() === false) {
                        $wgOut->addHTML("<br />\n" . wfMsg('couldntremove', htmlspecialchars($one)));
                    } else {
                        wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$article));
                        $wgOut->addHTML(' (' . htmlspecialchars($one) . ')');
                    }
                }
            } else {
                $wgOut->addHTML("<br />\n" . wfMsg('iteminvalidname', htmlspecialchars($one)));
            }
        }
        $wgOut->addHTML("<br />\n" . wfMsg('wldone') . "</p>\n");
    }
    if ($wgUseWatchlistCache) {
        $memckey = "{$wgDBname}:watchlist:id:" . $wgUser->getId();
        $cache_s = @$wgMemc->get($memckey);
        if ($cache_s) {
            $wgOut->addWikiText(wfMsg('wlsaved'));
            $wgOut->addHTML($cache_s);
            return;
        }
    }
    $dbr =& wfGetDB(DB_SLAVE);
    extract($dbr->tableNames('page', 'revision', 'watchlist', 'recentchanges'));
    $sql = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_user={$uid}";
    $res = $dbr->query($sql, $fname);
    $s = $dbr->fetchObject($res);
    #	Patch *** A1 *** (see A2 below)
    #	adjust for page X, talk:page X, which are both stored separately, but treated together
    $nitems = floor($s->n / 2);
    #	$nitems = $s->n;
    if ($nitems == 0) {
        $wgOut->addWikiText(wfMsg('nowatchlist'));
        return;
    }
    if (is_null($days) || !is_numeric($days)) {
        $big = 1000;
        /* The magical big */
        // WERELATE - don't change default; pages don't change that often
        //		if($nitems > $big) {
        # Set default cutoff shorter
        //			$days = $defaults['days'] = (12.0 / 24.0); # 12 hours...
        //		} else {
        $days = $defaults['days'];
        # default cutoff for shortlisters
        //		}
    } else {
        $days = floatval($days);
    }
    // Dump everything here
    $nondefaults = array();
    wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
    if ($days <= 0) {
        $docutoff = '';
        $cutoff = false;
        $npages = wfMsg('watchlistall1');
    } else {
        $docutoff = "AND rev_timestamp > '" . ($cutoff = $dbr->timestamp(time() - intval($days * 86400))) . "'";
        /*
        $sql = "SELECT COUNT(*) AS n FROM $page, $revision  WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
        $res = $dbr->query( $sql, $fname );
        $s = $dbr->fetchObject( $res );
        $npages = $s->n;
        */
        $npages = 40000 * $days;
    }
    /* Edit watchlist form */
    if ($wgRequest->getBool('edit') || $par == 'edit') {
        $wgOut->addWikiText(wfMsg('watchlistcontains', $wgLang->formatNum($nitems)) . "\n\n" . wfMsg('watcheditlist'));
        $wgOut->addHTML('<form action=\'' . $specialTitle->escapeLocalUrl('action=submit') . "' method='post'>\n");
        #		Patch A2
        #		The following was proposed by KTurner 07.11.2004 to T.Gries
        #		$sql = "SELECT distinct (wl_namespace & ~1),wl_title FROM $watchlist WHERE wl_user=$uid";
        $sql = "SELECT wl_namespace, wl_title, page_is_redirect FROM {$watchlist} LEFT JOIN {$page} ON wl_namespace = page_namespace AND wl_title = page_title WHERE wl_user={$uid}";
        $res = $dbr->query($sql, $fname);
        # Batch existence check
        $linkBatch = new LinkBatch();
        while ($row = $dbr->fetchObject($res)) {
            $linkBatch->addObj(Title::makeTitleSafe($row->wl_namespace, $row->wl_title));
        }
        $linkBatch->execute();
        if ($dbr->numRows($res) > 0) {
            $dbr->dataSeek($res, 0);
        }
        # Let's do the time warp again!
        $sk = $wgUser->getSkin();
        $list = array();
        while ($s = $dbr->fetchObject($res)) {
            $list[$s->wl_namespace][$s->wl_title] = $s->page_is_redirect;
        }
        // TODO: Display a TOC
        foreach ($list as $ns => $titles) {
            if (Namespac::isTalk($ns)) {
                continue;
            }
            if ($ns != NS_MAIN) {
                $wgOut->addHTML('<h2>' . $wgContLang->getFormattedNsText($ns) . '</h2>');
            }
            $wgOut->addHTML('<ul>');
            foreach ($titles as $title => $redir) {
                $titleObj = Title::makeTitle($ns, $title);
                if (is_null($titleObj)) {
                    $wgOut->addHTML('<!-- bad title "' . htmlspecialchars($s->wl_title) . '" in namespace ' . $s->wl_namespace . " -->\n");
                } else {
                    global $wgContLang;
                    $toolLinks = array();
                    $titleText = $titleObj->getPrefixedText();
                    $pageLink = $sk->makeLinkObj($titleObj);
                    $toolLinks[] = $sk->makeLinkObj($titleObj->getTalkPage(), $wgLang->getNsText(NS_TALK));
                    if ($titleObj->exists()) {
                        $toolLinks[] = $sk->makeKnownLinkObj($titleObj, wfMsgHtml('history_short'), 'action=history');
                    }
                    $toolLinks = '(' . implode(' | ', $toolLinks) . ')';
                    $checkbox = '<input type="checkbox" name="id[]" value="' . htmlspecialchars($titleObj->getPrefixedText()) . '" /> ' . ($wgContLang->isRTL() ? '&rlm;' : '&lrm;');
                    if ($redir) {
                        $spanopen = '<span class="watchlistredir">';
                        $spanclosed = '</span>';
                    } else {
                        $spanopen = $spanclosed = '';
                    }
                    $wgOut->addHTML("<li>{$checkbox}{$spanopen}{$pageLink}{$spanclosed} {$toolLinks}</li>\n");
                }
            }
            $wgOut->addHTML('</ul>');
        }
        $wgOut->addHTML("<input type='submit' name='remove' value=\"" . htmlspecialchars(wfMsg("removechecked")) . "\" />\n" . "</form>\n");
        return;
    }
    # If the watchlist is relatively short, it's simplest to zip
    # down its entirety and then sort the results.
    # If it's relatively long, it may be worth our while to zip
    # through the time-sorted page list checking for watched items.
    # Up estimate of watched items by 15% to compensate for talk pages...
    # Toggles
    $andHideOwn = $hideOwn ? "AND (rc_user <> {$uid})" : '';
    $andHideBots = $hideBots ? "AND (rc_bot = 0)" : '';
    # Show watchlist header
    $header = '';
    if ($wgUser->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
        $header .= wfMsg('wlheader-enotif') . "\n";
    }
    if ($wgEnotifWatchlist && $wgShowUpdatedMarker) {
        $header .= wfMsg('wlheader-showupdated') . "\n";
    }
    # Toggle watchlist content (all recent edits or just the latest)
    if ($wgUser->getOption('extendwatchlist')) {
        $andLatest = '';
        $limitWatchlist = 'LIMIT ' . intval($wgUser->getOption('wllimit'));
    } else {
        $andLatest = 'AND rc_this_oldid=page_latest';
        $limitWatchlist = '';
    }
    # TODO: Consider removing the third parameter
    $header .= wfMsg('watchdetails', $wgLang->formatNum($nitems), $wgLang->formatNum($npages), '', $specialTitle->getFullUrl('edit=yes'));
    $wgOut->addWikiText($header);
    if ($wgEnotifWatchlist && $wgShowUpdatedMarker) {
        $wgOut->addHTML('<form action="' . $specialTitle->escapeLocalUrl() . '" method="post"><input type="submit" name="dummy" value="' . htmlspecialchars(wfMsg('enotif_reset')) . '" /><input type="hidden" name="reset" value="all" /></form>' . "\n\n");
    }
    // WERELATE - handle changed view
    if ($wgRequest->getBool('changed') || $par == 'changed') {
        $wgOut->addHTML('<hr /><h2>All pages changed since last visited</h2><ul><li><a href="' . $specialTitle->getFullUrl() . '">Show recently-changed pages</a></li></ul>');
        $sql = 'select wl_namespace, wl_title from watchlist where wl_user='******' and wl_notificationtimestamp > \'0\'';
        $res = $dbr->query($sql, $fname);
        $sk = $wgUser->getSkin();
        $changed = '';
        $count = 0;
        while ($obj = $dbr->fetchObject($res)) {
            $t = Title::makeTitle($obj->wl_namespace, $obj->wl_title);
            $historylink = $sk->makeKnownLinkObj($t, 'hist', wfArrayToCGI(array('action' => 'history')));
            $articlelink = $sk->makeKnownLinkObj($t);
            $changed .= "<li> ( {$historylink} ) . . {$articlelink}</li>\n";
            $count += 1;
        }
        $dbr->freeResult($res);
        $wgOut->addHTML("<h3>{$count} page(s)</h3>\n<ul>" . $changed . '</ul>');
        return;
    }
    // WERELATE - remove join with page table
    $sql = "SELECT\n\t  rc_namespace AS page_namespace, rc_title AS page_title,\n\t  rc_comment AS rev_comment, rc_cur_id AS page_id,\n\t  rc_user AS rev_user, rc_user_text AS rev_user_text,\n\t  rc_timestamp AS rev_timestamp, rc_minor AS rev_minor_edit,\n\t  rc_this_oldid AS rev_id,\n\t  rc_last_oldid, rc_id, rc_patrolled,\n\t  rc_new AS page_is_new,wl_notificationtimestamp\n\t  FROM {$watchlist},{$recentchanges}\n\t  WHERE wl_user={$uid}\n\t  AND wl_namespace=rc_namespace\n\t  AND wl_title=rc_title\n\t  AND rc_timestamp > '{$cutoff}'\n\t  {$andHideOwn}\n\t  {$andHideBots}\n\t  {$nameSpaceClause}\n\t  ORDER BY rc_timestamp DESC\n\t  {$limitWatchlist}";
    $res = $dbr->query($sql, $fname);
    // WERELATE - moved up from below so we can calculate $numRows inside the loop
    //	$numRows = $dbr->numRows( $res );
    $numRows = 0;
    $list = ChangesList::newFromUser($wgUser);
    $rcs = $list->beginRecentChangesList();
    $counter = 1;
    // WERELATE - added array of seen pagetitles
    $seen = array();
    while ($obj = $dbr->fetchObject($res)) {
        $nsTitle = "{$obj->page_namespace}:{$obj->page_title}";
        if (!$andLatest || !isset($seen[$nsTitle])) {
            $seen[$nsTitle] = 1;
            $numRows++;
            # Make fake RC entry
            $rc = RecentChange::newFromCurRow($obj, $obj->rc_last_oldid);
            $rc->counter = $counter++;
            if ($wgShowUpdatedMarker) {
                $updated = $obj->wl_notificationtimestamp;
            } else {
                // Same visual appearance as MW 1.4
                $updated = true;
            }
            if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
                $sql3 = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_title='" . wfStrencode($obj->page_title) . "' AND wl_namespace='{$obj->page_namespace}'";
                $res3 = $dbr->query($sql3, DB_READ, $fname);
                $x = $dbr->fetchObject($res3);
                $rc->numberofWatchingusers = $x->n;
            } else {
                $rc->numberofWatchingusers = 0;
            }
            $rcs .= $list->recentChangesLine($rc, $updated);
        }
    }
    $rcs .= $list->endRecentChangesList();
    $dbr->freeResult($res);
    /* Start bottom header */
    // WERELATE - add link to changed view
    //	$wgOut->addHTML( "<hr />\n<p>" );
    $wgOut->addHTML('<hr /><h2>Recently-changed pages</h2><ul><li><a href="' . $specialTitle->getFullUrl('changed=yes') . '">Show all pages changed since last visited</a></li></ul><br/><p>');
    if ($days >= 1) {
        $wgOut->addWikiText(wfMsg('rcnote', $wgLang->formatNum($numRows), $wgLang->formatNum($days), $wgLang->timeAndDate(wfTimestampNow(), true)) . '<br />', false);
    } elseif ($days > 0) {
        $wgOut->addWikiText(wfMsg('wlnote', $wgLang->formatNum($numRows), $wgLang->formatNum(round($days * 24))) . '<br />', false);
    }
    $wgOut->addHTML("\n" . wlCutoffLinks($days, 'Watchlist', $nondefaults) . "<br />\n");
    # Spit out some control panel links
    $thisTitle = Title::makeTitle(NS_SPECIAL, 'Watchlist');
    $skin = $wgUser->getSkin();
    $linkElements = array('hideOwn' => 'wlhideshowown', 'hideBots' => 'wlhideshowbots');
    # Problems encountered using the fancier method
    $label = $hideBots ? wfMsgHtml('show') : wfMsgHtml('hide');
    $linkBits = wfArrayToCGI(array('hideBots' => 1 - (int) $hideBots), $nondefaults);
    $link = $skin->makeKnownLinkObj($thisTitle, $label, $linkBits);
    $links[] = wfMsgHtml('wlhideshowbots', $link);
    $label = $hideOwn ? wfMsgHtml('show') : wfMsgHtml('hide');
    $linkBits = wfArrayToCGI(array('hideOwn' => 1 - (int) $hideOwn), $nondefaults);
    $link = $skin->makeKnownLinkObj($thisTitle, $label, $linkBits);
    $links[] = wfMsgHtml('wlhideshowown', $link);
    $wgOut->addHTML(implode(' | ', $links));
    # Form for namespace filtering
    $thisAction = $thisTitle->escapeLocalUrl();
    $nsForm = "<form method=\"post\" action=\"{$thisAction}\">\n";
    $nsForm .= "<label for=\"namespace\">" . wfMsgExt('namespace', array('parseinline')) . "</label> ";
    $nsForm .= HTMLnamespaceselector($nameSpace, '') . "\n";
    $nsForm .= $hideOwn ? "<input type=\"hidden\" name=\"hideown\" value=\"1\" />\n" : "";
    $nsForm .= $hideBots ? "<input type=\"hidden\" name=\"hidebots\" value=\"1\" />\n" : "";
    $nsForm .= "<input type=\"hidden\" name=\"days\" value=\"" . $days . "\" />\n";
    $nsForm .= "<input type=\"submit\" name=\"submit\" value=\"" . wfMsgExt('allpagessubmit', array('escape')) . "\" />\n";
    $nsForm .= "</form>\n";
    $wgOut->addHTML($nsForm);
    if ($numRows == 0) {
        $wgOut->addWikitext("<br />" . wfMsg('watchnochange'), false);
        $wgOut->addHTML("</p>\n");
        return;
    }
    $wgOut->addHTML("</p>\n");
    /* End bottom header */
    // WERELATE - change $s to $rcs
    $wgOut->addHTML($rcs);
    if ($wgUseWatchlistCache) {
        $wgMemc->set($memckey, $s, $wgWLCacheTimeout);
    }
}
/**
 * Constructor
 */
function wfSpecialRecentchanges($par, $specialPage)
{
    global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
    global $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
    global $wgAllowCategorizedRecentChanges;
    $fname = 'wfSpecialRecentchanges';
    $userGroups = $wgUser->getGroups();
    if (!$wgUser->isAllowed('patrol') || in_array('patrolblock', $userGroups)) {
        $wgOut->errorpage('nosuchspecialpage', 'nospecialpagetext');
        return;
    }
    # Get query parameters
    $feedFormat = $wgRequest->getVal('feed');
    /* Checkbox values can't be true by default, because
     * we cannot differentiate between unset and not set at all
     */
    $defaults = array('days' => $wgUser->getDefaultOption('rcdays'), 'limit' => $wgUser->getDefaultOption('rclimit'), 'hideminor' => false, 'hidebots' => true, 'hideanons' => false, 'hideliu' => false, 'hidepatrolled' => false, 'hidemyself' => false, 'from' => '', 'namespace' => null, 'invert' => false, 'categories_any' => false, 'reverse' => false, 'featured' => false, 'categories_any' => false);
    extract($defaults);
    $days = $wgUser->getOption('rcdays', $defaults['days']);
    $days = $wgRequest->getInt('days', $days);
    $limit = $wgUser->getOption('rclimit', $defaults['limit']);
    #	list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
    $limit = $wgRequest->getInt('limit', $limit);
    /* order of selection: url > preferences > default */
    $hideminor = $wgRequest->getBool('hideminor', $wgUser->getOption('hideminor') ? true : $defaults['hideminor']);
    # As a feed, use limited settings only
    if ($feedFormat) {
        global $wgFeedLimit;
        if ($limit > $wgFeedLimit) {
            $limit = $wgFeedLimit;
        }
    } else {
        $namespace = $wgRequest->getIntOrNull('namespace');
        $invert = $wgRequest->getBool('invert', $defaults['invert']);
        //XXADDED
        $reverse = $wgRequest->getBool('reverse', $defaults['reverse']);
        $featured = $wgRequest->getBool('featured', $defaults['featured']);
        $hidebots = $wgRequest->getBool('hidebots', $defaults['hidebots']);
        $hideanons = $wgRequest->getBool('hideanons', $defaults['hideanons']);
        $hideliu = $wgRequest->getBool('hideliu', $defaults['hideliu']);
        $hidepatrolled = $wgRequest->getBool('hidepatrolled', $defaults['hidepatrolled']);
        $hidemyself = $wgRequest->getBool('hidemyself', $defaults['hidemyself']);
        $from = $wgRequest->getVal('from', $defaults['from']);
        # Get query parameters from path
        if ($par) {
            $bits = preg_split('/\\s*,\\s*/', trim($par));
            foreach ($bits as $bit) {
                if ('hidebots' == $bit) {
                    $hidebots = 1;
                }
                if ('bots' == $bit) {
                    $hidebots = 0;
                }
                if ('hideminor' == $bit) {
                    $hideminor = 1;
                }
                if ('minor' == $bit) {
                    $hideminor = 0;
                }
                if ('hideliu' == $bit) {
                    $hideliu = 1;
                }
                if ('hidepatrolled' == $bit) {
                    $hidepatrolled = 1;
                }
                if ('hideanons' == $bit) {
                    $hideanons = 1;
                }
                if ('hidemyself' == $bit) {
                    $hidemyself = 1;
                }
                if (is_numeric($bit)) {
                    $limit = $bit;
                }
                $m = array();
                if (preg_match('/^limit=(\\d+)$/', $bit, $m)) {
                    $limit = $m[1];
                }
                if (preg_match('/^days=(\\d+)$/', $bit, $m)) {
                    $days = $m[1];
                }
            }
        }
    }
    if ($limit < 0 || $limit > 5000) {
        $limit = $defaults['limit'];
    }
    # Database connection and caching
    $dbr = wfGetDB(DB_SLAVE);
    list($recentchanges, $watchlist) = $dbr->tableNamesN('recentchanges', 'watchlist');
    $cutoff_unixtime = time() - $days * 86400;
    $cutoff_unixtime = $cutoff_unixtime - $cutoff_unixtime % 86400;
    $cutoff = $dbr->timestamp($cutoff_unixtime);
    if (preg_match('/^[0-9]{14}$/', $from) and $from > wfTimestamp(TS_MW, $cutoff)) {
        $cutoff = $dbr->timestamp($from);
    } else {
        $from = $defaults['from'];
    }
    # 10 seconds server-side caching max
    $wgOut->setSquidMaxage(0);
    # Get last modified date, for client caching
    # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
    $lastmod = $dbr->selectField('recentchanges', 'MAX(rc_timestamp)', false, $fname);
    if ($feedFormat || !$wgUseRCPatrol) {
        if ($lastmod && $wgOut->checkLastModified($lastmod)) {
            # Client cache fresh and headers sent, nothing more to do.
            return;
        }
    }
    # It makes no sense to hide both anons and logged-in users
    # Where this occurs, force anons to be shown
    if ($hideanons && $hideliu) {
        $hideanons = false;
    }
    # Form WHERE fragments for all the options
    $hidem = $hideminor ? 'AND rc_minor = 0' : '';
    $hidem .= $hidebots ? ' AND rc_bot = 0' : '';
    $hidem .= $hideliu ? ' AND rc_user = 0' : '';
    $hidem .= $wgUseRCPatrol && $hidepatrolled ? ' AND rc_patrolled = 0' : '';
    $hidem .= $hideanons ? ' AND rc_user != 0' : '';
    if ($hidemyself) {
        if ($wgUser->getID()) {
            $hidem .= ' AND rc_user != ' . $wgUser->getID();
        } else {
            $hidem .= ' AND rc_user_text != ' . $dbr->addQuotes($wgUser->getName());
        }
    }
    # Namespace filtering
    $hidem .= is_null($namespace) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
    //XXADDED
    $order = $reverse ? " ASC" : "DESC";
    $ft = $featured ? " AND page_is_featured = 1 " : "";
    // This is the big thing!
    $uid = $wgUser->getID();
    //XXCHANGED
    // Perform query
    $forceclause = $dbr->useIndexClause("rc_timestamp");
    $sql2 = "SELECT * FROM {$recentchanges} {$forceclause}" . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . " LEFT OUTER JOIN page ON page_title=rc_title AND page_namespace=rc_namespace " . "WHERE rc_timestamp >= '{$cutoff}' {$hidem} {$ft} " . "ORDER BY rc_timestamp {$order} ";
    $sql2 = $dbr->limitResult($sql2, $limit, 0);
    $res = $dbr->query($sql2, $fname);
    // Fetch results, prepare a batch link existence check query
    $rows = array();
    $batch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $rows[] = $row;
        if (!$feedFormat) {
            // User page and talk links
            $batch->add(NS_USER, $row->rc_user_text);
            $batch->add(NS_USER_TALK, $row->rc_user_text);
        }
    }
    $dbr->freeResult($res);
    if ($feedFormat) {
        rcOutputFeed($rows, $feedFormat, $limit, $hideminor, $lastmod);
    } else {
        # Web output...
        // Run existence checks
        $batch->execute();
        $any = $wgRequest->getBool('categories_any', $defaults['categories_any']);
        // Output header
        if (!$specialPage->including()) {
            $wgOut->addWikiText('<div class="minor_text">' . wfMsgForContentNoTrans("recentchangestext") . '<br /></div>');
            // Dump everything here
            $nondefaults = array();
            wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('limit', $limit, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideminor', $hideminor, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidebots', $hidebots, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideanons', $hideanons, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideliu', $hideliu, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidemyself', $hidemyself, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('from', $from, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('namespace', $namespace, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('invert', $invert, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('categories_any', $any, $defaults, $nondefaults);
            // Add end of the texts
            $wgOut->addHTML('<div class="rcoptions">' . rcOptionsPanel($defaults, $nondefaults) . "\n");
            //XXCHANGED
            $wgOut->addHTML(rcNamespaceForm($namespace, $invert, $reverse, $featured, $nondefaults, $any) . '</div>' . "\n");
            //XXADDED
            global $wgLanguageCode;
            if ($wgUser->getID() > 0 && $wgLanguageCode == 'en') {
                $sk = $wgUser->getSkin();
                $url = $wgRequest->getRequestURL();
                if ($wgRequest->getVal('refresh', null) != null) {
                    $url = str_replace("&refresh=1", "", $url);
                    $url = str_replace("?refresh=1", "", $url);
                    $wgOut->addHTML("<a href='{$url}' class='button secondary'>" . wfMsg('rc_turn_refresh_off') . "</a>");
                } else {
                    if (strpos($url, "?") !== false) {
                        $url .= "&refresh=1";
                    } else {
                        $url .= "?refresh=1";
                    }
                    $wgOut->addHTML("<a href='{$url}' class='button secondary'>" . wfMsg('rc_turn_refresh_on') . "</a>");
                }
                $wgOut->addHTML("&nbsp;<a class='button secondary' href='#' onclick=\"open('/index.php?title=Special:RCBuddy&hidepatrolled=1&limit=200&featured=1', '', 'scrollbars=no,status=no,width=570,height=200,resizable=yes,titlebar=no');\">RC Buddy</a>");
            }
        }
        // And now for the content
        $wgOut->setSyndicated(true);
        $list = ChangesList::newFromUser($wgUser);
        if ($wgAllowCategorizedRecentChanges) {
            $categories = trim($wgRequest->getVal('categories', ""));
            $categories = str_replace("|", "\n", $categories);
            $categories = explode("\n", $categories);
            rcFilterByCategories($rows, $categories, $any);
        }
        $s = $list->beginRecentChangesList();
        $s .= "<div id='recentchanges'>\n";
        $counter = 1;
        $showWatcherCount = $wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching');
        $watcherCache = array();
        foreach ($rows as $obj) {
            if ($limit == 0) {
                break;
            }
            if (!($hideminor && $obj->rc_minor) && !($hidepatrolled && $obj->rc_patrolled)) {
                $rc = RecentChange::newFromRow($obj);
                $rc->counter = $counter++;
                if ($wgShowUpdatedMarker && !empty($obj->wl_notificationtimestamp) && $obj->rc_timestamp >= $obj->wl_notificationtimestamp) {
                    $rc->notificationtimestamp = true;
                } else {
                    $rc->notificationtimestamp = false;
                }
                $rc->numberofWatchingusers = 0;
                // Default
                if ($showWatcherCount && $obj->rc_namespace >= 0) {
                    if (!isset($watcherCache[$obj->rc_namespace][$obj->rc_title])) {
                        $watcherCache[$obj->rc_namespace][$obj->rc_title] = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_namespace' => $obj->rc_namespace, 'wl_title' => $obj->rc_title), __METHOD__ . '-watchers');
                    }
                    $rc->numberofWatchingusers = $watcherCache[$obj->rc_namespace][$obj->rc_title];
                }
                $rc->show_namespace = $namespace;
                $rc->invert = $invert;
                $rc->reverse = $reverse;
                $rc->featured = $featured;
                $s .= $list->recentChangesLine($rc, !empty($obj->wl_user));
                --$limit;
            }
        }
        $s .= $list->endRecentChangesList();
        $s .= "</div>\n";
        $wgOut->addHTML($s);
    }
}
 /**
  * Display the interwiki watchlist
  */
 function execute($par)
 {
     global $wgUser, $wgOut, $wgLang, $wgRequest;
     global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
     // Add feed links
     $wlToken = $wgUser->getOption('watchlisttoken');
     if (!$wlToken) {
         $wlToken = sha1(mt_rand() . microtime(true));
         $wgUser->setOption('watchlisttoken', $wlToken);
         $wgUser->saveSettings();
     }
     global $wgServer, $wgScriptPath, $wgFeedClasses;
     $apiParams = array('action' => 'feedwatchlist', 'allrev' => 'allrev', 'wlowner' => $wgUser->getName(), 'wltoken' => $wlToken);
     $feedTemplate = wfScript('api') . '?';
     foreach ($wgFeedClasses as $format => $class) {
         $theseParams = $apiParams + array('feedformat' => $format);
         $url = $feedTemplate . wfArrayToCGI($theseParams);
         $wgOut->addFeedLink($format, $url);
     }
     $skin = $wgUser->getSkin();
     $specialTitle = SpecialPage::getTitleFor('InterwikiWatchlist');
     $wgOut->setRobotPolicy('noindex,nofollow');
     # Anons don't get a watchlist
     if ($wgUser->isAnon()) {
         $wgOut->setPageTitle(wfMsg('watchnologin'));
         $llink = $skin->linkKnown(SpecialPage::getTitleFor('Userlogin'), wfMsgHtml('loginreqlink'), array(), array('returnto' => $specialTitle->getPrefixedText()));
         $wgOut->addHTML(wfMsgWikiHtml('watchlistanontext', $llink));
         return;
     }
     $wgOut->setPageTitle(wfMsg('interwikiwatchlist'));
     $sub = wfMsgExt('watchlistfor', 'parseinline', $wgUser->getName());
     $sub .= '<br />' . SpecialEditWatchlist::buildTools($wgUser->getSkin());
     $wgOut->setSubtitle($sub);
     $mode = SpecialEditWatchlist::getMode($this->getRequest(), $par);
     if ($mode !== false) {
         # TODO: localise?
         switch ($mode) {
             case SpecialEditWatchlist::EDIT_CLEAR:
                 $mode = 'clear';
                 break;
             case SpecialEditWatchlist::EDIT_RAW:
                 $mode = 'raw';
                 break;
             default:
                 $mode = null;
         }
         $title = SpecialPage::getTitleFor('EditWatchlist', $mode);
         $wgOut->redirect($title->getLocalUrl());
         return;
     }
     $uid = $wgUser->getId();
     if (($wgEnotifWatchlist || $wgShowUpdatedMarker) && $wgRequest->getVal('reset') && $wgRequest->wasPosted()) {
         $wgUser->clearAllNotifications();
         $wgOut->redirect($specialTitle->getFullUrl());
         return;
     }
     $defaults = array('days' => floatval($wgUser->getOption('watchlistdays')), 'hideMinor' => (int) $wgUser->getBoolOption('watchlisthideminor'), 'hideBots' => (int) $wgUser->getBoolOption('watchlisthidebots'), 'hideAnons' => (int) $wgUser->getBoolOption('watchlisthideanons'), 'hideLiu' => (int) $wgUser->getBoolOption('watchlisthideliu'), 'hidePatrolled' => (int) $wgUser->getBoolOption('watchlisthidepatrolled'), 'hideOwn' => (int) $wgUser->getBoolOption('watchlisthideown'), 'namespace' => 'all', 'invert' => false);
     extract($defaults);
     # Extract variables from the request, falling back to user preferences or
     # other default values if these don't exist
     $prefs['days'] = floatval($wgUser->getOption('watchlistdays'));
     $prefs['hideminor'] = $wgUser->getBoolOption('watchlisthideminor');
     $prefs['hidebots'] = $wgUser->getBoolOption('watchlisthidebots');
     $prefs['hideanons'] = $wgUser->getBoolOption('watchlisthideanon');
     $prefs['hideliu'] = $wgUser->getBoolOption('watchlisthideliu');
     $prefs['hideown'] = $wgUser->getBoolOption('watchlisthideown');
     $prefs['hidepatrolled'] = $wgUser->getBoolOption('watchlisthidepatrolled');
     # Get query variables
     $days = $wgRequest->getVal('days', $prefs['days']);
     $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
     $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
     $hideAnons = $wgRequest->getBool('hideAnons', $prefs['hideanons']);
     $hideLiu = $wgRequest->getBool('hideLiu', $prefs['hideliu']);
     $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
     $hidePatrolled = $wgRequest->getBool('hidePatrolled', $prefs['hidepatrolled']);
     # Get namespace value, if supplied, and prepare a WHERE fragment
     $nameSpace = $wgRequest->getIntOrNull('namespace');
     $invert = $wgRequest->getIntOrNull('invert');
     if (!is_null($nameSpace)) {
         $nameSpace = intval($nameSpace);
         if ($invert && $nameSpace !== 'all') {
             $nameSpaceClause = "integration_rc_namespace != {$nameSpace}";
         } else {
             $nameSpaceClause = "integration_rc_namespace = {$nameSpace}";
         }
     } else {
         $nameSpace = '';
         $nameSpaceClause = '';
     }
     $dbr = wfGetDB(DB_SLAVE, 'integration_watchlist');
     $recentchanges = $dbr->tableName('integration_recentchanges');
     $nitems = $this->countItems();
     if (is_null($days) || !is_numeric($days)) {
         $big = 1000;
         /* The magical big */
         if ($nitems > $big) {
             # Set default cutoff shorter
             $days = $defaults['days'] = 12.0 / 24.0;
             # 12 hours...
         } else {
             $days = $defaults['days'];
             # default cutoff for shortlisters
         }
     } else {
         $days = floatval($days);
     }
     // Dump everything here
     $nondefaults = array();
     wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideAnons', (int) $hideAnons, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideLiu', (int) $hideLiu, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hidePatrolled', (int) $hidePatrolled, $defaults, $nondefaults);
     if ($nitems == 0) {
         $wgOut->addWikiMsg('nowatchlist');
         return;
     }
     # Possible where conditions
     $conds = array();
     if ($days <= 0) {
         $andcutoff = '';
     } else {
         $conds[] = "integration_rc_timestamp > '" . $dbr->timestamp(time() - intval($days * 86400)) . "'";
     }
     # If the watchlist is relatively short, it's simplest to zip
     # down its entirety and then sort the results.
     # If it's relatively long, it may be worth our while to zip
     # through the time-sorted page list checking for watched items.
     # Up estimate of watched items by 15% to compensate for talk pages...
     # Toggles
     if ($hideOwn) {
         $conds[] = "integration_rc_user != {$uid}";
     }
     if ($hideBots) {
         $conds[] = 'integration_rc_bot = 0';
     }
     if ($hideMinor) {
         $conds[] = 'integration_rc_minor = 0';
     }
     if ($hideLiu) {
         $conds[] = 'integration_rc_user = 0';
     }
     if ($hideAnons) {
         $conds[] = 'integration_rc_user != 0';
     }
     if ($wgUser->useRCPatrol() && $hidePatrolled) {
         $conds[] = 'integration_rc_patrolled != 1';
     }
     if ($nameSpaceClause) {
         $conds[] = $nameSpaceClause;
     }
     # Toggle watchlist content (all recent edits or just the latest)
     if ($wgUser->getOption('extendwatchlist')) {
         $limitWatchlist = intval($wgUser->getOption('wllimit'));
         $usePage = false;
     } else {
         # Top log Ids for a page are not stored
         $conds[] = 'integration_rc_this_oldid=integration_page_latest OR integration_rc_type=' . RC_LOG;
         $limitWatchlist = 0;
         $usePage = true;
     }
     # Show a message about slave lag, if applicable
     $lag = wfGetLB()->safeGetLag($dbr);
     if ($lag > 0) {
         $wgOut->showLagWarning($lag);
     }
     # Create output form
     $form = Xml::fieldset(wfMsg('watchlist-options'), false, array('id' => 'mw-watchlist-options'));
     # Show watchlist header
     $form .= wfMsgExt('watchlist-details', array('parseinline'), $wgLang->formatNum($nitems));
     if ($wgUser->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
         $form .= wfMsgExt('wlheader-enotif', 'parse') . "\n";
     }
     if ($wgShowUpdatedMarker) {
         $form .= Xml::openElement('form', array('method' => 'post', 'action' => $specialTitle->getLocalUrl(), 'id' => 'mw-watchlist-resetbutton')) . wfMsgExt('wlheader-showupdated', array('parseinline')) . ' ' . Xml::submitButton(wfMsg('enotif_reset'), array('name' => 'dummy')) . Html::Hidden('reset', 'all') . Xml::closeElement('form');
     }
     $form .= '<hr />';
     $tables = array('integration_recentchanges', 'integration_watchlist');
     $fields = array("{$recentchanges}.*");
     $join_conds = array('integration_watchlist' => array('INNER JOIN', "integration_wl_user='******' AND integration_wl_namespace=integration_rc_namespace AND integration_wl_title=integration_rc_title AND integration_wl_db=integration_rc_db"));
     $options = array('ORDER BY' => 'integration_rc_timestamp DESC');
     if ($wgShowUpdatedMarker) {
         $fields[] = 'integration_wl_notificationtimestamp';
     }
     if ($limitWatchlist) {
         $options['LIMIT'] = $limitWatchlist;
     }
     $rollbacker = $wgUser->isAllowed('rollback');
     if ($usePage || $rollbacker) {
         $tables[] = 'integration_page';
         $join_conds['integration_page'] = array('LEFT JOIN', 'integration_rc_cur_id=integration_page_id', 'integration_rc_db=integration_page_db');
         if ($rollbacker) {
             $fields[] = 'integration_page_latest';
         }
     }
     InterwikiIntegrationFunctions::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $options, '');
     wfRunHooks('SpecialWatchlistQuery', array(&$conds, &$tables, &$join_conds, &$fields));
     $res = $dbr->select($tables, $fields, $conds, __METHOD__, $options, $join_conds);
     $numRows = $dbr->numRows($res);
     /* Start bottom header */
     $wlInfo = '';
     if ($days >= 1) {
         $wlInfo = wfMsgExt('rcnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum($days), $wgLang->timeAndDate(wfTimestampNow(), true), $wgLang->date(wfTimestampNow(), true), $wgLang->time(wfTimestampNow(), true)) . '<br />';
     } elseif ($days > 0) {
         $wlInfo = wfMsgExt('wlnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum(round($days * 24))) . '<br />';
     }
     $cutofflinks = "\n" . $this->cutoffLinks($days, $nondefaults) . "<br />\n";
     # Spit out some control panel links
     $links[] = $this->showHideLink($nondefaults, 'rcshowhideminor', 'hideMinor', $hideMinor);
     $links[] = $this->showHideLink($nondefaults, 'rcshowhidebots', 'hideBots', $hideBots);
     $links[] = $this->showHideLink($nondefaults, 'rcshowhideanons', 'hideAnons', $hideAnons);
     $links[] = $this->showHideLink($nondefaults, 'rcshowhideliu', 'hideLiu', $hideLiu);
     $links[] = $this->showHideLink($nondefaults, 'rcshowhidemine', 'hideOwn', $hideOwn);
     if ($wgUser->useRCPatrol()) {
         $links[] = $this->showHideLink($nondefaults, 'rcshowhidepatr', 'hidePatrolled', $hidePatrolled);
     }
     # Namespace filter and put the whole form together.
     $form .= $wlInfo;
     $form .= $cutofflinks;
     $form .= $wgLang->pipeList($links);
     $form .= Xml::openElement('form', array('method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector'));
     $form .= '<hr /><p>';
     $form .= Xml::label(wfMsg('namespace'), 'namespace') . '&#160;';
     $form .= Xml::namespaceSelector($nameSpace, '') . '&#160;';
     $form .= Xml::checkLabel(wfMsg('invert'), 'invert', 'nsinvert', $invert) . '&#160;';
     $form .= Xml::submitButton(wfMsg('allpagessubmit')) . '</p>';
     $form .= Html::Hidden('days', $days);
     if ($hideMinor) {
         $form .= Html::Hidden('hideMinor', 1);
     }
     if ($hideBots) {
         $form .= Html::Hidden('hideBots', 1);
     }
     if ($hideAnons) {
         $form .= Html::Hidden('hideAnons', 1);
     }
     if ($hideLiu) {
         $form .= Html::Hidden('hideLiu', 1);
     }
     if ($hideOwn) {
         $form .= Html::Hidden('hideOwn', 1);
     }
     $form .= Xml::closeElement('form');
     $form .= Xml::closeElement('fieldset');
     $wgOut->addHTML($form);
     $wgOut->addHTML(InterwikiIntegrationChangesList::flagLegend());
     # If there's nothing to show, stop here
     if ($numRows == 0) {
         $wgOut->addWikiMsg('watchnochange');
         return;
     }
     /* End bottom header */
     /* Do link batch query */
     $linkBatch = new LinkBatch();
     while ($row = $dbr->fetchObject($res)) {
         $userNameUnderscored = str_replace(' ', '_', $row->integration_rc_user_text);
         if ($row->integration_rc_user != 0) {
             $linkBatch->add(NS_USER, $userNameUnderscored);
         }
         $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
         $linkBatch->add($row->integration_rc_namespace, $row->integration_rc_title);
     }
     $linkBatch->execute();
     $dbr->dataSeek($res, 0);
     $list = InterwikiIntegrationChangesList::newFromUser($wgUser);
     $list->setWatchlistDivs();
     $s = $list->beginRecentInterwikiIntegrationChangesList();
     $counter = 1;
     while ($obj = $dbr->fetchObject($res)) {
         # Make RC entry
         $rc = InterwikiIntegrationRecentChange::newFromRow($obj);
         $rc->counter = $counter++;
         if ($wgShowUpdatedMarker) {
             $updated = $obj->integration_wl_notificationtimestamp;
         } else {
             $updated = false;
         }
         if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
             $rc->numberofWatchingusers = $dbr->selectField('integration_watchlist', 'COUNT(*)', array('integration_wl_namespace' => $obj->integration_rc_namespace, 'integration_wl_title' => $obj->integration_rc_title), __METHOD__);
         } else {
             $rc->numberofWatchingusers = 0;
         }
         $s .= $list->recentChangesLine($rc, $updated, $counter);
     }
     $s .= $list->endRecentInterwikiIntegrationChangesList();
     $dbr->freeResult($res);
     $wgOut->addHTML($s);
 }
/**
 * Constructor
 */
function wfSpecialRecentchanges($par, $specialPage)
{
    global $wgUser, $wgOut, $wgLang, $wgContLang, $wgTitle, $wgMemc, $wgDBname;
    global $wgRequest, $wgSitename, $wgLanguageCode, $wgContLanguageCode;
    global $wgFeedClasses, $wgUseRCPatrol;
    global $wgRCShowCurrentRevisionOnly, $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
    global $wgLinkCache;
    $fname = 'wfSpecialRecentchanges';
    # Get query parameters
    $feedFormat = $wgRequest->getVal('feed');
    $defaults = array('days' => $wgUser->getDefaultOption('rcdays'), 'limit' => $wgUser->getDefaultOption('rclimit'), 'hideminor' => false, 'hidebots' => true, 'hideliu' => false, 'hidepatrolled' => false, 'from' => '', 'namespace' => null, 'invert' => false);
    extract($defaults);
    $days = $wgUser->getOption('rcdays');
    if (!$days) {
        $days = $defaults['days'];
    }
    $days = $wgRequest->getInt('days', $days);
    $limit = $wgUser->getOption('rclimit');
    if (!$limit) {
        $limit = $defaults['limit'];
    }
    #	list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
    $limit = $wgRequest->getInt('limit', $limit);
    /* order of selection: url > preferences > default */
    $hideminor = $wgRequest->getBool('hideminor', $wgUser->getOption('hideminor') ? true : $defaults['hideminor']);
    # As a feed, use limited settings only
    if ($feedFormat) {
        global $wgFeedLimit;
        if ($limit > $wgFeedLimit) {
            $options['limit'] = $wgFeedLimit;
        }
    } else {
        $namespace = $wgRequest->getIntOrNull('namespace');
        $invert = $wgRequest->getBool('invert', $defaults['invert']);
        $hidebots = $wgRequest->getBool('hidebots', $defaults['hidebots']);
        $hideliu = $wgRequest->getBool('hideliu', $defaults['hideliu']);
        $hidepatrolled = $wgRequest->getBool('hidepatrolled', $defaults['hidepatrolled']);
        $from = $wgRequest->getVal('from', $defaults['from']);
        # Get query parameters from path
        if ($par) {
            $bits = preg_split('/\\s*,\\s*/', trim($par));
            foreach ($bits as $bit) {
                if ('hidebots' == $bit) {
                    $hidebots = 1;
                }
                if ('bots' == $bit) {
                    $hidebots = 0;
                }
                if ('hideminor' == $bit) {
                    $hideminor = 1;
                }
                if ('minor' == $bit) {
                    $hideminor = 0;
                }
                if ('hideliu' == $bit) {
                    $hideliu = 1;
                }
                if ('hidepatrolled' == $bit) {
                    $hidepatrolled = 1;
                }
                if (is_numeric($bit)) {
                    $limit = $bit;
                }
                if (preg_match('/^limit=(\\d+)$/', $bit, $m)) {
                    $limit = $m[1];
                }
                if (preg_match('/^days=(\\d+)$/', $bit, $m)) {
                    $days = $m[1];
                }
            }
        }
    }
    if ($limit < 0 || $limit > 5000) {
        $limit = $defaults['limit'];
    }
    # Database connection and caching
    $dbr =& wfGetDB(DB_SLAVE);
    extract($dbr->tableNames('recentchanges', 'watchlist', 'page'));
    $cutoff_unixtime = time() - $days * 86400;
    $cutoff_unixtime = $cutoff_unixtime - $cutoff_unixtime % 86400;
    $cutoff = $dbr->timestamp($cutoff_unixtime);
    if (preg_match('/^[0-9]{14}$/', $from) and $from > wfTimestamp(TS_MW, $cutoff)) {
        $cutoff = $dbr->timestamp($from);
    } else {
        $from = $defaults['from'];
    }
    # 10 seconds server-side caching max
    $wgOut->setSquidMaxage(10);
    # Get last modified date, for client caching
    # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
    $lastmod = $dbr->selectField('recentchanges', 'MAX(rc_timestamp)', false, $fname);
    if ($feedFormat || !$wgUseRCPatrol) {
        if ($lastmod && $wgOut->checkLastModified($lastmod)) {
            # Client cache fresh and headers sent, nothing more to do.
            return;
        }
    }
    $hidem = $hideminor ? 'AND rc_minor=0' : '';
    $hidem .= $hidebots ? ' AND rc_bot=0' : '';
    $hidem .= $hideliu ? ' AND rc_user=0' : '';
    $hidem .= $hidepatrolled ? ' AND rc_patrolled=0' : '';
    $hidem .= is_null($namespace) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
    // This is the big thing!
    $uid = $wgUser->getID();
    // Perform query
    if ($wgRCShowCurrentRevisionOnly && $wgUser->getOption('rccurrevonly')) {
        $sql2 = "SELECT {$recentchanges}.*" . ($uid ? ",wl_user,wl_notificationtimestamp,wl_lastvisitedrevision" : "") . " FROM {$recentchanges},{$page} " . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "WHERE rc_timestamp > '{$cutoff}' {$hidem} AND rc_this_oldid=page_latest " . "ORDER BY rc_timestamp DESC LIMIT {$limit}";
    } else {
        $sql2 = "SELECT {$recentchanges}.*" . ($uid ? ",wl_user,wl_notificationtimestamp,wl_lastvisitedrevision" : "") . " FROM {$recentchanges} " . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "WHERE rc_timestamp > '{$cutoff}' {$hidem} " . "ORDER BY rc_timestamp DESC LIMIT {$limit}";
    }
    $res = $dbr->query($sql2, $fname);
    // Fetch results, prepare a batch link existence check query
    $rows = array();
    $batch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $rows[] = $row;
        // User page link
        $title = Title::makeTitleSafe(NS_USER, $row->rc_user_text);
        $batch->addObj($title);
        // User talk
        $title = Title::makeTitleSafe(NS_USER_TALK, $row->rc_user_text);
        $batch->addObj($title);
    }
    $dbr->freeResult($res);
    // Run existence checks
    $batch->execute($wgLinkCache);
    if ($feedFormat) {
        rcOutputFeed($rows, $feedFormat, $limit, $hideminor, $lastmod);
    } else {
        # Web output...
        // Output header
        if (!$specialPage->including()) {
            $wgOut->addWikiText(wfMsgForContent("recentchangestext"));
            // Dump everything here
            $nondefaults = array();
            wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('limit', $limit, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideminor', $hideminor, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidebots', $hidebots, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideliu', $hideliu, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('from', $from, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('namespace', $namespace, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('invert', $invert, $defaults, $nondefaults);
            // Add end of the texts
            $wgOut->addHTML('<div class="rcoptions">' . rcOptionsPanel($defaults, $nondefaults));
            $wgOut->addHTML(rcNamespaceForm($namespace, $invert, $nondefaults) . '</div>');
        }
        // And now for the content
        $sk = $wgUser->getSkin();
        $wgOut->setSyndicated(true);
        $list =& new ChangesList($sk);
        $s = $list->beginRecentChangesList();
        $counter = 1;
        foreach ($rows as $obj) {
            if ($limit == 0) {
                break;
            }
            if (!($hideminor && $obj->rc_minor) && !($hidepatrolled && $obj->rc_patrolled)) {
                $rc = RecentChange::newFromRow($obj);
                $rc->counter = $counter++;
                if ($wgShowUpdatedMarker && $wgUser->getOption('showupdated') && !empty($obj->wl_notificationtimestamp) && $obj->rc_timestamp >= $obj->wl_notificationtimestamp) {
                    $rc->notificationtimestamp = true;
                } else {
                    $rc->notificationtimestamp = false;
                }
                if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
                    $sql3 = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_title='" . $dbr->strencode($obj->rc_title) . "' AND wl_namespace={$obj->rc_namespace}";
                    $res3 = $dbr->query($sql3, 'wfSpecialRecentChanges');
                    $x = $dbr->fetchObject($res3);
                    $rc->numberofWatchingusers = $x->n;
                } else {
                    $rc->numberofWatchingusers = 0;
                }
                $rc->lastvisitedrevision = $uid ? $obj->wl_lastvisitedrevision : 0;
                $s .= $list->recentChangesLine($rc, !empty($obj->wl_user));
                --$limit;
            }
        }
        $s .= $list->endRecentChangesList();
        $wgOut->addHTML($s);
    }
}
/**
 * Constructor
 *
 * @param $par Parameter passed to the page
 */
function wfSpecialWatchlist($par)
{
    global $wgUser, $wgOut, $wgLang, $wgRequest;
    global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
    global $wgEnotifWatchlist;
    $skin = $wgUser->getSkin();
    $specialTitle = SpecialPage::getTitleFor('Watchlist');
    $wgOut->setRobotPolicy('noindex,nofollow');
    # Anons don't get a watchlist
    if ($wgUser->isAnon()) {
        $wgOut->setPageTitle(wfMsg('watchnologin'));
        $llink = $skin->makeKnownLinkObj(SpecialPage::getTitleFor('Userlogin'), wfMsgHtml('loginreqlink'), 'returnto=' . $specialTitle->getPrefixedUrl());
        $wgOut->addHTML(wfMsgWikiHtml('watchlistanontext', $llink));
        return;
    }
    $wgOut->setPageTitle(wfMsg('watchlist'));
    $sub = wfMsgExt('watchlistfor', 'parseinline', $wgUser->getName());
    $sub .= '<br />' . WatchlistEditor::buildTools($wgUser->getSkin());
    $wgOut->setSubtitle($sub);
    if (($mode = WatchlistEditor::getMode($wgRequest, $par)) !== false) {
        $editor = new WatchlistEditor();
        $editor->execute($wgUser, $wgOut, $wgRequest, $mode);
        return;
    }
    $uid = $wgUser->getId();
    if (($wgEnotifWatchlist || $wgShowUpdatedMarker) && $wgRequest->getVal('reset') && $wgRequest->wasPosted()) {
        $wgUser->clearAllNotifications($uid);
        $wgOut->redirect($specialTitle->getFullUrl());
        return;
    }
    $defaults = array('days' => floatval($wgUser->getOption('watchlistdays')), 'hideMinor' => (int) $wgUser->getBoolOption('watchlisthideminor'), 'hideBots' => (int) $wgUser->getBoolOption('watchlisthidebots'), 'hideAnons' => (int) $wgUser->getBoolOption('watchlisthideanons'), 'hideLiu' => (int) $wgUser->getBoolOption('watchlisthideliu'), 'hidePatrolled' => (int) $wgUser->getBoolOption('watchlisthidepatrolled'), 'hideOwn' => (int) $wgUser->getBoolOption('watchlisthideown'), 'namespace' => 'all', 'invert' => false);
    extract($defaults);
    # Extract variables from the request, falling back to user preferences or
    # other default values if these don't exist
    $prefs['days'] = floatval($wgUser->getOption('watchlistdays'));
    $prefs['hideminor'] = $wgUser->getBoolOption('watchlisthideminor');
    $prefs['hidebots'] = $wgUser->getBoolOption('watchlisthidebots');
    $prefs['hideanons'] = $wgUser->getBoolOption('watchlisthideanon');
    $prefs['hideliu'] = $wgUser->getBoolOption('watchlisthideliu');
    $prefs['hideown'] = $wgUser->getBoolOption('watchlisthideown');
    $prefs['hidepatrolled'] = $wgUser->getBoolOption('watchlisthidepatrolled');
    # Get query variables
    $days = $wgRequest->getVal('days', $prefs['days']);
    $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
    $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
    $hideAnons = $wgRequest->getBool('hideAnons', $prefs['hideanons']);
    $hideLiu = $wgRequest->getBool('hideLiu', $prefs['hideliu']);
    $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
    $hidePatrolled = $wgRequest->getBool('hidePatrolled', $prefs['hidepatrolled']);
    # Get namespace value, if supplied, and prepare a WHERE fragment
    $nameSpace = $wgRequest->getIntOrNull('namespace');
    $invert = $wgRequest->getIntOrNull('invert');
    if (!is_null($nameSpace)) {
        $nameSpace = intval($nameSpace);
        if ($invert && $nameSpace !== 'all') {
            $nameSpaceClause = "rc_namespace != {$nameSpace}";
        } else {
            $nameSpaceClause = "rc_namespace = {$nameSpace}";
        }
    } else {
        $nameSpace = '';
        $nameSpaceClause = '';
    }
    $dbr = wfGetDB(DB_SLAVE, 'watchlist');
    list($page, $watchlist, $recentchanges) = $dbr->tableNamesN('page', 'watchlist', 'recentchanges');
    $watchlistCount = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_user' => $uid), __METHOD__);
    // Adjust for page X, talk:page X, which are both stored separately,
    // but treated together
    $nitems = floor($watchlistCount / 2);
    if (is_null($days) || !is_numeric($days)) {
        $big = 1000;
        /* The magical big */
        if ($nitems > $big) {
            # Set default cutoff shorter
            $days = $defaults['days'] = 12.0 / 24.0;
            # 12 hours...
        } else {
            $days = $defaults['days'];
            # default cutoff for shortlisters
        }
    } else {
        $days = floatval($days);
    }
    // Dump everything here
    $nondefaults = array();
    wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideAnons', (int) $hideAnons, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideLiu', (int) $hideLiu, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hidePatrolled', (int) $hidePatrolled, $defaults, $nondefaults);
    if ($nitems == 0) {
        $wgOut->addWikiMsg('nowatchlist');
        return;
    }
    if ($days <= 0) {
        $andcutoff = '';
    } else {
        $andcutoff = "rc_timestamp > '" . $dbr->timestamp(time() - intval($days * 86400)) . "'";
    }
    # If the watchlist is relatively short, it's simplest to zip
    # down its entirety and then sort the results.
    # If it's relatively long, it may be worth our while to zip
    # through the time-sorted page list checking for watched items.
    # Up estimate of watched items by 15% to compensate for talk pages...
    # Toggles
    $andHideOwn = $hideOwn ? "rc_user != {$uid}" : '';
    $andHideBots = $hideBots ? "rc_bot = 0" : '';
    $andHideMinor = $hideMinor ? "rc_minor = 0" : '';
    $andHideLiu = $hideLiu ? "rc_user = 0" : '';
    $andHideAnons = $hideAnons ? "rc_user != 0" : '';
    $andHidePatrolled = $wgUser->useRCPatrol() && $hidePatrolled ? "rc_patrolled != 1" : '';
    # Toggle watchlist content (all recent edits or just the latest)
    if ($wgUser->getOption('extendwatchlist')) {
        $andLatest = '';
        $limitWatchlist = intval($wgUser->getOption('wllimit'));
    } else {
        # Top log Ids for a page are not stored
        $andLatest = 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG;
        $limitWatchlist = 0;
    }
    # Show a message about slave lag, if applicable
    if (($lag = $dbr->getLag()) > 0) {
        $wgOut->showLagWarning($lag);
    }
    # Create output form
    $form = Xml::fieldset(wfMsg('watchlist-options'), false, array('id' => 'mw-watchlist-options'));
    # Show watchlist header
    $form .= wfMsgExt('watchlist-details', array('parseinline'), $wgLang->formatNum($nitems));
    if ($wgUser->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
        $form .= wfMsgExt('wlheader-enotif', 'parse') . "\n";
    }
    if ($wgShowUpdatedMarker) {
        $form .= Xml::openElement('form', array('method' => 'post', 'action' => $specialTitle->getLocalUrl(), 'id' => 'mw-watchlist-resetbutton')) . wfMsgExt('wlheader-showupdated', array('parseinline')) . ' ' . Xml::submitButton(wfMsg('enotif_reset'), array('name' => 'dummy')) . Xml::hidden('reset', 'all') . Xml::closeElement('form');
    }
    $form .= '<hr />';
    $tables = array('recentchanges', 'watchlist', 'page');
    $fields = array("{$recentchanges}.*");
    $conds = array();
    $join_conds = array('watchlist' => array('INNER JOIN', "wl_user='******' AND wl_namespace=rc_namespace AND wl_title=rc_title"), 'page' => array('LEFT JOIN', 'rc_cur_id=page_id'));
    $options = array('ORDER BY' => 'rc_timestamp DESC');
    if ($wgShowUpdatedMarker) {
        $fields[] = 'wl_notificationtimestamp';
    }
    if ($limitWatchlist) {
        $options['LIMIT'] = $limitWatchlist;
    }
    if ($andcutoff) {
        $conds[] = $andcutoff;
    }
    if ($andLatest) {
        $conds[] = $andLatest;
    }
    if ($andHideOwn) {
        $conds[] = $andHideOwn;
    }
    if ($andHideBots) {
        $conds[] = $andHideBots;
    }
    if ($andHideMinor) {
        $conds[] = $andHideMinor;
    }
    if ($andHideLiu) {
        $conds[] = $andHideLiu;
    }
    if ($andHideAnons) {
        $conds[] = $andHideAnons;
    }
    if ($andHidePatrolled) {
        $conds[] = $andHidePatrolled;
    }
    if ($nameSpaceClause) {
        $conds[] = $nameSpaceClause;
    }
    wfRunHooks('SpecialWatchlistQuery', array(&$conds, &$tables, &$join_conds, &$fields));
    $res = $dbr->select($tables, $fields, $conds, __METHOD__, $options, $join_conds);
    $numRows = $dbr->numRows($res);
    /* Start bottom header */
    $wlInfo = '';
    if ($days >= 1) {
        $wlInfo = wfMsgExt('rcnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum($days), $wgLang->timeAndDate(wfTimestampNow(), true), $wgLang->date(wfTimestampNow(), true), $wgLang->time(wfTimestampNow(), true)) . '<br />';
    } elseif ($days > 0) {
        $wlInfo = wfMsgExt('wlnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum(round($days * 24))) . '<br />';
    }
    $cutofflinks = "\n" . wlCutoffLinks($days, 'Watchlist', $nondefaults) . "<br />\n";
    # Spit out some control panel links
    $thisTitle = SpecialPage::getTitleFor('Watchlist');
    $skin = $wgUser->getSkin();
    $showLinktext = wfMsgHtml('show');
    $hideLinktext = wfMsgHtml('hide');
    # Hide/show minor edits
    $label = $hideMinor ? $showLinktext : $hideLinktext;
    $linkBits = wfArrayToCGI(array('hideMinor' => 1 - (int) $hideMinor), $nondefaults);
    $links[] = wfMsgHtml('rcshowhideminor', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    # Hide/show bot edits
    $label = $hideBots ? $showLinktext : $hideLinktext;
    $linkBits = wfArrayToCGI(array('hideBots' => 1 - (int) $hideBots), $nondefaults);
    $links[] = wfMsgHtml('rcshowhidebots', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    # Hide/show anonymous edits
    $label = $hideAnons ? $showLinktext : $hideLinktext;
    $linkBits = wfArrayToCGI(array('hideAnons' => 1 - (int) $hideAnons), $nondefaults);
    $links[] = wfMsgHtml('rcshowhideanons', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    # Hide/show logged in edits
    $label = $hideLiu ? $showLinktext : $hideLinktext;
    $linkBits = wfArrayToCGI(array('hideLiu' => 1 - (int) $hideLiu), $nondefaults);
    $links[] = wfMsgHtml('rcshowhideliu', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    # Hide/show own edits
    $label = $hideOwn ? $showLinktext : $hideLinktext;
    $linkBits = wfArrayToCGI(array('hideOwn' => 1 - (int) $hideOwn), $nondefaults);
    $links[] = wfMsgHtml('rcshowhidemine', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    # Hide/show patrolled edits
    if ($wgUser->useRCPatrol()) {
        $label = $hidePatrolled ? $showLinktext : $hideLinktext;
        $linkBits = wfArrayToCGI(array('hidePatrolled' => 1 - (int) $hidePatrolled), $nondefaults);
        $links[] = wfMsgHtml('rcshowhidepatr', $skin->makeKnownLinkObj($thisTitle, $label, $linkBits));
    }
    # Namespace filter and put the whole form together.
    $form .= $wlInfo;
    $form .= $cutofflinks;
    $form .= implode(' | ', $links);
    $form .= Xml::openElement('form', array('method' => 'post', 'action' => $thisTitle->getLocalUrl()));
    $form .= '<hr /><p>';
    $form .= Xml::label(wfMsg('namespace'), 'namespace') . '&nbsp;';
    $form .= Xml::namespaceSelector($nameSpace, '') . '&nbsp;';
    $form .= Xml::checkLabel(wfMsg('invert'), 'invert', 'nsinvert', $invert) . '&nbsp;';
    $form .= Xml::submitButton(wfMsg('allpagessubmit')) . '</p>';
    $form .= Xml::hidden('days', $days);
    if ($hideMinor) {
        $form .= Xml::hidden('hideMinor', 1);
    }
    if ($hideBots) {
        $form .= Xml::hidden('hideBots', 1);
    }
    if ($hideAnons) {
        $form .= Xml::hidden('hideAnons', 1);
    }
    if ($hideLiu) {
        $form .= Xml::hidden('hideLiu', 1);
    }
    if ($hideOwn) {
        $form .= Xml::hidden('hideOwn', 1);
    }
    $form .= Xml::closeElement('form');
    $form .= Xml::closeElement('fieldset');
    $wgOut->addHTML($form);
    # If there's nothing to show, stop here
    if ($numRows == 0) {
        $wgOut->addWikiMsg('watchnochange');
        return;
    }
    /* End bottom header */
    /* Do link batch query */
    $linkBatch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
        if ($row->rc_user != 0) {
            $linkBatch->add(NS_USER, $userNameUnderscored);
        }
        $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
    }
    $linkBatch->execute();
    $dbr->dataSeek($res, 0);
    $list = ChangesList::newFromUser($wgUser);
    $s = $list->beginRecentChangesList();
    $counter = 1;
    while ($obj = $dbr->fetchObject($res)) {
        # Make RC entry
        $rc = RecentChange::newFromRow($obj);
        $rc->counter = $counter++;
        if ($wgShowUpdatedMarker) {
            $updated = $obj->wl_notificationtimestamp;
        } else {
            $updated = false;
        }
        if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
            $rc->numberofWatchingusers = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_namespace' => $obj->rc_namespace, 'wl_title' => $obj->rc_title), __METHOD__);
        } else {
            $rc->numberofWatchingusers = 0;
        }
        $s .= $list->recentChangesLine($rc, $updated);
    }
    $s .= $list->endRecentChangesList();
    $dbr->freeResult($res);
    $wgOut->addHTML($s);
}
 protected function setup($parameters)
 {
     $defaults = array('module' => '', 'language' => $this->getUser()->getOption('language'), 'export' => false, 'savetodb' => false);
     /**
      * Place where all non default variables will end.
      */
     $nondefaults = array();
     /**
      * Temporary store possible values parsed from parameters.
      */
     $options = $defaults;
     $request = $this->getRequest();
     foreach ($options as $v => $t) {
         if (is_bool($t)) {
             $r = $request->getBool($v, $options[$v]);
         } elseif (is_int($t)) {
             $r = $request->getInt($v, $options[$v]);
         } elseif (is_string($t)) {
             $r = $request->getText($v, $options[$v]);
         }
         if (!isset($r)) {
             throw new MWException('$r was not set');
         }
         wfAppendToArrayIfNotDefault($v, $r, $defaults, $nondefaults);
     }
     $this->defaults = $defaults;
     $this->nondefaults = $nondefaults;
     $this->options = $nondefaults + $defaults;
 }
    /**
     * Main execution point
     *
     * @param $par Parameter passed to the page
     */
    function execute($par)
    {
        global $wgUser, $wgOut, $wgLang, $wgRequest;
        global $wgRCShowWatchingUsers;
        global $wgEnotifWatchlist;
        // Add feed links
        $wlToken = $wgUser->getOption('watchlisttoken');
        if (!$wlToken) {
            $wlToken = sha1(mt_rand() . microtime(true));
            $wgUser->setOption('watchlisttoken', $wlToken);
            $wgUser->saveSettings();
        }
        global $wgFeedClasses;
        $apiParams = array('action' => 'feedwatchlist', 'allrev' => 'allrev', 'wlowner' => $wgUser->getName(), 'wltoken' => $wlToken);
        $feedTemplate = wfScript('api') . '?';
        foreach ($wgFeedClasses as $format => $class) {
            $theseParams = $apiParams + array('feedformat' => $format);
            $url = $feedTemplate . wfArrayToCGI($theseParams);
            $wgOut->addFeedLink($format, $url);
        }
        $skin = $wgUser->getSkin();
        $specialTitle = SpecialPage::getTitleFor('CollabWatchlist');
        $wgOut->setRobotPolicy('noindex,nofollow');
        # Anons don't get a watchlist
        if ($wgUser->isAnon()) {
            $wgOut->setPageTitle(wfMsg('watchnologin'));
            $llink = $skin->linkKnown(SpecialPage::getTitleFor('Userlogin'), wfMsgHtml('loginreqlink'), array(), array('returnto' => $specialTitle->getPrefixedText()));
            $wgOut->addHTML(wfMsgWikiHtml('watchlistanontext', $llink));
            return;
        }
        $wgOut->setPageTitle(wfMsg('collabwatchlist'));
        $listIdsAndNames = CollabWatchlistChangesList::getCollabWatchlistIdAndName($wgUser->getId());
        $sub = wfMsgExt('watchlistfor2', array('parseinline', 'replaceafter'), $wgUser->getName(), '');
        $sub .= '<br />' . CollabWatchlistEditor::buildTools($listIdsAndNames, $wgUser->getSkin());
        $wgOut->setSubtitle($sub);
        $uid = $wgUser->getId();
        // The filter form has one checkbox for each tag, build an array
        $postValues = $wgRequest->getValues();
        $tagFilter = array();
        foreach ($postValues as $key => $value) {
            if (stripos($key, 'collaborative-watchlist-filtertag-') === 0) {
                $tagFilter[] = $postValues[$key];
            }
        }
        // Alternative syntax for requests from links (show / hide ...)
        if (empty($tagFilter)) {
            $tagFilter = explode('|', $wgRequest->getVal('filterTags'));
        }
        $defaults = array('days' => floatval($wgUser->getOption('watchlistdays')), 'hideMinor' => (int) $wgUser->getBoolOption('watchlisthideminor'), 'hideBots' => (int) $wgUser->getBoolOption('watchlisthidebots'), 'hideAnons' => (int) $wgUser->getBoolOption('watchlisthideanons'), 'hideLiu' => (int) $wgUser->getBoolOption('watchlisthideliu'), 'hideListUser' => (int) $wgUser->getBoolOption('collabwatchlisthidelistuser'), 'hidePatrolled' => (int) $wgUser->getBoolOption('watchlisthidepatrolled'), 'hideOwn' => (int) $wgUser->getBoolOption('watchlisthideown'), 'collabwatchlist' => 0, 'globalwatch' => 'all', 'invert' => false, 'invertTags' => false, 'filterTags' => '');
        extract($defaults);
        # Extract variables from the request, falling back to user preferences or
        # other default values if these don't exist
        $prefs['days'] = floatval($wgUser->getOption('watchlistdays'));
        $prefs['hideminor'] = $wgUser->getBoolOption('watchlisthideminor');
        $prefs['hidebots'] = $wgUser->getBoolOption('watchlisthidebots');
        $prefs['hideanons'] = $wgUser->getBoolOption('watchlisthideanon');
        $prefs['hideliu'] = $wgUser->getBoolOption('watchlisthideliu');
        $prefs['hideown'] = $wgUser->getBoolOption('watchlisthideown');
        $prefs['hidelistuser'] = $wgUser->getBoolOption('collabwatchlisthidelistuser');
        $prefs['hidepatrolled'] = $wgUser->getBoolOption('watchlisthidepatrolled');
        $prefs['invertTags'] = $wgUser->getBoolOption('collabwatchlistinverttags');
        $prefs['filterTags'] = $wgUser->getOption('collabwatchlistfiltertags');
        # Get query variables
        $days = $wgRequest->getVal('days', $prefs['days']);
        $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
        $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
        $hideAnons = $wgRequest->getBool('hideAnons', $prefs['hideanons']);
        $hideLiu = $wgRequest->getBool('hideLiu', $prefs['hideliu']);
        $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
        $hideListUser = $wgRequest->getBool('hideListUser', $prefs['hidelistuser']);
        $hidePatrolled = $wgRequest->getBool('hidePatrolled', $prefs['hidepatrolled']);
        $filterTags = implode('|', $tagFilter);
        $invertTags = $wgRequest->getBool('invertTags', $prefs['invertTags']);
        # Get collabwatchlist value, if supplied, and prepare a WHERE fragment
        $collabWatchlist = $wgRequest->getIntOrNull('collabwatchlist');
        if (!is_null($collabWatchlist) && $collabWatchlist !== 'all') {
            $collabWatchlist = intval($collabWatchlist);
        }
        if (array_key_exists($collabWatchlist, $listIdsAndNames)) {
            $wgOut->addHTML(Xml::element('h2', null, $listIdsAndNames[$collabWatchlist]));
        }
        if (($mode = CollabWatchlistEditor::getMode($wgRequest, $par)) !== false) {
            $editor = new CollabWatchlistEditor();
            $editor->execute($collabWatchlist, $listIdsAndNames, $wgOut, $wgRequest, $mode);
            return;
        }
        if (!$collabWatchlist) {
            return;
        }
        $dbr = wfGetDB(DB_SLAVE, 'watchlist');
        $recentchanges = $dbr->tableName('recentchanges');
        $nitems = $dbr->selectField('collabwatchlistcategory', 'COUNT(*)', $collabWatchlist == 0 ? array() : array('cw_id' => $collabWatchlist), __METHOD__);
        if ($nitems == 0) {
            $wgOut->addWikiMsg('nowatchlist');
            return;
        }
        // Dump everything here
        $nondefaults = array();
        wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideAnons', (int) $hideAnons, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideLiu', (int) $hideLiu, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hideListUser', (int) $hideListUser, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('collabwatchlist', $collabWatchlist, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('hidePatrolled', (int) $hidePatrolled, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('filterTags', $filterTags, $defaults, $nondefaults);
        wfAppendToArrayIfNotDefault('invertTags', $invertTags, $defaults, $nondefaults);
        if ($days <= 0) {
            $andcutoff = '';
        } else {
            $andcutoff = "rc_timestamp > '" . $dbr->timestamp(time() - intval($days * 86400)) . "'";
        }
        # If the watchlist is relatively short, it's simplest to zip
        # down its entirety and then sort the results.
        # If it's relatively long, it may be worth our while to zip
        # through the time-sorted page list checking for watched items.
        # Up estimate of watched items by 15% to compensate for talk pages...
        # Toggles
        $andHideOwn = $hideOwn ? "rc_user != {$uid}" : '';
        $andHideBots = $hideBots ? "rc_bot = 0" : '';
        $andHideMinor = $hideMinor ? "rc_minor = 0" : '';
        $andHideLiu = $hideLiu ? "rc_user = 0" : '';
        $andHideAnons = $hideAnons ? "rc_user != 0" : '';
        $andHideListUser = $hideListUser ? $this->wlGetFilterClauseListUser($collabWatchlist) : '';
        $andHidePatrolled = $wgUser->useRCPatrol() && $hidePatrolled ? "rc_patrolled != 1" : '';
        # Toggle watchlist content (all recent edits or just the latest)
        if ($wgUser->getOption('extendwatchlist')) {
            $andLatest = '';
            $limitWatchlist = intval($wgUser->getOption('wllimit'));
            $usePage = false;
        } else {
            # Top log Ids for a page are not stored
            $andLatest = 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG;
            $limitWatchlist = 0;
            $usePage = true;
        }
        # Show a message about slave lag, if applicable
        $lag = wfGetLB()->safeGetLag($dbr);
        if ($lag > 0) {
            $wgOut->showLagWarning($lag);
        }
        # Create output form
        $form = Xml::fieldset(wfMsg('watchlist-options'), false, array('id' => 'mw-watchlist-options'));
        # Show watchlist header
        $form .= wfMsgExt('collabwatchlist-details', array('parseinline'), $wgLang->formatNum($nitems));
        if ($wgUser->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
            $form .= wfMsgExt('wlheader-enotif', 'parse') . "\n";
        }
        $form .= '<hr />';
        $tables = array('recentchanges', 'categorylinks');
        $fields = array("{$recentchanges}.*");
        $categoryClause = $this->wlGetFilterClauseForCollabWatchlistIds($collabWatchlist, 'cl_to', 'rc_cur_id');
        // If this collaborative watchlist does not contain any categories, add a clause which gives
        // us an empty result
        $conds = isset($categoryClause) ? array($categoryClause) : array('false');
        $join_conds = array('categorylinks' => array('LEFT OUTER JOIN', "rc_cur_id=cl_from"));
        if (!empty($tagFilter)) {
            // The tag filter causes a query runtime of O(MxN), where M is relative to the number
            // of recentchanges we select (from a table which is purged periodically, limited to 250)
            // and N is relative the number of change_tag entries for a recentchange. Doing it
            // the other way around (selecting from change_tag first, is probably slower, as the
            // change_tag table is never purged.
            // Using the tag_summary table for filtering is difficult, at least I have been unable to
            // find a common SQL compliant way for using regular expressions which works across Postgre / Mysql
            // Furthermore, ChangeTags does not seem to prevent tags containing ',' from being set,
            // which renders tag_summary quite unusable
            if ($invertTags) {
                $filter = 'EXISTS ';
            } else {
                $filter = 'NOT EXISTS ';
            }
            $filter .= '(SELECT cwlrt.ct_rc_id FROM collabwatchlistrevisiontag cwlrt
					WHERE cwlrt.ct_rc_id = recentchanges.rc_id AND cwlrt.ct_tag ';
            if (count($tagFilter) > 1) {
                $filter .= 'IN (' . $dbr->makeList($tagFilter) . '))';
            } else {
                $filter .= ' = ' . $dbr->addQuotes(current($tagFilter)) . ')';
            }
            $conds[] = $filter;
        }
        $options = array('ORDER BY' => 'rc_timestamp DESC');
        if ($limitWatchlist) {
            $options['LIMIT'] = $limitWatchlist;
        }
        if ($andcutoff) {
            $conds[] = $andcutoff;
        }
        if ($andLatest) {
            $conds[] = $andLatest;
        }
        if ($andHideOwn) {
            $conds[] = $andHideOwn;
        }
        if ($andHideBots) {
            $conds[] = $andHideBots;
        }
        if ($andHideMinor) {
            $conds[] = $andHideMinor;
        }
        if ($andHideLiu) {
            $conds[] = $andHideLiu;
        }
        if ($andHideAnons) {
            $conds[] = $andHideAnons;
        }
        if ($andHideListUser) {
            $conds[] = $andHideListUser;
        }
        if ($andHidePatrolled) {
            $conds[] = $andHidePatrolled;
        }
        $rollbacker = $wgUser->isAllowed('rollback');
        if ($usePage || $rollbacker) {
            $tables[] = 'page';
            $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page.page_id');
            if ($rollbacker) {
                $fields[] = 'page_latest';
            }
        }
        ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $options, '');
        wfRunHooks('SpecialCollabWatchlistQuery', array(&$conds, &$tables, &$join_conds, &$fields));
        $res = $dbr->select($tables, $fields, $conds, __METHOD__, $options, $join_conds);
        $numRows = $dbr->numRows($res);
        /* Start bottom header */
        $wlInfo = '';
        if ($days >= 1) {
            $wlInfo = wfMsgExt('rcnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum($days), $wgLang->timeAndDate(wfTimestampNow(), true), $wgLang->date(wfTimestampNow(), true), $wgLang->time(wfTimestampNow(), true)) . '<br />';
        } elseif ($days > 0) {
            $wlInfo = wfMsgExt('wlnote', 'parseinline', $wgLang->formatNum($numRows), $wgLang->formatNum(round($days * 24))) . '<br />';
        }
        $cutofflinks = "\n" . $this->cutoffLinks($days, 'CollabWatchlist', $nondefaults) . "<br />\n";
        $thisTitle = SpecialPage::getTitleFor('CollabWatchlist');
        # Spit out some control panel links
        $links[] = $this->showHideLink($nondefaults, 'rcshowhideminor', 'hideMinor', $hideMinor);
        $links[] = $this->showHideLink($nondefaults, 'rcshowhidebots', 'hideBots', $hideBots);
        $links[] = $this->showHideLink($nondefaults, 'rcshowhideanons', 'hideAnons', $hideAnons);
        $links[] = $this->showHideLink($nondefaults, 'rcshowhideliu', 'hideLiu', $hideLiu);
        $links[] = $this->showHideLink($nondefaults, 'rcshowhidemine', 'hideOwn', $hideOwn);
        $links[] = $this->showHideLink($nondefaults, 'collabwatchlistshowhidelistusers', 'hideListUser', $hideListUser);
        if ($wgUser->useRCPatrol()) {
            $links[] = $this->showHideLink($nondefaults, 'rcshowhidepatr', 'hidePatrolled', $hidePatrolled);
        }
        # Namespace filter and put the whole form together.
        $form .= $wlInfo;
        $form .= $cutofflinks;
        $form .= $wgLang->pipeList($links);
        $form .= Xml::openElement('form', array('method' => 'get', 'action' => $thisTitle->getLocalUrl()));
        $form .= '<hr /><p>';
        $tagsAndInfo = CollabWatchlistChangesList::getValidTagsAndInfo(array_keys($listIdsAndNames));
        if (count($tagsAndInfo) > 0) {
            $form .= wfMsg('collabwatchlistfiltertags') . ':&nbsp;&nbsp;';
        }
        foreach ($tagsAndInfo as $tag => $tagInfo) {
            $tagAttr = array('name' => 'collaborative-watchlist-filtertag-' . $tag, 'type' => 'checkbox', 'value' => $tag);
            if (in_array($tag, $tagFilter)) {
                $tagAttr['checked'] = 'checked';
            }
            $form .= Xml::element('input', $tagAttr) . '&nbsp;' . Xml::label($tag, 'collaborative-watchlist-filtertag-' . $tag) . '&nbsp;';
        }
        if (count($tagsAndInfo) > 0) {
            $form .= '<br />';
        }
        $form .= Xml::checkLabel(wfMsg('collabwatchlistinverttags'), 'invertTags', 'nsinvertTags', $invertTags) . '<br />';
        $form .= CollabWatchlistChangesList::collabWatchlistSelector($listIdsAndNames, $collabWatchlist, '', 'collabwatchlist', wfMsg('collabwatchlist')) . '&nbsp;';
        $form .= Xml::submitButton(wfMsg('allpagessubmit')) . '</p>';
        $form .= Html::hidden('days', $days);
        if ($hideMinor) {
            $form .= Html::hidden('hideMinor', 1);
        }
        if ($hideBots) {
            $form .= Html::hidden('hideBots', 1);
        }
        if ($hideAnons) {
            $form .= Html::hidden('hideAnons', 1);
        }
        if ($hideLiu) {
            $form .= Html::hidden('hideLiu', 1);
        }
        if ($hideOwn) {
            $form .= Html::hidden('hideOwn', 1);
        }
        if ($hideListUser) {
            $form .= Html::hidden('hideListUser', 1);
        }
        if ($wgUser->useRCPatrol()) {
            if ($hidePatrolled) {
                $form .= Html::hidden('hidePatrolled', 1);
            }
        }
        $form .= Xml::closeElement('form');
        $form .= Xml::closeElement('fieldset');
        $wgOut->addHTML($form);
        # If there's nothing to show, stop here
        if ($numRows == 0) {
            $wgOut->addWikiMsg('watchnochange');
            return;
        }
        /* End bottom header */
        /* Do link batch query */
        $linkBatch = new LinkBatch();
        foreach ($res as $row) {
            $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
            if ($row->rc_user != 0) {
                $linkBatch->add(NS_USER, $userNameUnderscored);
            }
            $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
            $linkBatch->add($row->rc_namespace, $row->rc_title);
        }
        $linkBatch->execute();
        $dbr->dataSeek($res, 0);
        $list = CollabWatchlistChangesList::newFromUser($wgUser);
        $list->setWatchlistDivs();
        $s = $list->beginRecentChangesList();
        $counter = 1;
        foreach ($res as $obj) {
            # Make RC entry
            $rc = RecentChange::newFromRow($obj);
            $rc->counter = $counter++;
            if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
                $rc->numberofWatchingusers = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_namespace' => $obj->rc_namespace, 'wl_title' => $obj->rc_title), __METHOD__);
            } else {
                $rc->numberofWatchingusers = 0;
            }
            $tags = $this->wlTagsForRevision($obj->rc_this_oldid, array($collabWatchlist));
            //			if( isset($tags) ) {
            //				// Filter recentchanges which contain unwanted tags
            //				$tagNames = array();
            //				foreach($tags as $tagInfo) {
            //					$tagNames[] = $tagInfo['ct_tag'];
            //				}
            //				$unwantedTagsFound = array_intersect($tagFilter, $tagNames);
            //				if( !empty($unwantedTagsFound) )
            //					continue;
            //			}
            $attrs = $rc->getAttributes();
            $attrs['collabwatchlist_tags'] = $tags;
            $rc->setAttribs($attrs);
            $s .= $list->recentChangesLine($rc, false, $counter);
        }
        $s .= $list->endRecentChangesList();
        $dbr->freeResult($res);
        $wgOut->addHTML($s);
    }
 /**
  * Execute
  * @param $par Parameter passed to the page
  */
 function execute($par)
 {
     global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
     $user = $this->getUser();
     $output = $this->getOutput();
     # Anons don't get a watchlist
     if ($user->isAnon()) {
         $output->setPageTitle($this->msg('watchnologin'));
         $output->setRobotPolicy('noindex,nofollow');
         $llink = Linker::linkKnown(SpecialPage::getTitleFor('Userlogin'), $this->msg('loginreqlink')->escaped(), array(), array('returnto' => $this->getTitle()->getPrefixedText()));
         $output->addHTML($this->msg('watchlistanontext')->rawParams($llink)->parse());
         return;
     }
     // Add feed links
     $wlToken = $user->getOption('watchlisttoken');
     if (!$wlToken) {
         $wlToken = MWCryptRand::generateHex(40);
         $user->setOption('watchlisttoken', $wlToken);
         $user->saveSettings();
     }
     $this->addFeedLinks(array('action' => 'feedwatchlist', 'allrev' => 'allrev', 'wlowner' => $user->getName(), 'wltoken' => $wlToken));
     $this->setHeaders();
     $this->outputHeader();
     $output->addSubtitle($this->msg('watchlistfor2', $user->getName())->rawParams(SpecialEditWatchlist::buildTools(null)));
     $request = $this->getRequest();
     $mode = SpecialEditWatchlist::getMode($request, $par);
     if ($mode !== false) {
         # TODO: localise?
         switch ($mode) {
             case SpecialEditWatchlist::EDIT_CLEAR:
                 $mode = 'clear';
                 break;
             case SpecialEditWatchlist::EDIT_RAW:
                 $mode = 'raw';
                 break;
             default:
                 $mode = null;
         }
         $title = SpecialPage::getTitleFor('EditWatchlist', $mode);
         $output->redirect($title->getLocalUrl());
         return;
     }
     $nitems = $this->countItems();
     if ($nitems == 0) {
         $output->addWikiMsg('nowatchlist');
         return;
     }
     // @TODO: use FormOptions!
     $defaults = array('days' => floatval($user->getOption('watchlistdays')), 'hideMinor' => (int) $user->getBoolOption('watchlisthideminor'), 'hideBots' => (int) $user->getBoolOption('watchlisthidebots'), 'hideAnons' => (int) $user->getBoolOption('watchlisthideanons'), 'hideLiu' => (int) $user->getBoolOption('watchlisthideliu'), 'hidePatrolled' => (int) $user->getBoolOption('watchlisthidepatrolled'), 'hideOwn' => (int) $user->getBoolOption('watchlisthideown'), 'namespace' => 'all', 'invert' => false, 'associated' => false);
     $this->customFilters = array();
     wfRunHooks('SpecialWatchlistFilters', array($this, &$this->customFilters));
     foreach ($this->customFilters as $key => $params) {
         $defaults[$key] = $params['msg'];
     }
     # Extract variables from the request, falling back to user preferences or
     # other default values if these don't exist
     $prefs['days'] = floatval($user->getOption('watchlistdays'));
     $prefs['hideminor'] = $user->getBoolOption('watchlisthideminor');
     $prefs['hidebots'] = $user->getBoolOption('watchlisthidebots');
     $prefs['hideanons'] = $user->getBoolOption('watchlisthideanons');
     $prefs['hideliu'] = $user->getBoolOption('watchlisthideliu');
     $prefs['hideown'] = $user->getBoolOption('watchlisthideown');
     $prefs['hidepatrolled'] = $user->getBoolOption('watchlisthidepatrolled');
     # Get query variables
     $values = array();
     $values['days'] = $request->getVal('days', $prefs['days']);
     $values['hideMinor'] = (int) $request->getBool('hideMinor', $prefs['hideminor']);
     $values['hideBots'] = (int) $request->getBool('hideBots', $prefs['hidebots']);
     $values['hideAnons'] = (int) $request->getBool('hideAnons', $prefs['hideanons']);
     $values['hideLiu'] = (int) $request->getBool('hideLiu', $prefs['hideliu']);
     $values['hideOwn'] = (int) $request->getBool('hideOwn', $prefs['hideown']);
     $values['hidePatrolled'] = (int) $request->getBool('hidePatrolled', $prefs['hidepatrolled']);
     foreach ($this->customFilters as $key => $params) {
         $values[$key] = (int) $request->getBool($key);
     }
     # Get namespace value, if supplied, and prepare a WHERE fragment
     $nameSpace = $request->getIntOrNull('namespace');
     $invert = $request->getBool('invert');
     $associated = $request->getBool('associated');
     if (!is_null($nameSpace)) {
         $eq_op = $invert ? '!=' : '=';
         $bool_op = $invert ? 'AND' : 'OR';
         $nameSpace = intval($nameSpace);
         // paranioa
         if (!$associated) {
             $nameSpaceClause = "rc_namespace {$eq_op} {$nameSpace}";
         } else {
             $associatedNS = MWNamespace::getAssociated($nameSpace);
             $nameSpaceClause = "rc_namespace {$eq_op} {$nameSpace} " . $bool_op . " rc_namespace {$eq_op} {$associatedNS}";
         }
     } else {
         $nameSpace = '';
         $nameSpaceClause = '';
     }
     $values['namespace'] = $nameSpace;
     $values['invert'] = $invert;
     $values['associated'] = $associated;
     if (is_null($values['days']) || !is_numeric($values['days'])) {
         $big = 1000;
         /* The magical big */
         if ($nitems > $big) {
             # Set default cutoff shorter
             $values['days'] = $defaults['days'] = 12.0 / 24.0;
             # 12 hours...
         } else {
             $values['days'] = $defaults['days'];
             # default cutoff for shortlisters
         }
     } else {
         $values['days'] = floatval($values['days']);
     }
     // Dump everything here
     $nondefaults = array();
     foreach ($defaults as $name => $defValue) {
         wfAppendToArrayIfNotDefault($name, $values[$name], $defaults, $nondefaults);
     }
     if (($wgEnotifWatchlist || $wgShowUpdatedMarker) && $request->getVal('reset') && $request->wasPosted()) {
         $user->clearAllNotifications();
         $output->redirect($this->getTitle()->getFullUrl($nondefaults));
         return;
     }
     $dbr = wfGetDB(DB_SLAVE, 'watchlist');
     # Possible where conditions
     $conds = array();
     if ($values['days'] > 0) {
         $conds[] = "rc_timestamp > '" . $dbr->timestamp(time() - intval($values['days'] * 86400)) . "'";
     }
     # If the watchlist is relatively short, it's simplest to zip
     # down its entirety and then sort the results.
     # If it's relatively long, it may be worth our while to zip
     # through the time-sorted page list checking for watched items.
     # Up estimate of watched items by 15% to compensate for talk pages...
     # Toggles
     if ($values['hideOwn']) {
         $conds[] = 'rc_user != ' . $user->getId();
     }
     if ($values['hideBots']) {
         $conds[] = 'rc_bot = 0';
     }
     if ($values['hideMinor']) {
         $conds[] = 'rc_minor = 0';
     }
     if ($values['hideLiu']) {
         $conds[] = 'rc_user = 0';
     }
     if ($values['hideAnons']) {
         $conds[] = 'rc_user != 0';
     }
     if ($user->useRCPatrol() && $values['hidePatrolled']) {
         $conds[] = 'rc_patrolled != 1';
     }
     if ($nameSpaceClause) {
         $conds[] = $nameSpaceClause;
     }
     # Toggle watchlist content (all recent edits or just the latest)
     if ($user->getOption('extendwatchlist')) {
         $limitWatchlist = intval($user->getOption('wllimit'));
         $usePage = false;
     } else {
         # Top log Ids for a page are not stored
         $conds[] = 'rc_this_oldid=page_latest OR rc_type=' . RC_LOG;
         $limitWatchlist = 0;
         $usePage = true;
     }
     # Show a message about slave lag, if applicable
     $lag = wfGetLB()->safeGetLag($dbr);
     if ($lag > 0) {
         $output->showLagWarning($lag);
     }
     # Create output form
     $form = Xml::fieldset($this->msg('watchlist-options')->text(), false, array('id' => 'mw-watchlist-options'));
     # Show watchlist header
     $form .= $this->msg('watchlist-details')->numParams($nitems)->parse();
     if ($user->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
         $form .= $this->msg('wlheader-enotif')->parseAsBlock() . "\n";
     }
     if ($wgShowUpdatedMarker) {
         $form .= Xml::openElement('form', array('method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-resetbutton')) . $this->msg('wlheader-showupdated')->parse() . ' ' . Xml::submitButton($this->msg('enotif_reset')->text(), array('name' => 'dummy')) . Html::hidden('reset', 'all');
         foreach ($nondefaults as $key => $value) {
             $form .= Html::hidden($key, $value);
         }
         $form .= Xml::closeElement('form');
     }
     $form .= '<hr />';
     $tables = array('recentchanges', 'watchlist');
     $fields = RecentChange::selectFields();
     $join_conds = array('watchlist' => array('INNER JOIN', array('wl_user' => $user->getId(), 'wl_namespace=rc_namespace', 'wl_title=rc_title')));
     $options = array('ORDER BY' => 'rc_timestamp DESC');
     if ($wgShowUpdatedMarker) {
         $fields[] = 'wl_notificationtimestamp';
     }
     if ($limitWatchlist) {
         $options['LIMIT'] = $limitWatchlist;
     }
     $rollbacker = $user->isAllowed('rollback');
     if ($usePage || $rollbacker) {
         $tables[] = 'page';
         $join_conds['page'] = array('LEFT JOIN', 'rc_cur_id=page_id');
         if ($rollbacker) {
             $fields[] = 'page_latest';
         }
     }
     ChangeTags::modifyDisplayQuery($tables, $fields, $conds, $join_conds, $options, '');
     wfRunHooks('SpecialWatchlistQuery', array(&$conds, &$tables, &$join_conds, &$fields));
     $res = $dbr->select($tables, $fields, $conds, __METHOD__, $options, $join_conds);
     $numRows = $res->numRows();
     /* Start bottom header */
     $lang = $this->getLanguage();
     $wlInfo = '';
     if ($values['days'] > 0) {
         $timestamp = wfTimestampNow();
         $wlInfo = $this->msg('wlnote')->numParams($numRows, round($values['days'] * 24))->params($lang->userDate($timestamp, $user), $lang->userTime($timestamp, $user))->parse() . '<br />';
     }
     $cutofflinks = "\n" . $this->cutoffLinks($values['days'], $nondefaults) . "<br />\n";
     # Spit out some control panel links
     $filters = array('hideMinor' => 'rcshowhideminor', 'hideBots' => 'rcshowhidebots', 'hideAnons' => 'rcshowhideanons', 'hideLiu' => 'rcshowhideliu', 'hideOwn' => 'rcshowhidemine', 'hidePatrolled' => 'rcshowhidepatr');
     foreach ($this->customFilters as $key => $params) {
         $filters[$key] = $params['msg'];
     }
     // Disable some if needed
     if (!$user->useNPPatrol()) {
         unset($filters['hidePatrolled']);
     }
     $links = array();
     foreach ($filters as $name => $msg) {
         $links[] = $this->showHideLink($nondefaults, $msg, $name, $values[$name]);
     }
     # Namespace filter and put the whole form together.
     $form .= $wlInfo;
     $form .= $cutofflinks;
     $form .= $lang->pipeList($links);
     $form .= Xml::openElement('form', array('method' => 'post', 'action' => $this->getTitle()->getLocalUrl(), 'id' => 'mw-watchlist-form-namespaceselector'));
     $form .= '<hr /><p>';
     $form .= Html::namespaceSelector(array('selected' => $nameSpace, 'all' => '', 'label' => $this->msg('namespace')->text()), array('name' => 'namespace', 'id' => 'namespace', 'class' => 'namespaceselector')) . '&#160;';
     $form .= Xml::checkLabel($this->msg('invert')->text(), 'invert', 'nsinvert', $invert, array('title' => $this->msg('tooltip-invert')->text())) . '&#160;';
     $form .= Xml::checkLabel($this->msg('namespace_association')->text(), 'associated', 'associated', $associated, array('title' => $this->msg('tooltip-namespace_association')->text())) . '&#160;';
     $form .= Xml::submitButton($this->msg('allpagessubmit')->text()) . '</p>';
     $form .= Html::hidden('days', $values['days']);
     foreach ($filters as $key => $msg) {
         if ($values[$key]) {
             $form .= Html::hidden($key, 1);
         }
     }
     $form .= Xml::closeElement('form');
     $form .= Xml::closeElement('fieldset');
     $output->addHTML($form);
     # If there's nothing to show, stop here
     if ($numRows == 0) {
         $output->addWikiMsg('watchnochange');
         return;
     }
     /* End bottom header */
     /* Do link batch query */
     $linkBatch = new LinkBatch();
     foreach ($res as $row) {
         $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
         if ($row->rc_user != 0) {
             $linkBatch->add(NS_USER, $userNameUnderscored);
         }
         $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
         $linkBatch->add($row->rc_namespace, $row->rc_title);
     }
     $linkBatch->execute();
     $dbr->dataSeek($res, 0);
     $list = ChangesList::newFromContext($this->getContext());
     $list->setWatchlistDivs();
     $s = $list->beginRecentChangesList();
     $counter = 1;
     foreach ($res as $obj) {
         # Make RC entry
         $rc = RecentChange::newFromRow($obj);
         $rc->counter = $counter++;
         if ($wgShowUpdatedMarker) {
             $updated = $obj->wl_notificationtimestamp;
         } else {
             $updated = false;
         }
         if ($wgRCShowWatchingUsers && $user->getOption('shownumberswatching')) {
             $rc->numberofWatchingusers = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_namespace' => $obj->rc_namespace, 'wl_title' => $obj->rc_title), __METHOD__);
         } else {
             $rc->numberofWatchingusers = 0;
         }
         $s .= $list->recentChangesLine($rc, $updated, $counter);
     }
     $s .= $list->endRecentChangesList();
     $output->addHTML($s);
 }
/**
 * Constructor
 *
 * @param $par Parameter passed to the page
 */
function wfSpecialWatchlist($par)
{
    global $wgUser, $wgOut, $wgLang, $wgRequest;
    global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
    global $wgEnotifWatchlist;
    $fname = 'wfSpecialWatchlist';
    $skin = $wgUser->getSkin();
    $specialTitle = SpecialPage::getTitleFor('Watchlist');
    $wgOut->setRobotPolicy('noindex,nofollow');
    # Anons don't get a watchlist
    if ($wgUser->isAnon()) {
        $wgOut->setPageTitle(wfMsg('watchnologin'));
        $llink = $skin->makeKnownLinkObj(SpecialPage::getTitleFor('Userlogin'), wfMsgHtml('loginreqlink'), 'returnto=' . $specialTitle->getPrefixedUrl());
        $wgOut->addHtml(wfMsgWikiHtml('watchlistanontext', $llink));
        return;
    }
    $wgOut->setPageTitle(wfMsg('watchlist'));
    $sub = wfMsgExt('watchlistfor', 'parseinline', $wgUser->getName());
    $sub .= '<br />' . WatchlistEditor::buildTools($wgUser->getSkin());
    $wgOut->setSubtitle($sub);
    if (($mode = WatchlistEditor::getMode($wgRequest, $par)) !== false) {
        $editor = new WatchlistEditor();
        $editor->execute($wgUser, $wgOut, $wgRequest, $mode);
        return;
    }
    $uid = $wgUser->getId();
    if ($wgEnotifWatchlist && $wgRequest->getVal('reset') && $wgRequest->wasPosted()) {
        $wgUser->clearAllNotifications($uid);
        $wgOut->redirect($specialTitle->getFullUrl());
        return;
    }
    $defaults = array('days' => floatval($wgUser->getOption('watchlistdays')), 'hideOwn' => (int) $wgUser->getBoolOption('watchlisthideown'), 'hideBots' => (int) $wgUser->getBoolOption('watchlisthidebots'), 'hideMinor' => (int) $wgUser->getBoolOption('watchlisthideminor'), 'namespace' => 'all');
    extract($defaults);
    # Extract variables from the request, falling back to user preferences or
    # other default values if these don't exist
    $prefs['days'] = floatval($wgUser->getOption('watchlistdays'));
    $prefs['hideown'] = $wgUser->getBoolOption('watchlisthideown');
    $prefs['hidebots'] = $wgUser->getBoolOption('watchlisthidebots');
    $prefs['hideminor'] = $wgUser->getBoolOption('watchlisthideminor');
    # Get query variables
    $days = $wgRequest->getVal('days', $prefs['days']);
    $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
    $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
    $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
    # Get namespace value, if supplied, and prepare a WHERE fragment
    $nameSpace = $wgRequest->getIntOrNull('namespace');
    if (!is_null($nameSpace)) {
        $nameSpace = intval($nameSpace);
        $nameSpaceClause = " AND rc_namespace = {$nameSpace}";
    } else {
        $nameSpace = '';
        $nameSpaceClause = '';
    }
    $dbr = wfGetDB(DB_SLAVE, 'watchlist');
    list($page, $watchlist, $recentchanges) = $dbr->tableNamesN('page', 'watchlist', 'recentchanges');
    $sql = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_user={$uid}";
    $res = $dbr->query($sql, $fname);
    $s = $dbr->fetchObject($res);
    #	Patch *** A1 *** (see A2 below)
    #	adjust for page X, talk:page X, which are both stored separately, but treated together
    $nitems = floor($s->n / 2);
    #	$nitems = $s->n;
    if ($nitems == 0) {
        $wgOut->addWikiText(wfMsg('nowatchlist'));
        return;
    }
    if (is_null($days) || !is_numeric($days)) {
        $big = 1000;
        /* The magical big */
        if ($nitems > $big) {
            # Set default cutoff shorter
            $days = $defaults['days'] = 12.0 / 24.0;
            # 12 hours...
        } else {
            $days = $defaults['days'];
            # default cutoff for shortlisters
        }
    } else {
        $days = floatval($days);
    }
    // Dump everything here
    $nondefaults = array();
    wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
    wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
    if ($days <= 0) {
        $andcutoff = '';
    } else {
        $andcutoff = "AND rc_timestamp > '" . $dbr->timestamp(time() - intval($days * 86400)) . "'";
        /*
        $sql = "SELECT COUNT(*) AS n FROM $page, $revision  WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
        $res = $dbr->query( $sql, $fname );
        $s = $dbr->fetchObject( $res );
        $npages = $s->n;
        */
    }
    # If the watchlist is relatively short, it's simplest to zip
    # down its entirety and then sort the results.
    # If it's relatively long, it may be worth our while to zip
    # through the time-sorted page list checking for watched items.
    # Up estimate of watched items by 15% to compensate for talk pages...
    # Toggles
    $andHideOwn = $hideOwn ? "AND (rc_user <> {$uid})" : '';
    $andHideBots = $hideBots ? "AND (rc_bot = 0)" : '';
    $andHideMinor = $hideMinor ? 'AND rc_minor = 0' : '';
    # Show watchlist header
    $header = '';
    if ($wgUser->getOption('enotifwatchlistpages') && $wgEnotifWatchlist) {
        $header .= wfMsg('wlheader-enotif') . "\n";
    }
    if ($wgEnotifWatchlist && $wgShowUpdatedMarker) {
        $header .= wfMsg('wlheader-showupdated') . "\n";
    }
    # Toggle watchlist content (all recent edits or just the latest)
    if ($wgUser->getOption('extendwatchlist')) {
        $andLatest = '';
        $limitWatchlist = 'LIMIT ' . intval($wgUser->getOption('wllimit'));
    } else {
        $andLatest = 'AND rc_this_oldid=page_latest';
        $limitWatchlist = '';
    }
    $header .= wfMsgExt('watchlist-details', array('parsemag'), $wgLang->formatNum($nitems));
    $wgOut->addWikiText($header);
    # Show a message about slave lag, if applicable
    if (($lag = $dbr->getLag()) > 0) {
        $wgOut->showLagWarning($lag);
    }
    if ($wgEnotifWatchlist && $wgShowUpdatedMarker) {
        $wgOut->addHTML('<form action="' . $specialTitle->escapeLocalUrl() . '" method="post"><input type="submit" name="dummy" value="' . htmlspecialchars(wfMsg('enotif_reset')) . '" /><input type="hidden" name="reset" value="all" /></form>' . "\n\n");
    }
    $sql = "SELECT *\r\n\t  FROM {$watchlist},{$recentchanges},{$page}\r\n\t  WHERE wl_user={$uid}\r\n\t  AND wl_namespace=rc_namespace\r\n\t  AND wl_title=rc_title\r\n\t  AND rc_cur_id=page_id\r\n\t  {$andcutoff}\r\n\t  {$andLatest}\r\n\t  {$andHideOwn}\r\n\t  {$andHideBots}\r\n\t  {$andHideMinor}\r\n\t  {$nameSpaceClause}\r\n\t  ORDER BY rc_timestamp DESC\r\n\t  {$limitWatchlist}";
    $res = $dbr->query($sql, $fname);
    $numRows = $dbr->numRows($res);
    /* Start bottom header */
    $wgOut->addHTML("<hr />\n");
    if ($days >= 1) {
        $wgOut->addWikiText(wfMsgExt('rcnote', array('parseinline'), $wgLang->formatNum($numRows), $wgLang->formatNum($days), $wgLang->timeAndDate(wfTimestampNow(), true)) . '<br />', false);
    } elseif ($days > 0) {
        $wgOut->addWikiText(wfMsgExt('wlnote', array('parseinline'), $wgLang->formatNum($numRows), $wgLang->formatNum(round($days * 24))) . '<br />', false);
    }
    $wgOut->addHTML("\n" . wlCutoffLinks($days, 'Watchlist', $nondefaults) . "<br />\n");
    # Spit out some control panel links
    $thisTitle = SpecialPage::getTitleFor('Watchlist');
    $skin = $wgUser->getSkin();
    # Hide/show bot edits
    $label = $hideBots ? wfMsgHtml('watchlist-show-bots') : wfMsgHtml('watchlist-hide-bots');
    $linkBits = wfArrayToCGI(array('hideBots' => 1 - (int) $hideBots), $nondefaults);
    $links[] = $skin->makeKnownLinkObj($thisTitle, $label, $linkBits);
    # Hide/show own edits
    $label = $hideOwn ? wfMsgHtml('watchlist-show-own') : wfMsgHtml('watchlist-hide-own');
    $linkBits = wfArrayToCGI(array('hideOwn' => 1 - (int) $hideOwn), $nondefaults);
    $links[] = $skin->makeKnownLinkObj($thisTitle, $label, $linkBits);
    # Hide/show minor edits
    $label = $hideMinor ? wfMsgHtml('watchlist-show-minor') : wfMsgHtml('watchlist-hide-minor');
    $linkBits = wfArrayToCGI(array('hideMinor' => 1 - (int) $hideMinor), $nondefaults);
    $links[] = $skin->makeKnownLinkObj($thisTitle, $label, $linkBits);
    $wgOut->addHTML(implode(' | ', $links));
    # Form for namespace filtering
    $form = Xml::openElement('form', array('method' => 'post', 'action' => $thisTitle->getLocalUrl()));
    $form .= '<p>';
    $form .= Xml::label(wfMsg('namespace'), 'namespace') . '&nbsp;';
    $form .= Xml::namespaceSelector($nameSpace, '') . '&nbsp;';
    $form .= Xml::submitButton(wfMsg('allpagessubmit')) . '</p>';
    $form .= Xml::hidden('days', $days);
    if ($hideOwn) {
        $form .= Xml::hidden('hideOwn', 1);
    }
    if ($hideBots) {
        $form .= Xml::hidden('hideBots', 1);
    }
    if ($hideMinor) {
        $form .= Xml::hidden('hideMinor', 1);
    }
    $form .= Xml::closeElement('form');
    $wgOut->addHtml($form);
    # If there's nothing to show, stop here
    if ($numRows == 0) {
        $wgOut->addWikiText(wfMsgNoTrans('watchnochange'));
        return;
    }
    /* End bottom header */
    /* Do link batch query */
    $linkBatch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
        if ($row->rc_user != 0) {
            $linkBatch->add(NS_USER, $userNameUnderscored);
        }
        $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
    }
    $linkBatch->execute();
    $dbr->dataSeek($res, 0);
    $list = ChangesList::newFromUser($wgUser);
    $s = $list->beginRecentChangesList();
    $counter = 1;
    while ($obj = $dbr->fetchObject($res)) {
        # Make RC entry
        $rc = RecentChange::newFromRow($obj);
        $rc->counter = $counter++;
        if ($wgShowUpdatedMarker) {
            $updated = $obj->wl_notificationtimestamp;
        } else {
            // Same visual appearance as MW 1.4
            $updated = true;
        }
        if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
            $sql3 = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_title='" . $dbr->strencode($obj->page_title) . "' AND wl_namespace='{$obj->page_namespace}'";
            $res3 = $dbr->query($sql3, $fname);
            $x = $dbr->fetchObject($res3);
            $rc->numberofWatchingusers = $x->n;
        } else {
            $rc->numberofWatchingusers = 0;
        }
        $s .= $list->recentChangesLine($rc, $updated);
    }
    $s .= $list->endRecentChangesList();
    $dbr->freeResult($res);
    $wgOut->addHTML($s);
}
 public function prepare()
 {
     global $wgUser, $wgRequest, $wgShowUpdatedMarker;
     $fname = 'Watchlist::prepare';
     $defaults = array('days' => floatval($wgUser->getGlobalPreference('watchlistdays')), 'hideOwn' => (int) $wgUser->getGlobalPreference('watchlisthideown'), 'hideBots' => (int) $wgUser->getGlobalPreference('watchlisthidebots'), 'hideMinor' => (int) $wgUser->getGlobalPreference('watchlisthideminor'), 'namespace' => 'all');
     extract($defaults);
     # Extract variables from the request, falling back to user preferences or
     # other default values if these don't exist
     $prefs['days'] = floatval($wgUser->getGlobalPreference('watchlistdays'));
     $prefs['hideown'] = (bool) $wgUser->getGlobalPreference('watchlisthideown');
     $prefs['hidebots'] = (bool) $wgUser->getGlobalPreference('watchlisthidebots');
     $prefs['hideminor'] = (bool) $wgUser->getGlobalPreference('watchlisthideminor');
     # Get query variables
     $days = $wgRequest->getVal('days', $prefs['days']);
     $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
     $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
     $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
     # Get namespace value, if supplied, and prepare a WHERE fragment
     $nameSpace = $wgRequest->getIntOrNull('namespace');
     if (!is_null($nameSpace)) {
         $nameSpace = intval($nameSpace);
         $nameSpaceClause = " AND rc_namespace = {$nameSpace}";
     } else {
         $nameSpace = '';
         $nameSpaceClause = '';
     }
     $this->mDbr = wfGetDB(DB_SLAVE, 'watchlist');
     list($page, $watchlist, $recentchanges) = $this->mDbr->tableNamesN('page', 'watchlist', 'recentchanges');
     $uid = $wgUser->getId();
     $watchlistCount = $this->mDbr->selectField('watchlist', 'COUNT(*)', array('wl_user' => $uid), __METHOD__);
     // Adjust for page X, talk:page X, which are both stored separately,
     // but treated together
     $nitems = floor($watchlistCount / 2);
     if (is_null($days) || !is_numeric($days)) {
         $big = 1000;
         /* The magical big */
         if ($nitems > $big) {
             # Set default cutoff shorter
             $days = $defaults['days'] = 12.0 / 24.0;
             # 12 hours...
         } else {
             $days = $defaults['days'];
             # default cutoff for shortlisters
         }
     } else {
         $days = floatval($days);
     }
     // Dump everything here
     $nondefaults = array();
     wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
     $hookSql = "";
     if (!wfRunHooks('BeforeWatchlist', array($nondefaults, $wgUser, &$hookSql))) {
         return;
     }
     if ($days <= 0) {
         $andcutoff = '';
     } else {
         $andcutoff = "AND rc_timestamp > '" . $this->mDbr->timestamp(time() - intval($days * 86400)) . "'";
         /*
         $sql = "SELECT COUNT(*) AS n FROM $page, $revision  WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
         $this->mChanges = $this->mDbr->query( $sql, $fname );
         $s = $this->mDbr->fetchObject( $this->mChanges );
         $npages = $s->n;
         */
     }
     # If the watchlist is relatively short, it's simplest to zip
     # down its entirety and then sort the results.
     # If it's relatively long, it may be worth our while to zip
     # through the time-sorted page list checking for watched items.
     # Up estimate of watched items by 15% to compensate for talk pages...
     # Toggles
     $andHideOwn = $hideOwn ? "AND (rc_user <> {$uid})" : '';
     $andHideBots = $hideBots ? "AND (rc_bot = 0)" : '';
     $andHideMinor = $hideMinor ? 'AND rc_minor = 0' : '';
     # Toggle watchlist content (all recent edits or just the latest)
     if ($wgUser->getGlobalPreference('extendwatchlist')) {
         $andLatest = '';
         $limitWatchlist = 'LIMIT ' . intval($wgUser->getGlobalPreference('wllimit'));
     } else {
         # Top log Ids for a page are not stored
         $andLatest = 'AND (rc_this_oldid=page_latest OR rc_type=' . RC_LOG . ') ';
         $limitWatchlist = '';
     }
     if ($wgShowUpdatedMarker) {
         $wltsfield = ", {$watchlist}.wl_notificationtimestamp ";
     } else {
         $wltsfield = '';
     }
     $sql = "SELECT {$recentchanges}.* {$wltsfield}\n\t\t  FROM {$watchlist},{$recentchanges}\n\t\t  LEFT JOIN {$page} ON rc_cur_id=page_id\n\t\t  WHERE wl_user={$uid}\n\t\t  AND wl_namespace=rc_namespace\n\t\t  AND wl_title=rc_title\n\t\t  {$andcutoff}\n\t\t  {$andLatest}\n\t\t  {$andHideOwn}\n\t\t  {$andHideBots}\n\t\t  {$andHideMinor}\n\t\t  {$nameSpaceClause}\n\t\t  {$hookSql}\n\t\t  ORDER BY rc_timestamp DESC\n\t\t  {$limitWatchlist}";
     $this->mChanges = $this->mDbr->query($sql, $fname);
     $numRows = $this->mDbr->numRows($this->mChanges);
     # If there's nothing to show, stop here
     if ($numRows == 0) {
         return;
     }
     // Do link batch query - NOTE: I don't know what this section does or wheter it's needed - SWC 20081127
     $linkBatch = new LinkBatch();
     while ($row = $this->mDbr->fetchObject($this->mChanges)) {
         $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
         if ($row->rc_user != 0) {
             $linkBatch->add(NS_USER, $userNameUnderscored);
         }
         $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
     }
     $linkBatch->execute();
     $this->mDbr->dataSeek($this->mChanges, 0);
 }
 public function buildRssWatch($par)
 {
     // TODO SU (04.07.11 10:35): Globals
     global $wgUser, $wgOut, $wgRequest, $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker, $wgEnotifWatchlist, $wgSitename;
     $skin = RequestContext::getMain()->getSkin();
     $specialTitle = SpecialPage::getTitleFor('Watchlist');
     $wgOut->setRobotPolicy('noindex,nofollow');
     # Anons don't get a watchlist
     if ($wgUser->isAnon()) {
         $_user = $wgRequest->getVal('u', '');
         $user = User::newFromName($_user);
         $_hash = $wgRequest->getVal('h', '');
         if (!($user && $_hash == md5($_user . $user->getToken() . $user->getId())) || $user->isAnon()) {
             $oTitle = SpecialPage::getTitleFor('Userlogin');
             $sLink = Linker::link($oTitle, wfMessage('loginreqlink')->plain(), array(), array('returnto' => $specialTitle->getLocalUrl()));
             throw new ErrorPageError('bs-rssstandards-watchnologin', 'watchlistanontext', array($sLink));
         }
     } else {
         $user = $wgUser;
     }
     $wgOut->setPageTitle(wfMessage('bs-rssstandards-watchlist')->plain());
     $sub = wfMessage('watchlistfor', $user->getName())->parse();
     $sub .= '<br />' . WatchlistEditor::buildTools($user->getSkin());
     $wgOut->setSubtitle($sub);
     if (($mode = WatchlistEditor::getMode($wgRequest, $par)) !== false) {
         $editor = new WatchlistEditor();
         $editor->execute($user, $wgOut, $wgRequest, $mode);
         return;
     }
     $uid = $user->getId();
     if (($wgEnotifWatchlist || $wgShowUpdatedMarker) && $wgRequest->getVal('reset') && $wgRequest->wasPosted()) {
         $user->clearAllNotifications($uid);
         $wgOut->redirect($specialTitle->getFullUrl());
         return;
     }
     $defaults = array('days' => floatval($user->getOption('watchlistdays')), 'hideOwn' => (int) $user->getBoolOption('watchlisthideown'), 'hideBots' => (int) $user->getBoolOption('watchlisthidebots'), 'hideMinor' => (int) $user->getBoolOption('watchlisthideminor'), 'namespace' => 'all');
     extract($defaults);
     # Extract variables from the request, falling back to user preferences or
     # other default values if these don't exist
     $prefs['days'] = floatval($user->getOption('watchlistdays'));
     $prefs['hideown'] = $user->getBoolOption('watchlisthideown');
     $prefs['hidebots'] = $user->getBoolOption('watchlisthidebots');
     $prefs['hideminor'] = $user->getBoolOption('watchlisthideminor');
     # Get query variables
     $days = $wgRequest->getVal('days', $prefs['days']);
     $hideOwn = $wgRequest->getBool('hideOwn', $prefs['hideown']);
     $hideBots = $wgRequest->getBool('hideBots', $prefs['hidebots']);
     $hideMinor = $wgRequest->getBool('hideMinor', $prefs['hideminor']);
     # Get namespace value, if supplied, and prepare a WHERE fragment
     $nameSpace = $wgRequest->getIntOrNull('namespace');
     if (!is_null($nameSpace)) {
         $nameSpace = intval($nameSpace);
         $nameSpaceClause = " AND rc_namespace = {$nameSpace}";
     } else {
         $nameSpace = '';
         $nameSpaceClause = '';
     }
     $dbr = wfGetDB(DB_SLAVE, 'watchlist');
     list($page, $watchlist, $recentchanges) = $dbr->tableNamesN('page', 'watchlist', 'recentchanges');
     $watchlistCount = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_user' => $uid), __METHOD__);
     // Adjust for page X, talk:page X, which are both stored separately,
     // but treated together
     $nitems = floor($watchlistCount / 2);
     if (is_null($days) || !is_numeric($days)) {
         $big = 1000;
         /* The magical big */
         if ($nitems > $big) {
             # Set default cutoff shorter
             $days = $defaults['days'] = 12.0 / 24.0;
             # 12 hours...
         } else {
             $days = $defaults['days'];
             # default cutoff for shortlisters
         }
     } else {
         $days = floatval($days);
     }
     // Dump everything here
     $nondefaults = array();
     wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideOwn', (int) $hideOwn, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideBots', (int) $hideBots, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('hideMinor', (int) $hideMinor, $defaults, $nondefaults);
     wfAppendToArrayIfNotDefault('namespace', $nameSpace, $defaults, $nondefaults);
     $hookSql = "";
     if (!wfRunHooks('BeforeWatchlist', array($nondefaults, $user, &$hookSql))) {
         return;
     }
     /*if ( $nitems == 0 ) {
     			$wgOut->addWikiMsg( 'nowatchlist' );
     			return;
     		}*/
     if ($days <= 0) {
         $andcutoff = '';
     } else {
         $andcutoff = "AND rc_timestamp > '" . $dbr->timestamp(time() - intval($days * 86400)) . "'";
     }
     # If the watchlist is relatively short, it's simplest to zip
     # down its entirety and then sort the results.
     # If it's relatively long, it may be worth our while to zip
     # through the time-sorted page list checking for watched items.
     # Up estimate of watched items by 15% to compensate for talk pages...
     # Toggles
     $andHideOwn = $hideOwn ? "AND (rc_user <> {$uid})" : '';
     $andHideBots = $hideBots ? "AND (rc_bot = 0)" : '';
     $andHideMinor = $hideMinor ? 'AND rc_minor = 0' : '';
     # Toggle watchlist content (all recent edits or just the latest)
     if ($user->getOption('extendwatchlist')) {
         $andLatest = '';
         $limitWatchlist = 'LIMIT ' . intval($user->getOption('wllimit'));
     } else {
         # Top log Ids for a page are not stored
         $andLatest = 'AND (rc_this_oldid=page_latest OR rc_type=' . RC_LOG . ') ';
         $limitWatchlist = '';
     }
     if ($wgShowUpdatedMarker) {
         $wltsfield = ", {$watchlist}.wl_notificationtimestamp ";
     } else {
         $wltsfield = '';
     }
     $sql = "SELECT {$recentchanges}.* {$wltsfield}\n\t  FROM {$watchlist},{$recentchanges}\n\t  LEFT JOIN {$page} ON rc_cur_id=page_id\n\t  WHERE wl_user={$uid}\n\t  AND wl_namespace=rc_namespace\n\t  AND wl_title=rc_title\n\t\t\t{$andcutoff}\n\t\t\t{$andLatest}\n\t\t\t{$andHideOwn}\n\t\t\t{$andHideBots}\n\t\t\t{$andHideMinor}\n\t\t\t{$nameSpaceClause}\n\t\t\t{$hookSql}\n\t  ORDER BY rc_timestamp DESC\n\t\t\t{$limitWatchlist}";
     $res = $dbr->query($sql, __METHOD__);
     $numRows = $dbr->numRows($res);
     /*# If there's nothing to show, stop here
     		if( $numRows == 0 ) {
     			$wgOut->addWikiMsg( 'watchnochange' );
     			return;
     		}*/
     /* End bottom header */
     if ($numRows > 0) {
         /* Do link batch query */
         $linkBatch = new LinkBatch();
         while ($row = $dbr->fetchObject($res)) {
             $userNameUnderscored = str_replace(' ', '_', $row->rc_user_text);
             if ($row->rc_user != 0) {
                 $linkBatch->add(NS_USER, $userNameUnderscored);
             }
             $linkBatch->add(NS_USER_TALK, $userNameUnderscored);
         }
         $linkBatch->execute();
         $dbr->dataSeek($res, 0);
     }
     $list = ChangesList::newFromContext($skin->getContext());
     //Thanks to Bartosz Dziewoński (https://gerrit.wikimedia.org/r/#/c/94082/)
     $channel = RSSCreator::createChannel(SpecialPage::getTitleFor('Watchlist') . ' (' . $user->getName() . ')', 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], wfMessage('bs-rssstandards-desc-watch')->plain());
     $html = $list->beginRecentChangesList();
     $counter = 1;
     $items = array();
     while ($obj = $dbr->fetchObject($res)) {
         $title = Title::newFromText($obj->rc_title, $obj->rc_namespace);
         $items[] = array('title' => $title->getPrefixedText(), 'link' => $title->getFullURL(), 'date' => wfTimestamp(TS_UNIX, $obj->rc_timestamp), 'comments' => $title->getTalkPage()->getFullURL());
         # Make RC entry
         $rc = RecentChange::newFromRow($obj);
         $rc->counter = $counter++;
         if ($wgShowUpdatedMarker) {
             $updated = $obj->wl_notificationtimestamp;
         } else {
             $updated = false;
         }
         if ($wgRCShowWatchingUsers && $user->getOption('shownumberswatching')) {
             $rc->numberofWatchingusers = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_namespace' => $obj->rc_namespace, 'wl_title' => $obj->rc_title), __METHOD__);
         } else {
             $rc->numberofWatchingusers = 0;
         }
         $rc->mAttribs['rc_timestamp'] = 0;
         $html .= $list->recentChangesLine($rc, false);
     }
     $html .= $list->endRecentChangesList();
     $lines = array();
     preg_match_all('%<li.*?>(.*?)</li>%', $html, $lines, PREG_SET_ORDER);
     foreach ($lines as $key => $line) {
         $item = $items[$key];
         $entry = RSSItemCreator::createItem($item['title'], $item['link'], RSSCreator::xmlEncode($line[1]));
         if ($entry == false) {
             wfDebugLog('BS::RSSStandards::buildRssWatch', 'Invalid item: ' . var_export($item, true));
             continue;
         }
         $entry->setPubDate($item['date']);
         $entry->setComments($item['comments']);
         $channel->addItem($entry);
     }
     $dbr->freeResult($res);
     return $channel->buildOutput();
 }
	protected function setup( $parameters ) {
		global $wgUser, $wgRequest;

		$defaults = array(
			/* str  */ 'module'   => '',
			/* str  */ 'language' => $wgUser->getOption( 'language' ),
			/* bool */ 'export'   => false,
			/* bool */ 'savetodb' => false,
		);

		/**
		 * Place where all non default variables will end.
		 */
		$nondefaults = array();

		/**
		 * Temporary store possible values parsed from parameters.
		 */
		$options = $defaults;
		foreach ( $options as $v => $t ) {
			if ( is_bool( $t ) ) {
				$r = $wgRequest->getBool( $v, $options[$v] );
			} elseif ( is_int( $t ) ) {
				$r = $wgRequest->getInt( $v, $options[$v] );
			} elseif ( is_string( $t ) ) {
				$r = $wgRequest->getText( $v, $options[$v] );
			}
			wfAppendToArrayIfNotDefault( $v, $r, $defaults, $nondefaults );
		}

		$this->defaults    = $defaults;
		$this->nondefaults = $nondefaults;
		$this->options     = $nondefaults + $defaults;
	}
	/**
	 * Execute
	 * @param $par Parameter passed to the page
	 */
	function execute( $par ) {
		global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;

		$user = $this->getUser();
		$output = $this->getOutput();

		# Anons don't get a watchlist
		if ( $user->isAnon() ) {
			$output->setPageTitle( $this->msg( 'watchnologin' ) );
			$output->setRobotPolicy( 'noindex,nofollow' );
			$llink = Linker::linkKnown(
				SpecialPage::getTitleFor( 'Userlogin' ),
				$this->msg( 'loginreqlink' )->escaped(),
				array(),
				array( 'returnto' => $this->getTitle()->getPrefixedText() )
			);
			$output->addHTML( $this->msg( 'watchlistanontext' )->rawParams( $llink )->parse() );
			return;
		}

		// Check permissions
		$this->checkPermissions();

		// Add feed links
		$wlToken = $user->getTokenFromOption( 'watchlisttoken' );
		if ( $wlToken ) {
			$this->addFeedLinks( array( 'action' => 'feedwatchlist', 'allrev' => 'allrev',
								'wlowner' => $user->getName(), 'wltoken' => $wlToken ) );
		}

		$this->setHeaders();
		$this->outputHeader();

		$output->addSubtitle( $this->msg( 'watchlistfor2', $user->getName()
			)->rawParams( SpecialEditWatchlist::buildTools( null ) ) );

		$request = $this->getRequest();

		$mode = SpecialEditWatchlist::getMode( $request, $par );
		if ( $mode !== false ) {
			# TODO: localise?
			switch ( $mode ) {
				case SpecialEditWatchlist::EDIT_CLEAR:
					$mode = 'clear';
					break;
				case SpecialEditWatchlist::EDIT_RAW:
					$mode = 'raw';
					break;
				default:
					$mode = null;
			}
			$title = SpecialPage::getTitleFor( 'EditWatchlist', $mode );
			$output->redirect( $title->getLocalURL() );
			return;
		}

		$dbr = wfGetDB( DB_SLAVE, 'watchlist' );

		$nitems = $this->countItems( $dbr );
		if ( $nitems == 0 ) {
			$output->addWikiMsg( 'nowatchlist' );
			return;
		}

		// @todo use FormOptions!
		$defaults = array(
		/* float */ 'days' => floatval( $user->getOption( 'watchlistdays' ) ),
		/* bool  */ 'hideMinor' => (int)$user->getBoolOption( 'watchlisthideminor' ),
		/* bool  */ 'hideBots' => (int)$user->getBoolOption( 'watchlisthidebots' ),
		/* bool  */ 'hideAnons' => (int)$user->getBoolOption( 'watchlisthideanons' ),
		/* bool  */ 'hideLiu' => (int)$user->getBoolOption( 'watchlisthideliu' ),
		/* bool  */ 'hidePatrolled' => (int)$user->getBoolOption( 'watchlisthidepatrolled' ),
		/* bool  */ 'hideOwn' => (int)$user->getBoolOption( 'watchlisthideown' ),
		/* bool  */ 'extended' => (int)$user->getBoolOption( 'extendwatchlist' ),
		/* ?     */ 'namespace' => '', //means all
		/* ?     */ 'invert' => false,
		/* bool  */ 'associated' => false,
		);
		$this->customFilters = array();
		wfRunHooks( 'SpecialWatchlistFilters', array( $this, &$this->customFilters ) );
		foreach ( $this->customFilters as $key => $params ) {
			$defaults[$key] = $params['default'];
		}

		# Extract variables from the request, falling back to user preferences or
		# other default values if these don't exist
		$values = array();
		$values['days'] = floatval( $request->getVal( 'days', $defaults['days'] ) );
		$values['hideMinor'] = (int)$request->getBool( 'hideMinor', $defaults['hideMinor'] );
		$values['hideBots'] = (int)$request->getBool( 'hideBots', $defaults['hideBots'] );
		$values['hideAnons'] = (int)$request->getBool( 'hideAnons', $defaults['hideAnons'] );
		$values['hideLiu'] = (int)$request->getBool( 'hideLiu', $defaults['hideLiu'] );
		$values['hideOwn'] = (int)$request->getBool( 'hideOwn', $defaults['hideOwn'] );
		$values['hidePatrolled'] = (int)$request->getBool( 'hidePatrolled', $defaults['hidePatrolled'] );
		$values['extended'] = (int)$request->getBool( 'extended', $defaults['extended'] );
		foreach ( $this->customFilters as $key => $params ) {
			$values[$key] = (int)$request->getBool( $key, $defaults[$key] );
		}

		# Get namespace value, if supplied, and prepare a WHERE fragment
		$nameSpace = $request->getIntOrNull( 'namespace' );
		$invert = $request->getBool( 'invert' );
		$associated = $request->getBool( 'associated' );
		if ( !is_null( $nameSpace ) ) {
			$eq_op = $invert ? '!=' : '=';
			$bool_op = $invert ? 'AND' : 'OR';
			$nameSpace = intval( $nameSpace ); // paranioa
			if ( !$associated ) {
				$nameSpaceClause = "rc_namespace $eq_op $nameSpace";
			} else {
				$associatedNS = MWNamespace::getAssociated( $nameSpace );
				$nameSpaceClause =
					"rc_namespace $eq_op $nameSpace " .
					$bool_op .
					" rc_namespace $eq_op $associatedNS";
			}
		} else {
			$nameSpace = '';
			$nameSpaceClause = '';
		}
		$values['namespace'] = $nameSpace;
		$values['invert'] = $invert;
		$values['associated'] = $associated;

		// Dump everything here
		$nondefaults = array();
		foreach ( $defaults as $name => $defValue ) {
			wfAppendToArrayIfNotDefault( $name, $values[$name], $defaults, $nondefaults );
		}

		if ( ( $wgEnotifWatchlist || $wgShowUpdatedMarker ) && $request->getVal( 'reset' ) &&
			$request->wasPosted() )
		{
			$user->clearAllNotifications();
			$output->redirect( $this->getTitle()->getFullURL( $nondefaults ) );
			return;
		}

		# Possible where conditions
		$conds = array();

		if ( $values['days'] > 0 ) {
			$conds[] = 'rc_timestamp > ' . $dbr->addQuotes( $dbr->timestamp( time() - intval( $values['days'] * 86400 ) ) );
		}

		# Toggles
		if ( $values['hideOwn'] ) {
			$conds[] = 'rc_user != ' . $user->getId();
		}
		if ( $values['hideBots'] ) {
			$conds[] = 'rc_bot = 0';
		}
		if ( $values['hideMinor'] ) {
			$conds[] = 'rc_minor = 0';
		}
		if ( $values['hideLiu'] ) {
			$conds[] = 'rc_user = 0';
		}
		if ( $values['hideAnons'] ) {
			$conds[] = 'rc_user != 0';
		}
		if ( $user->useRCPatrol() && $values['hidePatrolled'] ) {
			$conds[] = 'rc_patrolled != 1';
		}
		if ( $nameSpaceClause ) {
			$conds[] = $nameSpaceClause;
		}

		# Toggle watchlist content (all recent edits or just the latest)
		if ( $values['extended'] ) {
			$limitWatchlist = $user->getIntOption( 'wllimit' );
			$usePage = false;
		} else {
			# Top log Ids for a page are not stored
			$nonRevisionTypes = array( RC_LOG );
			wfRunHooks( 'SpecialWatchlistGetNonRevisionTypes', array( &$nonRevisionTypes ) );
			if ( $nonRevisionTypes ) {
				if ( count( $nonRevisionTypes ) === 1 ) {
					// if only one use an equality instead of IN condition
					$nonRevisionTypes = reset( $nonRevisionTypes );
				}
				$conds[] = $dbr->makeList(
					array(
						'rc_this_oldid=page_latest',
						'rc_type' => $nonRevisionTypes,
					),
					LIST_OR
				);
			}
			$limitWatchlist = 0;
			$usePage = true;
		}

		# Show a message about slave lag, if applicable
		$lag = wfGetLB()->safeGetLag( $dbr );
		if ( $lag > 0 ) {
			$output->showLagWarning( $lag );
		}

		# Create output
		$form = '';

		# Show watchlist header
		$form .= "<p>";
		$form .= $this->msg( 'watchlist-details' )->numParams( $nitems )->parse() . "\n";
		if ( $wgEnotifWatchlist && $user->getOption( 'enotifwatchlistpages' ) ) {
			$form .= $this->msg( 'wlheader-enotif' )->parse() . "\n";
		}
		if ( $wgShowUpdatedMarker ) {
			$form .= $this->msg( 'wlheader-showupdated' )->parse() . "\n";
		}
		$form .= "</p>";

		if ( $wgShowUpdatedMarker ) {
			$form .= Xml::openElement( 'form', array( 'method' => 'post',
				'action' => $this->getTitle()->getLocalURL(),
				'id' => 'mw-watchlist-resetbutton' ) ) . "\n" .
			Xml::submitButton( $this->msg( 'enotif_reset' )->text(), array( 'name' => 'dummy' ) ) . "\n" .
			Html::hidden( 'reset', 'all' ) . "\n";
			foreach ( $nondefaults as $key => $value ) {
				$form .= Html::hidden( $key, $value ) . "\n";
			}
			$form .= Xml::closeElement( 'form' ) . "\n";
		}

		$form .= Xml::openElement( 'form', array(
			'method' => 'post',
			'action' => $this->getTitle()->getLocalURL(),
			'id' => 'mw-watchlist-form'
		) );
		$form .= Xml::fieldset(
			$this->msg( 'watchlist-options' )->text(),
			false,
			array( 'id' => 'mw-watchlist-options' )
		);

		$tables = array( 'recentchanges', 'watchlist' );
		$fields = RecentChange::selectFields();
		$join_conds = array(
			'watchlist' => array(
				'INNER JOIN',
				array(
					'wl_user' => $user->getId(),
					'wl_namespace=rc_namespace',
					'wl_title=rc_title'
				),
			),
		);
		$options = array( 'ORDER BY' => 'rc_timestamp DESC' );
		if ( $wgShowUpdatedMarker ) {
			$fields[] = 'wl_notificationtimestamp';
		}
		if ( $limitWatchlist ) {
			$options['LIMIT'] = $limitWatchlist;
		}

		$rollbacker = $user->isAllowed( 'rollback' );
		if ( $usePage || $rollbacker ) {
			$tables[] = 'page';
			$join_conds['page'] = array( 'LEFT JOIN', 'rc_cur_id=page_id' );
			if ( $rollbacker ) {
				$fields[] = 'page_latest';
			}
		}

		// Log entries with DELETED_ACTION must not show up unless the user has
		// the necessary rights.
		if ( !$user->isAllowed( 'deletedhistory' ) ) {
			$bitmask = LogPage::DELETED_ACTION;
		} elseif ( !$user->isAllowed( 'suppressrevision' ) ) {
			$bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
		} else {
			$bitmask = 0;
		}
		if ( $bitmask ) {
			$conds[] = $dbr->makeList( array(
				'rc_type != ' . RC_LOG,
				$dbr->bitAnd( 'rc_deleted', $bitmask ) . " != $bitmask",
			), LIST_OR );
		}

		ChangeTags::modifyDisplayQuery( $tables, $fields, $conds, $join_conds, $options, '' );
		wfRunHooks( 'SpecialWatchlistQuery', array( &$conds, &$tables, &$join_conds, &$fields, $values ) );

		$res = $dbr->select( $tables, $fields, $conds, __METHOD__, $options, $join_conds );
		$numRows = $res->numRows();

		/* Start bottom header */

		$lang = $this->getLanguage();
		$wlInfo = '';
		if ( $values['days'] > 0 ) {
			$timestamp = wfTimestampNow();
			$wlInfo = $this->msg( 'wlnote' )->numParams( $numRows, round( $values['days'] * 24 ) )->params(
				$lang->userDate( $timestamp, $user ), $lang->userTime( $timestamp, $user ) )->parse() . "<br />\n";
		}

		$cutofflinks = $this->cutoffLinks( $values['days'], $nondefaults ) . "<br />\n";

		# Spit out some control panel links
		$filters = array(
			'hideMinor' => 'rcshowhideminor',
			'hideBots' => 'rcshowhidebots',
			'hideAnons' => 'rcshowhideanons',
			'hideLiu' => 'rcshowhideliu',
			'hideOwn' => 'rcshowhidemine',
			'hidePatrolled' => 'rcshowhidepatr'
		);
		foreach ( $this->customFilters as $key => $params ) {
			$filters[$key] = $params['msg'];
		}
		// Disable some if needed
		if ( !$user->useNPPatrol() ) {
			unset( $filters['hidePatrolled'] );
		}

		$links = array();
		foreach ( $filters as $name => $msg ) {
			$links[] = $this->showHideLink( $nondefaults, $msg, $name, $values[$name] );
		}

		$hiddenFields = $nondefaults;
		unset( $hiddenFields['namespace'] );
		unset( $hiddenFields['invert'] );
		unset( $hiddenFields['associated'] );

		# Namespace filter and put the whole form together.
		$form .= $wlInfo;
		$form .= $cutofflinks;
		$form .= $lang->pipeList( $links ) . "\n";
		$form .= "<hr />\n<p>";
		$form .= Html::namespaceSelector(
			array(
				'selected' => $nameSpace,
				'all' => '',
				'label' => $this->msg( 'namespace' )->text()
			), array(
				'name' => 'namespace',
				'id' => 'namespace',
				'class' => 'namespaceselector',
			)
		) . '&#160;';
		$form .= Xml::checkLabel(
			$this->msg( 'invert' )->text(),
			'invert',
			'nsinvert',
			$invert,
			array( 'title' => $this->msg( 'tooltip-invert' )->text() )
		) . '&#160;';
		$form .= Xml::checkLabel(
			$this->msg( 'namespace_association' )->text(),
			'associated',
			'associated',
			$associated,
			array( 'title' => $this->msg( 'tooltip-namespace_association' )->text() )
		) . '&#160;';
		$form .= Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "</p>\n";
		foreach ( $hiddenFields as $key => $value ) {
			$form .= Html::hidden( $key, $value ) . "\n";
		}
		$form .= Xml::closeElement( 'fieldset' ) . "\n";
		$form .= Xml::closeElement( 'form' ) . "\n";
		$output->addHTML( $form );

		# If there's nothing to show, stop here
		if ( $numRows == 0 ) {
			$output->wrapWikiMsg(
				"<div class='mw-changeslist-empty'>\n$1\n</div>", 'recentchanges-noresult'
			);
			return;
		}

		/* End bottom header */

		/* Do link batch query */
		$linkBatch = new LinkBatch;
		foreach ( $res as $row ) {
			$userNameUnderscored = str_replace( ' ', '_', $row->rc_user_text );
			if ( $row->rc_user != 0 ) {
				$linkBatch->add( NS_USER, $userNameUnderscored );
			}
			$linkBatch->add( NS_USER_TALK, $userNameUnderscored );

			$linkBatch->add( $row->rc_namespace, $row->rc_title );
		}
		$linkBatch->execute();
		$dbr->dataSeek( $res, 0 );

		$list = ChangesList::newFromContext( $this->getContext() );
		$list->setWatchlistDivs();

		$s = $list->beginRecentChangesList();
		$counter = 1;
		foreach ( $res as $obj ) {
			# Make RC entry
			$rc = RecentChange::newFromRow( $obj );
			$rc->counter = $counter++;

			if ( $wgShowUpdatedMarker ) {
				$updated = $obj->wl_notificationtimestamp;
			} else {
				$updated = false;
			}

			if ( $wgRCShowWatchingUsers && $user->getOption( 'shownumberswatching' ) ) {
				$rc->numberofWatchingusers = $dbr->selectField( 'watchlist',
					'COUNT(*)',
					array(
						'wl_namespace' => $obj->rc_namespace,
						'wl_title' => $obj->rc_title,
					),
					__METHOD__ );
			} else {
				$rc->numberofWatchingusers = 0;
			}

			$changeLine = $list->recentChangesLine( $rc, $updated, $counter );
			if ( $changeLine !== false ) {
				$s .= $changeLine;
			}
		}
		$s .= $list->endRecentChangesList();

		$output->addHTML( $s );
	}
 protected function setup($parameters)
 {
     $request = $this->getRequest();
     $isBeta = self::isBeta($request);
     $defaults = array('taction' => 'translate', 'task' => $isBeta ? 'custom' : 'untranslated', 'language' => $this->getLanguage()->getCode(), 'group' => $isBeta ? '!additions' : '', 'offset' => '', 'limit' => $isBeta ? 0 : 100, 'optional' => '0');
     // Dump everything here
     $nondefaults = array();
     $parameters = array_map('trim', explode(';', $parameters));
     $pars = array();
     foreach ($parameters as $_) {
         if ($_ === '') {
             continue;
         }
         if (strpos($_, '=') !== false) {
             list($key, $value) = array_map('trim', explode('=', $_, 2));
         } else {
             $key = 'group';
             $value = $_;
         }
         $pars[$key] = $value;
     }
     foreach ($defaults as $v => $t) {
         if (is_bool($t)) {
             $r = isset($pars[$v]) ? (bool) $pars[$v] : $defaults[$v];
             $r = $request->getBool($v, $r);
         } elseif (is_int($t)) {
             $r = isset($pars[$v]) ? (int) $pars[$v] : $defaults[$v];
             $r = $request->getInt($v, $r);
         } elseif (is_string($t)) {
             $r = isset($pars[$v]) ? (string) $pars[$v] : $defaults[$v];
             $r = $request->getText($v, $r);
         }
         if (!isset($r)) {
             throw new MWException('$r was not set');
         }
         wfAppendToArrayIfNotDefault($v, $r, $defaults, $nondefaults);
     }
     // Fix defaults based on what we got
     if (isset($nondefaults['taction'])) {
         if ($nondefaults['taction'] === 'proofread') {
             if ($this->getUser()->isAllowed('translate-messagereview')) {
                 $defaults['task'] = 'acceptqueue';
             } else {
                 $defaults['task'] = 'reviewall';
             }
         } elseif ($nondefaults['taction'] === 'export') {
             $defaults['task'] = '';
         }
     }
     if ($isBeta) {
         /* @todo fix all the places in Translate to create correct links.
          * The least effort way is to change them once we totally drop the
          * old UI. The penalty is only http redirect in some cases. More
          * effort would be to create utilities like makeTranslationLink
          * and makeProofreadLink.
          */
         $this->rewriteLegacyUrls($nondefaults);
     }
     $this->defaults = $defaults;
     $this->nondefaults = $nondefaults;
     Hooks::run('TranslateGetSpecialTranslateOptions', array(&$defaults, &$nondefaults));
     $this->options = $nondefaults + $defaults;
     $this->group = MessageGroups::getGroup($this->options['group']);
     if ($this->group) {
         $this->options['group'] = $this->group->getId();
     }
     $this->task = TranslateTasks::getTask($this->options['task']);
     if ($this->group && MessageGroups::isDynamic($this->group)) {
         $this->group->setLanguage($this->options['language']);
     }
 }
/**
 * Constructor
 */
function wfSpecialRecentchanges($par, $specialPage)
{
    global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
    global $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
    global $wgAllowCategorizedRecentChanges;
    $fname = 'wfSpecialRecentchanges';
    # Get query parameters
    $feedFormat = $wgRequest->getVal('feed');
    /* Checkbox values can't be true by default, because
     * we cannot differentiate between unset and not set at all
     */
    $defaults = array('days' => $wgUser->getDefaultOption('rcdays'), 'limit' => $wgUser->getDefaultOption('rclimit'), 'hideminor' => false, 'hidebots' => true, 'hideanons' => false, 'hideliu' => false, 'hidepatrolled' => false, 'hidemyself' => false, 'from' => '', 'namespace' => null, 'invert' => false, 'categories_any' => false);
    extract($defaults);
    $days = $wgUser->getOption('rcdays', $defaults['days']);
    $days = $wgRequest->getInt('days', $days);
    $limit = $wgUser->getOption('rclimit', $defaults['limit']);
    #	list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
    $limit = $wgRequest->getInt('limit', $limit);
    /* order of selection: url > preferences > default */
    $hideminor = $wgRequest->getBool('hideminor', $wgUser->getOption('hideminor') ? true : $defaults['hideminor']);
    # As a feed, use limited settings only
    if ($feedFormat) {
        global $wgFeedLimit;
        if ($limit > $wgFeedLimit) {
            $limit = $wgFeedLimit;
        }
    } else {
        $namespace = $wgRequest->getIntOrNull('namespace');
        $invert = $wgRequest->getBool('invert', $defaults['invert']);
        $hidebots = $wgRequest->getBool('hidebots', $defaults['hidebots']);
        $hideanons = $wgRequest->getBool('hideanons', $defaults['hideanons']);
        $hideliu = $wgRequest->getBool('hideliu', $defaults['hideliu']);
        $hidepatrolled = $wgRequest->getBool('hidepatrolled', $defaults['hidepatrolled']);
        $hidemyself = $wgRequest->getBool('hidemyself', $defaults['hidemyself']);
        $from = $wgRequest->getVal('from', $defaults['from']);
        # Get query parameters from path
        if ($par) {
            $bits = preg_split('/\\s*,\\s*/', trim($par));
            foreach ($bits as $bit) {
                if ('hidebots' == $bit) {
                    $hidebots = 1;
                }
                if ('bots' == $bit) {
                    $hidebots = 0;
                }
                if ('hideminor' == $bit) {
                    $hideminor = 1;
                }
                if ('minor' == $bit) {
                    $hideminor = 0;
                }
                if ('hideliu' == $bit) {
                    $hideliu = 1;
                }
                if ('hidepatrolled' == $bit) {
                    $hidepatrolled = 1;
                }
                if ('hideanons' == $bit) {
                    $hideanons = 1;
                }
                if ('hidemyself' == $bit) {
                    $hidemyself = 1;
                }
                if (is_numeric($bit)) {
                    $limit = $bit;
                }
                $m = array();
                if (preg_match('/^limit=(\\d+)$/', $bit, $m)) {
                    $limit = $m[1];
                }
                if (preg_match('/^days=(\\d+)$/', $bit, $m)) {
                    $days = $m[1];
                }
            }
        }
    }
    if ($limit < 0 || $limit > 5000) {
        $limit = $defaults['limit'];
    }
    # Database connection and caching
    $dbr = wfGetDB(DB_SLAVE);
    list($recentchanges, $watchlist) = $dbr->tableNamesN('recentchanges', 'watchlist');
    $cutoff_unixtime = time() - $days * 86400;
    $cutoff_unixtime = $cutoff_unixtime - $cutoff_unixtime % 86400;
    $cutoff = $dbr->timestamp($cutoff_unixtime);
    if (preg_match('/^[0-9]{14}$/', $from) and $from > wfTimestamp(TS_MW, $cutoff)) {
        $cutoff = $dbr->timestamp($from);
    } else {
        $from = $defaults['from'];
    }
    # 10 seconds server-side caching max
    $wgOut->setSquidMaxage(10);
    # Get last modified date, for client caching
    # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
    $lastmod = $dbr->selectField('recentchanges', 'MAX(rc_timestamp)', false, $fname);
    if ($feedFormat || !$wgUseRCPatrol) {
        if ($lastmod && $wgOut->checkLastModified($lastmod)) {
            # Client cache fresh and headers sent, nothing more to do.
            return;
        }
    }
    # It makes no sense to hide both anons and logged-in users
    # Where this occurs, force anons to be shown
    if ($hideanons && $hideliu) {
        $hideanons = false;
    }
    # Form WHERE fragments for all the options
    $hidem = $hideminor ? 'AND rc_minor = 0' : '';
    $hidem .= $hidebots ? ' AND rc_bot = 0' : '';
    $hidem .= $hideliu ? ' AND rc_user = 0' : '';
    $hidem .= $wgUseRCPatrol && $hidepatrolled ? ' AND rc_patrolled = 0' : '';
    $hidem .= $hideanons ? ' AND rc_user != 0' : '';
    if ($hidemyself) {
        if ($wgUser->getID()) {
            $hidem .= ' AND rc_user != ' . $wgUser->getID();
        } else {
            $hidem .= ' AND rc_user_text != ' . $dbr->addQuotes($wgUser->getName());
        }
    }
    # Namespace filtering
    $hidem .= is_null($namespace) ? '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
    // This is the big thing!
    $uid = $wgUser->getID();
    // Perform query
    $forceclause = $dbr->useIndexClause("rc_timestamp");
    $sql2 = "SELECT * FROM {$recentchanges} {$forceclause}" . ($uid ? "LEFT OUTER JOIN {$watchlist} ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") . "WHERE rc_timestamp >= '{$cutoff}' {$hidem} " . "ORDER BY rc_timestamp DESC";
    $sql2 = $dbr->limitResult($sql2, $limit, 0);
    $res = $dbr->query($sql2, $fname);
    // Fetch results, prepare a batch link existence check query
    $rows = array();
    $batch = new LinkBatch();
    while ($row = $dbr->fetchObject($res)) {
        $rows[] = $row;
        if (!$feedFormat) {
            // User page link
            $title = Title::makeTitleSafe(NS_USER, $row->rc_user_text);
            $batch->addObj($title);
            // User talk
            $title = Title::makeTitleSafe(NS_USER_TALK, $row->rc_user_text);
            $batch->addObj($title);
        }
    }
    $dbr->freeResult($res);
    if ($feedFormat) {
        rcOutputFeed($rows, $feedFormat, $limit, $hideminor, $lastmod);
    } else {
        # Web output...
        // Run existence checks
        $batch->execute();
        $any = $wgRequest->getBool('categories_any', $defaults['categories_any']);
        // Output header
        if (!$specialPage->including()) {
            $wgOut->addWikiText(wfMsgForContentNoTrans("recentchangestext"));
            // Dump everything here
            $nondefaults = array();
            wfAppendToArrayIfNotDefault('days', $days, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('limit', $limit, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideminor', $hideminor, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidebots', $hidebots, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideanons', $hideanons, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hideliu', $hideliu, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('hidemyself', $hidemyself, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('from', $from, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('namespace', $namespace, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('invert', $invert, $defaults, $nondefaults);
            wfAppendToArrayIfNotDefault('categories_any', $any, $defaults, $nondefaults);
            // Add end of the texts
            $wgOut->addHTML('<div class="rcoptions">' . rcOptionsPanel($defaults, $nondefaults) . "\n");
            $wgOut->addHTML(rcNamespaceForm($namespace, $invert, $nondefaults, $any) . '</div>' . "\n");
        }
        // And now for the content
        $list = ChangesList::newFromUser($wgUser);
        if ($wgAllowCategorizedRecentChanges) {
            $categories = trim($wgRequest->getVal('categories', ""));
            $categories = str_replace("|", "\n", $categories);
            $categories = explode("\n", $categories);
            rcFilterByCategories($rows, $categories, $any);
        }
        $s = $list->beginRecentChangesList();
        $counter = 1;
        foreach ($rows as $obj) {
            if ($limit == 0) {
                break;
            }
            if (!($hideminor && $obj->rc_minor) && !($hidepatrolled && $obj->rc_patrolled)) {
                $rc = RecentChange::newFromRow($obj);
                $rc->counter = $counter++;
                if ($wgShowUpdatedMarker && !empty($obj->wl_notificationtimestamp) && $obj->rc_timestamp >= $obj->wl_notificationtimestamp) {
                    $rc->notificationtimestamp = true;
                } else {
                    $rc->notificationtimestamp = false;
                }
                if ($wgRCShowWatchingUsers && $wgUser->getOption('shownumberswatching')) {
                    $sql3 = "SELECT COUNT(*) AS n FROM {$watchlist} WHERE wl_title='" . $dbr->strencode($obj->rc_title) . "' AND wl_namespace={$obj->rc_namespace}";
                    $res3 = $dbr->query($sql3, 'wfSpecialRecentChanges');
                    $x = $dbr->fetchObject($res3);
                    $rc->numberofWatchingusers = $x->n;
                } else {
                    $rc->numberofWatchingusers = 0;
                }
                $s .= $list->recentChangesLine($rc, !empty($obj->wl_user));
                --$limit;
            }
        }
        $s .= $list->endRecentChangesList();
        $wgOut->addHTML($s);
    }
}
 protected function setup($parameters)
 {
     global $wgUser, $wgRequest;
     $defaults = array('task' => 'untranslated', 'sort' => 'normal', 'language' => $wgUser->getOption('language'), 'group' => '', 'offset' => 0, 'limit' => 100);
     // Dump everything here
     $nondefaults = array();
     $parameters = array_map('trim', explode(';', $parameters));
     $pars = array();
     foreach ($parameters as $_) {
         if ($_ === '') {
             continue;
         }
         if (strpos($_, '=') !== false) {
             list($key, $value) = array_map('trim', explode('=', $_, 2));
         } else {
             $key = 'group';
             $value = $_;
         }
         $pars[$key] = $value;
     }
     foreach ($defaults as $v => $t) {
         if (is_bool($t)) {
             $r = isset($pars[$v]) ? (bool) $pars[$v] : $defaults[$v];
             $r = $wgRequest->getBool($v, $r);
         } elseif (is_int($t)) {
             $r = isset($pars[$v]) ? (int) $pars[$v] : $defaults[$v];
             $r = $wgRequest->getInt($v, $r);
         } elseif (is_string($t)) {
             $r = isset($pars[$v]) ? (string) $pars[$v] : $defaults[$v];
             $r = $wgRequest->getText($v, $r);
         }
         wfAppendToArrayIfNotDefault($v, $r, $defaults, $nondefaults);
     }
     $this->defaults = $defaults;
     $this->nondefaults = $nondefaults;
     $this->options = $nondefaults + $defaults;
     $this->group = MessageGroups::getGroup($this->options['group']);
     $this->task = TranslateTasks::getTask($this->options['task']);
     if ($this->group instanceof RecentMessageGroup) {
         $this->group->setLanguage($this->options['language']);
     }
 }