4 * This is a more formal version of @{class:PhabricatorEdgeQuery} that is used
5 * to expose edges to Conduit.
7 final class PhabricatorEdgeObjectQuery
8 extends PhabricatorCursorPagedPolicyAwareQuery
{
11 private $sourcePHIDType;
13 private $destinationPHIDs;
15 public function withSourcePHIDs(array $source_phids) {
16 $this->sourcePHIDs
= $source_phids;
20 public function withEdgeTypes(array $types) {
21 $this->edgeTypes
= $types;
25 public function withDestinationPHIDs(array $destination_phids) {
26 $this->destinationPHIDs
= $destination_phids;
30 protected function willExecute() {
31 $source_phids = $this->sourcePHIDs
;
36 'Edge object query must be executed with a nonempty list of '.
42 foreach ($source_phids as $phid) {
43 $this_type = phid_get_type($phid);
44 if ($this_type == PhabricatorPHIDConstants
::PHID_TYPE_UNKNOWN
) {
47 'Source PHID "%s" in edge object query has unknown PHID type.',
51 if ($phid_type === null) {
52 $phid_type = $this_type;
57 if ($phid_type !== $this_type) {
60 'Two source PHIDs ("%s" and "%s") have different PHID types '.
61 '("%s" and "%s"). All PHIDs must be of the same type to execute '.
62 'an edge object query.',
70 $this->sourcePHIDType
= $phid_type;
73 protected function loadPage() {
74 $type = $this->sourcePHIDType
;
75 $conn = PhabricatorEdgeConfig
::establishConnection($type, 'r');
76 $table = PhabricatorEdgeConfig
::TABLE_NAME_EDGE
;
77 $rows = $this->loadStandardPageRowsWithConnection($conn, $table);
80 foreach ($rows as $row) {
81 $result[] = PhabricatorEdgeObject
::newFromRow($row);
87 protected function buildWhereClauseParts(AphrontDatabaseConnection
$conn) {
88 $parts = parent
::buildWhereClauseParts($conn);
100 if ($this->destinationPHIDs
!== null) {
104 $this->destinationPHIDs
);
110 public function getQueryApplicationClass() {
114 protected function getPrimaryTableAlias() {
118 public function getOrderableColumns() {
120 'dateCreated' => array(
122 'column' => 'dateCreated',
130 // TODO: This is not actually unique, but we're just doing our best
137 protected function getDefaultOrderVector() {
138 return array('dateCreated', 'sequence');
141 protected function newInternalCursorFromExternalCursor($cursor) {
142 list($epoch, $sequence) = $this->parseCursor($cursor);
144 // Instead of actually loading an edge, we're just making a fake edge
145 // with the properties the cursor describes.
147 $edge_object = PhabricatorEdgeObject
::newFromRow(
149 'dateCreated' => $epoch,
153 return id(new PhabricatorQueryCursor())
154 ->setObject($edge_object);
157 protected function newPagingMapFromPartialObject($object) {
159 'dateCreated' => $object->getDateCreated(),
160 'sequence' => $object->getSequence(),
164 protected function newExternalCursorStringForResult($object) {
167 $object->getDateCreated(),
168 $object->getSequence());
171 private function parseCursor($cursor) {
172 if (!preg_match('/^\d+_\d+\z/', $cursor)) {
173 $this->throwCursorException(
175 'Expected edge cursor in the form "0123_6789", got "%s".',
179 return explode('_', $cursor);