Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / infrastructure / edges / query / PhabricatorEdgeObjectQuery.php
blob048a2a9fb457f0134ae587ffe784e5ea5baa9edd
1 <?php
3 /**
4 * This is a more formal version of @{class:PhabricatorEdgeQuery} that is used
5 * to expose edges to Conduit.
6 */
7 final class PhabricatorEdgeObjectQuery
8 extends PhabricatorCursorPagedPolicyAwareQuery {
10 private $sourcePHIDs;
11 private $sourcePHIDType;
12 private $edgeTypes;
13 private $destinationPHIDs;
15 public function withSourcePHIDs(array $source_phids) {
16 $this->sourcePHIDs = $source_phids;
17 return $this;
20 public function withEdgeTypes(array $types) {
21 $this->edgeTypes = $types;
22 return $this;
25 public function withDestinationPHIDs(array $destination_phids) {
26 $this->destinationPHIDs = $destination_phids;
27 return $this;
30 protected function willExecute() {
31 $source_phids = $this->sourcePHIDs;
33 if (!$source_phids) {
34 throw new Exception(
35 pht(
36 'Edge object query must be executed with a nonempty list of '.
37 'source PHIDs.'));
40 $phid_item = null;
41 $phid_type = null;
42 foreach ($source_phids as $phid) {
43 $this_type = phid_get_type($phid);
44 if ($this_type == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {
45 throw new Exception(
46 pht(
47 'Source PHID "%s" in edge object query has unknown PHID type.',
48 $phid));
51 if ($phid_type === null) {
52 $phid_type = $this_type;
53 $phid_item = $phid;
54 continue;
57 if ($phid_type !== $this_type) {
58 throw new Exception(
59 pht(
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.',
63 $phid_item,
64 $phid,
65 $phid_type,
66 $this_type));
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);
79 $result = array();
80 foreach ($rows as $row) {
81 $result[] = PhabricatorEdgeObject::newFromRow($row);
84 return $result;
87 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
88 $parts = parent::buildWhereClauseParts($conn);
90 $parts[] = qsprintf(
91 $conn,
92 'src IN (%Ls)',
93 $this->sourcePHIDs);
95 $parts[] = qsprintf(
96 $conn,
97 'type IN (%Ls)',
98 $this->edgeTypes);
100 if ($this->destinationPHIDs !== null) {
101 $parts[] = qsprintf(
102 $conn,
103 'dst IN (%Ls)',
104 $this->destinationPHIDs);
107 return $parts;
110 public function getQueryApplicationClass() {
111 return null;
114 protected function getPrimaryTableAlias() {
115 return 'edge';
118 public function getOrderableColumns() {
119 return array(
120 'dateCreated' => array(
121 'table' => 'edge',
122 'column' => 'dateCreated',
123 'type' => 'int',
125 'sequence' => array(
126 'table' => 'edge',
127 'column' => 'seq',
128 'type' => 'int',
130 // TODO: This is not actually unique, but we're just doing our best
131 // here.
132 'unique' => true,
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(
148 array(
149 'dateCreated' => $epoch,
150 'seq' => $sequence,
153 return id(new PhabricatorQueryCursor())
154 ->setObject($edge_object);
157 protected function newPagingMapFromPartialObject($object) {
158 return array(
159 'dateCreated' => $object->getDateCreated(),
160 'sequence' => $object->getSequence(),
164 protected function newExternalCursorStringForResult($object) {
165 return sprintf(
166 '%d_%d',
167 $object->getDateCreated(),
168 $object->getSequence());
171 private function parseCursor($cursor) {
172 if (!preg_match('/^\d+_\d+\z/', $cursor)) {
173 $this->throwCursorException(
174 pht(
175 'Expected edge cursor in the form "0123_6789", got "%s".',
176 $cursor));
179 return explode('_', $cursor);