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); }