Path: blob/master/src/applications/feed/query/PhabricatorFeedQuery.php
12242 views
<?php12final class PhabricatorFeedQuery3extends PhabricatorCursorPagedPolicyAwareQuery {45private $filterPHIDs;6private $chronologicalKeys;7private $rangeMin;8private $rangeMax;910public function withFilterPHIDs(array $phids) {11$this->filterPHIDs = $phids;12return $this;13}1415public function withChronologicalKeys(array $keys) {16$this->chronologicalKeys = $keys;17return $this;18}1920public function withEpochInRange($range_min, $range_max) {21$this->rangeMin = $range_min;22$this->rangeMax = $range_max;23return $this;24}2526public function newResultObject() {27return new PhabricatorFeedStoryData();28}2930protected function loadPage() {31// NOTE: We return raw rows from this method, which is a little unusual.32return $this->loadStandardPageRows($this->newResultObject());33}3435protected function willFilterPage(array $data) {36$stories = PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer());3738foreach ($stories as $key => $story) {39if (!$story->isVisibleInFeed()) {40unset($stories[$key]);41}42}4344return $stories;45}4647protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {48$joins = parent::buildJoinClauseParts($conn);4950// NOTE: We perform this join unconditionally (even if we have no filter51// PHIDs) to omit rows which have no story references. These story data52// rows are notifications or realtime alerts.5354$ref_table = new PhabricatorFeedStoryReference();55$joins[] = qsprintf(56$conn,57'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey',58$ref_table->getTableName());5960return $joins;61}6263protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {64$where = parent::buildWhereClauseParts($conn);6566if ($this->filterPHIDs !== null) {67$where[] = qsprintf(68$conn,69'ref.objectPHID IN (%Ls)',70$this->filterPHIDs);71}7273if ($this->chronologicalKeys !== null) {74// NOTE: We can't use "%d" to format these large integers on 32-bit75// systems. Historically, we formatted these into integers in an76// awkward way because MySQL could sometimes (?) fail to use the proper77// keys if the values were formatted as strings instead of integers.7879// After the "qsprintf()" update to use PhutilQueryString, we can no80// longer do this in a sneaky way. However, the MySQL key issue also81// no longer appears to reproduce across several systems. So: just use82// strings until problems turn up?8384$where[] = qsprintf(85$conn,86'ref.chronologicalKey IN (%Ls)',87$this->chronologicalKeys);88}8990// NOTE: We may not have 64-bit PHP, so do the shifts in MySQL instead.91// From EXPLAIN, it appears like MySQL is smart enough to compute the92// result and make use of keys to execute the query.9394if ($this->rangeMin !== null) {95$where[] = qsprintf(96$conn,97'ref.chronologicalKey >= (%d << 32)',98$this->rangeMin);99}100101if ($this->rangeMax !== null) {102$where[] = qsprintf(103$conn,104'ref.chronologicalKey < (%d << 32)',105$this->rangeMax);106}107108return $where;109}110111protected function buildGroupClause(AphrontDatabaseConnection $conn) {112if ($this->filterPHIDs !== null) {113return qsprintf($conn, 'GROUP BY ref.chronologicalKey');114} else {115return qsprintf($conn, 'GROUP BY story.chronologicalKey');116}117}118119protected function getDefaultOrderVector() {120return array('key');121}122123public function getBuiltinOrders() {124return array(125'newest' => array(126'vector' => array('key'),127'name' => pht('Creation (Newest First)'),128'aliases' => array('created'),129),130'oldest' => array(131'vector' => array('-key'),132'name' => pht('Creation (Oldest First)'),133),134);135}136137public function getOrderableColumns() {138$table = ($this->filterPHIDs ? 'ref' : 'story');139return array(140'key' => array(141'table' => $table,142'column' => 'chronologicalKey',143'type' => 'string',144'unique' => true,145),146);147}148149protected function applyExternalCursorConstraintsToQuery(150PhabricatorCursorPagedPolicyAwareQuery $subquery,151$cursor) {152$subquery->withChronologicalKeys(array($cursor));153}154155protected function newExternalCursorStringForResult($object) {156return $object->getChronologicalKey();157}158159protected function newPagingMapFromPartialObject($object) {160// This query is unusual, and the "object" is a raw result row.161return array(162'key' => $object['chronologicalKey'],163);164}165166protected function getPrimaryTableAlias() {167return 'story';168}169170public function getQueryApplicationClass() {171return 'PhabricatorFeedApplication';172}173174}175176177