Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F391198
PhabricatorFeedQuery.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
PhabricatorFeedQuery.php
View Options
<?php
final
class
PhabricatorFeedQuery
extends
PhabricatorCursorPagedPolicyAwareQuery
{
private
$filterPHIDs
;
private
$chronologicalKeys
;
private
$rangeMin
;
private
$rangeMax
;
public
function
withFilterPHIDs
(
array
$phids
)
{
$this
->
filterPHIDs
=
$phids
;
return
$this
;
}
public
function
withChronologicalKeys
(
array
$keys
)
{
$this
->
chronologicalKeys
=
$keys
;
return
$this
;
}
/**
* @param int|null $range_min Minimum epoch value of feed stories
* @param int|null $range_max Maximum epoch value of feed stories
*/
public
function
withEpochInRange
(
$range_min
,
$range_max
)
{
if
(
$range_min
&&
$range_max
&&
$range_min
>
$range_max
)
{
throw
new
PhutilArgumentUsageException
(
pht
(
'Feed query minimum range must be lower than maximum range.'
));
}
$this
->
rangeMin
=
$range_min
;
$this
->
rangeMax
=
$range_max
;
return
$this
;
}
public
function
newResultObject
()
{
return
new
PhabricatorFeedStoryData
();
}
protected
function
loadPage
()
{
// NOTE: We return raw rows from this method, which is a little unusual.
return
$this
->
loadStandardPageRows
(
$this
->
newResultObject
());
}
protected
function
willFilterPage
(
array
$data
)
{
$stories
=
PhabricatorFeedStory
::
loadAllFromRows
(
$data
,
$this
->
getViewer
());
foreach
(
$stories
as
$key
=>
$story
)
{
if
(!
$story
->
isVisibleInFeed
())
{
unset
(
$stories
[
$key
]);
}
}
return
$stories
;
}
protected
function
buildJoinClauseParts
(
AphrontDatabaseConnection
$conn
)
{
$joins
=
parent
::
buildJoinClauseParts
(
$conn
);
// NOTE: We perform this join unconditionally (even if we have no filter
// PHIDs) to omit rows which have no story references. These story data
// rows are notifications or realtime alerts.
$ref_table
=
new
PhabricatorFeedStoryReference
();
$joins
[]
=
qsprintf
(
$conn
,
'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey'
,
$ref_table
->
getTableName
());
return
$joins
;
}
protected
function
buildWhereClauseParts
(
AphrontDatabaseConnection
$conn
)
{
$where
=
parent
::
buildWhereClauseParts
(
$conn
);
if
(
$this
->
filterPHIDs
!==
null
)
{
$where
[]
=
qsprintf
(
$conn
,
'ref.objectPHID IN (%Ls)'
,
$this
->
filterPHIDs
);
}
if
(
$this
->
chronologicalKeys
!==
null
)
{
// NOTE: We can't use "%d" to format these large integers on 32-bit
// systems. Historically, we formatted these into integers in an
// awkward way because MySQL could sometimes (?) fail to use the proper
// keys if the values were formatted as strings instead of integers.
// After the "qsprintf()" update to use PhutilQueryString, we can no
// longer do this in a sneaky way. However, the MySQL key issue also
// no longer appears to reproduce across several systems. So: just use
// strings until problems turn up?
$where
[]
=
qsprintf
(
$conn
,
'ref.chronologicalKey IN (%Ls)'
,
$this
->
chronologicalKeys
);
}
// NOTE: We may not have 64-bit PHP, so do the shifts in MySQL instead.
// From EXPLAIN, it appears like MySQL is smart enough to compute the
// result and make use of keys to execute the query.
if
(
$this
->
rangeMin
!==
null
)
{
$where
[]
=
qsprintf
(
$conn
,
'ref.chronologicalKey >= (%d << 32)'
,
$this
->
rangeMin
);
}
if
(
$this
->
rangeMax
!==
null
)
{
$where
[]
=
qsprintf
(
$conn
,
'ref.chronologicalKey < (%d << 32)'
,
$this
->
rangeMax
);
}
return
$where
;
}
protected
function
buildGroupClause
(
AphrontDatabaseConnection
$conn
)
{
if
(
$this
->
filterPHIDs
!==
null
)
{
return
qsprintf
(
$conn
,
'GROUP BY ref.chronologicalKey'
);
}
else
{
return
qsprintf
(
$conn
,
'GROUP BY story.chronologicalKey'
);
}
}
protected
function
getDefaultOrderVector
()
{
return
array
(
'key'
);
}
public
function
getBuiltinOrders
()
{
return
array
(
'newest'
=>
array
(
'vector'
=>
array
(
'key'
),
'name'
=>
pht
(
'Creation (Newest First)'
),
'aliases'
=>
array
(
'created'
),
),
'oldest'
=>
array
(
'vector'
=>
array
(
'-key'
),
'name'
=>
pht
(
'Creation (Oldest First)'
),
),
);
}
public
function
getOrderableColumns
()
{
$table
=
(
$this
->
filterPHIDs
?
'ref'
:
'story'
);
return
array
(
'key'
=>
array
(
'table'
=>
$table
,
'column'
=>
'chronologicalKey'
,
'type'
=>
'string'
,
'unique'
=>
true
,
),
);
}
protected
function
applyExternalCursorConstraintsToQuery
(
PhabricatorCursorPagedPolicyAwareQuery
$subquery
,
$cursor
)
{
$subquery
->
withChronologicalKeys
(
array
(
$cursor
));
}
protected
function
newExternalCursorStringForResult
(
$object
)
{
return
$object
->
getChronologicalKey
();
}
protected
function
newPagingMapFromPartialObject
(
$object
)
{
// This query is unusual, and the "object" is a raw result row.
return
array
(
'key'
=>
$object
[
'chronologicalKey'
],
);
}
protected
function
getPrimaryTableAlias
()
{
return
'story'
;
}
public
function
getQueryApplicationClass
()
{
return
PhabricatorFeedApplication
::
class
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sun, Apr 20, 12:59 AM (22 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
48605
Default Alt Text
PhabricatorFeedQuery.php (5 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment