Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2890175
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/infrastructure/edges/query/PhabricatorEdgeQuery.php b/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
index fdeb8fda8b..4676829231 100644
--- a/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
+++ b/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
@@ -1,215 +1,276 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Load object edges created by @{class:PhabricatorEdgeEditor}.
*
* name=Querying Edges
* $src = $earth_phid;
* $type = PhabricatorEdgeConfig::TYPE_BODY_HAS_SATELLITE;
*
* // Load the earth's satellites.
* $satellite_edges = id(new PhabricatorEdgeQuery())
* ->withSourcePHIDs(array($src))
* ->withEdgeTypes(array($type))
* ->execute();
*
* For more information on edges, see @{article:Using Edges}.
*
* @task config Configuring the Query
* @task exec Executing the Query
* @task internal Internal
*/
final class PhabricatorEdgeQuery extends PhabricatorQuery {
private $sourcePHIDs;
private $edgeTypes;
+ private $resultSet;
private $needEdgeData;
/* -( Configuring the Query )---------------------------------------------- */
/**
* Find edges originating at one or more source PHIDs. You MUST provide this
* to execute an edge query.
*
* @param list List of source PHIDs.
* @return this
*
* @task config
*/
public function withSourcePHIDs(array $source_phids) {
$this->sourcePHIDs = $source_phids;
return $this;
}
/**
* Find edges of specific types.
*
* @param list List of PhabricatorEdgeConfig type constants.
* @return this
*
* @task config
*/
public function withEdgeTypes(array $types) {
$this->edgeTypes = $types;
return $this;
}
/**
* When loading edges, also load edge data.
*
* @param bool True to load edge data.
* @return this
*
* @task config
*/
public function needEdgeData($need) {
$this->needEdgeData = $need;
return $this;
}
/* -( Executing the Query )------------------------------------------------ */
/**
* Convenience method for loading destination PHIDs with one source and one
* edge type. Equivalent to building a full query, but simplifies a common
* use case.
*
* @param phid Source PHID.
* @param const Edge type.
* @return list<phid> List of destination PHIDs.
*/
public static function loadDestinationPHIDs($src_phid, $edge_type) {
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($src_phid))
->withEdgeTypes(array($edge_type))
->execute();
return array_keys($edges[$src_phid][$edge_type]);
}
/**
* Load specified edges.
*
* @task exec
*/
public function execute() {
if (!$this->sourcePHIDs) {
throw new Exception(
"You must use withSourcePHIDs() to query edges.");
}
$sources = phid_group_by_type($this->sourcePHIDs);
$result = array();
// When a query specifies types, make sure we return data for all queried
// types. This is mostly to make sure PhabricatorLiskDAO->attachEdges()
// gets some data, so that getEdges() doesn't throw later.
if ($this->edgeTypes) {
foreach ($this->sourcePHIDs as $phid) {
foreach ($this->edgeTypes as $type) {
$result[$phid][$type] = array();
}
}
}
foreach ($sources as $type => $phids) {
$conn_r = PhabricatorEdgeConfig::establishConnection($type, 'r');
$where = $this->buildWhereClause($conn_r);
$order = $this->buildOrderClause($conn_r);
$edges = queryfx_all(
$conn_r,
'SELECT edge.* FROM %T edge %Q %Q',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
$where,
$order);
if ($this->needEdgeData) {
$data_ids = array_filter(ipull($edges, 'dataID'));
$data_map = array();
if ($data_ids) {
$data_rows = queryfx_all(
$conn_r,
'SELECT edgedata.* FROM %T edgedata WHERE id IN (%Ld)',
PhabricatorEdgeConfig::TABLE_NAME_EDGEDATA,
$data_ids);
foreach ($data_rows as $row) {
$data_map[$row['id']] = idx(
json_decode($row['data'], true),
'data');
}
}
foreach ($edges as $key => $edge) {
$edges[$key]['data'] = idx($data_map, $edge['dataID']);
}
}
foreach ($edges as $edge) {
$result[$edge['src']][$edge['type']][$edge['dst']] = $edge;
}
}
+ $this->resultSet = $result;
return $result;
}
+ /**
+ * Convenience function for selecting edge destination PHIDs after calling
+ * execute().
+ *
+ * Returns a flat list of PHIDs matching the provided source PHID and type
+ * filters. By default, the filters are empty so all PHIDs will be returned.
+ * For example, if you're doing a batch query from several sources, you might
+ * write code like this:
+ *
+ * $query = new PhabricatorEdgeQuery();
+ * $query->withSourcePHIDs(mpull($objects, 'getPHID'));
+ * $query->withEdgeTypes(array($some_type));
+ * $query->execute();
+ *
+ * // Gets all of the destinations.
+ * $all_phids = $query->getDestinationPHIDs();
+ * $handles = id(new PhabricatorObjectHandleData($all_phids))
+ * ->loadHandles();
+ *
+ * foreach ($objects as $object) {
+ * // Get all of the destinations for the given object.
+ * $dst_phids = $query->getDestinationPHIDs(array($object->getPHID()));
+ * $object->attachHandles(array_select_keys($handles, $dst_phids));
+ * }
+ *
+ * @param list? List of PHIDs to select, or empty to select all.
+ * @param list? List of edge types to select, or empty to select all.
+ * @return list<phid> List of matching destination PHIDs.
+ */
+ public function getDestinationPHIDs(
+ array $src_phids = array(),
+ array $types = array()) {
+ if ($this->resultSet === null) {
+ throw new Exception(
+ "You must execute() a query before you you can getDestinationPHIDs().");
+ }
+
+ $src_phids = array_fill_keys($src_phids, true);
+ $types = array_fill_keys($types, true);
+
+ $result_phids = array();
+ foreach ($this->resultSet as $src => $edges_by_type) {
+ if ($src_phids && empty($src_phids[$src])) {
+ continue;
+ }
+ foreach ($edges_by_type as $type => $edges_by_dst) {
+ if ($types && empty($types[$type])) {
+ continue;
+ }
+ foreach ($edges_by_dst as $dst => $edge) {
+ $result_phids[$dst] = true;
+ }
+ }
+ }
+
+ return array_keys($result_phids);
+ }
+
+
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
private function buildWhereClause($conn_r) {
$where = array();
if ($this->sourcePHIDs) {
$where[] = qsprintf(
$conn_r,
'edge.src IN (%Ls)',
$this->sourcePHIDs);
}
if ($this->edgeTypes) {
$where[] = qsprintf(
$conn_r,
'edge.type IN (%Ls)',
$this->edgeTypes);
}
return $this->formatWhereClause($where);
}
/**
* @task internal
*/
private function buildOrderClause($conn_r) {
return 'ORDER BY edge.dateCreated DESC, edge.seq ASC';
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 13:10 (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1124928
Default Alt Text
(7 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment