protected function doDBUpdates()
 {
     /** @var DatabaseBase $dbr */
     $dbr = Container::get('db.factory')->getDB(DB_SLAVE);
     $countableActions = $this->getCountableActions();
     // defaults = date of first Flow commit up until now
     $continue = UUID::getComparisonUUID($this->getOption('start', '20130710230511'));
     $stop = UUID::getComparisonUUID($this->getOption('stop', time()));
     while ($continue !== false) {
         $continue = $this->refreshBatch($dbr, $continue, $countableActions, $stop);
         // wait for core (we're updating user table) slaves to catch up
         wfWaitForSlaves();
     }
     $this->output("Done increasing edit counts. Increased:\n");
     foreach ($this->updates as $userId => $count) {
         $userName = User::newFromId($userId)->getName();
         $this->output("  User {$userId} ({$userName}): +{$count}\n");
     }
     return true;
 }
 /**
  * @param ContribsPager|DeletedContribsPager $pager Object hooked into
  * @param string $offset Index offset, inclusive
  * @param bool $descending Query direction, false for ascending, true for descending
  * @return array Query conditions
  */
 protected function buildConditions($pager, $offset, $descending)
 {
     $conditions = array();
     // Work out user condition
     if (property_exists($pager, 'contribs') && $pager->contribs == 'newbie') {
         list($minUserId, $excludeUserIds) = $this->getNewbieConditionInfo($pager);
         $conditions['rev_user_wiki'] = wfWikiId();
         $conditions[] = 'rev_user_id > ' . (int) $minUserId;
         if ($excludeUserIds) {
             // better safe than sorry - make sure everything's an int
             $excludeUserIds = array_map('intval', $excludeUserIds);
             $conditions[] = 'rev_user_id NOT IN ( ' . implode(',', $excludeUserIds) . ' )';
             $conditions['rev_user_ip'] = null;
         }
     } else {
         $uid = User::idFromName($pager->target);
         if ($uid) {
             $conditions['rev_user_id'] = $uid;
             $conditions['rev_user_ip'] = null;
             $conditions['rev_user_wiki'] = wfWikiId();
         } else {
             $conditions['rev_user_id'] = 0;
             $conditions['rev_user_ip'] = $pager->target;
             $conditions['rev_user_wiki'] = wfWikiId();
         }
     }
     // Make offset parameter.
     if ($offset) {
         $dbr = $this->dbFactory->getDB(DB_SLAVE);
         $offsetUUID = UUID::getComparisonUUID($offset);
         $direction = $descending ? '>' : '<';
         $conditions[] = "rev_id {$direction} " . $dbr->addQuotes($offsetUUID->getBinary());
     }
     // Find only within requested wiki/namespace
     $conditions['workflow_wiki'] = wfWikiId();
     if ($pager->namespace !== '') {
         $conditions['workflow_namespace'] = $pager->namespace;
     }
     return $conditions;
 }
 /**
  * This overrides the default title link to include highlights for the posts
  * that have not yet been seen.
  *
  * @param array $data
  * @param FormatterRow $row
  * @param IContextSource $ctx
  * @return string
  */
 protected function getTitleLink(array $data, FormatterRow $row, IContextSource $ctx)
 {
     if (!$row instanceof RecentChangesRow) {
         // actually, this should be typehint, but can't because this needs
         // to match the parent's more generic typehint
         return parent::getTitleLink($data, $row, $ctx);
     }
     if (!isset($data['links']['topic']) || !$data['links']['topic'] instanceof Anchor) {
         // no valid title anchor (probably header entry)
         return parent::getTitleLink($data, $row, $ctx);
     }
     $watched = $row->recentChange->getAttribute('wl_notificationtimestamp');
     if (is_bool($watched)) {
         // RC & watchlist share most code; the latter is unaware of when
         // something was watched though, so we'll ignore that here
         return parent::getTitleLink($data, $row, $ctx);
     }
     if ($watched === null) {
         // there is no data for unread posts - they've all been seen
         return parent::getTitleLink($data, $row, $ctx);
     }
     // get comparison UUID corresponding to this last watched timestamp
     $uuid = UUID::getComparisonUUID($watched);
     // add highlight details to anchor
     /** @var Anchor $anchor */
     $anchor = clone $data['links']['topic'];
     $anchor->query['fromnotif'] = '1';
     $anchor->fragment = '#flow-post-' . $uuid->getAlphadecimal();
     $data['links']['topic'] = $anchor;
     // now pass it on to parent with the new, updated, link ;)
     return parent::getTitleLink($data, $row, $ctx);
 }
 /**
  * Overwriting default writer because I want to use Flow storage methods so
  * the updates also affect cache, not just DB.
  *
  * @param array[] $updates
  */
 public function write(array $updates)
 {
     /*
      * from:
      * array(
      *     'primaryKey' => array( 'workflow_id' => $id ),
      *     'updates' => array( 'workflow_last_update_timestamp' => $timestamp ),
      * )
      * to:
      * array( $id => $timestamp );
      */
     $timestamps = array_combine($this->arrayColumn($this->arrayColumn($updates, 'primaryKey'), 'workflow_id'), $this->arrayColumn($this->arrayColumn($updates, 'changes'), 'workflow_last_update_timestamp'));
     /** @var UUID[] $uuids */
     $uuids = array_map(array('Flow\\Model\\UUID', 'create'), array_keys($timestamps));
     /** @var Workflow[] $workflows */
     $workflows = $this->storage->getMulti('Workflow', $uuids);
     foreach ($workflows as $workflow) {
         $timestamp = $timestamps[$workflow->getId()->getBinary()];
         $workflow->updateLastModified(UUID::getComparisonUUID($timestamp));
     }
     $this->storage->multiPut($workflows);
     // prevent memory from filling up
     $this->storage->clear();
     wfWaitForSlaves(false, false, $this->clusterName);
 }
 /**
  * @param AbstractRevision[] $revisions
  * @return UUID
  */
 protected function getNextFromId(array $revisions)
 {
     /** @var AbstractRevision $last */
     $last = end($revisions);
     if ($last instanceof \Flow\Model\Header) {
         $timestamp = $last->getRevisionId()->getTimestampObj();
     } else {
         $timestamp = $last->getCollection()->getWorkflow()->getLastModifiedObj();
     }
     // $timestamp is the timestamp of the last revision we fetched. fromId
     // is inclusive, and we don't want to include what we already have here,
     // so we'll advance 1 more and call that the next fromId
     $timestamp = (int) $timestamp->getTimestamp(TS_UNIX);
     return UUID::getComparisonUUID($timestamp + 1);
 }