Path: blob/master/src/infrastructure/edges/query/PhabricatorEdgeObjectQuery.php
13409 views
<?php12/**3* This is a more formal version of @{class:PhabricatorEdgeQuery} that is used4* to expose edges to Conduit.5*/6final class PhabricatorEdgeObjectQuery7extends PhabricatorCursorPagedPolicyAwareQuery {89private $sourcePHIDs;10private $sourcePHIDType;11private $edgeTypes;12private $destinationPHIDs;1314public function withSourcePHIDs(array $source_phids) {15$this->sourcePHIDs = $source_phids;16return $this;17}1819public function withEdgeTypes(array $types) {20$this->edgeTypes = $types;21return $this;22}2324public function withDestinationPHIDs(array $destination_phids) {25$this->destinationPHIDs = $destination_phids;26return $this;27}2829protected function willExecute() {30$source_phids = $this->sourcePHIDs;3132if (!$source_phids) {33throw new Exception(34pht(35'Edge object query must be executed with a nonempty list of '.36'source PHIDs.'));37}3839$phid_item = null;40$phid_type = null;41foreach ($source_phids as $phid) {42$this_type = phid_get_type($phid);43if ($this_type == PhabricatorPHIDConstants::PHID_TYPE_UNKNOWN) {44throw new Exception(45pht(46'Source PHID "%s" in edge object query has unknown PHID type.',47$phid));48}4950if ($phid_type === null) {51$phid_type = $this_type;52$phid_item = $phid;53continue;54}5556if ($phid_type !== $this_type) {57throw new Exception(58pht(59'Two source PHIDs ("%s" and "%s") have different PHID types '.60'("%s" and "%s"). All PHIDs must be of the same type to execute '.61'an edge object query.',62$phid_item,63$phid,64$phid_type,65$this_type));66}67}6869$this->sourcePHIDType = $phid_type;70}7172protected function loadPage() {73$type = $this->sourcePHIDType;74$conn = PhabricatorEdgeConfig::establishConnection($type, 'r');75$table = PhabricatorEdgeConfig::TABLE_NAME_EDGE;76$rows = $this->loadStandardPageRowsWithConnection($conn, $table);7778$result = array();79foreach ($rows as $row) {80$result[] = PhabricatorEdgeObject::newFromRow($row);81}8283return $result;84}8586protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {87$parts = parent::buildWhereClauseParts($conn);8889$parts[] = qsprintf(90$conn,91'src IN (%Ls)',92$this->sourcePHIDs);9394$parts[] = qsprintf(95$conn,96'type IN (%Ls)',97$this->edgeTypes);9899if ($this->destinationPHIDs !== null) {100$parts[] = qsprintf(101$conn,102'dst IN (%Ls)',103$this->destinationPHIDs);104}105106return $parts;107}108109public function getQueryApplicationClass() {110return null;111}112113protected function getPrimaryTableAlias() {114return 'edge';115}116117public function getOrderableColumns() {118return array(119'dateCreated' => array(120'table' => 'edge',121'column' => 'dateCreated',122'type' => 'int',123),124'sequence' => array(125'table' => 'edge',126'column' => 'seq',127'type' => 'int',128129// TODO: This is not actually unique, but we're just doing our best130// here.131'unique' => true,132),133);134}135136protected function getDefaultOrderVector() {137return array('dateCreated', 'sequence');138}139140protected function newInternalCursorFromExternalCursor($cursor) {141list($epoch, $sequence) = $this->parseCursor($cursor);142143// Instead of actually loading an edge, we're just making a fake edge144// with the properties the cursor describes.145146$edge_object = PhabricatorEdgeObject::newFromRow(147array(148'dateCreated' => $epoch,149'seq' => $sequence,150));151152return id(new PhabricatorQueryCursor())153->setObject($edge_object);154}155156protected function newPagingMapFromPartialObject($object) {157return array(158'dateCreated' => $object->getDateCreated(),159'sequence' => $object->getSequence(),160);161}162163protected function newExternalCursorStringForResult($object) {164return sprintf(165'%d_%d',166$object->getDateCreated(),167$object->getSequence());168}169170private function parseCursor($cursor) {171if (!preg_match('/^\d+_\d+\z/', $cursor)) {172$this->throwCursorException(173pht(174'Expected edge cursor in the form "0123_6789", got "%s".',175$cursor));176}177178return explode('_', $cursor);179}180181}182183184