/**
  * @param ApiPageSet $resultPageSet
  * @throws MWException
  * @throws \UsageException
  */
 private function run($resultPageSet = null)
 {
     $params = $this->extractRequestParams();
     $isGenerator = $resultPageSet !== null;
     ApiMixinListAccess::checkListAccess($this->getDB(), $this, $params, $isWatchlist, $ownerId);
     if ($isWatchlist) {
         $titles = $this->queryLegacyWatchlist($params, $isGenerator, $ownerId);
     } else {
         $titles = $this->queryListItems($params, $isGenerator);
     }
     if (!$isGenerator) {
         $this->getResult()->addIndexedTagName($this->modulePath, 'wr');
     } else {
         $resultPageSet->populateFromTitles($titles);
     }
 }
 public function execute()
 {
     $titles = $this->getPageSet()->getGoodAndMissingTitles();
     $titleLookup = $this->getPageSet()->getGoodAndMissingTitlesByNamespace();
     if (!count($titles)) {
         # Nothing to do
         return;
     }
     $params = $this->extractRequestParams();
     $db = $this->getDB();
     // watchlist and gather_list_item tables are very similar, and have one identifying value -
     // UserID for watchlists, and ListID for lists. CheckListAccess will tell us which table we
     // should use. If userId is returned, use watchlist, otherwise the $params['id'] is valid,
     // and should be used for the gather_list_item.
     ApiMixinListAccess::checkListAccess($db, $this, $params, $isWatchlist, $ownerId);
     if ($isWatchlist) {
         $prefix = 'wl';
         $db = $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist');
         $this->addTables('watchlist');
         $this->addWhereFld('wl_user', $ownerId);
     } else {
         $prefix = 'gli';
         $this->addTables('gather_list_item');
         $this->addWhereFld('gli_gl_id', $params['id']);
     }
     $this->addFields(array('ns' => "{$prefix}_namespace", 'title' => "{$prefix}_title"));
     $lb = new LinkBatch($titles);
     $this->addWhere($lb->constructSet($prefix, $db));
     if ($params['continue'] !== null) {
         $cont = explode('|', $params['continue']);
         $this->dieContinueUsageIf(count($cont) != 2);
         $contNs = intval($cont[0]);
         $this->dieContinueUsageIf(strval($contNs) !== $cont[0]);
         $contTitle = $db->addQuotes($cont[1]);
         $this->addWhere("{$prefix}_namespace > {$contNs} OR " . "({$prefix}_namespace = {$contNs} AND " . "{$prefix}_title >= {$contTitle})");
     }
     // Don't ORDER BY namespace if it's constant in the WHERE clause
     if (count($titleLookup) === 1) {
         $this->addOption('ORDER BY', "{$prefix}_title");
     } else {
         $this->addOption('ORDER BY', array("{$prefix}_namespace", "{$prefix}_title"));
     }
     // NOTE: We never set listmembership=false because we don't really know which ones are not
     // in the database. If we ran out of memory halfway and need to continue, next time we will
     // skip those already done, so even though DB contains rows, we skipped them and gotten
     // the next batch. In other words, the pages that at the end of this module do not have
     // listmembership=true might still be true, but they were reported in the previous API call.
     $result = $this->getResult();
     foreach ($this->select(__METHOD__) as $row) {
         $ns = intval($row->ns);
         if (!isset($titleLookup[$ns][$row->title])) {
             wfDebug(__METHOD__ . " Unexpected DB row {$row->ns}:{$row->title}\n");
             continue;
         }
         $fit = $result->addValue(array('query', 'pages', $titleLookup[$ns][$row->title]), 'listmembership', true);
         if (!$fit) {
             $this->setContinueEnumParameter('continue', $row->ns . '|' . $row->title);
             break;
         }
     }
 }