/**
  * Ensure that current params make sense, specify an existing list, and the requesting user has
  * access to it. Die if that's not the case.
  * @param DatabaseBase $db
  * @param ApiBase $module
  * @param array $params module parameters
  * @param bool $isWatchlist Will be set to true if the requested list is a watchlist
  * @param int $ownerId Will be set to the user ID of the list's owner
  * @throws \UsageException In case access is not allowed
  */
 public static function checkListAccess(DatabaseBase $db, ApiBase $module, array $params, &$isWatchlist, &$ownerId)
 {
     global $wgGatherAutohideFlagLimit;
     if (is_null($params['owner']) !== is_null($params['token'])) {
         $p = $module->getModulePrefix();
         $module->dieUsage("Both {$p}owner and {$p}token must be given or missing", 'invalidparammix');
     }
     if (!$params['id']) {
         // If collection id is not given (or equals to 0), this is a watchlist access;
         // ApiBase::getWatchlistUser does all the necessary checks
         $isWatchlist = true;
         $ownerId = $module->getWatchlistUser($params)->getId();
         return;
     }
     // Id was given, this could be public or private list, legacy watchlist or regular
     // Allow access to any public list/watchlist, and to private with proper owner/self
     $listRow = $db->selectRow('gather_list', array('gl_label', 'gl_user', 'gl_perm', 'gl_perm_override', 'gl_flag_count', 'gl_needs_review'), array('gl_id' => $params['id']), __METHOD__);
     if ($listRow === false) {
         $module->dieUsage('List does not exist', 'badid');
     }
     $listRow = ApiEditList::normalizeRow($listRow);
     if ($params['owner'] !== null) {
         // Caller supplied token: treat them as trusted, someone who could see even private
         // At the same time, owner param must match list's owner
         // TODO: if we allow non-matching owner, we could treat it as public-only,
         // but that might be unexpected behavior
         $user = $module->getWatchlistUser($params);
         if ($listRow->gl_user !== $user->getId()) {
             $module->dieUsage('The owner supplied does not match the list\'s owner', 'permissiondenied');
         }
         $showPrivate = true;
     } else {
         $user = $module->getUser();
         $showPrivate = $user->isLoggedIn() && $listRow->gl_user === $user->getId() && $user->isAllowed('viewmywatchlist');
     }
     // Check if this is a public list (if required)
     if (!$showPrivate && ($listRow->gl_perm !== ApiEditList::PERM_PUBLIC || $listRow->gl_perm_override === ApiEditList::PERM_OVERRIDE_HIDDEN || $listRow->gl_flag_count >= $wgGatherAutohideFlagLimit && $listRow->gl_perm_override !== ApiEditList::PERM_OVERRIDE_APPROVED)) {
         $module->dieUsage('You have no rights to see this list', 'badid');
     }
     // If true, this is actually a watchlist, and it is either public or belongs to current user
     $isWatchlist = $listRow->gl_label === '';
     $ownerId = $listRow->gl_user;
 }
 /**
  * Process one row, even if that row is a fake watchlist.
  * @param object|null $row A result row, e.g. from iterating a ResultWrapper. Null for the
  *   fake watchlist.
  * @param int $count Row count, will be incremented on each call.
  * @param string $mode Mode API parameter.
  * @param int $limit Row limit; used to detect when to set continuation parameters.
  * @param bool $useInfo True if one of the info fields was requested.
  * @param Title|null $title Title object corresponding to the title parameter of the API.
  * @param bool $fld_label True if the label property is requested.
  * @param bool $fld_description True if the description property is requested.
  * @param bool $fld_public True if the public property is requested.
  * @param bool $fld_review True if the review property is requested.
  * @param bool $fld_image True if the image property is requested.
  * @param bool $fld_updated True if the updated property is requested.
  * @param bool $fld_owner True if the owner property is requested.
  * @param array $path API module path.
  * @param User|null $owner The user whose lists are being shown.
  * @param callable $getContinueEnumParameter A function that receives $row and returns a
  *   continuation key that corresponds to the ordering of the query.
  * @return bool
  */
 private function processRow($row, &$count, $mode, $limit, $useInfo, $title, $fld_label, $fld_description, $fld_public, $fld_review, $fld_image, $fld_updated, $fld_owner, $path, $owner, $getContinueEnumParameter)
 {
     global $wgGatherAutohideFlagLimit;
     if ($row === null) {
         // Fake watchlist row
         $row = (object) array('gl_id' => 0, 'gl_label' => '', 'gl_perm' => ApiEditList::PERM_PRIVATE, 'gl_perm_override' => ApiEditList::PERM_OVERRIDE_NONE, 'gl_needs_review' => 0, 'gl_flag_count' => 0, 'gl_updated' => '', 'gl_info' => '');
     } else {
         $row = ApiEditList::normalizeRow($row);
     }
     $count++;
     if ($count > $limit) {
         // We've reached the one extra which shows that there are
         // additional pages to be had. Stop here...
         $this->setContinueEnumParameter('continue', $getContinueEnumParameter($row));
         return false;
     }
     $isWatchlist = property_exists($row, 'isWl') ? $row->isWl : $row->gl_label === '';
     $data = array('id' => $row->gl_id);
     if ($isWatchlist) {
         $data['watchlist'] = true;
     }
     if ($fld_label) {
         // TODO: check if this is the right wfMessage to show
         $data['label'] = !$isWatchlist ? $row->gl_label : wfMessage('watchlist')->plain();
     }
     if ($fld_owner) {
         $data['owner'] = property_exists($row, 'user_name') ? $row->user_name : $owner->getName();
     }
     if ($title) {
         if ($isWatchlist) {
             $data['title'] = $this->isTitleInWatchlist($owner, $title);
         } else {
             $data['title'] = isset($row->isIn);
         }
     }
     if ($fld_public) {
         $permMap = array_flip(ApiEditList::$permMap);
         $permOverrideMap = self::$permOverrideApiMap;
         if (!array_key_exists($row->gl_perm, $permMap)) {
             $this->dieDebug(__METHOD__, "Unknown gather perm={$row->gl_perm} for id {$row->gl_id}");
         }
         if (!array_key_exists($row->gl_perm_override, $permOverrideMap)) {
             $this->dieDebug(__METHOD__, "Unknown gather " . "perm_override={$row->gl_perm_override} for id {$row->gl_id}");
         }
         $data['perm'] = $permMap[$row->gl_perm];
         if ($permOverrideMap[$row->gl_perm_override]) {
             $data['perm_override'] = $permOverrideMap[$row->gl_perm_override];
         }
         if ($row->gl_flag_count >= $wgGatherAutohideFlagLimit) {
             $data['flagged'] = true;
         }
         if ($row->gl_perm_override === ApiEditList::PERM_OVERRIDE_HIDDEN || $row->gl_perm_override === ApiEditList::PERM_OVERRIDE_NONE && $row->gl_flag_count >= $wgGatherAutohideFlagLimit) {
             $data['hidden'] = true;
         }
     }
     if ($fld_review) {
         if ($row->gl_needs_review || $row->gl_flag_count >= $wgGatherAutohideFlagLimit) {
             $data['review'] = true;
         }
     }
     if ($useInfo) {
         $info = ApiEditList::parseListInfo($row->gl_info, $row->gl_id, false);
         if ($fld_description) {
             $data['description'] = property_exists($info, 'description') ? $info->description : '';
         }
         if ($fld_image) {
             if (property_exists($info, 'image') && $info->image) {
                 $data['image'] = $info->image;
                 $file = wfFindFile($info->image);
                 if (!$file) {
                     $data['badimage'] = true;
                 } else {
                     $data['imageurl'] = $file->getFullUrl();
                     $data['imagewidth'] = intval($file->getWidth());
                     $data['imageheight'] = intval($file->getHeight());
                 }
             } else {
                 $data['image'] = false;
             }
         }
     }
     if ($fld_updated) {
         $data['updated'] = wfTimestamp(TS_ISO_8601, $row->gl_updated);
     }
     $fit = $this->getResult()->addValue($path, null, $data);
     if (!$fit) {
         $this->setContinueEnumParameter('continue', $getContinueEnumParameter($row));
         return false;
     }
     return true;
 }