Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/feed/query/PhabricatorFeedQuery.php
12242 views
1
<?php
2
3
final class PhabricatorFeedQuery
4
extends PhabricatorCursorPagedPolicyAwareQuery {
5
6
private $filterPHIDs;
7
private $chronologicalKeys;
8
private $rangeMin;
9
private $rangeMax;
10
11
public function withFilterPHIDs(array $phids) {
12
$this->filterPHIDs = $phids;
13
return $this;
14
}
15
16
public function withChronologicalKeys(array $keys) {
17
$this->chronologicalKeys = $keys;
18
return $this;
19
}
20
21
public function withEpochInRange($range_min, $range_max) {
22
$this->rangeMin = $range_min;
23
$this->rangeMax = $range_max;
24
return $this;
25
}
26
27
public function newResultObject() {
28
return new PhabricatorFeedStoryData();
29
}
30
31
protected function loadPage() {
32
// NOTE: We return raw rows from this method, which is a little unusual.
33
return $this->loadStandardPageRows($this->newResultObject());
34
}
35
36
protected function willFilterPage(array $data) {
37
$stories = PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer());
38
39
foreach ($stories as $key => $story) {
40
if (!$story->isVisibleInFeed()) {
41
unset($stories[$key]);
42
}
43
}
44
45
return $stories;
46
}
47
48
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
49
$joins = parent::buildJoinClauseParts($conn);
50
51
// NOTE: We perform this join unconditionally (even if we have no filter
52
// PHIDs) to omit rows which have no story references. These story data
53
// rows are notifications or realtime alerts.
54
55
$ref_table = new PhabricatorFeedStoryReference();
56
$joins[] = qsprintf(
57
$conn,
58
'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey',
59
$ref_table->getTableName());
60
61
return $joins;
62
}
63
64
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
65
$where = parent::buildWhereClauseParts($conn);
66
67
if ($this->filterPHIDs !== null) {
68
$where[] = qsprintf(
69
$conn,
70
'ref.objectPHID IN (%Ls)',
71
$this->filterPHIDs);
72
}
73
74
if ($this->chronologicalKeys !== null) {
75
// NOTE: We can't use "%d" to format these large integers on 32-bit
76
// systems. Historically, we formatted these into integers in an
77
// awkward way because MySQL could sometimes (?) fail to use the proper
78
// keys if the values were formatted as strings instead of integers.
79
80
// After the "qsprintf()" update to use PhutilQueryString, we can no
81
// longer do this in a sneaky way. However, the MySQL key issue also
82
// no longer appears to reproduce across several systems. So: just use
83
// strings until problems turn up?
84
85
$where[] = qsprintf(
86
$conn,
87
'ref.chronologicalKey IN (%Ls)',
88
$this->chronologicalKeys);
89
}
90
91
// NOTE: We may not have 64-bit PHP, so do the shifts in MySQL instead.
92
// From EXPLAIN, it appears like MySQL is smart enough to compute the
93
// result and make use of keys to execute the query.
94
95
if ($this->rangeMin !== null) {
96
$where[] = qsprintf(
97
$conn,
98
'ref.chronologicalKey >= (%d << 32)',
99
$this->rangeMin);
100
}
101
102
if ($this->rangeMax !== null) {
103
$where[] = qsprintf(
104
$conn,
105
'ref.chronologicalKey < (%d << 32)',
106
$this->rangeMax);
107
}
108
109
return $where;
110
}
111
112
protected function buildGroupClause(AphrontDatabaseConnection $conn) {
113
if ($this->filterPHIDs !== null) {
114
return qsprintf($conn, 'GROUP BY ref.chronologicalKey');
115
} else {
116
return qsprintf($conn, 'GROUP BY story.chronologicalKey');
117
}
118
}
119
120
protected function getDefaultOrderVector() {
121
return array('key');
122
}
123
124
public function getBuiltinOrders() {
125
return array(
126
'newest' => array(
127
'vector' => array('key'),
128
'name' => pht('Creation (Newest First)'),
129
'aliases' => array('created'),
130
),
131
'oldest' => array(
132
'vector' => array('-key'),
133
'name' => pht('Creation (Oldest First)'),
134
),
135
);
136
}
137
138
public function getOrderableColumns() {
139
$table = ($this->filterPHIDs ? 'ref' : 'story');
140
return array(
141
'key' => array(
142
'table' => $table,
143
'column' => 'chronologicalKey',
144
'type' => 'string',
145
'unique' => true,
146
),
147
);
148
}
149
150
protected function applyExternalCursorConstraintsToQuery(
151
PhabricatorCursorPagedPolicyAwareQuery $subquery,
152
$cursor) {
153
$subquery->withChronologicalKeys(array($cursor));
154
}
155
156
protected function newExternalCursorStringForResult($object) {
157
return $object->getChronologicalKey();
158
}
159
160
protected function newPagingMapFromPartialObject($object) {
161
// This query is unusual, and the "object" is a raw result row.
162
return array(
163
'key' => $object['chronologicalKey'],
164
);
165
}
166
167
protected function getPrimaryTableAlias() {
168
return 'story';
169
}
170
171
public function getQueryApplicationClass() {
172
return 'PhabricatorFeedApplication';
173
}
174
175
}
176
177