Page Menu
Home
styx hydra
Search
Configure Global Search
Log In
Files
F208963
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Advanced/Developer...
View Handle
View Hovercard
Size
534 KB
Referenced Files
None
Subscribers
None
View Options
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/applications/almanac/query/AlmanacBindingQuery.php b/src/applications/almanac/query/AlmanacBindingQuery.php
index dd4336db8c..0b6d7cda3a 100644
--- a/src/applications/almanac/query/AlmanacBindingQuery.php
+++ b/src/applications/almanac/query/AlmanacBindingQuery.php
@@ -1,139 +1,139 @@
<?php
final class AlmanacBindingQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $servicePHIDs;
private $devicePHIDs;
private $interfacePHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withServicePHIDs(array $phids) {
$this->servicePHIDs = $phids;
return $this;
}
public function withDevicePHIDs(array $phids) {
$this->devicePHIDs = $phids;
return $this;
}
public function withInterfacePHIDs(array $phids) {
$this->interfacePHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new AlmanacBinding();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $bindings) {
$service_phids = mpull($bindings, 'getServicePHID');
$device_phids = mpull($bindings, 'getDevicePHID');
$interface_phids = mpull($bindings, 'getInterfacePHID');
$services = id(new AlmanacServiceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($service_phids)
->execute();
$services = mpull($services, null, 'getPHID');
$devices = id(new AlmanacDeviceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($device_phids)
->execute();
$devices = mpull($devices, null, 'getPHID');
$interfaces = id(new AlmanacInterfaceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($interface_phids)
->execute();
$interfaces = mpull($interfaces, null, 'getPHID');
foreach ($bindings as $key => $binding) {
$service = idx($services, $binding->getServicePHID());
$device = idx($devices, $binding->getDevicePHID());
$interface = idx($interfaces, $binding->getInterfacePHID());
if (!$service || !$device || !$interface) {
$this->didRejectResult($binding);
unset($bindings[$key]);
continue;
}
$binding->attachService($service);
$binding->attachDevice($device);
$binding->attachInterface($interface);
}
return $bindings;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->servicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'servicePHID IN (%Ls)',
$this->servicePHIDs);
}
if ($this->devicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'devicePHID IN (%Ls)',
$this->devicePHIDs);
}
if ($this->interfacePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'interfacePHID IN (%Ls)',
$this->interfacePHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/almanac/query/AlmanacDeviceQuery.php b/src/applications/almanac/query/AlmanacDeviceQuery.php
index bd1797088f..287af6c647 100644
--- a/src/applications/almanac/query/AlmanacDeviceQuery.php
+++ b/src/applications/almanac/query/AlmanacDeviceQuery.php
@@ -1,103 +1,103 @@
<?php
final class AlmanacDeviceQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $names;
private $namePrefix;
private $nameSuffix;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNamePrefix($prefix) {
$this->namePrefix = $prefix;
return $this;
}
public function withNameSuffix($suffix) {
$this->nameSuffix = $suffix;
return $this;
}
protected function loadPage() {
$table = new AlmanacDevice();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->names !== null) {
$hashes = array();
foreach ($this->names as $name) {
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn_r,
'nameIndex IN (%Ls)',
$hashes);
}
if ($this->namePrefix !== null) {
$where[] = qsprintf(
$conn_r,
'name LIKE %>',
$this->namePrefix);
}
if ($this->nameSuffix !== null) {
$where[] = qsprintf(
$conn_r,
'name LIKE %<',
$this->nameSuffix);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
}
diff --git a/src/applications/almanac/query/AlmanacInterfaceQuery.php b/src/applications/almanac/query/AlmanacInterfaceQuery.php
index 7e2a867d29..e119203da5 100644
--- a/src/applications/almanac/query/AlmanacInterfaceQuery.php
+++ b/src/applications/almanac/query/AlmanacInterfaceQuery.php
@@ -1,139 +1,139 @@
<?php
final class AlmanacInterfaceQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $networkPHIDs;
private $devicePHIDs;
private $addresses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNetworkPHIDs(array $phids) {
$this->networkPHIDs = $phids;
return $this;
}
public function withDevicePHIDs(array $phids) {
$this->devicePHIDs = $phids;
return $this;
}
public function withAddresses(array $addresses) {
$this->addresses = $addresses;
return $this;
}
protected function loadPage() {
$table = new AlmanacInterface();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $interfaces) {
$network_phids = mpull($interfaces, 'getNetworkPHID');
$device_phids = mpull($interfaces, 'getDevicePHID');
$networks = id(new AlmanacNetworkQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($network_phids)
->execute();
$networks = mpull($networks, null, 'getPHID');
$devices = id(new AlmanacDeviceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($device_phids)
->execute();
$devices = mpull($devices, null, 'getPHID');
foreach ($interfaces as $key => $interface) {
$network = idx($networks, $interface->getNetworkPHID());
$device = idx($devices, $interface->getDevicePHID());
if (!$network || !$device) {
$this->didRejectResult($interface);
unset($interfaces[$key]);
continue;
}
$interface->attachNetwork($network);
$interface->attachDevice($device);
}
return $interfaces;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->networkPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'networkPHID IN (%Ls)',
$this->networkPHIDs);
}
if ($this->devicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'devicePHID IN (%Ls)',
$this->devicePHIDs);
}
if ($this->addresses !== null) {
$parts = array();
foreach ($this->addresses as $address) {
$parts[] = qsprintf(
$conn_r,
'(networkPHID = %s AND address = %s AND port = %d)',
$address->getNetworkPHID(),
$address->getAddress(),
$address->getPort());
}
$where[] = implode(' OR ', $parts);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
}
diff --git a/src/applications/almanac/query/AlmanacNetworkQuery.php b/src/applications/almanac/query/AlmanacNetworkQuery.php
index 1eb43fa828..d33def72ea 100644
--- a/src/applications/almanac/query/AlmanacNetworkQuery.php
+++ b/src/applications/almanac/query/AlmanacNetworkQuery.php
@@ -1,60 +1,60 @@
<?php
final class AlmanacNetworkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new AlmanacNetwork();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
}
diff --git a/src/applications/almanac/query/AlmanacPropertyQuery.php b/src/applications/almanac/query/AlmanacPropertyQuery.php
index 470ea62618..886c26a7be 100644
--- a/src/applications/almanac/query/AlmanacPropertyQuery.php
+++ b/src/applications/almanac/query/AlmanacPropertyQuery.php
@@ -1,111 +1,111 @@
<?php
final class AlmanacPropertyQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
private $names;
private $disablePolicyFilteringAndAttachment;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function setDisablePolicyFilteringAndAttachment($disable) {
$this->disablePolicyFilteringAndAttachment = $disable;
return $this;
}
protected function shouldDisablePolicyFiltering() {
return $this->disablePolicyFilteringAndAttachment;
}
protected function loadPage() {
$table = new AlmanacProperty();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $properties) {
if (!$this->disablePolicyFilteringAndAttachment) {
$object_phids = mpull($properties, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($properties as $key => $property) {
$object = idx($objects, $property->getObjectPHID());
if (!$object) {
unset($properties[$key]);
continue;
}
$property->attachObject($object);
}
}
return $properties;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->names !== null) {
$hashes = array();
foreach ($this->names as $name) {
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn_r,
'fieldIndex IN (%Ls)',
$hashes);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorAlmanacApplication';
}
}
diff --git a/src/applications/almanac/query/AlmanacServiceQuery.php b/src/applications/almanac/query/AlmanacServiceQuery.php
index d9aca2650e..d961b2e4ab 100644
--- a/src/applications/almanac/query/AlmanacServiceQuery.php
+++ b/src/applications/almanac/query/AlmanacServiceQuery.php
@@ -1,224 +1,224 @@
<?php
final class AlmanacServiceQuery
extends AlmanacQuery {
private $ids;
private $phids;
private $names;
private $serviceClasses;
private $devicePHIDs;
private $locked;
private $namePrefix;
private $nameSuffix;
private $needBindings;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withServiceClasses(array $classes) {
$this->serviceClasses = $classes;
return $this;
}
public function withDevicePHIDs(array $phids) {
$this->devicePHIDs = $phids;
return $this;
}
public function withLocked($locked) {
$this->locked = $locked;
return $this;
}
public function withNamePrefix($prefix) {
$this->namePrefix = $prefix;
return $this;
}
public function withNameSuffix($suffix) {
$this->nameSuffix = $suffix;
return $this;
}
public function needBindings($need_bindings) {
$this->needBindings = $need_bindings;
return $this;
}
protected function loadPage() {
$table = new AlmanacService();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT service.* FROM %T service %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function buildJoinClause($conn_r) {
$joins = array();
if ($this->devicePHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T binding ON service.phid = binding.servicePHID',
id(new AlmanacBinding())->getTableName());
}
return implode(' ', $joins);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'service.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'service.phid IN (%Ls)',
$this->phids);
}
if ($this->names !== null) {
$hashes = array();
foreach ($this->names as $name) {
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn_r,
'service.nameIndex IN (%Ls)',
$hashes);
}
if ($this->serviceClasses !== null) {
$where[] = qsprintf(
$conn_r,
'service.serviceClass IN (%Ls)',
$this->serviceClasses);
}
if ($this->devicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'binding.devicePHID IN (%Ls)',
$this->devicePHIDs);
}
if ($this->locked !== null) {
$where[] = qsprintf(
$conn_r,
'service.isLocked = %d',
(int)$this->locked);
}
if ($this->namePrefix !== null) {
$where[] = qsprintf(
$conn_r,
'service.name LIKE %>',
$this->namePrefix);
}
if ($this->nameSuffix !== null) {
$where[] = qsprintf(
$conn_r,
'service.name LIKE %<',
$this->nameSuffix);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $services) {
$service_types = AlmanacServiceType::getAllServiceTypes();
foreach ($services as $key => $service) {
$service_class = $service->getServiceClass();
$service_type = idx($service_types, $service_class);
if (!$service_type) {
$this->didRejectResult($service);
unset($services[$key]);
continue;
}
$service->attachServiceType($service_type);
}
return $services;
}
protected function didFilterPage(array $services) {
if ($this->needBindings) {
$service_phids = mpull($services, 'getPHID');
$bindings = id(new AlmanacBindingQuery())
->setViewer($this->getViewer())
->withServicePHIDs($service_phids)
->execute();
$bindings = mgroup($bindings, 'getServicePHID');
foreach ($services as $service) {
$service_bindings = idx($bindings, $service->getPHID(), array());
$service->attachBindings($service_bindings);
}
}
return parent::didFilterPage($services);
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'table' => 'service',
'column' => 'name',
'type' => 'string',
'unique' => true,
'reverse' => true,
),
);
}
protected function getValueMap($cursor, array $keys) {
$service = $this->loadCursorObject($cursor);
return array(
'id' => $service->getID(),
'name' => $service->getServiceName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name'),
'name' => pht('Service Name'),
),
) + parent::getBuiltinOrders();
}
}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
index f6feea5041..cdfeb0ca43 100644
--- a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
@@ -1,111 +1,111 @@
<?php
final class PhabricatorCalendarEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $rangeBegin;
private $rangeEnd;
private $invitedPHIDs;
private $creatorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDateRange($begin, $end) {
$this->rangeBegin = $begin;
$this->rangeEnd = $end;
return $this;
}
public function withInvitedPHIDs(array $phids) {
$this->invitedPHIDs = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorCalendarEvent();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->rangeBegin) {
$where[] = qsprintf(
$conn_r,
'dateTo >= %d',
$this->rangeBegin);
}
if ($this->rangeEnd) {
$where[] = qsprintf(
$conn_r,
'dateFrom <= %d',
$this->rangeEnd);
}
// TODO: Currently, the creator is always the only invitee, but you can
// query them separately since this won't always be true.
if ($this->invitedPHIDs) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->invitedPHIDs);
}
if ($this->creatorPHIDs) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->creatorPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorCalendarApplication';
}
}
diff --git a/src/applications/chatlog/query/PhabricatorChatLogChannelQuery.php b/src/applications/chatlog/query/PhabricatorChatLogChannelQuery.php
index 4dcc4a16a9..2aded5c11b 100644
--- a/src/applications/chatlog/query/PhabricatorChatLogChannelQuery.php
+++ b/src/applications/chatlog/query/PhabricatorChatLogChannelQuery.php
@@ -1,63 +1,63 @@
<?php
final class PhabricatorChatLogChannelQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $channels;
private $channelIDs;
public function withChannelNames(array $channels) {
$this->channels = $channels;
return $this;
}
public function withIDs(array $channel_ids) {
$this->channelIDs = $channel_ids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorChatLogChannel();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T c %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$logs = $table->loadAllFromArray($data);
return $logs;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->channelIDs) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->channelIDs);
}
if ($this->channels) {
$where[] = qsprintf(
$conn_r,
'channelName IN (%Ls)',
$this->channels);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorChatLogApplication';
}
}
diff --git a/src/applications/chatlog/query/PhabricatorChatLogQuery.php b/src/applications/chatlog/query/PhabricatorChatLogQuery.php
index cb7fe53128..d174fdac90 100644
--- a/src/applications/chatlog/query/PhabricatorChatLogQuery.php
+++ b/src/applications/chatlog/query/PhabricatorChatLogQuery.php
@@ -1,84 +1,84 @@
<?php
final class PhabricatorChatLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $channelIDs;
private $maximumEpoch;
public function withChannelIDs(array $channel_ids) {
$this->channelIDs = $channel_ids;
return $this;
}
public function withMaximumEpoch($epoch) {
$this->maximumEpoch = $epoch;
return $this;
}
protected function loadPage() {
$table = new PhabricatorChatLogEvent();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T e %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$logs = $table->loadAllFromArray($data);
return $logs;
}
protected function willFilterPage(array $events) {
$channel_ids = mpull($events, 'getChannelID', 'getChannelID');
$channels = id(new PhabricatorChatLogChannelQuery())
->setViewer($this->getViewer())
->withIDs($channel_ids)
->execute();
$channels = mpull($channels, null, 'getID');
foreach ($events as $key => $event) {
$channel = idx($channels, $event->getChannelID());
if (!$channel) {
unset($events[$key]);
continue;
}
$event->attachChannel($channel);
}
return $events;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->maximumEpoch) {
$where[] = qsprintf(
$conn_r,
'epoch <= %d',
$this->maximumEpoch);
}
if ($this->channelIDs) {
$where[] = qsprintf(
$conn_r,
'channelID IN (%Ld)',
$this->channelIDs);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorChatLogApplication';
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitLogQuery.php b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
index 56934caf45..4d66cccae5 100644
--- a/src/applications/conduit/query/PhabricatorConduitLogQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitLogQuery.php
@@ -1,46 +1,46 @@
<?php
final class PhabricatorConduitLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $methods;
public function withMethods(array $methods) {
$this->methods = $methods;
return $this;
}
protected function loadPage() {
$table = new PhabricatorConduitMethodCallLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->methods) {
$where[] = qsprintf(
$conn_r,
'method IN (%Ls)',
$this->methods);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorConduitApplication';
}
}
diff --git a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
index 563e437a4a..870043cac8 100644
--- a/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
+++ b/src/applications/conduit/query/PhabricatorConduitTokenQuery.php
@@ -1,128 +1,128 @@
<?php
final class PhabricatorConduitTokenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
private $expired;
private $tokens;
private $tokenTypes;
public function withExpired($expired) {
$this->expired = $expired;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function withTokens(array $tokens) {
$this->tokens = $tokens;
return $this;
}
public function withTokenTypes(array $types) {
$this->tokenTypes = $types;
return $this;
}
protected function loadPage() {
$table = new PhabricatorConduitToken();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->tokens !== null) {
$where[] = qsprintf(
$conn_r,
'token IN (%Ls)',
$this->tokens);
}
if ($this->tokenTypes !== null) {
$where[] = qsprintf(
$conn_r,
'tokenType IN (%Ls)',
$this->tokenTypes);
}
if ($this->expired !== null) {
if ($this->expired) {
$where[] = qsprintf(
$conn_r,
'expires <= %d',
PhabricatorTime::getNow());
} else {
$where[] = qsprintf(
$conn_r,
'expires IS NULL OR expires > %d',
PhabricatorTime::getNow());
}
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $tokens) {
$object_phids = mpull($tokens, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($tokens as $key => $token) {
$object = idx($objects, $token->getObjectPHID(), null);
if (!$object) {
$this->didRejectResult($token);
unset($tokens[$key]);
continue;
}
$token->attachObject($object);
}
return $tokens;
}
public function getQueryApplicationClass() {
return 'PhabricatorConduitApplication';
}
}
diff --git a/src/applications/config/query/PhabricatorConfigEntryQuery.php b/src/applications/config/query/PhabricatorConfigEntryQuery.php
index 01982ca7d0..56bf15a267 100644
--- a/src/applications/config/query/PhabricatorConfigEntryQuery.php
+++ b/src/applications/config/query/PhabricatorConfigEntryQuery.php
@@ -1,60 +1,60 @@
<?php
final class PhabricatorConfigEntryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ids;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorConfigEntry();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorConfigApplication';
}
}
diff --git a/src/applications/conpherence/query/ConpherenceFulltextQuery.php b/src/applications/conpherence/query/ConpherenceFulltextQuery.php
index 780c4914cf..244791076c 100644
--- a/src/applications/conpherence/query/ConpherenceFulltextQuery.php
+++ b/src/applications/conpherence/query/ConpherenceFulltextQuery.php
@@ -1,68 +1,68 @@
<?php
final class ConpherenceFulltextQuery
extends PhabricatorOffsetPagedQuery {
private $threadPHIDs;
private $fulltext;
public function withThreadPHIDs(array $phids) {
$this->threadPHIDs = $phids;
return $this;
}
public function withFulltext($fulltext) {
$this->fulltext = $fulltext;
return $this;
}
public function execute() {
$table = new ConpherenceIndex();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT threadPHID, transactionPHID, previousTransactionPHID
FROM %T i %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderByClause($conn_r),
$this->buildLimitClause($conn_r));
return $rows;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->threadPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'i.threadPHID IN (%Ls)',
$this->threadPHIDs);
}
if (strlen($this->fulltext)) {
$where[] = qsprintf(
$conn_r,
'MATCH(i.corpus) AGAINST (%s IN BOOLEAN MODE)',
$this->fulltext);
}
return $this->formatWhereClause($where);
}
private function buildOrderByClause(AphrontDatabaseConnection $conn_r) {
if (strlen($this->fulltext)) {
return qsprintf(
$conn_r,
'ORDER BY MATCH(i.corpus) AGAINST (%s IN BOOLEAN MODE) DESC',
$this->fulltext);
} else {
return qsprintf(
$conn_r,
'ORDER BY id DESC');
}
}
}
diff --git a/src/applications/conpherence/query/ConpherenceParticipantCountQuery.php b/src/applications/conpherence/query/ConpherenceParticipantCountQuery.php
index 1d0cb81f8c..7a4f170c3a 100644
--- a/src/applications/conpherence/query/ConpherenceParticipantCountQuery.php
+++ b/src/applications/conpherence/query/ConpherenceParticipantCountQuery.php
@@ -1,73 +1,73 @@
<?php
/**
* Query class that answers the question:
*
* - Q: How many unread conpherences am I participating in?
* - A:
* id(new ConpherenceParticipantCountQuery())
* ->withParticipantPHIDs(array($my_phid))
* ->withParticipationStatus(ConpherenceParticipationStatus::BEHIND)
* ->execute();
*/
final class ConpherenceParticipantCountQuery
extends PhabricatorOffsetPagedQuery {
private $participantPHIDs;
private $participationStatus;
public function withParticipantPHIDs(array $phids) {
$this->participantPHIDs = $phids;
return $this;
}
public function withParticipationStatus($participation_status) {
$this->participationStatus = $participation_status;
return $this;
}
public function execute() {
$table = new ConpherenceParticipant();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT COUNT(*) as count, participantPHID '.
'FROM %T participant %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildGroupByClause($conn_r),
$this->buildLimitClause($conn_r));
return ipull($rows, 'count', 'participantPHID');
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->participantPHIDs) {
$where[] = qsprintf(
$conn_r,
'participantPHID IN (%Ls)',
$this->participantPHIDs);
}
if ($this->participationStatus !== null) {
$where[] = qsprintf(
$conn_r,
'participationStatus = %d',
$this->participationStatus);
}
return $this->formatWhereClause($where);
}
private function buildGroupByClause(AphrontDatabaseConnection $conn_r) {
$group_by = qsprintf(
$conn_r,
'GROUP BY participantPHID');
return $group_by;
}
}
diff --git a/src/applications/conpherence/query/ConpherenceParticipantQuery.php b/src/applications/conpherence/query/ConpherenceParticipantQuery.php
index f9c31deed6..bb879be4e4 100644
--- a/src/applications/conpherence/query/ConpherenceParticipantQuery.php
+++ b/src/applications/conpherence/query/ConpherenceParticipantQuery.php
@@ -1,128 +1,128 @@
<?php
/**
* Query class that answers these questions:
*
* - Q: What are the conpherences to show when I land on /conpherence/ ?
* - A:
*
* id(new ConpherenceParticipantQuery())
* ->withParticipantPHIDs(array($my_phid))
* ->execute();
*
* - Q: What are the next set of conpherences as I scroll up (more recent) or
* down (less recent) this list of conpherences?
* - A:
*
* id(new ConpherenceParticipantQuery())
* ->withParticipantPHIDs(array($my_phid))
* ->withParticipantCursor($top_participant)
* ->setOrder(ConpherenceParticipantQuery::ORDER_NEWER)
* ->execute();
*
* -or-
*
* id(new ConpherenceParticipantQuery())
* ->withParticipantPHIDs(array($my_phid))
* ->withParticipantCursor($bottom_participant)
* ->setOrder(ConpherenceParticipantQuery::ORDER_OLDER)
* ->execute();
*
* For counts of read, un-read, or all conpherences by participant, see
* @{class:ConpherenceParticipantCountQuery}.
*/
final class ConpherenceParticipantQuery extends PhabricatorOffsetPagedQuery {
const LIMIT = 100;
const ORDER_NEWER = 'newer';
const ORDER_OLDER = 'older';
private $participantPHIDs;
private $participantCursor;
private $order = self::ORDER_OLDER;
public function withParticipantPHIDs(array $phids) {
$this->participantPHIDs = $phids;
return $this;
}
public function withParticipantCursor(ConpherenceParticipant $participant) {
$this->participantCursor = $participant;
return $this;
}
public function setOrder($order) {
$this->order = $order;
return $this;
}
public function execute() {
$table = new ConpherenceParticipant();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T participant %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$participants = $table->loadAllFromArray($data);
$participants = mpull($participants, null, 'getConpherencePHID');
if ($this->order == self::ORDER_NEWER) {
$participants = array_reverse($participants);
}
return $participants;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->participantPHIDs) {
$where[] = qsprintf(
$conn_r,
'participantPHID IN (%Ls)',
$this->participantPHIDs);
}
if ($this->participantCursor) {
$date_touched = $this->participantCursor->getDateTouched();
$id = $this->participantCursor->getID();
if ($this->order == self::ORDER_OLDER) {
$compare_date = '<';
$compare_id = '<=';
} else {
$compare_date = '>';
$compare_id = '>=';
}
$where[] = qsprintf(
$conn_r,
'(dateTouched %Q %d OR (dateTouched = %d AND id %Q %d))',
$compare_date,
$date_touched,
$date_touched,
$compare_id,
$id);
}
return $this->formatWhereClause($where);
}
private function buildOrderClause(AphrontDatabaseConnection $conn_r) {
$order_word = ($this->order == self::ORDER_OLDER) ? 'DESC' : 'ASC';
// if these are different direction we won't get as efficient a query
// see http://dev.mysql.com/doc/refman/5.5/en/order-by-optimization.html
$order = qsprintf(
$conn_r,
'ORDER BY dateTouched %Q, id %Q',
$order_word,
$order_word);
return $order;
}
}
diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php
index b5607c1061..c191a763b4 100644
--- a/src/applications/conpherence/query/ConpherenceThreadQuery.php
+++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php
@@ -1,383 +1,383 @@
<?php
final class ConpherenceThreadQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const TRANSACTION_LIMIT = 100;
private $phids;
private $ids;
private $participantPHIDs;
private $isRoom;
private $needParticipants;
private $needWidgetData;
private $needTransactions;
private $needParticipantCache;
private $needFilePHIDs;
private $afterTransactionID;
private $beforeTransactionID;
private $transactionLimit;
public function needFilePHIDs($need_file_phids) {
$this->needFilePHIDs = $need_file_phids;
return $this;
}
public function needParticipantCache($participant_cache) {
$this->needParticipantCache = $participant_cache;
return $this;
}
public function needParticipants($need) {
$this->needParticipants = $need;
return $this;
}
public function needWidgetData($need_widget_data) {
$this->needWidgetData = $need_widget_data;
return $this;
}
public function needTransactions($need_transactions) {
$this->needTransactions = $need_transactions;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withParticipantPHIDs(array $phids) {
$this->participantPHIDs = $phids;
return $this;
}
public function withIsRoom($bool) {
$this->isRoom = $bool;
return $this;
}
public function setAfterTransactionID($id) {
$this->afterTransactionID = $id;
return $this;
}
public function setBeforeTransactionID($id) {
$this->beforeTransactionID = $id;
return $this;
}
public function setTransactionLimit($transaction_limit) {
$this->transactionLimit = $transaction_limit;
return $this;
}
public function getTransactionLimit() {
return $this->transactionLimit;
}
protected function loadPage() {
$table = new ConpherenceThread();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT conpherence_thread.* FROM %T conpherence_thread %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$conpherences = $table->loadAllFromArray($data);
if ($conpherences) {
$conpherences = mpull($conpherences, null, 'getPHID');
$this->loadParticipantsAndInitHandles($conpherences);
if ($this->needParticipantCache) {
$this->loadCoreHandles($conpherences, 'getRecentParticipantPHIDs');
}
if ($this->needWidgetData || $this->needParticipants) {
$this->loadCoreHandles($conpherences, 'getParticipantPHIDs');
}
if ($this->needTransactions) {
$this->loadTransactionsAndHandles($conpherences);
}
if ($this->needFilePHIDs || $this->needWidgetData) {
$this->loadFilePHIDs($conpherences);
}
if ($this->needWidgetData) {
$this->loadWidgetData($conpherences);
}
}
return $conpherences;
}
private function buildGroupClause($conn_r) {
if ($this->participantPHIDs !== null) {
return 'GROUP BY conpherence_thread.id';
} else {
return $this->buildApplicationSearchGroupClause($conn_r);
}
}
private function buildJoinClause($conn_r) {
$joins = array();
if ($this->participantPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T p ON p.conpherencePHID = conpherence_thread.phid',
id(new ConpherenceParticipant())->getTableName());
}
$viewer = $this->getViewer();
if ($this->shouldJoinForViewer($viewer)) {
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T v ON v.conpherencePHID = conpherence_thread.phid '.
'AND v.participantPHID = %s',
id(new ConpherenceParticipant())->getTableName(),
$viewer->getPHID());
}
$joins[] = $this->buildApplicationSearchJoinClause($conn_r);
return implode(' ', $joins);
}
private function shouldJoinForViewer(PhabricatorUser $viewer) {
if ($viewer->isLoggedIn() &&
$this->ids === null &&
$this->phids === null) {
return true;
}
return false;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'conpherence_thread.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'conpherence_thread.phid IN (%Ls)',
$this->phids);
}
if ($this->participantPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'p.participantPHID IN (%Ls)',
$this->participantPHIDs);
}
if ($this->isRoom !== null) {
$where[] = qsprintf(
$conn_r,
'conpherence_thread.isRoom = %d',
(int)$this->isRoom);
}
$viewer = $this->getViewer();
if ($this->shouldJoinForViewer($viewer)) {
$where[] = qsprintf(
$conn_r,
'conpherence_thread.isRoom = 1 OR v.participantPHID IS NOT NULL');
} else if ($this->phids === null && $this->ids === null) {
$where[] = qsprintf(
$conn_r,
'conpherence_thread.isRoom = 1');
}
return $this->formatWhereClause($where);
}
private function loadParticipantsAndInitHandles(array $conpherences) {
$participants = id(new ConpherenceParticipant())
->loadAllWhere('conpherencePHID IN (%Ls)', array_keys($conpherences));
$map = mgroup($participants, 'getConpherencePHID');
foreach ($conpherences as $current_conpherence) {
$conpherence_phid = $current_conpherence->getPHID();
$conpherence_participants = idx(
$map,
$conpherence_phid,
array());
$conpherence_participants = mpull(
$conpherence_participants,
null,
'getParticipantPHID');
$current_conpherence->attachParticipants($conpherence_participants);
$current_conpherence->attachHandles(array());
}
return $this;
}
private function loadCoreHandles(
array $conpherences,
$method) {
$handle_phids = array();
foreach ($conpherences as $conpherence) {
$handle_phids[$conpherence->getPHID()] =
$conpherence->$method();
}
$flat_phids = array_mergev($handle_phids);
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($flat_phids)
->execute();
foreach ($handle_phids as $conpherence_phid => $phids) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachHandles(
$conpherence->getHandles() + array_select_keys($handles, $phids));
}
return $this;
}
private function loadTransactionsAndHandles(array $conpherences) {
$query = id(new ConpherenceTransactionQuery())
->setViewer($this->getViewer())
->withObjectPHIDs(array_keys($conpherences))
->needHandles(true);
// We have to flip these for the underyling query class. The semantics of
// paging are tricky business.
if ($this->afterTransactionID) {
$query->setBeforeID($this->afterTransactionID);
} else if ($this->beforeTransactionID) {
$query->setAfterID($this->beforeTransactionID);
}
if ($this->getTransactionLimit()) {
// fetch an extra for "show older" scenarios
$query->setLimit($this->getTransactionLimit() + 1);
}
$transactions = $query->execute();
$transactions = mgroup($transactions, 'getObjectPHID');
foreach ($conpherences as $phid => $conpherence) {
$current_transactions = idx($transactions, $phid, array());
$handles = array();
foreach ($current_transactions as $transaction) {
$handles += $transaction->getHandles();
}
$conpherence->attachHandles($conpherence->getHandles() + $handles);
$conpherence->attachTransactions($current_transactions);
}
return $this;
}
private function loadFilePHIDs(array $conpherences) {
$edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST;
$file_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($conpherences))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($file_edges as $conpherence_phid => $data) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachFilePHIDs(array_keys($data[$edge_type]));
}
return $this;
}
private function loadWidgetData(array $conpherences) {
$participant_phids = array();
$file_phids = array();
foreach ($conpherences as $conpherence) {
$participant_phids[] = array_keys($conpherence->getParticipants());
$file_phids[] = $conpherence->getFilePHIDs();
}
$participant_phids = array_mergev($participant_phids);
$file_phids = array_mergev($file_phids);
$epochs = CalendarTimeUtil::getCalendarEventEpochs(
$this->getViewer());
$start_epoch = $epochs['start_epoch'];
$end_epoch = $epochs['end_epoch'];
$statuses = id(new PhabricatorCalendarEventQuery())
->setViewer($this->getViewer())
->withInvitedPHIDs($participant_phids)
->withDateRange($start_epoch, $end_epoch)
->execute();
$statuses = mgroup($statuses, 'getUserPHID');
// attached files
$files = array();
$file_author_phids = array();
$authors = array();
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
$file_author_phids = mpull($files, 'getAuthorPHID', 'getPHID');
$authors = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($file_author_phids)
->execute();
$authors = mpull($authors, null, 'getPHID');
}
foreach ($conpherences as $phid => $conpherence) {
$participant_phids = array_keys($conpherence->getParticipants());
$statuses = array_select_keys($statuses, $participant_phids);
$statuses = array_mergev($statuses);
$statuses = msort($statuses, 'getDateFrom');
$conpherence_files = array();
$files_authors = array();
foreach ($conpherence->getFilePHIDs() as $curr_phid) {
$curr_file = idx($files, $curr_phid);
if (!$curr_file) {
// this file was deleted or user doesn't have permission to see it
// this is generally weird
continue;
}
$conpherence_files[$curr_phid] = $curr_file;
// some files don't have authors so be careful
$current_author = null;
$current_author_phid = idx($file_author_phids, $curr_phid);
if ($current_author_phid) {
$current_author = $authors[$current_author_phid];
}
$files_authors[$curr_phid] = $current_author;
}
$widget_data = array(
'statuses' => $statuses,
'files' => $conpherence_files,
'files_authors' => $files_authors,
);
$conpherence->attachWidgetData($widget_data);
}
return $this;
}
public function getQueryApplicationClass() {
return 'PhabricatorConpherenceApplication';
}
}
diff --git a/src/applications/countdown/query/PhabricatorCountdownQuery.php b/src/applications/countdown/query/PhabricatorCountdownQuery.php
index 5d04dfde6a..c5f206a4e2 100644
--- a/src/applications/countdown/query/PhabricatorCountdownQuery.php
+++ b/src/applications/countdown/query/PhabricatorCountdownQuery.php
@@ -1,88 +1,88 @@
<?php
final class PhabricatorCountdownQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $upcoming;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withUpcoming($upcoming) {
$this->upcoming = true;
return $this;
}
protected function loadPage() {
$table = new PhabricatorCountdown();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$countdowns = $table->loadAllFromArray($data);
return $countdowns;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID in (%Ls)',
$this->authorPHIDs);
}
if ($this->upcoming) {
$where[] = qsprintf(
$conn_r,
'epoch >= %d',
time());
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorCountdownApplication';
}
}
diff --git a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
index 545c412f86..5822194d06 100644
--- a/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
+++ b/src/applications/daemon/query/PhabricatorDaemonLogQuery.php
@@ -1,194 +1,194 @@
<?php
final class PhabricatorDaemonLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const STATUS_ALL = 'status-all';
const STATUS_ALIVE = 'status-alive';
const STATUS_RUNNING = 'status-running';
private $ids;
private $notIDs;
private $status = self::STATUS_ALL;
private $daemonClasses;
private $allowStatusWrites;
private $daemonIDs;
public static function getTimeUntilUnknown() {
return 3 * PhutilDaemonHandle::getHeartbeatEventFrequency();
}
public static function getTimeUntilDead() {
return 30 * PhutilDaemonHandle::getHeartbeatEventFrequency();
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withoutIDs(array $ids) {
$this->notIDs = $ids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withDaemonClasses(array $classes) {
$this->daemonClasses = $classes;
return $this;
}
public function setAllowStatusWrites($allow) {
$this->allowStatusWrites = $allow;
return $this;
}
public function withDaemonIDs(array $daemon_ids) {
$this->daemonIDs = $daemon_ids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorDaemonLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $daemons) {
$unknown_delay = PhabricatorDaemonLogQuery::getTimeUntilUnknown();
$dead_delay = PhabricatorDaemonLogQuery::getTimeUntilDead();
$status_running = PhabricatorDaemonLog::STATUS_RUNNING;
$status_unknown = PhabricatorDaemonLog::STATUS_UNKNOWN;
$status_wait = PhabricatorDaemonLog::STATUS_WAIT;
$status_exiting = PhabricatorDaemonLog::STATUS_EXITING;
$status_exited = PhabricatorDaemonLog::STATUS_EXITED;
$status_dead = PhabricatorDaemonLog::STATUS_DEAD;
$filter = array_fuse($this->getStatusConstants());
foreach ($daemons as $key => $daemon) {
$status = $daemon->getStatus();
$seen = $daemon->getDateModified();
$is_running = ($status == $status_running) ||
($status == $status_wait) ||
($status == $status_exiting);
// If we haven't seen the daemon recently, downgrade its status to
// unknown.
$unknown_time = ($seen + $unknown_delay);
if ($is_running && ($unknown_time < time())) {
$status = $status_unknown;
}
// If the daemon hasn't been seen in quite a while, assume it is dead.
$dead_time = ($seen + $dead_delay);
if (($status == $status_unknown) && ($dead_time < time())) {
$status = $status_dead;
}
// If we changed the daemon's status, adjust it.
if ($status != $daemon->getStatus()) {
$daemon->setStatus($status);
// ...and write it, if we're in a context where that's reasonable.
if ($this->allowStatusWrites) {
$guard = AphrontWriteGuard::beginScopedUnguardedWrites();
$daemon->save();
unset($guard);
}
}
// If the daemon no longer matches the filter, get rid of it.
if ($filter) {
if (empty($filter[$daemon->getStatus()])) {
unset($daemons[$key]);
}
}
}
return $daemons;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->notIDs !== null) {
$where[] = qsprintf(
$conn_r,
'id NOT IN (%Ld)',
$this->notIDs);
}
if ($this->getStatusConstants()) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ls)',
$this->getStatusConstants());
}
if ($this->daemonClasses !== null) {
$where[] = qsprintf(
$conn_r,
'daemon IN (%Ls)',
$this->daemonClasses);
}
if ($this->daemonIDs !== null) {
$where[] = qsprintf(
$conn_r,
'daemonID IN (%Ls)',
$this->daemonIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function getStatusConstants() {
$status = $this->status;
switch ($status) {
case self::STATUS_ALL:
return array();
case self::STATUS_RUNNING:
return array(
PhabricatorDaemonLog::STATUS_RUNNING,
);
case self::STATUS_ALIVE:
return array(
PhabricatorDaemonLog::STATUS_UNKNOWN,
PhabricatorDaemonLog::STATUS_RUNNING,
PhabricatorDaemonLog::STATUS_WAIT,
PhabricatorDaemonLog::STATUS_EXITING,
);
default:
throw new Exception(pht('Unknown status "%s"!', $status));
}
}
public function getQueryApplicationClass() {
return 'PhabricatorDaemonsApplication';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
index 9641f33338..a9a062ffb2 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorDashboardPanelQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $archived;
private $panelTypes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withArchived($archived) {
$this->archived = $archived;
return $this;
}
public function withPanelTypes(array $types) {
$this->panelTypes = $types;
return $this;
}
protected function loadPage() {
$table = new PhabricatorDashboardPanel();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->archived !== null) {
$where[] = qsprintf(
$conn_r,
'isArchived = %d',
(int)$this->archived);
}
if ($this->panelTypes !== null) {
$where[] = qsprintf(
$conn_r,
'panelType IN (%Ls)',
$this->panelTypes);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDashboardApplication';
}
}
diff --git a/src/applications/dashboard/query/PhabricatorDashboardQuery.php b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
index d8ba184e81..324151e722 100644
--- a/src/applications/dashboard/query/PhabricatorDashboardQuery.php
+++ b/src/applications/dashboard/query/PhabricatorDashboardQuery.php
@@ -1,102 +1,102 @@
<?php
final class PhabricatorDashboardQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $needPanels;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function needPanels($need_panels) {
$this->needPanels = $need_panels;
return $this;
}
protected function loadPage() {
$table = new PhabricatorDashboard();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function didFilterPage(array $dashboards) {
if ($this->needPanels) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($dashboards, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorDashboardDashboardHasPanelEdgeType::EDGECONST,
));
$edge_query->execute();
$panel_phids = $edge_query->getDestinationPHIDs();
if ($panel_phids) {
$panels = id(new PhabricatorDashboardPanelQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($panel_phids)
->execute();
$panels = mpull($panels, null, 'getPHID');
} else {
$panels = array();
}
foreach ($dashboards as $dashboard) {
$dashboard_phids = $edge_query->getDestinationPHIDs(
array($dashboard->getPHID()));
$dashboard_panels = array_select_keys($panels, $dashboard_phids);
$dashboard->attachPanelPHIDs($dashboard_phids);
$dashboard->attachPanels($dashboard_panels);
}
}
return $dashboards;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDashboardApplication';
}
}
diff --git a/src/applications/differential/query/DifferentialChangesetQuery.php b/src/applications/differential/query/DifferentialChangesetQuery.php
index 6cb60e04e9..7b9f2e6d10 100644
--- a/src/applications/differential/query/DifferentialChangesetQuery.php
+++ b/src/applications/differential/query/DifferentialChangesetQuery.php
@@ -1,153 +1,153 @@
<?php
final class DifferentialChangesetQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $diffs;
private $needAttachToDiffs;
private $needHunks;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withDiffs(array $diffs) {
assert_instances_of($diffs, 'DifferentialDiff');
$this->diffs = $diffs;
return $this;
}
public function needAttachToDiffs($attach) {
$this->needAttachToDiffs = $attach;
return $this;
}
public function needHunks($need) {
$this->needHunks = $need;
return $this;
}
protected function willExecute() {
// If we fail to load any changesets (which is possible in the case of an
// empty commit) we'll never call didFilterPage(). Attach empty changeset
// lists now so that we end up with the right result.
if ($this->needAttachToDiffs) {
foreach ($this->diffs as $diff) {
$diff->attachChangesets(array());
}
}
}
protected function loadPage() {
$table = new DifferentialChangeset();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $changesets) {
// First, attach all the diffs we already have. We can just do this
// directly without worrying about querying for them. When we don't have
// a diff, record that we need to load it.
if ($this->diffs) {
$have_diffs = mpull($this->diffs, null, 'getID');
} else {
$have_diffs = array();
}
$must_load = array();
foreach ($changesets as $key => $changeset) {
$diff_id = $changeset->getDiffID();
if (isset($have_diffs[$diff_id])) {
$changeset->attachDiff($have_diffs[$diff_id]);
} else {
$must_load[$key] = $changeset;
}
}
// Load all the diffs we don't have.
$need_diff_ids = mpull($must_load, 'getDiffID');
$more_diffs = array();
if ($need_diff_ids) {
$more_diffs = id(new DifferentialDiffQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withIDs($need_diff_ids)
->execute();
$more_diffs = mpull($more_diffs, null, 'getID');
}
// Attach the diffs we loaded.
foreach ($must_load as $key => $changeset) {
$diff_id = $changeset->getDiffID();
if (isset($more_diffs[$diff_id])) {
$changeset->attachDiff($more_diffs[$diff_id]);
} else {
// We didn't have the diff, and could not load it (it does not exist,
// or we can't see it), so filter this result out.
unset($changesets[$key]);
}
}
return $changesets;
}
protected function didFilterPage(array $changesets) {
if ($this->needAttachToDiffs) {
$changeset_groups = mgroup($changesets, 'getDiffID');
foreach ($this->diffs as $diff) {
$diff_changesets = idx($changeset_groups, $diff->getID(), array());
$diff->attachChangesets($diff_changesets);
}
}
if ($this->needHunks) {
id(new DifferentialHunkQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withChangesets($changesets)
->needAttachToChangesets(true)
->execute();
}
return $changesets;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->diffs !== null) {
$where[] = qsprintf(
$conn_r,
'diffID IN (%Ld)',
mpull($this->diffs, 'getID'));
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
}
diff --git a/src/applications/differential/query/DifferentialDiffQuery.php b/src/applications/differential/query/DifferentialDiffQuery.php
index 3d58e12f8a..15ddc9c46b 100644
--- a/src/applications/differential/query/DifferentialDiffQuery.php
+++ b/src/applications/differential/query/DifferentialDiffQuery.php
@@ -1,156 +1,156 @@
<?php
final class DifferentialDiffQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $revisionIDs;
private $needChangesets = false;
private $needArcanistProjects = false;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRevisionIDs(array $revision_ids) {
$this->revisionIDs = $revision_ids;
return $this;
}
public function needChangesets($bool) {
$this->needChangesets = $bool;
return $this;
}
public function needArcanistProjects($bool) {
$this->needArcanistProjects = $bool;
return $this;
}
protected function loadPage() {
$table = new DifferentialDiff();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $diffs) {
$revision_ids = array_filter(mpull($diffs, 'getRevisionID'));
$revisions = array();
if ($revision_ids) {
$revisions = id(new DifferentialRevisionQuery())
->setViewer($this->getViewer())
->withIDs($revision_ids)
->execute();
}
foreach ($diffs as $key => $diff) {
if (!$diff->getRevisionID()) {
continue;
}
$revision = idx($revisions, $diff->getRevisionID());
if ($revision) {
$diff->attachRevision($revision);
continue;
}
unset($diffs[$key]);
}
if ($diffs && $this->needChangesets) {
$diffs = $this->loadChangesets($diffs);
}
if ($diffs && $this->needArcanistProjects) {
$diffs = $this->loadArcanistProjects($diffs);
}
return $diffs;
}
private function loadChangesets(array $diffs) {
id(new DifferentialChangesetQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withDiffs($diffs)
->needAttachToDiffs(true)
->needHunks(true)
->execute();
return $diffs;
}
private function loadArcanistProjects(array $diffs) {
$phids = array_filter(mpull($diffs, 'getArcanistProjectPHID'));
$projects = array();
$project_map = array();
if ($phids) {
$projects = id(new PhabricatorRepositoryArcanistProject())
->loadAllWhere(
'phid IN (%Ls)',
$phids);
$project_map = mpull($projects, null, 'getPHID');
}
foreach ($diffs as $diff) {
$project = null;
if ($diff->getArcanistProjectPHID()) {
$project = idx($project_map, $diff->getArcanistProjectPHID());
}
$diff->attachArcanistProject($project);
}
return $diffs;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->revisionIDs) {
$where[] = qsprintf(
$conn_r,
'revisionID IN (%Ld)',
$this->revisionIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
}
diff --git a/src/applications/differential/query/DifferentialHunkQuery.php b/src/applications/differential/query/DifferentialHunkQuery.php
index 94bc0297b3..3c9f898810 100644
--- a/src/applications/differential/query/DifferentialHunkQuery.php
+++ b/src/applications/differential/query/DifferentialHunkQuery.php
@@ -1,120 +1,120 @@
<?php
final class DifferentialHunkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $changesets;
private $shouldAttachToChangesets;
public function withChangesets(array $changesets) {
assert_instances_of($changesets, 'DifferentialChangeset');
$this->changesets = $changesets;
return $this;
}
public function needAttachToChangesets($attach) {
$this->shouldAttachToChangesets = $attach;
return $this;
}
protected function willExecute() {
// If we fail to load any hunks at all (for example, because all of
// the requested changesets are directories or empty files and have no
// hunks) we'll never call didFilterPage(), and thus never have an
// opportunity to attach hunks. Attach empty hunk lists now so that we
// end up with the right result.
if ($this->shouldAttachToChangesets) {
foreach ($this->changesets as $changeset) {
$changeset->attachHunks(array());
}
}
}
protected function loadPage() {
$all_results = array();
// Load modern hunks.
$table = new DifferentialModernHunk();
$conn_r = $table->establishConnection('r');
$modern_data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$modern_results = $table->loadAllFromArray($modern_data);
// Now, load legacy hunks.
$table = new DifferentialLegacyHunk();
$conn_r = $table->establishConnection('r');
$legacy_data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$legacy_results = $table->loadAllFromArray($legacy_data);
// Strip all the IDs off since they're not unique and nothing should be
// using them.
return array_values(array_merge($legacy_results, $modern_results));
}
protected function willFilterPage(array $hunks) {
$changesets = mpull($this->changesets, null, 'getID');
foreach ($hunks as $key => $hunk) {
$changeset = idx($changesets, $hunk->getChangesetID());
if (!$changeset) {
unset($hunks[$key]);
}
$hunk->attachChangeset($changeset);
}
return $hunks;
}
protected function didFilterPage(array $hunks) {
if ($this->shouldAttachToChangesets) {
$hunk_groups = mgroup($hunks, 'getChangesetID');
foreach ($this->changesets as $changeset) {
$hunks = idx($hunk_groups, $changeset->getID(), array());
$changeset->attachHunks($hunks);
}
}
return $hunks;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if (!$this->changesets) {
throw new Exception(
pht('You must load hunks via changesets, with withChangesets()!'));
}
$where[] = qsprintf(
$conn_r,
'changesetID IN (%Ld)',
mpull($this->changesets, 'getID'));
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
protected function getDefaultOrderVector() {
// TODO: Do we need this?
return array('-id');
}
}
diff --git a/src/applications/differential/query/DifferentialInlineCommentQuery.php b/src/applications/differential/query/DifferentialInlineCommentQuery.php
index f605a78b02..127dcb7c7d 100644
--- a/src/applications/differential/query/DifferentialInlineCommentQuery.php
+++ b/src/applications/differential/query/DifferentialInlineCommentQuery.php
@@ -1,170 +1,170 @@
<?php
/**
* Temporary wrapper for transitioning Differential to ApplicationTransactions.
*/
final class DifferentialInlineCommentQuery
extends PhabricatorOffsetPagedQuery {
private $revisionIDs;
private $notDraft;
private $ids;
private $phids;
private $commentIDs;
private $viewerAndChangesetIDs;
private $draftComments;
private $draftsByAuthors;
public function withRevisionIDs(array $ids) {
$this->revisionIDs = $ids;
return $this;
}
public function withNotDraft($not_draft) {
$this->notDraft = $not_draft;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withViewerAndChangesetIDs($author_phid, array $ids) {
$this->viewerAndChangesetIDs = array($author_phid, $ids);
return $this;
}
public function withDraftComments($author_phid, $revision_id) {
$this->draftComments = array($author_phid, $revision_id);
return $this;
}
public function withDraftsByAuthors(array $author_phids) {
$this->draftsByAuthors = $author_phids;
return $this;
}
public function execute() {
$table = new DifferentialTransactionComment();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildLimitClause($conn_r));
$comments = $table->loadAllFromArray($data);
foreach ($comments as $key => $value) {
$comments[$key] = DifferentialInlineComment::newFromModernComment(
$value);
}
return $comments;
}
public function executeOne() {
return head($this->execute());
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
// Only find inline comments.
$where[] = qsprintf(
$conn_r,
'changesetID IS NOT NULL');
if ($this->revisionIDs) {
// Look up revision PHIDs.
$revision_phids = queryfx_all(
$conn_r,
'SELECT phid FROM %T WHERE id IN (%Ld)',
id(new DifferentialRevision())->getTableName(),
$this->revisionIDs);
if (!$revision_phids) {
throw new PhabricatorEmptyQueryException();
}
$revision_phids = ipull($revision_phids, 'phid');
$where[] = qsprintf(
$conn_r,
'revisionPHID IN (%Ls)',
$revision_phids);
}
if ($this->notDraft) {
$where[] = qsprintf(
$conn_r,
'transactionPHID IS NOT NULL');
}
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->viewerAndChangesetIDs) {
list($phid, $ids) = $this->viewerAndChangesetIDs;
$where[] = qsprintf(
$conn_r,
'changesetID IN (%Ld) AND
((authorPHID = %s AND isDeleted = 0) OR transactionPHID IS NOT NULL)',
$ids,
$phid);
}
if ($this->draftComments) {
list($phid, $rev_id) = $this->draftComments;
$rev_phid = queryfx_one(
$conn_r,
'SELECT phid FROM %T WHERE id = %d',
id(new DifferentialRevision())->getTableName(),
$rev_id);
if (!$rev_phid) {
throw new PhabricatorEmptyQueryException();
}
$rev_phid = $rev_phid['phid'];
$where[] = qsprintf(
$conn_r,
'authorPHID = %s AND revisionPHID = %s AND transactionPHID IS NULL
AND isDeleted = 0',
$phid,
$rev_phid);
}
if ($this->draftsByAuthors) {
$where[] = qsprintf(
$conn_r,
'authorPHID IN (%Ls) AND isDeleted = 0 AND transactionPHID IS NULL',
$this->draftsByAuthors);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php
index 13399bd7cc..63b5256454 100644
--- a/src/applications/differential/query/DifferentialRevisionQuery.php
+++ b/src/applications/differential/query/DifferentialRevisionQuery.php
@@ -1,1164 +1,1164 @@
<?php
/**
* Flexible query API for Differential revisions. Example:
*
* // Load open revisions
* $revisions = id(new DifferentialRevisionQuery())
* ->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
* ->execute();
*
* @task config Query Configuration
* @task exec Query Execution
* @task internal Internals
*/
final class DifferentialRevisionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $pathIDs = array();
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_ACCEPTED = 'status-accepted';
const STATUS_NEEDS_REVIEW = 'status-needs-review';
const STATUS_NEEDS_REVISION = 'status-needs-revision';
const STATUS_CLOSED = 'status-closed';
const STATUS_ABANDONED = 'status-abandoned';
private $authors = array();
private $draftAuthors = array();
private $ccs = array();
private $reviewers = array();
private $revIDs = array();
private $commitHashes = array();
private $commitPHIDs = array();
private $phids = array();
private $responsibles = array();
private $branches = array();
private $arcanistProjectPHIDs = array();
private $repositoryPHIDs;
private $updatedEpochMin;
private $updatedEpochMax;
const ORDER_MODIFIED = 'order-modified';
const ORDER_CREATED = 'order-created';
private $needRelationships = false;
private $needActiveDiffs = false;
private $needDiffIDs = false;
private $needCommitPHIDs = false;
private $needHashes = false;
private $needReviewerStatus = false;
private $needReviewerAuthority;
private $needDrafts;
private $needFlags;
private $buildingGlobalOrder;
/* -( Query Configuration )------------------------------------------------ */
/**
* Filter results to revisions which affect a Diffusion path ID in a given
* repository. You can call this multiple times to select revisions for
* several paths.
*
* @param int Diffusion repository ID.
* @param int Diffusion path ID.
* @return this
* @task config
*/
public function withPath($repository_id, $path_id) {
$this->pathIDs[] = array(
'repositoryID' => $repository_id,
'pathID' => $path_id,
);
return $this;
}
/**
* Filter results to revisions authored by one of the given PHIDs. Calling
* this function will clear anything set by previous calls to
* @{method:withAuthors}.
*
* @param array List of PHIDs of authors
* @return this
* @task config
*/
public function withAuthors(array $author_phids) {
$this->authors = $author_phids;
return $this;
}
/**
* Filter results to revisions with comments authored by the given PHIDs.
*
* @param array List of PHIDs of authors
* @return this
* @task config
*/
public function withDraftRepliesByAuthors(array $author_phids) {
$this->draftAuthors = $author_phids;
return $this;
}
/**
* Filter results to revisions which CC one of the listed people. Calling this
* function will clear anything set by previous calls to @{method:withCCs}.
*
* @param array List of PHIDs of subscribers.
* @return this
* @task config
*/
public function withCCs(array $cc_phids) {
$this->ccs = $cc_phids;
return $this;
}
/**
* Filter results to revisions that have one of the provided PHIDs as
* reviewers. Calling this function will clear anything set by previous calls
* to @{method:withReviewers}.
*
* @param array List of PHIDs of reviewers
* @return this
* @task config
*/
public function withReviewers(array $reviewer_phids) {
$this->reviewers = $reviewer_phids;
return $this;
}
/**
* Filter results to revisions that have one of the provided commit hashes.
* Calling this function will clear anything set by previous calls to
* @{method:withCommitHashes}.
*
* @param array List of pairs <Class
* ArcanistDifferentialRevisionHash::HASH_$type constant,
* hash>
* @return this
* @task config
*/
public function withCommitHashes(array $commit_hashes) {
$this->commitHashes = $commit_hashes;
return $this;
}
/**
* Filter results to revisions that have one of the provided PHIDs as
* commits. Calling this function will clear anything set by previous calls
* to @{method:withCommitPHIDs}.
*
* @param array List of PHIDs of commits
* @return this
* @task config
*/
public function withCommitPHIDs(array $commit_phids) {
$this->commitPHIDs = $commit_phids;
return $this;
}
/**
* Filter results to revisions with a given status. Provide a class constant,
* such as `DifferentialRevisionQuery::STATUS_OPEN`.
*
* @param const Class STATUS constant, like STATUS_OPEN.
* @return this
* @task config
*/
public function withStatus($status_constant) {
$this->status = $status_constant;
return $this;
}
/**
* Filter results to revisions on given branches.
*
* @param list List of branch names.
* @return this
* @task config
*/
public function withBranches(array $branches) {
$this->branches = $branches;
return $this;
}
/**
* Filter results to only return revisions whose ids are in the given set.
*
* @param array List of revision ids
* @return this
* @task config
*/
public function withIDs(array $ids) {
$this->revIDs = $ids;
return $this;
}
/**
* Filter results to only return revisions whose PHIDs are in the given set.
*
* @param array List of revision PHIDs
* @return this
* @task config
*/
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
/**
* Given a set of users, filter results to return only revisions they are
* responsible for (i.e., they are either authors or reviewers).
*
* @param array List of user PHIDs.
* @return this
* @task config
*/
public function withResponsibleUsers(array $responsible_phids) {
$this->responsibles = $responsible_phids;
return $this;
}
/**
* Filter results to only return revisions with a given set of arcanist
* projects.
*
* @param array List of project PHIDs.
* @return this
* @task config
*/
public function withArcanistProjectPHIDs(array $arc_project_phids) {
$this->arcanistProjectPHIDs = $arc_project_phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withUpdatedEpochBetween($min, $max) {
$this->updatedEpochMin = $min;
$this->updatedEpochMax = $max;
return $this;
}
/**
* Set result ordering. Provide a class constant, such as
* `DifferentialRevisionQuery::ORDER_CREATED`.
*
* @task config
*/
public function setOrder($order_constant) {
switch ($order_constant) {
case self::ORDER_CREATED:
$this->setOrderVector(array('id'));
break;
case self::ORDER_MODIFIED:
$this->setOrderVector(array('updated', 'id'));
break;
default:
throw new Exception(pht('Unknown order "%s".', $order_constant));
}
return $this;
}
/**
* Set whether or not the query will load and attach relationships.
*
* @param bool True to load and attach relationships.
* @return this
* @task config
*/
public function needRelationships($need_relationships) {
$this->needRelationships = $need_relationships;
return $this;
}
/**
* Set whether or not the query should load the active diff for each
* revision.
*
* @param bool True to load and attach diffs.
* @return this
* @task config
*/
public function needActiveDiffs($need_active_diffs) {
$this->needActiveDiffs = $need_active_diffs;
return $this;
}
/**
* Set whether or not the query should load the associated commit PHIDs for
* each revision.
*
* @param bool True to load and attach diffs.
* @return this
* @task config
*/
public function needCommitPHIDs($need_commit_phids) {
$this->needCommitPHIDs = $need_commit_phids;
return $this;
}
/**
* Set whether or not the query should load associated diff IDs for each
* revision.
*
* @param bool True to load and attach diff IDs.
* @return this
* @task config
*/
public function needDiffIDs($need_diff_ids) {
$this->needDiffIDs = $need_diff_ids;
return $this;
}
/**
* Set whether or not the query should load associated commit hashes for each
* revision.
*
* @param bool True to load and attach commit hashes.
* @return this
* @task config
*/
public function needHashes($need_hashes) {
$this->needHashes = $need_hashes;
return $this;
}
/**
* Set whether or not the query should load associated reviewer status.
*
* @param bool True to load and attach reviewers.
* @return this
* @task config
*/
public function needReviewerStatus($need_reviewer_status) {
$this->needReviewerStatus = $need_reviewer_status;
return $this;
}
/**
* Request information about the viewer's authority to act on behalf of each
* reviewer. In particular, they have authority to act on behalf of projects
* they are a member of.
*
* @param bool True to load and attach authority.
* @return this
* @task config
*/
public function needReviewerAuthority($need_reviewer_authority) {
$this->needReviewerAuthority = $need_reviewer_authority;
return $this;
}
public function needFlags($need_flags) {
$this->needFlags = $need_flags;
return $this;
}
public function needDrafts($need_drafts) {
$this->needDrafts = $need_drafts;
return $this;
}
/* -( Query Execution )---------------------------------------------------- */
/**
* Execute the query as configured, returning matching
* @{class:DifferentialRevision} objects.
*
* @return list List of matching DifferentialRevision objects.
* @task exec
*/
protected function loadPage() {
$table = new DifferentialRevision();
$conn_r = $table->establishConnection('r');
$data = $this->loadData();
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $revisions) {
$viewer = $this->getViewer();
$repository_phids = mpull($revisions, 'getRepositoryPHID');
$repository_phids = array_filter($repository_phids);
$repositories = array();
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
}
// If a revision is associated with a repository:
//
// - the viewer must be able to see the repository; or
// - the viewer must have an automatic view capability.
//
// In the latter case, we'll load the revision but not load the repository.
$can_view = PhabricatorPolicyCapability::CAN_VIEW;
foreach ($revisions as $key => $revision) {
$repo_phid = $revision->getRepositoryPHID();
if (!$repo_phid) {
// The revision has no associated repository. Attach `null` and move on.
$revision->attachRepository(null);
continue;
}
$repository = idx($repositories, $repo_phid);
if ($repository) {
// The revision has an associated repository, and the viewer can see
// it. Attach it and move on.
$revision->attachRepository($repository);
continue;
}
if ($revision->hasAutomaticCapability($can_view, $viewer)) {
// The revision has an associated repository which the viewer can not
// see, but the viewer has an automatic capability on this revision.
// Load the revision without attaching a repository.
$revision->attachRepository(null);
continue;
}
if ($this->getViewer()->isOmnipotent()) {
// The viewer is omnipotent. Allow the revision to load even without
// a repository.
$revision->attachRepository(null);
continue;
}
// The revision has an associated repository, and the viewer can't see
// it, and the viewer has no special capabilities. Filter out this
// revision.
$this->didRejectResult($revision);
unset($revisions[$key]);
}
if (!$revisions) {
return array();
}
$table = new DifferentialRevision();
$conn_r = $table->establishConnection('r');
if ($this->needRelationships) {
$this->loadRelationships($conn_r, $revisions);
}
if ($this->needCommitPHIDs) {
$this->loadCommitPHIDs($conn_r, $revisions);
}
$need_active = $this->needActiveDiffs;
$need_ids = $need_active || $this->needDiffIDs;
if ($need_ids) {
$this->loadDiffIDs($conn_r, $revisions);
}
if ($need_active) {
$this->loadActiveDiffs($conn_r, $revisions);
}
if ($this->needHashes) {
$this->loadHashes($conn_r, $revisions);
}
if ($this->needReviewerStatus || $this->needReviewerAuthority) {
$this->loadReviewers($conn_r, $revisions);
}
return $revisions;
}
protected function didFilterPage(array $revisions) {
$viewer = $this->getViewer();
if ($this->needFlags) {
$flags = id(new PhabricatorFlagQuery())
->setViewer($viewer)
->withOwnerPHIDs(array($viewer->getPHID()))
->withObjectPHIDs(mpull($revisions, 'getPHID'))
->execute();
$flags = mpull($flags, null, 'getObjectPHID');
foreach ($revisions as $revision) {
$revision->attachFlag(
$viewer,
idx($flags, $revision->getPHID()));
}
}
if ($this->needDrafts) {
$drafts = id(new DifferentialDraft())->loadAllWhere(
'authorPHID = %s AND objectPHID IN (%Ls)',
$viewer->getPHID(),
mpull($revisions, 'getPHID'));
$drafts = mgroup($drafts, 'getObjectPHID');
foreach ($revisions as $revision) {
$revision->attachDrafts(
$viewer,
idx($drafts, $revision->getPHID(), array()));
}
}
return $revisions;
}
private function loadData() {
$table = new DifferentialRevision();
$conn_r = $table->establishConnection('r');
$selects = array();
// NOTE: If the query includes "responsiblePHIDs", we execute it as a
// UNION of revisions they own and revisions they're reviewing. This has
// much better performance than doing it with JOIN/WHERE.
if ($this->responsibles) {
$basic_authors = $this->authors;
$basic_reviewers = $this->reviewers;
$authority_projects = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withMemberPHIDs($this->responsibles)
->execute();
$authority_phids = mpull($authority_projects, 'getPHID');
try {
// Build the query where the responsible users are authors.
$this->authors = array_merge($basic_authors, $this->responsibles);
$this->reviewers = $basic_reviewers;
$selects[] = $this->buildSelectStatement($conn_r);
// Build the query where the responsible users are reviewers, or
// projects they are members of are reviewers.
$this->authors = $basic_authors;
$this->reviewers = array_merge(
$basic_reviewers,
$this->responsibles,
$authority_phids);
$selects[] = $this->buildSelectStatement($conn_r);
// Put everything back like it was.
$this->authors = $basic_authors;
$this->reviewers = $basic_reviewers;
} catch (Exception $ex) {
$this->authors = $basic_authors;
$this->reviewers = $basic_reviewers;
throw $ex;
}
} else {
$selects[] = $this->buildSelectStatement($conn_r);
}
if (count($selects) > 1) {
$this->buildingGlobalOrder = true;
$query = qsprintf(
$conn_r,
'%Q %Q %Q',
implode(' UNION DISTINCT ', $selects),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
} else {
$query = head($selects);
}
return queryfx_all($conn_r, '%Q', $query);
}
private function buildSelectStatement(AphrontDatabaseConnection $conn_r) {
$table = new DifferentialRevision();
$select = qsprintf(
$conn_r,
'SELECT r.* FROM %T r',
$table->getTableName());
$joins = $this->buildJoinsClause($conn_r);
$where = $this->buildWhereClause($conn_r);
$group_by = $this->buildGroupByClause($conn_r);
$this->buildingGlobalOrder = false;
$order_by = $this->buildOrderClause($conn_r);
$limit = $this->buildLimitClause($conn_r);
return qsprintf(
$conn_r,
'(%Q %Q %Q %Q %Q %Q)',
$select,
$joins,
$where,
$group_by,
$order_by,
$limit);
}
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
private function buildJoinsClause($conn_r) {
$joins = array();
if ($this->pathIDs) {
$path_table = new DifferentialAffectedPath();
$joins[] = qsprintf(
$conn_r,
'JOIN %T p ON p.revisionID = r.id',
$path_table->getTableName());
}
if ($this->commitHashes) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T hash_rel ON hash_rel.revisionID = r.id',
ArcanistDifferentialRevisionHash::TABLE_NAME);
}
if ($this->ccs) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T e_ccs ON e_ccs.src = r.phid '.
'AND e_ccs.type = %s '.
'AND e_ccs.dst in (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorObjectHasSubscriberEdgeType::EDGECONST,
$this->ccs);
}
if ($this->reviewers) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T e_reviewers ON e_reviewers.src = r.phid '.
'AND e_reviewers.type = %s '.
'AND e_reviewers.dst in (%Ls)',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
DifferentialRevisionHasReviewerEdgeType::EDGECONST,
$this->reviewers);
}
if ($this->draftAuthors) {
$differential_draft = new DifferentialDraft();
$joins[] = qsprintf(
$conn_r,
'JOIN %T has_draft ON has_draft.objectPHID = r.phid '.
'AND has_draft.authorPHID IN (%Ls)',
$differential_draft->getTableName(),
$this->draftAuthors);
}
if ($this->commitPHIDs) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T commits ON commits.revisionID = r.id',
DifferentialRevision::TABLE_COMMIT);
}
$joins = implode(' ', $joins);
return $joins;
}
/**
* @task internal
*/
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->pathIDs) {
$path_clauses = array();
$repo_info = igroup($this->pathIDs, 'repositoryID');
foreach ($repo_info as $repository_id => $paths) {
$path_clauses[] = qsprintf(
$conn_r,
'(p.repositoryID = %d AND p.pathID IN (%Ld))',
$repository_id,
ipull($paths, 'pathID'));
}
$path_clauses = '('.implode(' OR ', $path_clauses).')';
$where[] = $path_clauses;
}
if ($this->authors) {
$where[] = qsprintf(
$conn_r,
'r.authorPHID IN (%Ls)',
$this->authors);
}
if ($this->revIDs) {
$where[] = qsprintf(
$conn_r,
'r.id IN (%Ld)',
$this->revIDs);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn_r,
'r.repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->commitHashes) {
$hash_clauses = array();
foreach ($this->commitHashes as $info) {
list($type, $hash) = $info;
$hash_clauses[] = qsprintf(
$conn_r,
'(hash_rel.type = %s AND hash_rel.hash = %s)',
$type,
$hash);
}
$hash_clauses = '('.implode(' OR ', $hash_clauses).')';
$where[] = $hash_clauses;
}
if ($this->commitPHIDs) {
$where[] = qsprintf(
$conn_r,
'commits.commitPHID IN (%Ls)',
$this->commitPHIDs);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'r.phid IN (%Ls)',
$this->phids);
}
if ($this->branches) {
$where[] = qsprintf(
$conn_r,
'r.branchName in (%Ls)',
$this->branches);
}
if ($this->arcanistProjectPHIDs) {
$where[] = qsprintf(
$conn_r,
'r.arcanistProjectPHID in (%Ls)',
$this->arcanistProjectPHIDs);
}
if ($this->updatedEpochMin !== null) {
$where[] = qsprintf(
$conn_r,
'r.dateModified >= %d',
$this->updatedEpochMin);
}
if ($this->updatedEpochMax !== null) {
$where[] = qsprintf(
$conn_r,
'r.dateModified <= %d',
$this->updatedEpochMax);
}
switch ($this->status) {
case self::STATUS_ANY:
break;
case self::STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
DifferentialRevisionStatus::getOpenStatuses());
break;
case self::STATUS_NEEDS_REVIEW:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
array(
ArcanistDifferentialRevisionStatus::NEEDS_REVIEW,
));
break;
case self::STATUS_NEEDS_REVISION:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
array(
ArcanistDifferentialRevisionStatus::NEEDS_REVISION,
));
break;
case self::STATUS_ACCEPTED:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
array(
ArcanistDifferentialRevisionStatus::ACCEPTED,
));
break;
case self::STATUS_CLOSED:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
DifferentialRevisionStatus::getClosedStatuses());
break;
case self::STATUS_ABANDONED:
$where[] = qsprintf(
$conn_r,
'r.status IN (%Ld)',
array(
ArcanistDifferentialRevisionStatus::ABANDONED,
));
break;
default:
throw new Exception(
"Unknown revision status filter constant '{$this->status}'!");
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
/**
* @task internal
*/
private function buildGroupByClause($conn_r) {
$join_triggers = array_merge(
$this->pathIDs,
$this->ccs,
$this->reviewers);
$needs_distinct = (count($join_triggers) > 1);
if ($needs_distinct) {
return 'GROUP BY r.id';
} else {
return '';
}
}
protected function getDefaultOrderVector() {
return array('updated', 'id');
}
public function getOrderableColumns() {
$primary = ($this->buildingGlobalOrder ? null : 'r');
return array(
'id' => array(
'table' => $primary,
'column' => 'id',
'type' => 'int',
'unique' => true,
),
'updated' => array(
'table' => $primary,
'column' => 'dateModified',
'type' => 'int',
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$revision = $this->loadCursorObject($cursor);
return array(
'id' => $revision->getID(),
'updated' => $revision->getDateModified(),
);
}
private function loadRelationships($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$type_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
$type_subscriber = PhabricatorObjectHasSubscriberEdgeType::EDGECONST;
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($revisions, 'getPHID'))
->withEdgeTypes(array($type_reviewer, $type_subscriber))
->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST)
->execute();
$type_map = array(
DifferentialRevision::RELATION_REVIEWER => $type_reviewer,
DifferentialRevision::RELATION_SUBSCRIBED => $type_subscriber,
);
foreach ($revisions as $revision) {
$data = array();
foreach ($type_map as $rel_type => $edge_type) {
$revision_edges = $edges[$revision->getPHID()][$edge_type];
foreach ($revision_edges as $dst_phid => $edge_data) {
$data[] = array(
'relation' => $rel_type,
'objectPHID' => $dst_phid,
'reasonPHID' => null,
);
}
}
$revision->attachRelationships($data);
}
}
private function loadCommitPHIDs($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$commit_phids = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE revisionID IN (%Ld)',
DifferentialRevision::TABLE_COMMIT,
mpull($revisions, 'getID'));
$commit_phids = igroup($commit_phids, 'revisionID');
foreach ($revisions as $revision) {
$phids = idx($commit_phids, $revision->getID(), array());
$phids = ipull($phids, 'commitPHID');
$revision->attachCommitPHIDs($phids);
}
}
private function loadDiffIDs($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$diff_table = new DifferentialDiff();
$diff_ids = queryfx_all(
$conn_r,
'SELECT revisionID, id FROM %T WHERE revisionID IN (%Ld)
ORDER BY id DESC',
$diff_table->getTableName(),
mpull($revisions, 'getID'));
$diff_ids = igroup($diff_ids, 'revisionID');
foreach ($revisions as $revision) {
$ids = idx($diff_ids, $revision->getID(), array());
$ids = ipull($ids, 'id');
$revision->attachDiffIDs($ids);
}
}
private function loadActiveDiffs($conn_r, array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$diff_table = new DifferentialDiff();
$load_ids = array();
foreach ($revisions as $revision) {
$diffs = $revision->getDiffIDs();
if ($diffs) {
$load_ids[] = max($diffs);
}
}
$active_diffs = array();
if ($load_ids) {
$active_diffs = $diff_table->loadAllWhere(
'id IN (%Ld)',
$load_ids);
}
$active_diffs = mpull($active_diffs, null, 'getRevisionID');
foreach ($revisions as $revision) {
$revision->attachActiveDiff(idx($active_diffs, $revision->getID()));
}
}
private function loadHashes(
AphrontDatabaseConnection $conn_r,
array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE revisionID IN (%Ld)',
'differential_revisionhash',
mpull($revisions, 'getID'));
$data = igroup($data, 'revisionID');
foreach ($revisions as $revision) {
$hashes = idx($data, $revision->getID(), array());
$list = array();
foreach ($hashes as $hash) {
$list[] = array($hash['type'], $hash['hash']);
}
$revision->attachHashes($list);
}
}
private function loadReviewers(
AphrontDatabaseConnection $conn_r,
array $revisions) {
assert_instances_of($revisions, 'DifferentialRevision');
$edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($revisions, 'getPHID'))
->withEdgeTypes(array($edge_type))
->needEdgeData(true)
->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST)
->execute();
$viewer = $this->getViewer();
$viewer_phid = $viewer->getPHID();
$allow_key = 'differential.allow-self-accept';
$allow_self = PhabricatorEnv::getEnvConfig($allow_key);
// Figure out which of these reviewers the viewer has authority to act as.
if ($this->needReviewerAuthority && $viewer_phid) {
$authority = $this->loadReviewerAuthority(
$revisions,
$edges,
$allow_self);
}
foreach ($revisions as $revision) {
$revision_edges = $edges[$revision->getPHID()][$edge_type];
$reviewers = array();
foreach ($revision_edges as $reviewer_phid => $edge) {
$reviewer = new DifferentialReviewer($reviewer_phid, $edge['data']);
if ($this->needReviewerAuthority) {
if (!$viewer_phid) {
// Logged-out users never have authority.
$has_authority = false;
} else if ((!$allow_self) &&
($revision->getAuthorPHID() == $viewer_phid)) {
// The author can never have authority unless we allow self-accept.
$has_authority = false;
} else {
// Otherwise, look up whether th viewer has authority.
$has_authority = isset($authority[$reviewer_phid]);
}
$reviewer->attachAuthority($viewer, $has_authority);
}
$reviewers[$reviewer_phid] = $reviewer;
}
$revision->attachReviewerStatus($reviewers);
}
}
public static function splitResponsible(array $revisions, array $user_phids) {
$blocking = array();
$active = array();
$waiting = array();
$status_review = ArcanistDifferentialRevisionStatus::NEEDS_REVIEW;
// Bucket revisions into $blocking (revisions where you are blocking
// others), $active (revisions you need to do something about) and $waiting
// (revisions you're waiting on someone else to do something about).
foreach ($revisions as $revision) {
$needs_review = ($revision->getStatus() == $status_review);
$filter_is_author = in_array($revision->getAuthorPHID(), $user_phids);
if (!$revision->getReviewers()) {
$needs_review = false;
$author_is_reviewer = false;
} else {
$author_is_reviewer = in_array(
$revision->getAuthorPHID(),
$revision->getReviewers());
}
// If exactly one of "needs review" and "the user is the author" is
// true, the user needs to act on it. Otherwise, they're waiting on
// it.
if ($needs_review ^ $filter_is_author) {
if ($needs_review) {
array_unshift($blocking, $revision);
} else {
$active[] = $revision;
}
// User is author **and** reviewer. An exotic but configurable workflow.
// User needs to act on it double.
} else if ($needs_review && $author_is_reviewer) {
array_unshift($blocking, $revision);
$active[] = $revision;
} else {
$waiting[] = $revision;
}
}
return array($blocking, $active, $waiting);
}
private function loadReviewerAuthority(
array $revisions,
array $edges,
$allow_self) {
$revision_map = mpull($revisions, null, 'getPHID');
$viewer_phid = $this->getViewer()->getPHID();
// Find all the project reviewers which the user may have authority over.
$project_phids = array();
$project_type = PhabricatorProjectProjectPHIDType::TYPECONST;
$edge_type = DifferentialRevisionHasReviewerEdgeType::EDGECONST;
foreach ($edges as $src => $types) {
if (!$allow_self) {
if ($revision_map[$src]->getAuthorPHID() == $viewer_phid) {
// If self-review isn't permitted, the user will never have
// authority over projects on revisions they authored because you
// can't accept your own revisions, so we don't need to load any
// data about these reviewers.
continue;
}
}
$edge_data = idx($types, $edge_type, array());
foreach ($edge_data as $dst => $data) {
if (phid_get_type($dst) == $project_type) {
$project_phids[] = $dst;
}
}
}
// Now, figure out which of these projects the viewer is actually a
// member of.
$project_authority = array();
if ($project_phids) {
$project_authority = id(new PhabricatorProjectQuery())
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->withMemberPHIDs(array($viewer_phid))
->execute();
$project_authority = mpull($project_authority, 'getPHID');
}
// Finally, the viewer has authority over themselves.
return array(
$viewer_phid => true,
) + array_fuse($project_authority);
}
public function getQueryApplicationClass() {
return 'PhabricatorDifferentialApplication';
}
}
diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php
index 22331e8510..8fd9d0c73e 100644
--- a/src/applications/diffusion/query/DiffusionCommitQuery.php
+++ b/src/applications/diffusion/query/DiffusionCommitQuery.php
@@ -1,566 +1,566 @@
<?php
final class DiffusionCommitQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $defaultRepository;
private $identifiers;
private $repositoryIDs;
private $repositoryPHIDs;
private $identifierMap;
private $needAuditRequests;
private $auditIDs;
private $auditorPHIDs;
private $auditAwaitingUser;
private $auditStatus;
const AUDIT_STATUS_ANY = 'audit-status-any';
const AUDIT_STATUS_OPEN = 'audit-status-open';
const AUDIT_STATUS_CONCERN = 'audit-status-concern';
const AUDIT_STATUS_ACCEPTED = 'audit-status-accepted';
const AUDIT_STATUS_PARTIAL = 'audit-status-partial';
private $needCommitData;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
/**
* Load commits by partial or full identifiers, e.g. "rXab82393", "rX1234",
* or "a9caf12". When an identifier matches multiple commits, they will all
* be returned; callers should be prepared to deal with more results than
* they queried for.
*/
public function withIdentifiers(array $identifiers) {
$this->identifiers = $identifiers;
return $this;
}
/**
* Look up commits in a specific repository. This is a shorthand for calling
* @{method:withDefaultRepository} and @{method:withRepositoryIDs}.
*/
public function withRepository(PhabricatorRepository $repository) {
$this->withDefaultRepository($repository);
$this->withRepositoryIDs(array($repository->getID()));
return $this;
}
/**
* Look up commits in a specific repository. Prefer
* @{method:withRepositoryIDs}; the underyling table is keyed by ID such
* that this method requires a separate initial query to map PHID to ID.
*/
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
}
/**
* If a default repository is provided, ambiguous commit identifiers will
* be assumed to belong to the default repository.
*
* For example, "r123" appearing in a commit message in repository X is
* likely to be unambiguously "rX123". Normally the reference would be
* considered ambiguous, but if you provide a default repository it will
* be correctly resolved.
*/
public function withDefaultRepository(PhabricatorRepository $repository) {
$this->defaultRepository = $repository;
return $this;
}
public function withRepositoryIDs(array $repository_ids) {
$this->repositoryIDs = $repository_ids;
return $this;
}
public function needCommitData($need) {
$this->needCommitData = $need;
return $this;
}
public function needAuditRequests($need) {
$this->needAuditRequests = $need;
return $this;
}
/**
* Returns true if we should join the audit table, either because we're
* interested in the information if it's available or because matching rows
* must always have it.
*/
private function shouldJoinAudits() {
return $this->auditStatus ||
$this->rowsMustHaveAudits();
}
/**
* Return true if we should `JOIN` (vs `LEFT JOIN`) the audit table, because
* matching commits will always have audit rows.
*/
private function rowsMustHaveAudits() {
return
$this->auditIDs ||
$this->auditorPHIDs ||
$this->auditAwaitingUser;
}
public function withAuditIDs(array $ids) {
$this->auditIDs = $ids;
return $this;
}
public function withAuditorPHIDs(array $auditor_phids) {
$this->auditorPHIDs = $auditor_phids;
return $this;
}
public function withAuditAwaitingUser(PhabricatorUser $user) {
$this->auditAwaitingUser = $user;
return $this;
}
public function withAuditStatus($status) {
$this->auditStatus = $status;
return $this;
}
public function getIdentifierMap() {
if ($this->identifierMap === null) {
throw new Exception(
'You must execute() the query before accessing the identifier map.');
}
return $this->identifierMap;
}
protected function getPrimaryTableAlias() {
return 'commit';
}
protected function willExecute() {
if ($this->identifierMap === null) {
$this->identifierMap = array();
}
}
protected function loadPage() {
$table = new PhabricatorRepositoryCommit();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT commit.* FROM %T commit %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $commits) {
$repository_ids = mpull($commits, 'getRepositoryID', 'getRepositoryID');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIDs($repository_ids)
->execute();
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$result = array();
foreach ($commits as $key => $commit) {
$repo = idx($repos, $commit->getRepositoryID());
if ($repo) {
$commit->attachRepository($repo);
} else {
unset($commits[$key]);
continue;
}
// Build the identifierMap
if ($this->identifiers !== null) {
$ids = array_fuse($this->identifiers);
$prefixes = array(
'r'.$commit->getRepository()->getCallsign(),
'r'.$commit->getRepository()->getCallsign().':',
'R'.$commit->getRepository()->getID().':',
'', // No prefix is valid too and will only match the commitIdentifier
);
$suffix = $commit->getCommitIdentifier();
if ($commit->getRepository()->isSVN()) {
foreach ($prefixes as $prefix) {
if (isset($ids[$prefix.$suffix])) {
$result[$prefix.$suffix][] = $commit;
}
}
} else {
// This awkward construction is so we can link the commits up in O(N)
// time instead of O(N^2).
for ($ii = $min_qualified; $ii <= strlen($suffix); $ii++) {
$part = substr($suffix, 0, $ii);
foreach ($prefixes as $prefix) {
if (isset($ids[$prefix.$part])) {
$result[$prefix.$part][] = $commit;
}
}
}
}
}
}
if ($result) {
foreach ($result as $identifier => $matching_commits) {
if (count($matching_commits) == 1) {
$result[$identifier] = head($matching_commits);
} else {
// This reference is ambiguous (it matches more than one commit) so
// don't link it.
unset($result[$identifier]);
}
}
$this->identifierMap += $result;
}
return $commits;
}
protected function didFilterPage(array $commits) {
if ($this->needCommitData) {
$data = id(new PhabricatorRepositoryCommitData())->loadAllWhere(
'commitID in (%Ld)',
mpull($commits, 'getID'));
$data = mpull($data, null, 'getCommitID');
foreach ($commits as $commit) {
$commit_data = idx($data, $commit->getID());
if (!$commit_data) {
$commit_data = new PhabricatorRepositoryCommitData();
}
$commit->attachCommitData($commit_data);
}
}
// TODO: This should just be `needAuditRequests`, not `shouldJoinAudits()`,
// but leave that for a future diff.
if ($this->needAuditRequests || $this->shouldJoinAudits()) {
$requests = id(new PhabricatorRepositoryAuditRequest())->loadAllWhere(
'commitPHID IN (%Ls)',
mpull($commits, 'getPHID'));
$requests = mgroup($requests, 'getCommitPHID');
foreach ($commits as $commit) {
$audit_requests = idx($requests, $commit->getPHID(), array());
$commit->attachAudits($audit_requests);
foreach ($audit_requests as $audit_request) {
$audit_request->attachCommit($commit);
}
}
}
return $commits;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->repositoryPHIDs !== null) {
$map_repositories = id (new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($this->repositoryPHIDs)
->execute();
if (!$map_repositories) {
throw new PhabricatorEmptyQueryException();
}
$repository_ids = mpull($map_repositories, 'getID');
if ($this->repositoryIDs !== null) {
$repository_ids = array_merge($repository_ids, $this->repositoryIDs);
}
$this->withRepositoryIDs($repository_ids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'commit.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'commit.phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryIDs !== null) {
$where[] = qsprintf(
$conn_r,
'commit.repositoryID IN (%Ld)',
$this->repositoryIDs);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'commit.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->identifiers !== null) {
$min_unqualified = PhabricatorRepository::MINIMUM_UNQUALIFIED_HASH;
$min_qualified = PhabricatorRepository::MINIMUM_QUALIFIED_HASH;
$refs = array();
$bare = array();
foreach ($this->identifiers as $identifier) {
$matches = null;
preg_match('/^(?:[rR]([A-Z]+:?|[0-9]+:))?(.*)$/',
$identifier, $matches);
$repo = nonempty(rtrim($matches[1], ':'), null);
$commit_identifier = nonempty($matches[2], null);
if ($repo === null) {
if ($this->defaultRepository) {
$repo = $this->defaultRepository->getCallsign();
}
}
if ($repo === null) {
if (strlen($commit_identifier) < $min_unqualified) {
continue;
}
$bare[] = $commit_identifier;
} else {
$refs[] = array(
'callsign' => $repo,
'identifier' => $commit_identifier,
);
}
}
$sql = array();
foreach ($bare as $identifier) {
$sql[] = qsprintf(
$conn_r,
'(commit.commitIdentifier LIKE %> AND '.
'LENGTH(commit.commitIdentifier) = 40)',
$identifier);
}
if ($refs) {
$callsigns = ipull($refs, 'callsign');
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIdentifiers($callsigns);
$repos->execute();
$repos = $repos->getIdentifierMap();
foreach ($refs as $key => $ref) {
$repo = idx($repos, $ref['callsign']);
if (!$repo) {
continue;
}
if ($repo->isSVN()) {
if (!ctype_digit($ref['identifier'])) {
continue;
}
$sql[] = qsprintf(
$conn_r,
'(commit.repositoryID = %d AND commit.commitIdentifier = %s)',
$repo->getID(),
// NOTE: Because the 'commitIdentifier' column is a string, MySQL
// ignores the index if we hand it an integer. Hand it a string.
// See T3377.
(int)$ref['identifier']);
} else {
if (strlen($ref['identifier']) < $min_qualified) {
continue;
}
$sql[] = qsprintf(
$conn_r,
'(commit.repositoryID = %d AND commit.commitIdentifier LIKE %>)',
$repo->getID(),
$ref['identifier']);
}
}
}
if (!$sql) {
// If we discarded all possible identifiers (e.g., they all referenced
// bogus repositories or were all too short), make sure the query finds
// nothing.
throw new PhabricatorEmptyQueryException(
pht('No commit identifiers.'));
}
$where[] = '('.implode(' OR ', $sql).')';
}
if ($this->auditIDs !== null) {
$where[] = qsprintf(
$conn_r,
'audit.id IN (%Ld)',
$this->auditIDs);
}
if ($this->auditorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'audit.auditorPHID IN (%Ls)',
$this->auditorPHIDs);
}
if ($this->auditAwaitingUser) {
$awaiting_user_phid = $this->auditAwaitingUser->getPHID();
// Exclude package and project audits associated with commits where
// the user is the author.
$where[] = qsprintf(
$conn_r,
'(commit.authorPHID IS NULL OR commit.authorPHID != %s)
OR (audit.auditorPHID = %s)',
$awaiting_user_phid,
$awaiting_user_phid);
}
$status = $this->auditStatus;
if ($status !== null) {
switch ($status) {
case self::AUDIT_STATUS_PARTIAL:
$where[] = qsprintf(
$conn_r,
'commit.auditStatus = %d',
PhabricatorAuditCommitStatusConstants::PARTIALLY_AUDITED);
break;
case self::AUDIT_STATUS_ACCEPTED:
$where[] = qsprintf(
$conn_r,
'commit.auditStatus = %d',
PhabricatorAuditCommitStatusConstants::FULLY_AUDITED);
break;
case self::AUDIT_STATUS_CONCERN:
$where[] = qsprintf(
$conn_r,
'audit.auditStatus = %s',
PhabricatorAuditStatusConstants::CONCERNED);
break;
case self::AUDIT_STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'audit.auditStatus in (%Ls)',
PhabricatorAuditStatusConstants::getOpenStatusConstants());
if ($this->auditAwaitingUser) {
$where[] = qsprintf(
$conn_r,
'awaiting.auditStatus IS NULL OR awaiting.auditStatus != %s',
PhabricatorAuditStatusConstants::RESIGNED);
}
break;
case self::AUDIT_STATUS_ANY:
break;
default:
$valid = array(
self::AUDIT_STATUS_ANY,
self::AUDIT_STATUS_OPEN,
self::AUDIT_STATUS_CONCERN,
self::AUDIT_STATUS_ACCEPTED,
self::AUDIT_STATUS_PARTIAL,
);
throw new Exception(
"Unknown audit status '{$status}'! Valid statuses are: ".
implode(', ', $valid));
}
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function didFilterResults(array $filtered) {
if ($this->identifierMap) {
foreach ($this->identifierMap as $name => $commit) {
if (isset($filtered[$commit->getPHID()])) {
unset($this->identifierMap[$name]);
}
}
}
}
private function buildJoinClause($conn_r) {
$joins = array();
$audit_request = new PhabricatorRepositoryAuditRequest();
if ($this->shouldJoinAudits()) {
$joins[] = qsprintf(
$conn_r,
'%Q %T audit ON commit.phid = audit.commitPHID',
($this->rowsMustHaveAudits() ? 'JOIN' : 'LEFT JOIN'),
$audit_request->getTableName());
}
if ($this->auditAwaitingUser) {
// Join the request table on the awaiting user's requests, so we can
// filter out package and project requests which the user has resigned
// from.
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T awaiting ON audit.commitPHID = awaiting.commitPHID AND
awaiting.auditorPHID = %s',
$audit_request->getTableName(),
$this->auditAwaitingUser->getPHID());
}
if ($joins) {
return implode(' ', $joins);
} else {
return '';
}
}
private function buildGroupClause(AphrontDatabaseConnection $conn_r) {
$should_group = $this->shouldJoinAudits();
// TODO: Currently, the audit table is missing a unique key, so we may
// require a GROUP BY if we perform this join. See T1768. This can be
// removed once the table has the key.
if ($this->auditAwaitingUser) {
$should_group = true;
}
if ($should_group) {
return 'GROUP BY commit.id';
} else {
return '';
}
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}
diff --git a/src/applications/diffusion/query/DiffusionLintCountQuery.php b/src/applications/diffusion/query/DiffusionLintCountQuery.php
index 89fca4cded..f85505af76 100644
--- a/src/applications/diffusion/query/DiffusionLintCountQuery.php
+++ b/src/applications/diffusion/query/DiffusionLintCountQuery.php
@@ -1,120 +1,123 @@
<?php
final class DiffusionLintCountQuery extends PhabricatorQuery {
private $branchIDs;
private $paths;
private $codes;
public function withBranchIDs(array $branch_ids) {
$this->branchIDs = $branch_ids;
return $this;
}
public function withPaths(array $paths) {
$this->paths = $paths;
return $this;
}
public function withCodes(array $codes) {
$this->codes = $codes;
return $this;
}
public function execute() {
if (!$this->paths) {
throw new Exception(pht('Call withPaths() before execute()!'));
}
if (!$this->branchIDs) {
throw new Exception(pht('Call withBranchIDs() before execute()!'));
}
$conn_r = id(new PhabricatorRepositoryCommit())->establishConnection('r');
$this->paths = array_unique($this->paths);
list($dirs, $paths) = $this->processPaths();
$parts = array();
foreach ($dirs as $dir) {
$parts[$dir] = qsprintf(
$conn_r,
'path LIKE %>',
$dir);
}
foreach ($paths as $path) {
$parts[$path] = qsprintf(
$conn_r,
'path = %s',
$path);
}
$queries = array();
foreach ($parts as $key => $part) {
$queries[] = qsprintf(
$conn_r,
'SELECT %s path_prefix, COUNT(*) N FROM %T %Q',
$key,
PhabricatorRepository::TABLE_LINTMESSAGE,
- $this->buildWhereClause($conn_r, $part));
+ $this->buildCustomWhereClause($conn_r, $part));
}
$huge_union_query = '('.implode(') UNION ALL (', $queries).')';
$data = queryfx_all(
$conn_r,
'%Q',
$huge_union_query);
return $this->processResults($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r, $part) {
+ protected function buildCustomWhereClause(
+ AphrontDatabaseConnection $conn_r,
+ $part) {
+
$where = array();
$where[] = $part;
if ($this->codes !== null) {
$where[] = qsprintf(
$conn_r,
'code IN (%Ls)',
$this->codes);
}
if ($this->branchIDs !== null) {
$where[] = qsprintf(
$conn_r,
'branchID IN (%Ld)',
$this->branchIDs);
}
return $this->formatWhereClause($where);
}
private function processPaths() {
$dirs = array();
$paths = array();
foreach ($this->paths as $path) {
$path = '/'.$path;
if (substr($path, -1) == '/') {
$dirs[] = $path;
} else {
$paths[] = $path;
}
}
return array($dirs, $paths);
}
private function processResults(array $data) {
$data = ipull($data, 'N', 'path_prefix');
// Strip the leading "/" back off each path.
$output = array();
foreach ($data as $path => $count) {
$output[substr($path, 1)] = $count;
}
return $output;
}
}
diff --git a/src/applications/diffusion/query/DiffusionPathQuery.php b/src/applications/diffusion/query/DiffusionPathQuery.php
index 33e7b57909..f442da7173 100644
--- a/src/applications/diffusion/query/DiffusionPathQuery.php
+++ b/src/applications/diffusion/query/DiffusionPathQuery.php
@@ -1,43 +1,43 @@
<?php
final class DiffusionPathQuery {
private $pathIDs;
public function withPathIDs(array $path_ids) {
$this->pathIDs = $path_ids;
return $this;
}
public function execute() {
$conn_r = id(new PhabricatorRepository())->establishConnection('r');
$where = $this->buildWhereClause($conn_r);
$results = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q',
PhabricatorRepository::TABLE_PATH,
$where);
return ipull($results, null, 'id');
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->pathIDs) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->pathIDs);
}
if ($where) {
return 'WHERE ('.implode(') AND (', $where).')';
} else {
return '';
}
}
}
diff --git a/src/applications/diffusion/query/DiffusionSymbolQuery.php b/src/applications/diffusion/query/DiffusionSymbolQuery.php
index e5cb2b91c4..053f4a222e 100644
--- a/src/applications/diffusion/query/DiffusionSymbolQuery.php
+++ b/src/applications/diffusion/query/DiffusionSymbolQuery.php
@@ -1,299 +1,299 @@
<?php
/**
* Query symbol information (class and function names and location), returning
* a list of matching @{class:PhabricatorRepositorySymbol} objects and possibly
* attached data.
*
* @task config Configuring the Query
* @task exec Executing the Query
* @task internal Internals
*/
final class DiffusionSymbolQuery extends PhabricatorOffsetPagedQuery {
private $viewer;
private $context;
private $namePrefix;
private $name;
private $projectIDs;
private $language;
private $type;
private $needPaths;
private $needArcanistProject;
private $needRepositories;
/* -( Configuring the Query )---------------------------------------------- */
/**
* @task config
*/
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
/**
* @task config
*/
public function getViewer() {
return $this->viewer;
}
/**
* @task config
*/
public function setContext($context) {
$this->context = $context;
return $this;
}
/**
* @task config
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* @task config
*/
public function setNamePrefix($name_prefix) {
$this->namePrefix = $name_prefix;
return $this;
}
/**
* @task config
*/
public function setProjectIDs(array $project_ids) {
$this->projectIDs = $project_ids;
return $this;
}
/**
* @task config
*/
public function setLanguage($language) {
$this->language = $language;
return $this;
}
/**
* @task config
*/
public function setType($type) {
$this->type = $type;
return $this;
}
/**
* @task config
*/
public function needPaths($need_paths) {
$this->needPaths = $need_paths;
return $this;
}
/**
* @task config
*/
public function needArcanistProjects($need_arcanist_projects) {
$this->needArcanistProjects = $need_arcanist_projects;
return $this;
}
/**
* @task config
*/
public function needRepositories($need_repositories) {
$this->needRepositories = $need_repositories;
return $this;
}
/* -( Executing the Query )------------------------------------------------ */
/**
* @task exec
*/
public function execute() {
if ($this->name && $this->namePrefix) {
throw new Exception(
'You can not set both a name and a name prefix!');
} else if (!$this->name && !$this->namePrefix) {
throw new Exception(
'You must set a name or a name prefix!');
}
$symbol = new PhabricatorRepositorySymbol();
$conn_r = $symbol->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$symbol->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$symbols = $symbol->loadAllFromArray($data);
if ($symbols) {
if ($this->needPaths) {
$this->loadPaths($symbols);
}
if ($this->needArcanistProjects || $this->needRepositories) {
$this->loadArcanistProjects($symbols);
}
if ($this->needRepositories) {
$this->loadRepositories($symbols);
}
}
return $symbols;
}
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
private function buildOrderClause($conn_r) {
return qsprintf(
$conn_r,
'ORDER BY symbolName ASC');
}
/**
* @task internal
*/
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if (isset($this->context)) {
$where[] = qsprintf(
$conn_r,
'symbolContext = %s',
$this->context);
}
if ($this->name) {
$where[] = qsprintf(
$conn_r,
'symbolName = %s',
$this->name);
}
if ($this->namePrefix) {
$where[] = qsprintf(
$conn_r,
'symbolName LIKE %>',
$this->namePrefix);
}
if ($this->projectIDs) {
$where[] = qsprintf(
$conn_r,
'arcanistProjectID IN (%Ld)',
$this->projectIDs);
}
if ($this->language) {
$where[] = qsprintf(
$conn_r,
'symbolLanguage = %s',
$this->language);
}
if ($this->type) {
$where[] = qsprintf(
$conn_r,
'symbolType = %s',
$this->type);
}
return $this->formatWhereClause($where);
}
/**
* @task internal
*/
private function loadPaths(array $symbols) {
assert_instances_of($symbols, 'PhabricatorRepositorySymbol');
$path_map = queryfx_all(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE id IN (%Ld)',
PhabricatorRepository::TABLE_PATH,
mpull($symbols, 'getPathID'));
$path_map = ipull($path_map, 'path', 'id');
foreach ($symbols as $symbol) {
$symbol->attachPath(idx($path_map, $symbol->getPathID()));
}
}
/**
* @task internal
*/
private function loadArcanistProjects(array $symbols) {
assert_instances_of($symbols, 'PhabricatorRepositorySymbol');
$projects = id(new PhabricatorRepositoryArcanistProject())->loadAllWhere(
'id IN (%Ld)',
mpull($symbols, 'getArcanistProjectID'));
foreach ($symbols as $symbol) {
$project = idx($projects, $symbol->getArcanistProjectID());
$symbol->attachArcanistProject($project);
}
}
/**
* @task internal
*/
private function loadRepositories(array $symbols) {
assert_instances_of($symbols, 'PhabricatorRepositorySymbol');
$projects = mpull($symbols, 'getArcanistProject');
$projects = array_filter($projects);
$repo_ids = mpull($projects, 'getRepositoryID');
$repo_ids = array_filter($repo_ids);
if ($repo_ids) {
$repos = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIDs($repo_ids)
->execute();
} else {
$repos = array();
}
foreach ($symbols as $symbol) {
$proj = $symbol->getArcanistProject();
if ($proj) {
$symbol->attachRepository(idx($repos, $proj->getRepositoryID()));
} else {
$symbol->attachRepository(null);
}
}
}
}
diff --git a/src/applications/diviner/query/DivinerAtomQuery.php b/src/applications/diviner/query/DivinerAtomQuery.php
index 5b9b8814f7..70759a2cc1 100644
--- a/src/applications/diviner/query/DivinerAtomQuery.php
+++ b/src/applications/diviner/query/DivinerAtomQuery.php
@@ -1,447 +1,447 @@
<?php
final class DivinerAtomQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $bookPHIDs;
private $names;
private $types;
private $contexts;
private $indexes;
private $includeUndocumentable;
private $includeGhosts;
private $nodeHashes;
private $titles;
private $nameContains;
private $needAtoms;
private $needExtends;
private $needChildren;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBookPHIDs(array $phids) {
$this->bookPHIDs = $phids;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withContexts(array $contexts) {
$this->contexts = $contexts;
return $this;
}
public function withIndexes(array $indexes) {
$this->indexes = $indexes;
return $this;
}
public function withNodeHashes(array $hashes) {
$this->nodeHashes = $hashes;
return $this;
}
public function withTitles($titles) {
$this->titles = $titles;
return $this;
}
public function withNameContains($text) {
$this->nameContains = $text;
return $this;
}
public function needAtoms($need) {
$this->needAtoms = $need;
return $this;
}
public function needChildren($need) {
$this->needChildren = $need;
return $this;
}
/**
* Include "ghosts", which are symbols which used to exist but do not exist
* currently (for example, a function which existed in an older version of
* the codebase but was deleted).
*
* These symbols had PHIDs assigned to them, and may have other sorts of
* metadata that we don't want to lose (like comments or flags), so we don't
* delete them outright. They might also come back in the future: the change
* which deleted the symbol might be reverted, or the documentation might
* have been generated incorrectly by accident. In these cases, we can
* restore the original data.
*
* However, most callers are not interested in these symbols, so they are
* excluded by default. You can use this method to include them in results.
*
* @param bool True to include ghosts.
* @return this
*/
public function withIncludeGhosts($include) {
$this->includeGhosts = $include;
return $this;
}
public function needExtends($need) {
$this->needExtends = $need;
return $this;
}
public function withIncludeUndocumentable($include) {
$this->includeUndocumentable = $include;
return $this;
}
protected function loadPage() {
$table = new DivinerLiveSymbol();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $atoms) {
$books = array_unique(mpull($atoms, 'getBookPHID'));
$books = id(new DivinerBookQuery())
->setViewer($this->getViewer())
->withPHIDs($books)
->execute();
$books = mpull($books, null, 'getPHID');
foreach ($atoms as $key => $atom) {
$book = idx($books, $atom->getBookPHID());
if (!$book) {
unset($atoms[$key]);
continue;
}
$atom->attachBook($book);
}
if ($this->needAtoms) {
$atom_data = id(new DivinerLiveAtom())->loadAllWhere(
'symbolPHID IN (%Ls)',
mpull($atoms, 'getPHID'));
$atom_data = mpull($atom_data, null, 'getSymbolPHID');
foreach ($atoms as $key => $atom) {
$data = idx($atom_data, $atom->getPHID());
if (!$data) {
unset($atoms[$key]);
continue;
}
$atom->attachAtom($data);
}
}
// Load all of the symbols this symbol extends, recursively. Commonly,
// this means all the ancestor classes and interfaces it extends and
// implements.
if ($this->needExtends) {
// First, load all the matching symbols by name. This does 99% of the
// work in most cases, assuming things are named at all reasonably.
$names = array();
foreach ($atoms as $atom) {
foreach ($atom->getAtom()->getExtends() as $xref) {
$names[] = $xref->getName();
}
}
if ($names) {
$xatoms = id(new DivinerAtomQuery())
->setViewer($this->getViewer())
->withNames($names)
->needExtends(true)
->needAtoms(true)
->needChildren($this->needChildren)
->execute();
$xatoms = mgroup($xatoms, 'getName', 'getType', 'getBookPHID');
} else {
$xatoms = array();
}
foreach ($atoms as $atom) {
$alang = $atom->getAtom()->getLanguage();
$extends = array();
foreach ($atom->getAtom()->getExtends() as $xref) {
// If there are no symbols of the matching name and type, we can't
// resolve this.
if (empty($xatoms[$xref->getName()][$xref->getType()])) {
continue;
}
// If we found matches in the same documentation book, prefer them
// over other matches. Otherwise, look at all the the matches.
$matches = $xatoms[$xref->getName()][$xref->getType()];
if (isset($matches[$atom->getBookPHID()])) {
$maybe = $matches[$atom->getBookPHID()];
} else {
$maybe = array_mergev($matches);
}
if (!$maybe) {
continue;
}
// Filter out matches in a different language, since, e.g., PHP
// classes can not implement JS classes.
$same_lang = array();
foreach ($maybe as $xatom) {
if ($xatom->getAtom()->getLanguage() == $alang) {
$same_lang[] = $xatom;
}
}
if (!$same_lang) {
continue;
}
// If we have duplicates remaining, just pick the first one. There's
// nothing more we can do to figure out which is the real one.
$extends[] = head($same_lang);
}
$atom->attachExtends($extends);
}
}
if ($this->needChildren) {
$child_hashes = $this->getAllChildHashes($atoms, $this->needExtends);
if ($child_hashes) {
$children = id(new DivinerAtomQuery())
->setViewer($this->getViewer())
->withIncludeUndocumentable(true)
->withNodeHashes($child_hashes)
->needAtoms($this->needAtoms)
->execute();
$children = mpull($children, null, 'getNodeHash');
} else {
$children = array();
}
$this->attachAllChildren($atoms, $children, $this->needExtends);
}
return $atoms;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->bookPHIDs) {
$where[] = qsprintf(
$conn_r,
'bookPHID IN (%Ls)',
$this->bookPHIDs);
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'type IN (%Ls)',
$this->types);
}
if ($this->names) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
if ($this->titles) {
$hashes = array();
foreach ($this->titles as $title) {
$slug = DivinerAtomRef::normalizeTitleString($title);
$hash = PhabricatorHash::digestForIndex($slug);
$hashes[] = $hash;
}
$where[] = qsprintf(
$conn_r,
'titleSlugHash in (%Ls)',
$hashes);
}
if ($this->contexts) {
$with_null = false;
$contexts = $this->contexts;
foreach ($contexts as $key => $value) {
if ($value === null) {
unset($contexts[$key]);
$with_null = true;
continue;
}
}
if ($contexts && $with_null) {
$where[] = qsprintf(
$conn_r,
'context IN (%Ls) OR context IS NULL',
$contexts);
} else if ($contexts) {
$where[] = qsprintf(
$conn_r,
'context IN (%Ls)',
$contexts);
} else if ($with_null) {
$where[] = qsprintf(
$conn_r,
'context IS NULL');
}
}
if ($this->indexes) {
$where[] = qsprintf(
$conn_r,
'atomIndex IN (%Ld)',
$this->indexes);
}
if (!$this->includeUndocumentable) {
$where[] = qsprintf(
$conn_r,
'isDocumentable = 1');
}
if (!$this->includeGhosts) {
$where[] = qsprintf(
$conn_r,
'graphHash IS NOT NULL');
}
if ($this->nodeHashes) {
$where[] = qsprintf(
$conn_r,
'nodeHash IN (%Ls)',
$this->nodeHashes);
}
if ($this->nameContains) {
// NOTE: This CONVERT() call makes queries case-insensitive, since the
// column has binary collation. Eventually, this should move into
// fulltext.
$where[] = qsprintf(
$conn_r,
'CONVERT(name USING utf8) LIKE %~',
$this->nameContains);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
/**
* Walk a list of atoms and collect all the node hashes of the atoms'
* children. When recursing, also walk up the tree and collect children of
* atoms they extend.
*
* @param list<DivinerLiveSymbol> List of symbols to collect child hashes of.
* @param bool True to collect children of extended atoms,
* as well.
* @return map<string, string> Hashes of atoms' children.
*/
private function getAllChildHashes(array $symbols, $recurse_up) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
$hashes = array();
foreach ($symbols as $symbol) {
foreach ($symbol->getAtom()->getChildHashes() as $hash) {
$hashes[$hash] = $hash;
}
if ($recurse_up) {
$hashes += $this->getAllChildHashes($symbol->getExtends(), true);
}
}
return $hashes;
}
/**
* Attach child atoms to existing atoms. In recursive mode, also attach child
* atoms to atoms that these atoms extend.
*
* @param list<DivinerLiveSymbol> List of symbols to attach children to.
* @param map<string, DivinerLiveSymbol> Map of symbols, keyed by node hash.
* @param bool True to attach children to extended atoms, as well.
* @return void
*/
private function attachAllChildren(
array $symbols,
array $children,
$recurse_up) {
assert_instances_of($symbols, 'DivinerLiveSymbol');
assert_instances_of($children, 'DivinerLiveSymbol');
foreach ($symbols as $symbol) {
$symbol_children = array();
foreach ($symbol->getAtom()->getChildHashes() as $hash) {
if (isset($children[$hash])) {
$symbol_children[] = $children[$hash];
}
}
$symbol->attachChildren($symbol_children);
if ($recurse_up) {
$this->attachAllChildren($symbol->getExtends(), $children, true);
}
}
}
public function getQueryApplicationClass() {
return 'PhabricatorDivinerApplication';
}
}
diff --git a/src/applications/diviner/query/DivinerBookQuery.php b/src/applications/diviner/query/DivinerBookQuery.php
index 31e6f336a9..90fed52a23 100644
--- a/src/applications/diviner/query/DivinerBookQuery.php
+++ b/src/applications/diviner/query/DivinerBookQuery.php
@@ -1,72 +1,72 @@
<?php
final class DivinerBookQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
protected function loadPage() {
$table = new DivinerLiveBook();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->names) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDivinerApplication';
}
}
diff --git a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
index 75ace905da..770678a687 100644
--- a/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
+++ b/src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
@@ -1,59 +1,59 @@
<?php
final class DoorkeeperExternalObjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
protected $phids;
protected $objectKeys;
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectKeys(array $keys) {
$this->objectKeys = $keys;
return $this;
}
protected function loadPage() {
$table = new DoorkeeperExternalObject();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->objectKeys) {
$where[] = qsprintf(
$conn_r,
'objectKey IN (%Ls)',
$this->objectKeys);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDoorkeeperApplication';
}
}
diff --git a/src/applications/drydock/query/DrydockBlueprintQuery.php b/src/applications/drydock/query/DrydockBlueprintQuery.php
index 4afdb582c2..b698855bcf 100644
--- a/src/applications/drydock/query/DrydockBlueprintQuery.php
+++ b/src/applications/drydock/query/DrydockBlueprintQuery.php
@@ -1,65 +1,65 @@
<?php
final class DrydockBlueprintQuery extends DrydockQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new DrydockBlueprint();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT blueprint.* FROM %T blueprint %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$blueprints = $table->loadAllFromArray($data);
$implementations =
DrydockBlueprintImplementation::getAllBlueprintImplementations();
foreach ($blueprints as $blueprint) {
if (array_key_exists($blueprint->getClassName(), $implementations)) {
$blueprint->attachImplementation(
$implementations[$blueprint->getClassName()]);
}
}
return $blueprints;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/drydock/query/DrydockLeaseQuery.php b/src/applications/drydock/query/DrydockLeaseQuery.php
index 028351bdae..d5d62f950e 100644
--- a/src/applications/drydock/query/DrydockLeaseQuery.php
+++ b/src/applications/drydock/query/DrydockLeaseQuery.php
@@ -1,108 +1,108 @@
<?php
final class DrydockLeaseQuery extends DrydockQuery {
private $ids;
private $phids;
private $resourceIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withResourceIDs(array $ids) {
$this->resourceIDs = $ids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
protected function loadPage() {
$table = new DrydockLease();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT lease.* FROM %T lease %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $leases) {
$resource_ids = array_filter(mpull($leases, 'getResourceID'));
if ($resource_ids) {
$resources = id(new DrydockResourceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withIDs($resource_ids)
->execute();
} else {
$resources = array();
}
foreach ($leases as $key => $lease) {
$resource = null;
if ($lease->getResourceID()) {
$resource = idx($resources, $lease->getResourceID());
if (!$resource) {
unset($leases[$key]);
continue;
}
}
$lease->attachResource($resource);
}
return $leases;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->resourceIDs) {
$where[] = qsprintf(
$conn_r,
'resourceID IN (%Ld)',
$this->resourceIDs);
}
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->statuses) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/drydock/query/DrydockLogQuery.php b/src/applications/drydock/query/DrydockLogQuery.php
index 83413d79c0..1e21864f10 100644
--- a/src/applications/drydock/query/DrydockLogQuery.php
+++ b/src/applications/drydock/query/DrydockLogQuery.php
@@ -1,113 +1,113 @@
<?php
final class DrydockLogQuery extends DrydockQuery {
private $resourceIDs;
private $leaseIDs;
public function withResourceIDs(array $ids) {
$this->resourceIDs = $ids;
return $this;
}
public function withLeaseIDs(array $ids) {
$this->leaseIDs = $ids;
return $this;
}
protected function loadPage() {
$table = new DrydockLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT log.* FROM %T log %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $logs) {
$resource_ids = array_filter(mpull($logs, 'getResourceID'));
if ($resource_ids) {
$resources = id(new DrydockResourceQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withIDs($resource_ids)
->execute();
} else {
$resources = array();
}
foreach ($logs as $key => $log) {
$resource = null;
if ($log->getResourceID()) {
$resource = idx($resources, $log->getResourceID());
if (!$resource) {
unset($logs[$key]);
continue;
}
}
$log->attachResource($resource);
}
$lease_ids = array_filter(mpull($logs, 'getLeaseID'));
if ($lease_ids) {
$leases = id(new DrydockLeaseQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withIDs($lease_ids)
->execute();
} else {
$leases = array();
}
foreach ($logs as $key => $log) {
$lease = null;
if ($log->getLeaseID()) {
$lease = idx($leases, $log->getLeaseID());
if (!$lease) {
unset($logs[$key]);
continue;
}
}
$log->attachLease($lease);
}
// These logs are meaningless and their policies aren't computable. They
// shouldn't exist, but throw them away if they do.
foreach ($logs as $key => $log) {
if (!$log->getResource() && !$log->getLease()) {
unset($logs[$key]);
}
}
return $logs;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->resourceIDs) {
$where[] = qsprintf(
$conn_r,
'resourceID IN (%Ld)',
$this->resourceIDs);
}
if ($this->leaseIDs) {
$where[] = qsprintf(
$conn_r,
'leaseID IN (%Ld)',
$this->leaseIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/drydock/query/DrydockResourceQuery.php b/src/applications/drydock/query/DrydockResourceQuery.php
index 468af91db4..af84fefa4a 100644
--- a/src/applications/drydock/query/DrydockResourceQuery.php
+++ b/src/applications/drydock/query/DrydockResourceQuery.php
@@ -1,96 +1,96 @@
<?php
final class DrydockResourceQuery extends DrydockQuery {
private $ids;
private $phids;
private $statuses;
private $types;
private $blueprintPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withBlueprintPHIDs(array $blueprint_phids) {
$this->blueprintPHIDs = $blueprint_phids;
return $this;
}
protected function loadPage() {
$table = new DrydockResource();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT resource.* FROM %T resource %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$resources = $table->loadAllFromArray($data);
return $resources;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'type IN (%Ls)',
$this->types);
}
if ($this->statuses) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ls)',
$this->statuses);
}
if ($this->blueprintPHIDs) {
$where[] = qsprintf(
$conn_r,
'blueprintPHID IN (%Ls)',
$this->blueprintPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/feed/query/PhabricatorFeedQuery.php b/src/applications/feed/query/PhabricatorFeedQuery.php
index 5f3efe5aaf..424658b342 100644
--- a/src/applications/feed/query/PhabricatorFeedQuery.php
+++ b/src/applications/feed/query/PhabricatorFeedQuery.php
@@ -1,126 +1,126 @@
<?php
final class PhabricatorFeedQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $filterPHIDs;
private $chronologicalKeys;
public function setFilterPHIDs(array $phids) {
$this->filterPHIDs = $phids;
return $this;
}
public function withChronologicalKeys(array $keys) {
$this->chronologicalKeys = $keys;
return $this;
}
protected function loadPage() {
$story_table = new PhabricatorFeedStoryData();
$conn = $story_table->establishConnection('r');
$data = queryfx_all(
$conn,
'SELECT story.* FROM %T story %Q %Q %Q %Q %Q',
$story_table->getTableName(),
$this->buildJoinClause($conn),
$this->buildWhereClause($conn),
$this->buildGroupClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $data;
}
protected function willFilterPage(array $data) {
return PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer());
}
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
// 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();
return qsprintf(
$conn_r,
'JOIN %T ref ON ref.chronologicalKey = story.chronologicalKey',
$ref_table->getTableName());
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->filterPHIDs) {
$where[] = qsprintf(
$conn_r,
'ref.objectPHID IN (%Ls)',
$this->filterPHIDs);
}
if ($this->chronologicalKeys) {
// NOTE: We want to use integers in the query so we can take advantage
// of keys, but can't use %d on 32-bit systems. Make sure all the keys
// are integers and then format them raw.
$keys = $this->chronologicalKeys;
foreach ($keys as $key) {
if (!ctype_digit($key)) {
throw new Exception("Key '{$key}' is not a valid chronological key!");
}
}
$where[] = qsprintf(
$conn_r,
'ref.chronologicalKey IN (%Q)',
implode(', ', $keys));
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function buildGroupClause(AphrontDatabaseConnection $conn_r) {
if ($this->filterPHIDs) {
return qsprintf($conn_r, 'GROUP BY ref.chronologicalKey');
} else {
return qsprintf($conn_r, 'GROUP BY story.chronologicalKey');
}
}
protected function getDefaultOrderVector() {
return array('key');
}
public function getOrderableColumns() {
$table = ($this->filterPHIDs ? 'ref' : 'story');
return array(
'key' => array(
'table' => $table,
'column' => 'chronologicalKey',
'type' => 'int',
'unique' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
return array(
'key' => $cursor,
);
}
protected function getResultCursor($item) {
if ($item instanceof PhabricatorFeedStory) {
return $item->getChronologicalKey();
}
return $item['chronologicalKey'];
}
public function getQueryApplicationClass() {
return 'PhabricatorFeedApplication';
}
}
diff --git a/src/applications/files/query/PhabricatorFileChunkQuery.php b/src/applications/files/query/PhabricatorFileChunkQuery.php
index 7c2a961fd0..b6fda13103 100644
--- a/src/applications/files/query/PhabricatorFileChunkQuery.php
+++ b/src/applications/files/query/PhabricatorFileChunkQuery.php
@@ -1,134 +1,134 @@
<?php
final class PhabricatorFileChunkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $chunkHandles;
private $rangeStart;
private $rangeEnd;
private $isComplete;
private $needDataFiles;
public function withChunkHandles(array $handles) {
$this->chunkHandles = $handles;
return $this;
}
public function withByteRange($start, $end) {
$this->rangeStart = $start;
$this->rangeEnd = $end;
return $this;
}
public function withIsComplete($complete) {
$this->isComplete = $complete;
return $this;
}
public function needDataFiles($need) {
$this->needDataFiles = $need;
return $this;
}
protected function loadPage() {
$table = new PhabricatorFileChunk();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $chunks) {
if ($this->needDataFiles) {
$file_phids = mpull($chunks, 'getDataFilePHID');
$file_phids = array_filter($file_phids);
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($chunks as $key => $chunk) {
$data_phid = $chunk->getDataFilePHID();
if (!$data_phid) {
$chunk->attachDataFile(null);
continue;
}
$file = idx($files, $data_phid);
if (!$file) {
unset($chunks[$key]);
$this->didRejectResult($chunk);
continue;
}
$chunk->attachDataFile($file);
}
if (!$chunks) {
return $chunks;
}
}
return $chunks;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->chunkHandles !== null) {
$where[] = qsprintf(
$conn_r,
'chunkHandle IN (%Ls)',
$this->chunkHandles);
}
if ($this->rangeStart !== null) {
$where[] = qsprintf(
$conn_r,
'byteEnd > %d',
$this->rangeStart);
}
if ($this->rangeEnd !== null) {
$where[] = qsprintf(
$conn_r,
'byteStart < %d',
$this->rangeEnd);
}
if ($this->isComplete !== null) {
if ($this->isComplete) {
$where[] = qsprintf(
$conn_r,
'dataFilePHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn_r,
'dataFilePHID IS NULL');
}
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorFilesApplication';
}
}
diff --git a/src/applications/files/query/PhabricatorFileQuery.php b/src/applications/files/query/PhabricatorFileQuery.php
index ad0bbbac1b..a15be0c0bb 100644
--- a/src/applications/files/query/PhabricatorFileQuery.php
+++ b/src/applications/files/query/PhabricatorFileQuery.php
@@ -1,342 +1,342 @@
<?php
final class PhabricatorFileQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $explicitUploads;
private $transforms;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $contentHashes;
private $minLength;
private $maxLength;
private $names;
private $isPartial;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withContentHashes(array $content_hashes) {
$this->contentHashes = $content_hashes;
return $this;
}
/**
* Select files which are transformations of some other file. For example,
* you can use this query to find previously generated thumbnails of an image
* file.
*
* As a parameter, provide a list of transformation specifications. Each
* specification is a dictionary with the keys `originalPHID` and `transform`.
* The `originalPHID` is the PHID of the original file (the file which was
* transformed) and the `transform` is the name of the transform to query
* for. If you pass `true` as the `transform`, all transformations of the
* file will be selected.
*
* For example:
*
* array(
* array(
* 'originalPHID' => 'PHID-FILE-aaaa',
* 'transform' => 'sepia',
* ),
* array(
* 'originalPHID' => 'PHID-FILE-bbbb',
* 'transform' => true,
* ),
* )
*
* This selects the `"sepia"` transformation of the file with PHID
* `PHID-FILE-aaaa` and all transformations of the file with PHID
* `PHID-FILE-bbbb`.
*
* @param list<dict> List of transform specifications, described above.
* @return this
*/
public function withTransforms(array $specs) {
foreach ($specs as $spec) {
if (!is_array($spec) ||
empty($spec['originalPHID']) ||
empty($spec['transform'])) {
throw new Exception(
"Transform specification must be a dictionary with keys ".
"'originalPHID' and 'transform'!");
}
}
$this->transforms = $specs;
return $this;
}
public function withLengthBetween($min, $max) {
$this->minLength = $min;
$this->maxLength = $max;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withIsPartial($partial) {
$this->isPartial = $partial;
return $this;
}
public function showOnlyExplicitUploads($explicit_uploads) {
$this->explicitUploads = $explicit_uploads;
return $this;
}
protected function loadPage() {
$table = new PhabricatorFile();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT f.* FROM %T f %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$files = $table->loadAllFromArray($data);
if (!$files) {
return $files;
}
// We need to load attached objects to perform policy checks for files.
// First, load the edges.
$edge_type = PhabricatorFileHasObjectEdgeType::EDGECONST;
$file_phids = mpull($files, 'getPHID');
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($file_phids)
->withEdgeTypes(array($edge_type))
->execute();
$object_phids = array();
foreach ($files as $file) {
$phids = array_keys($edges[$file->getPHID()][$edge_type]);
$file->attachObjectPHIDs($phids);
foreach ($phids as $phid) {
$object_phids[$phid] = true;
}
}
// If this file is a transform of another file, load that file too. If you
// can see the original file, you can see the thumbnail.
// TODO: It might be nice to put this directly on PhabricatorFile and remove
// the PhabricatorTransformedFile table, which would be a little simpler.
$xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
'transformedPHID IN (%Ls)',
$file_phids);
$xform_phids = mpull($xforms, 'getOriginalPHID', 'getTransformedPHID');
foreach ($xform_phids as $derived_phid => $original_phid) {
$object_phids[$original_phid] = true;
}
$object_phids = array_keys($object_phids);
// Now, load the objects.
$objects = array();
if ($object_phids) {
// NOTE: We're explicitly turning policy exceptions off, since the rule
// here is "you can see the file if you can see ANY associated object".
// Without this explicit flag, we'll incorrectly throw unless you can
// see ALL associated objects.
$objects = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($object_phids)
->setRaisePolicyExceptions(false)
->execute();
$objects = mpull($objects, null, 'getPHID');
}
foreach ($files as $file) {
$file_objects = array_select_keys($objects, $file->getObjectPHIDs());
$file->attachObjects($file_objects);
}
foreach ($files as $key => $file) {
$original_phid = idx($xform_phids, $file->getPHID());
if ($original_phid == PhabricatorPHIDConstants::PHID_VOID) {
// This is a special case for builtin files, which are handled
// oddly.
$original = null;
} else if ($original_phid) {
$original = idx($objects, $original_phid);
if (!$original) {
// If the viewer can't see the original file, also prevent them from
// seeing the transformed file.
$this->didRejectResult($file);
unset($files[$key]);
continue;
}
} else {
$original = null;
}
$file->attachOriginalFile($original);
}
return $files;
}
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if ($this->transforms) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T t ON t.transformedPHID = f.phid',
id(new PhabricatorTransformedFile())->getTableName());
}
return implode(' ', $joins);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'f.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'f.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'f.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->explicitUploads !== null) {
$where[] = qsprintf(
$conn_r,
'f.isExplicitUpload = true');
}
if ($this->transforms !== null) {
$clauses = array();
foreach ($this->transforms as $transform) {
if ($transform['transform'] === true) {
$clauses[] = qsprintf(
$conn_r,
'(t.originalPHID = %s)',
$transform['originalPHID']);
} else {
$clauses[] = qsprintf(
$conn_r,
'(t.originalPHID = %s AND t.transform = %s)',
$transform['originalPHID'],
$transform['transform']);
}
}
$where[] = qsprintf($conn_r, '(%Q)', implode(') OR (', $clauses));
}
if ($this->dateCreatedAfter !== null) {
$where[] = qsprintf(
$conn_r,
'f.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore !== null) {
$where[] = qsprintf(
$conn_r,
'f.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->contentHashes !== null) {
$where[] = qsprintf(
$conn_r,
'f.contentHash IN (%Ls)',
$this->contentHashes);
}
if ($this->minLength !== null) {
$where[] = qsprintf(
$conn_r,
'byteSize >= %d',
$this->minLength);
}
if ($this->maxLength !== null) {
$where[] = qsprintf(
$conn_r,
'byteSize <= %d',
$this->maxLength);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn_r,
'name in (%Ls)',
$this->names);
}
if ($this->isPartial !== null) {
$where[] = qsprintf(
$conn_r,
'isPartial = %d',
(int)$this->isPartial);
}
return $this->formatWhereClause($where);
}
protected function getPrimaryTableAlias() {
return 'f';
}
public function getQueryApplicationClass() {
return 'PhabricatorFilesApplication';
}
}
diff --git a/src/applications/flag/query/PhabricatorFlagQuery.php b/src/applications/flag/query/PhabricatorFlagQuery.php
index 910ed7dfa9..0b1902f6f1 100644
--- a/src/applications/flag/query/PhabricatorFlagQuery.php
+++ b/src/applications/flag/query/PhabricatorFlagQuery.php
@@ -1,165 +1,165 @@
<?php
final class PhabricatorFlagQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const GROUP_COLOR = 'color';
const GROUP_NONE = 'none';
private $ownerPHIDs;
private $types;
private $objectPHIDs;
private $colors;
private $groupBy = self::GROUP_NONE;
private $needHandles;
private $needObjects;
public function withOwnerPHIDs(array $owner_phids) {
$this->ownerPHIDs = $owner_phids;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withColors(array $colors) {
$this->colors = $colors;
return $this;
}
/**
* NOTE: this is done in PHP and not in MySQL, which means its inappropriate
* for large datasets. Pragmatically, this is fine for user flags which are
* typically well under 100 flags per user.
*/
public function setGroupBy($group) {
$this->groupBy = $group;
return $this;
}
public function needHandles($need) {
$this->needHandles = $need;
return $this;
}
public function needObjects($need) {
$this->needObjects = $need;
return $this;
}
public static function loadUserFlag(PhabricatorUser $user, $object_phid) {
// Specifying the type in the query allows us to use a key.
return id(new PhabricatorFlagQuery())
->setViewer($user)
->withOwnerPHIDs(array($user->getPHID()))
->withTypes(array(phid_get_type($object_phid)))
->withObjectPHIDs(array($object_phid))
->executeOne();
}
protected function loadPage() {
$table = new PhabricatorFlag();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T flag %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $flags) {
if ($this->needObjects) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($flags, 'getObjectPHID'))
->execute();
$objects = mpull($objects, null, 'getPHID');
foreach ($flags as $key => $flag) {
$object = idx($objects, $flag->getObjectPHID());
if ($object) {
$flags[$key]->attachObject($object);
} else {
unset($flags[$key]);
}
}
}
if ($this->needHandles) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($flags, 'getObjectPHID'))
->execute();
foreach ($flags as $flag) {
$flag->attachHandle($handles[$flag->getObjectPHID()]);
}
}
switch ($this->groupBy) {
case self::GROUP_COLOR:
$flags = msort($flags, 'getColor');
break;
case self::GROUP_NONE:
break;
default:
throw new Exception("Unknown groupBy parameter: $this->groupBy");
break;
}
return $flags;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ownerPHIDs) {
$where[] = qsprintf(
$conn_r,
'flag.ownerPHID IN (%Ls)',
$this->ownerPHIDs);
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'flag.type IN (%Ls)',
$this->types);
}
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn_r,
'flag.objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->colors) {
$where[] = qsprintf(
$conn_r,
'flag.color IN (%Ld)',
$this->colors);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorFlagsApplication';
}
}
diff --git a/src/applications/fund/query/FundBackerQuery.php b/src/applications/fund/query/FundBackerQuery.php
index 505de2bdf3..5f7406f5ad 100644
--- a/src/applications/fund/query/FundBackerQuery.php
+++ b/src/applications/fund/query/FundBackerQuery.php
@@ -1,118 +1,118 @@
<?php
final class FundBackerQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $initiativePHIDs;
private $backerPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withInitiativePHIDs(array $phids) {
$this->initiativePHIDs = $phids;
return $this;
}
public function withBackerPHIDs(array $phids) {
$this->backerPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new FundBacker();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $backers) {
$initiative_phids = mpull($backers, 'getInitiativePHID');
$initiatives = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($initiative_phids)
->execute();
$initiatives = mpull($initiatives, null, 'getPHID');
foreach ($backers as $backer) {
$initiative_phid = $backer->getInitiativePHID();
$initiative = idx($initiatives, $initiative_phid);
$backer->attachInitiative($initiative);
}
return $backers;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->initiativePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'initiativePHID IN (%Ls)',
$this->initiativePHIDs);
}
if ($this->backerPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'backerPHID IN (%Ls)',
$this->backerPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorFundApplication';
}
}
diff --git a/src/applications/fund/query/FundInitiativeQuery.php b/src/applications/fund/query/FundInitiativeQuery.php
index 8fd910c046..66f87a883c 100644
--- a/src/applications/fund/query/FundInitiativeQuery.php
+++ b/src/applications/fund/query/FundInitiativeQuery.php
@@ -1,116 +1,116 @@
<?php
final class FundInitiativeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $ownerPHIDs;
private $statuses;
private $needProjectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withOwnerPHIDs(array $phids) {
$this->ownerPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needProjectPHIDs($need) {
$this->needProjectPHIDs = $need;
return $this;
}
protected function loadPage() {
$table = new FundInitiative();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
protected function didFilterPage(array $initiatives) {
if ($this->needProjectPHIDs) {
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($initiatives, 'getPHID'))
->withEdgeTypes(
array(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
));
$edge_query->execute();
foreach ($initiatives as $initiative) {
$phids = $edge_query->getDestinationPHIDs(
array(
$initiative->getPHID(),
));
$initiative->attachProjectPHIDs($phids);
}
}
return $initiatives;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->ownerPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'ownerPHID IN (%Ls)',
$this->ownerPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorFundApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
index 077e77a4bd..553780aa76 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildArtifactQuery.php
@@ -1,124 +1,124 @@
<?php
final class HarbormasterBuildArtifactQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $buildTargetPHIDs;
private $artifactTypes;
private $artifactKeys;
private $keyBuildPHID;
private $keyBuildGeneration;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
public function withArtifactTypes(array $artifact_types) {
$this->artifactTypes = $artifact_types;
return $this;
}
public function withArtifactKeys(
$build_phid,
$build_gen,
array $artifact_keys) {
$this->keyBuildPHID = $build_phid;
$this->keyBuildGeneration = $build_gen;
$this->artifactKeys = $artifact_keys;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildArtifact();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$build_targets = array();
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $build_log) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->buildTargetPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
if ($this->artifactTypes) {
$where[] = qsprintf(
$conn_r,
'artifactType in (%Ls)',
$this->artifactTypes);
}
if ($this->artifactKeys) {
$indexes = array();
foreach ($this->artifactKeys as $key) {
$indexes[] = PhabricatorHash::digestForIndex(
$this->keyBuildPHID.$this->keyBuildGeneration.$key);
}
$where[] = qsprintf(
$conn_r,
'artifactIndex IN (%Ls)',
$indexes);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildItemQuery.php b/src/applications/harbormaster/query/HarbormasterBuildItemQuery.php
index 2c82588940..1c54cf1fa7 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildItemQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildItemQuery.php
@@ -1,60 +1,60 @@
<?php
final class HarbormasterBuildItemQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildItem();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid in (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
index 461697a1e4..f0f2021fd8 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildLogQuery.php
@@ -1,98 +1,98 @@
<?php
final class HarbormasterBuildLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildTargetPHIDs(array $build_target_phids) {
$this->buildTargetPHIDs = $build_target_phids;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$build_targets = array();
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
}
foreach ($page as $key => $build_log) {
$build_target_phid = $build_log->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$build_log->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->buildTargetPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
index 816bafc1ad..749fdd76d4 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildMessageQuery.php
@@ -1,98 +1,98 @@
<?php
final class HarbormasterBuildMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $buildTargetPHIDs;
private $consumed;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withBuildTargetPHIDs(array $phids) {
$this->buildTargetPHIDs = $phids;
return $this;
}
public function withConsumed($consumed) {
$this->consumed = $consumed;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildMessage();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$build_target_phids = array_filter(mpull($page, 'getBuildTargetPHID'));
if ($build_target_phids) {
$build_targets = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($build_target_phids)
->setParentQuery($this)
->execute();
$build_targets = mpull($build_targets, null, 'getPHID');
} else {
$build_targets = array();
}
foreach ($page as $key => $message) {
$build_target_phid = $message->getBuildTargetPHID();
if (empty($build_targets[$build_target_phid])) {
unset($page[$key]);
continue;
}
$message->attachBuildTarget($build_targets[$build_target_phid]);
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->buildTargetPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildTargetPHID IN (%Ls)',
$this->buildTargetPHIDs);
}
if ($this->consumed !== null) {
$where[] = qsprintf(
$conn_r,
'isConsumed = %d',
(int)$this->consumed);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
index 8ea76ba36f..4123941665 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildPlanQuery.php
@@ -1,113 +1,113 @@
<?php
final class HarbormasterBuildPlanQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $statuses;
private $datasourceQuery;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildPlan();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->statuses) {
$where[] = qsprintf(
$conn_r,
'planStatus IN (%Ls)',
$this->statuses);
}
if (strlen($this->datasourceQuery)) {
$where[] = qsprintf(
$conn_r,
'name LIKE %>',
$this->datasourceQuery);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'column' => 'name',
'type' => 'string',
'reverse' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$plan = $this->loadCursorObject($cursor);
return array(
'id' => $plan->getID(),
'name' => $plan->getName(),
);
}
public function getBuiltinOrders() {
return array(
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Name'),
),
) + parent::getBuiltinOrders();
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildQuery.php b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
index 0daf5ac906..d0b1e7420c 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildQuery.php
@@ -1,186 +1,186 @@
<?php
final class HarbormasterBuildQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildStatuses;
private $buildablePHIDs;
private $buildPlanPHIDs;
private $needBuildTargets;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildStatuses(array $build_statuses) {
$this->buildStatuses = $build_statuses;
return $this;
}
public function withBuildablePHIDs(array $buildable_phids) {
$this->buildablePHIDs = $buildable_phids;
return $this;
}
public function withBuildPlanPHIDs(array $build_plan_phids) {
$this->buildPlanPHIDs = $build_plan_phids;
return $this;
}
public function needBuildTargets($need_targets) {
$this->needBuildTargets = $need_targets;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuild();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$buildables = array();
$buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($buildable_phids) {
$buildables = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildable_phids)
->setParentQuery($this)
->execute();
$buildables = mpull($buildables, null, 'getPHID');
}
foreach ($page as $key => $build) {
$buildable_phid = $build->getBuildablePHID();
if (empty($buildables[$buildable_phid])) {
unset($page[$key]);
continue;
}
$build->attachBuildable($buildables[$buildable_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
$plans = array();
$plan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
if ($plan_phids) {
$plans = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($plan_phids)
->setParentQuery($this)
->execute();
$plans = mpull($plans, null, 'getPHID');
}
foreach ($page as $key => $build) {
$plan_phid = $build->getBuildPlanPHID();
$build->attachBuildPlan(idx($plans, $plan_phid));
}
$build_phids = mpull($page, 'getPHID');
$commands = id(new HarbormasterBuildCommand())->loadAllWhere(
'targetPHID IN (%Ls) ORDER BY id ASC',
$build_phids);
$commands = mgroup($commands, 'getTargetPHID');
foreach ($page as $build) {
$unprocessed_commands = idx($commands, $build->getPHID(), array());
$build->attachUnprocessedCommands($unprocessed_commands);
}
if ($this->needBuildTargets) {
$targets = id(new HarbormasterBuildTargetQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withBuildPHIDs($build_phids)
->execute();
// TODO: Some day, when targets have dependencies, we should toposort
// these. For now, just put them into chronological order.
$targets = array_reverse($targets);
$targets = mgroup($targets, 'getBuildPHID');
foreach ($page as $build) {
$build_targets = idx($targets, $build->getPHID(), array());
foreach ($build_targets as $phid => $target) {
if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {
unset($build_targets[$phid]);
}
}
$build->attachBuildTargets($build_targets);
}
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid in (%Ls)',
$this->phids);
}
if ($this->buildStatuses !== null) {
$where[] = qsprintf(
$conn_r,
'buildStatus in (%Ls)',
$this->buildStatuses);
}
if ($this->buildablePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'buildablePHID IN (%Ls)',
$this->buildablePHIDs);
}
if ($this->buildPlanPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'buildPlanPHID IN (%Ls)',
$this->buildPlanPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
index bea3ec10f0..c14185116c 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildStepQuery.php
@@ -1,98 +1,98 @@
<?php
final class HarbormasterBuildStepQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPlanPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildPlanPHIDs(array $phids) {
$this->buildPlanPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildStep();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid in (%Ls)',
$this->phids);
}
if ($this->buildPlanPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildPlanPHID in (%Ls)',
$this->buildPlanPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $page) {
$plans = array();
$buildplan_phids = array_filter(mpull($page, 'getBuildPlanPHID'));
if ($buildplan_phids) {
$plans = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildplan_phids)
->setParentQuery($this)
->execute();
$plans = mpull($plans, null, 'getPHID');
}
foreach ($page as $key => $build) {
$buildable_phid = $build->getBuildPlanPHID();
if (empty($plans[$buildable_phid])) {
unset($page[$key]);
continue;
}
$build->attachBuildPlan($plans[$buildable_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
index 213a6a4a20..c61c0bd8b0 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildTargetQuery.php
@@ -1,142 +1,142 @@
<?php
final class HarbormasterBuildTargetQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildPHIDs;
private $buildGenerations;
private $needBuildSteps;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildPHIDs(array $build_phids) {
$this->buildPHIDs = $build_phids;
return $this;
}
public function withBuildGenerations(array $build_generations) {
$this->buildGenerations = $build_generations;
return $this;
}
public function needBuildSteps($need_build_steps) {
$this->needBuildSteps = $need_build_steps;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildTarget();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid in (%Ls)',
$this->phids);
}
if ($this->buildPHIDs) {
$where[] = qsprintf(
$conn_r,
'buildPHID in (%Ls)',
$this->buildPHIDs);
}
if ($this->buildGenerations) {
$where[] = qsprintf(
$conn_r,
'buildGeneration in (%Ld)',
$this->buildGenerations);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function didFilterPage(array $page) {
if ($this->needBuildSteps) {
$step_phids = array();
foreach ($page as $target) {
$step_phids[] = $target->getBuildStepPHID();
}
$steps = id(new HarbormasterBuildStepQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($step_phids)
->execute();
$steps = mpull($steps, null, 'getPHID');
foreach ($page as $target) {
$target->attachBuildStep(
idx($steps, $target->getBuildStepPHID()));
}
}
return $page;
}
protected function willFilterPage(array $page) {
$builds = array();
$build_phids = array_filter(mpull($page, 'getBuildPHID'));
if ($build_phids) {
$builds = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($build_phids)
->setParentQuery($this)
->execute();
$builds = mpull($builds, null, 'getPHID');
}
foreach ($page as $key => $build_target) {
$build_phid = $build_target->getBuildPHID();
if (empty($builds[$build_phid])) {
unset($page[$key]);
continue;
}
$build_target->attachBuild($builds[$build_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
index 5b5972fa2f..1b1956a0c7 100644
--- a/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
+++ b/src/applications/harbormaster/query/HarbormasterBuildableQuery.php
@@ -1,222 +1,222 @@
<?php
final class HarbormasterBuildableQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $buildablePHIDs;
private $containerPHIDs;
private $manualBuildables;
private $needContainerObjects;
private $needContainerHandles;
private $needBuildableHandles;
private $needBuilds;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBuildablePHIDs(array $buildable_phids) {
$this->buildablePHIDs = $buildable_phids;
return $this;
}
public function withContainerPHIDs(array $container_phids) {
$this->containerPHIDs = $container_phids;
return $this;
}
public function withManualBuildables($manual) {
$this->manualBuildables = $manual;
return $this;
}
public function needContainerObjects($need) {
$this->needContainerObjects = $need;
return $this;
}
public function needContainerHandles($need) {
$this->needContainerHandles = $need;
return $this;
}
public function needBuildableHandles($need) {
$this->needBuildableHandles = $need;
return $this;
}
public function needBuilds($need) {
$this->needBuilds = $need;
return $this;
}
protected function loadPage() {
$table = new HarbormasterBuildable();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$buildables = array();
$buildable_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($buildable_phids) {
$buildables = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($buildable_phids)
->setParentQuery($this)
->execute();
$buildables = mpull($buildables, null, 'getPHID');
}
foreach ($page as $key => $buildable) {
$buildable_phid = $buildable->getBuildablePHID();
if (empty($buildables[$buildable_phid])) {
unset($page[$key]);
continue;
}
$buildable->attachBuildableObject($buildables[$buildable_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
if ($this->needContainerObjects || $this->needContainerHandles) {
$container_phids = array_filter(mpull($page, 'getContainerPHID'));
if ($this->needContainerObjects) {
$containers = array();
if ($container_phids) {
$containers = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($container_phids)
->setParentQuery($this)
->execute();
$containers = mpull($containers, null, 'getPHID');
}
foreach ($page as $key => $buildable) {
$container_phid = $buildable->getContainerPHID();
$buildable->attachContainerObject(idx($containers, $container_phid));
}
}
if ($this->needContainerHandles) {
$handles = array();
if ($container_phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($container_phids)
->setParentQuery($this)
->execute();
}
foreach ($page as $key => $buildable) {
$container_phid = $buildable->getContainerPHID();
$buildable->attachContainerHandle(idx($handles, $container_phid));
}
}
}
if ($this->needBuildableHandles) {
$handles = array();
$handle_phids = array_filter(mpull($page, 'getBuildablePHID'));
if ($handle_phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($handle_phids)
->setParentQuery($this)
->execute();
}
foreach ($page as $key => $buildable) {
$handle_phid = $buildable->getBuildablePHID();
$buildable->attachBuildableHandle(idx($handles, $handle_phid));
}
}
if ($this->needBuilds) {
$builds = id(new HarbormasterBuildQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withBuildablePHIDs(mpull($page, 'getPHID'))
->execute();
$builds = mgroup($builds, 'getBuildablePHID');
foreach ($page as $key => $buildable) {
$buildable->attachBuilds(idx($builds, $buildable->getPHID(), array()));
}
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->buildablePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'buildablePHID IN (%Ls)',
$this->buildablePHIDs);
}
if ($this->containerPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'containerPHID in (%Ls)',
$this->containerPHIDs);
}
if ($this->manualBuildables !== null) {
$where[] = qsprintf(
$conn_r,
'isManualBuildable = %d',
(int)$this->manualBuildables);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHarbormasterApplication';
}
}
diff --git a/src/applications/herald/query/HeraldRuleQuery.php b/src/applications/herald/query/HeraldRuleQuery.php
index 6e88dc40a0..5967c6ffc9 100644
--- a/src/applications/herald/query/HeraldRuleQuery.php
+++ b/src/applications/herald/query/HeraldRuleQuery.php
@@ -1,276 +1,276 @@
<?php
final class HeraldRuleQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $ruleTypes;
private $contentTypes;
private $disabled;
private $triggerObjectPHIDs;
private $needConditionsAndActions;
private $needAppliedToPHIDs;
private $needValidateAuthors;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withRuleTypes(array $types) {
$this->ruleTypes = $types;
return $this;
}
public function withContentTypes(array $types) {
$this->contentTypes = $types;
return $this;
}
public function withExecutableRules($executable) {
$this->executable = $executable;
return $this;
}
public function withDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
public function withTriggerObjectPHIDs(array $phids) {
$this->triggerObjectPHIDs = $phids;
return $this;
}
public function needConditionsAndActions($need) {
$this->needConditionsAndActions = $need;
return $this;
}
public function needAppliedToPHIDs(array $phids) {
$this->needAppliedToPHIDs = $phids;
return $this;
}
public function needValidateAuthors($need) {
$this->needValidateAuthors = $need;
return $this;
}
protected function loadPage() {
$table = new HeraldRule();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT rule.* FROM %T rule %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $rules) {
$rule_ids = mpull($rules, 'getID');
// Filter out any rules that have invalid adapters, or have adapters the
// viewer isn't permitted to see or use (for example, Differential rules
// if the user can't use Differential or Differential is not installed).
$types = HeraldAdapter::getEnabledAdapterMap($this->getViewer());
foreach ($rules as $key => $rule) {
if (empty($types[$rule->getContentType()])) {
$this->didRejectResult($rule);
unset($rules[$key]);
}
}
if ($this->needValidateAuthors) {
$this->validateRuleAuthors($rules);
}
if ($this->needConditionsAndActions) {
$conditions = id(new HeraldCondition())->loadAllWhere(
'ruleID IN (%Ld)',
$rule_ids);
$conditions = mgroup($conditions, 'getRuleID');
$actions = id(new HeraldAction())->loadAllWhere(
'ruleID IN (%Ld)',
$rule_ids);
$actions = mgroup($actions, 'getRuleID');
foreach ($rules as $rule) {
$rule->attachActions(idx($actions, $rule->getID(), array()));
$rule->attachConditions(idx($conditions, $rule->getID(), array()));
}
}
if ($this->needAppliedToPHIDs) {
$conn_r = id(new HeraldRule())->establishConnection('r');
$applied = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE ruleID IN (%Ld) AND phid IN (%Ls)',
HeraldRule::TABLE_RULE_APPLIED,
$rule_ids,
$this->needAppliedToPHIDs);
$map = array();
foreach ($applied as $row) {
$map[$row['ruleID']][$row['phid']] = true;
}
foreach ($rules as $rule) {
foreach ($this->needAppliedToPHIDs as $phid) {
$rule->setRuleApplied(
$phid,
isset($map[$rule->getID()][$phid]));
}
}
}
$object_phids = array();
foreach ($rules as $rule) {
if ($rule->isObjectRule()) {
$object_phids[] = $rule->getTriggerObjectPHID();
}
}
if ($object_phids) {
$objects = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
foreach ($rules as $key => $rule) {
if ($rule->isObjectRule()) {
$object = idx($objects, $rule->getTriggerObjectPHID());
if (!$object) {
unset($rules[$key]);
continue;
}
$rule->attachTriggerObject($object);
}
}
return $rules;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'rule.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'rule.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'rule.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->ruleTypes) {
$where[] = qsprintf(
$conn_r,
'rule.ruleType IN (%Ls)',
$this->ruleTypes);
}
if ($this->contentTypes) {
$where[] = qsprintf(
$conn_r,
'rule.contentType IN (%Ls)',
$this->contentTypes);
}
if ($this->disabled !== null) {
$where[] = qsprintf(
$conn_r,
'rule.isDisabled = %d',
(int)$this->disabled);
}
if ($this->triggerObjectPHIDs) {
$where[] = qsprintf(
$conn_r,
'rule.triggerObjectPHID IN (%Ls)',
$this->triggerObjectPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function validateRuleAuthors(array $rules) {
// "Global" and "Object" rules always have valid authors.
foreach ($rules as $key => $rule) {
if ($rule->isGlobalRule() || $rule->isObjectRule()) {
$rule->attachValidAuthor(true);
unset($rules[$key]);
continue;
}
}
if (!$rules) {
return;
}
// For personal rules, the author needs to exist and not be disabled.
$user_phids = mpull($rules, 'getAuthorPHID');
$users = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer())
->withPHIDs($user_phids)
->execute();
$users = mpull($users, null, 'getPHID');
foreach ($rules as $key => $rule) {
$author_phid = $rule->getAuthorPHID();
if (empty($users[$author_phid])) {
$rule->attachValidAuthor(false);
continue;
}
if (!$users[$author_phid]->isUserActivated()) {
$rule->attachValidAuthor(false);
continue;
}
$rule->attachValidAuthor(true);
$rule->attachAuthor($users[$author_phid]);
}
}
public function getQueryApplicationClass() {
return 'PhabricatorHeraldApplication';
}
}
diff --git a/src/applications/herald/query/HeraldTranscriptQuery.php b/src/applications/herald/query/HeraldTranscriptQuery.php
index b76b657a7f..d679009c4e 100644
--- a/src/applications/herald/query/HeraldTranscriptQuery.php
+++ b/src/applications/herald/query/HeraldTranscriptQuery.php
@@ -1,114 +1,114 @@
<?php
final class HeraldTranscriptQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
private $needPartialRecords;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function needPartialRecords($need_partial) {
$this->needPartialRecords = $need_partial;
return $this;
}
protected function loadPage() {
$transcript = new HeraldTranscript();
$conn_r = $transcript->establishConnection('r');
// NOTE: Transcripts include a potentially enormous amount of serialized
// data, so we're loading only some of the fields here if the caller asked
// for partial records.
if ($this->needPartialRecords) {
$fields = implode(
', ',
array(
'id',
'phid',
'objectPHID',
'time',
'duration',
'dryRun',
'host',
));
} else {
$fields = '*';
}
$rows = queryfx_all(
$conn_r,
'SELECT %Q FROM %T t %Q %Q %Q',
$fields,
$transcript->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$transcripts = $transcript->loadAllFromArray($rows);
if ($this->needPartialRecords) {
// Make sure nothing tries to write these; they aren't complete.
foreach ($transcripts as $transcript) {
$transcript->makeEphemeral();
}
}
return $transcripts;
}
protected function willFilterPage(array $transcripts) {
$phids = mpull($transcripts, 'getObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($phids)
->execute();
foreach ($transcripts as $key => $transcript) {
if (empty($objects[$transcript->getObjectPHID()])) {
$this->didRejectResult($transcript);
unset($transcripts[$key]);
}
}
return $transcripts;
}
- public function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn_r,
'objectPHID in (%Ls)',
$this->objectPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorHeraldApplication';
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentQuery.php b/src/applications/legalpad/query/LegalpadDocumentQuery.php
index 03ec6b3d3c..e2e43e0e28 100644
--- a/src/applications/legalpad/query/LegalpadDocumentQuery.php
+++ b/src/applications/legalpad/query/LegalpadDocumentQuery.php
@@ -1,278 +1,278 @@
<?php
final class LegalpadDocumentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $creatorPHIDs;
private $contributorPHIDs;
private $signerPHIDs;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $signatureRequired;
private $needDocumentBodies;
private $needContributors;
private $needSignatures;
private $needViewerSignatures;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
public function withContributorPHIDs(array $phids) {
$this->contributorPHIDs = $phids;
return $this;
}
public function withSignerPHIDs(array $phids) {
$this->signerPHIDs = $phids;
return $this;
}
public function withSignatureRequired($bool) {
$this->signatureRequired = $bool;
return $this;
}
public function needDocumentBodies($need_bodies) {
$this->needDocumentBodies = $need_bodies;
return $this;
}
public function needContributors($need_contributors) {
$this->needContributors = $need_contributors;
return $this;
}
public function needSignatures($need_signatures) {
$this->needSignatures = $need_signatures;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function needViewerSignatures($need) {
$this->needViewerSignatures = $need;
return $this;
}
protected function loadPage() {
$table = new LegalpadDocument();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT d.* FROM %T d %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$documents = $table->loadAllFromArray($data);
return $documents;
}
protected function willFilterPage(array $documents) {
if ($this->needDocumentBodies) {
$documents = $this->loadDocumentBodies($documents);
}
if ($this->needContributors) {
$documents = $this->loadContributors($documents);
}
if ($this->needSignatures) {
$documents = $this->loadSignatures($documents);
}
if ($this->needViewerSignatures) {
if ($documents) {
if ($this->getViewer()->getPHID()) {
$signatures = id(new LegalpadDocumentSignatureQuery())
->setViewer($this->getViewer())
->withSignerPHIDs(array($this->getViewer()->getPHID()))
->withDocumentPHIDs(mpull($documents, 'getPHID'))
->execute();
$signatures = mpull($signatures, null, 'getDocumentPHID');
} else {
$signatures = array();
}
foreach ($documents as $document) {
$signature = idx($signatures, $document->getPHID());
$document->attachUserSignature(
$this->getViewer()->getPHID(),
$signature);
}
}
}
return $documents;
}
private function buildJoinClause($conn_r) {
$joins = array();
if ($this->contributorPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN edge contributor ON contributor.src = d.phid
AND contributor.type = %d',
PhabricatorObjectHasContributorEdgeType::EDGECONST);
}
if ($this->signerPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T signer ON signer.documentPHID = d.phid
AND signer.signerPHID IN (%Ls)',
id(new LegalpadDocumentSignature())->getTableName(),
$this->signerPHIDs);
}
return implode(' ', $joins);
}
private function buildGroupClause(AphrontDatabaseConnection $conn_r) {
if ($this->contributorPHIDs || $this->signerPHIDs) {
return 'GROUP BY d.id';
} else {
return '';
}
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'd.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'd.phid IN (%Ls)',
$this->phids);
}
if ($this->creatorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'd.creatorPHID IN (%Ls)',
$this->creatorPHIDs);
}
if ($this->dateCreatedAfter !== null) {
$where[] = qsprintf(
$conn_r,
'd.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore !== null) {
$where[] = qsprintf(
$conn_r,
'd.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->contributorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'contributor.dst IN (%Ls)',
$this->contributorPHIDs);
}
if ($this->signatureRequired !== null) {
$where[] = qsprintf(
$conn_r,
'd.requireSignature = %d',
$this->signatureRequired);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function loadDocumentBodies(array $documents) {
$body_phids = mpull($documents, 'getDocumentBodyPHID');
$bodies = id(new LegalpadDocumentBody())->loadAllWhere(
'phid IN (%Ls)',
$body_phids);
$bodies = mpull($bodies, null, 'getPHID');
foreach ($documents as $document) {
$body = idx($bodies, $document->getDocumentBodyPHID());
$document->attachDocumentBody($body);
}
return $documents;
}
private function loadContributors(array $documents) {
$document_map = mpull($documents, null, 'getPHID');
$edge_type = PhabricatorObjectHasContributorEdgeType::EDGECONST;
$contributor_data = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($document_map))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($document_map as $document_phid => $document) {
$data = $contributor_data[$document_phid];
$contributors = array_keys(idx($data, $edge_type, array()));
$document->attachContributors($contributors);
}
return $documents;
}
private function loadSignatures(array $documents) {
$document_map = mpull($documents, null, 'getPHID');
$signatures = id(new LegalpadDocumentSignatureQuery())
->setViewer($this->getViewer())
->withDocumentPHIDs(array_keys($document_map))
->execute();
$signatures = mgroup($signatures, 'getDocumentPHID');
foreach ($documents as $document) {
$sigs = idx($signatures, $document->getPHID(), array());
$document->attachSignatures($sigs);
}
return $documents;
}
public function getQueryApplicationClass() {
return 'PhabricatorLegalpadApplication';
}
}
diff --git a/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php b/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
index 3bb3628c99..452ea6759b 100644
--- a/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
+++ b/src/applications/legalpad/query/LegalpadDocumentSignatureQuery.php
@@ -1,150 +1,150 @@
<?php
final class LegalpadDocumentSignatureQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $documentPHIDs;
private $signerPHIDs;
private $documentVersions;
private $secretKeys;
private $nameContains;
private $emailContains;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withDocumentPHIDs(array $phids) {
$this->documentPHIDs = $phids;
return $this;
}
public function withSignerPHIDs(array $phids) {
$this->signerPHIDs = $phids;
return $this;
}
public function withDocumentVersions(array $versions) {
$this->documentVersions = $versions;
return $this;
}
public function withSecretKeys(array $keys) {
$this->secretKeys = $keys;
return $this;
}
public function withNameContains($text) {
$this->nameContains = $text;
return $this;
}
public function withEmailContains($text) {
$this->emailContains = $text;
return $this;
}
protected function loadPage() {
$table = new LegalpadDocumentSignature();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$signatures = $table->loadAllFromArray($data);
return $signatures;
}
protected function willFilterPage(array $signatures) {
$document_phids = mpull($signatures, 'getDocumentPHID');
$documents = id(new LegalpadDocumentQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($document_phids)
->execute();
$documents = mpull($documents, null, 'getPHID');
foreach ($signatures as $key => $signature) {
$document_phid = $signature->getDocumentPHID();
$document = idx($documents, $document_phid);
if ($document) {
$signature->attachDocument($document);
} else {
unset($signatures[$key]);
}
}
return $signatures;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->documentPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'documentPHID IN (%Ls)',
$this->documentPHIDs);
}
if ($this->signerPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'signerPHID IN (%Ls)',
$this->signerPHIDs);
}
if ($this->documentVersions !== null) {
$where[] = qsprintf(
$conn_r,
'documentVersion IN (%Ld)',
$this->documentVersions);
}
if ($this->secretKeys !== null) {
$where[] = qsprintf(
$conn_r,
'secretKey IN (%Ls)',
$this->secretKeys);
}
if ($this->nameContains !== null) {
$where[] = qsprintf(
$conn_r,
'signerName LIKE %~',
$this->nameContains);
}
if ($this->emailContains !== null) {
$where[] = qsprintf(
$conn_r,
'signerEmail LIKE %~',
$this->emailContains);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorLegalpadApplication';
}
}
diff --git a/src/applications/mailinglists/query/PhabricatorMailingListQuery.php b/src/applications/mailinglists/query/PhabricatorMailingListQuery.php
index 44f54edbda..113bb4c80d 100644
--- a/src/applications/mailinglists/query/PhabricatorMailingListQuery.php
+++ b/src/applications/mailinglists/query/PhabricatorMailingListQuery.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorMailingListQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ids;
private $emails;
private $names;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
public function withEmails(array $emails) {
$this->emails = $emails;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
protected function loadPage() {
$table = new PhabricatorMetaMTAMailingList();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->names) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
if ($this->emails) {
$where[] = qsprintf(
$conn_r,
'email IN (%Ls)',
$this->emails);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorMailingListsApplication';
}
}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
index d2ac2f17a6..b173224914 100644
--- a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
+++ b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
@@ -1,125 +1,125 @@
<?php
final class PhabricatorMetaMTAApplicationEmailQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $addresses;
private $addressPrefix;
private $applicationPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAddresses(array $addresses) {
$this->addresses = $addresses;
return $this;
}
public function withAddressPrefix($prefix) {
$this->addressPrefix = $prefix;
return $this;
}
public function withApplicationPHIDs(array $phids) {
$this->applicationPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorMetaMTAApplicationEmail();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T appemail %Q %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildApplicationSearchGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $app_emails) {
$app_emails_map = mgroup($app_emails, 'getApplicationPHID');
$applications = id(new PhabricatorApplicationQuery())
->setViewer($this->getViewer())
->withPHIDs(array_keys($app_emails_map))
->execute();
$applications = mpull($applications, null, 'getPHID');
foreach ($app_emails_map as $app_phid => $app_emails_group) {
foreach ($app_emails_group as $app_email) {
$application = idx($applications, $app_phid);
if (!$application) {
unset($app_emails[$app_phid]);
continue;
}
$app_email->attachApplication($application);
}
}
return $app_emails;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->addresses !== null) {
$where[] = qsprintf(
$conn_r,
'appemail.address IN (%Ls)',
$this->addresses);
}
if ($this->addressPrefix !== null) {
$where[] = qsprintf(
$conn_r,
'appemail.address LIKE %>',
$this->addressPrefix);
}
if ($this->applicationPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'appemail.applicationPHID IN (%Ls)',
$this->applicationPHIDs);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'appemail.phid IN (%Ls)',
$this->phids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'appemail.id IN (%Ld)',
$this->ids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function getPrimaryTableAlias() {
return 'appemail';
}
public function getQueryApplicationClass() {
return 'PhabricatorMetaMTAApplication';
}
}
diff --git a/src/applications/notification/query/PhabricatorNotificationQuery.php b/src/applications/notification/query/PhabricatorNotificationQuery.php
index a1f8ac63c7..aa430a2518 100644
--- a/src/applications/notification/query/PhabricatorNotificationQuery.php
+++ b/src/applications/notification/query/PhabricatorNotificationQuery.php
@@ -1,114 +1,114 @@
<?php
/**
* @task config Configuring the Query
* @task exec Query Execution
*/
final class PhabricatorNotificationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $userPHIDs;
private $keys;
private $unread;
/* -( Configuring the Query )---------------------------------------------- */
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
/**
* Filter results by read/unread status. Note that `true` means to return
* only unread notifications, while `false` means to return only //read//
* notifications. The default is `null`, which returns both.
*
* @param mixed True or false to filter results by read status. Null to remove
* the filter.
* @return this
* @task config
*/
public function withUnread($unread) {
$this->unread = $unread;
return $this;
}
/* -( Query Execution )---------------------------------------------------- */
protected function loadPage() {
$story_table = new PhabricatorFeedStoryData();
$notification_table = new PhabricatorFeedStoryNotification();
$conn = $story_table->establishConnection('r');
$data = queryfx_all(
$conn,
'SELECT story.*, notif.hasViewed FROM %T notif
JOIN %T story ON notif.chronologicalKey = story.chronologicalKey
%Q
ORDER BY notif.chronologicalKey DESC
%Q',
$notification_table->getTableName(),
$story_table->getTableName(),
$this->buildWhereClause($conn),
$this->buildLimitClause($conn));
$viewed_map = ipull($data, 'hasViewed', 'chronologicalKey');
$stories = PhabricatorFeedStory::loadAllFromRows(
$data,
$this->getViewer());
foreach ($stories as $key => $story) {
$story->setHasViewed($viewed_map[$key]);
}
return $stories;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'notif.userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->unread !== null) {
$where[] = qsprintf(
$conn_r,
'notif.hasViewed = %d',
(int)!$this->unread);
}
if ($this->keys) {
$where[] = qsprintf(
$conn_r,
'notif.chronologicalKey IN (%Ls)',
$this->keys);
}
return $this->formatWhereClause($where);
}
protected function getResultCursor($item) {
return $item->getChronologicalKey();
}
public function getQueryApplicationClass() {
return 'PhabricatorNotificationsApplication';
}
}
diff --git a/src/applications/nuance/query/NuanceItemQuery.php b/src/applications/nuance/query/NuanceItemQuery.php
index 5264c4b527..4b87f38a77 100644
--- a/src/applications/nuance/query/NuanceItemQuery.php
+++ b/src/applications/nuance/query/NuanceItemQuery.php
@@ -1,70 +1,70 @@
<?php
final class NuanceItemQuery
extends NuanceQuery {
private $ids;
private $phids;
private $sourceIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withSourceIDs($source_ids) {
$this->sourceIDs = $source_ids;
return $this;
}
protected function loadPage() {
$table = new NuanceItem();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->sourceID) {
$where[] = qsprintf(
$conn_r,
'sourceID IN (%Ld)',
$this->sourceIDs);
}
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/nuance/query/NuanceQueueQuery.php b/src/applications/nuance/query/NuanceQueueQuery.php
index b4a067f01c..822a60c620 100644
--- a/src/applications/nuance/query/NuanceQueueQuery.php
+++ b/src/applications/nuance/query/NuanceQueueQuery.php
@@ -1,56 +1,56 @@
<?php
final class NuanceQueueQuery
extends NuanceQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new NuanceQueue();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/nuance/query/NuanceRequestorQuery.php b/src/applications/nuance/query/NuanceRequestorQuery.php
index e23cc71343..91a9878b83 100644
--- a/src/applications/nuance/query/NuanceRequestorQuery.php
+++ b/src/applications/nuance/query/NuanceRequestorQuery.php
@@ -1,56 +1,56 @@
<?php
final class NuanceRequestorQuery
extends NuanceQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new NuanceRequestor();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/nuance/query/NuanceSourceQuery.php b/src/applications/nuance/query/NuanceSourceQuery.php
index 3a177a4e42..77421656e7 100644
--- a/src/applications/nuance/query/NuanceSourceQuery.php
+++ b/src/applications/nuance/query/NuanceSourceQuery.php
@@ -1,83 +1,83 @@
<?php
final class NuanceSourceQuery
extends NuanceQuery {
private $ids;
private $phids;
private $creatorPHIDs;
private $types;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->CreatorPHIDs = $phids;
return $this;
}
public function withTypes($types) {
$this->types = $types;
return $this;
}
protected function loadPage() {
$table = new NuanceSource();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->creatorPHIDs) {
$where[] = qsprintf(
$conn_r,
'creatorPHID IN (%Ls)',
$this->creatorPHIDs);
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'type IN (%Ld)',
$this->types);
}
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
index 754e3474ab..f19be14434 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhabricatorOAuthClientAuthorizationQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $userPHIDs;
private $clientPHIDs;
public function witHPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withUserPHIDs(array $phids) {
$this->userPHIDs = $phids;
return $this;
}
public function withClientPHIDs(array $phids) {
$this->clientPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorOAuthClientAuthorization();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T auth %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $authorizations) {
$client_phids = mpull($authorizations, 'getClientPHID');
$clients = id(new PhabricatorOAuthServerClientQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($client_phids)
->execute();
$clients = mpull($clients, null, 'getPHID');
foreach ($authorizations as $key => $authorization) {
$client = idx($clients, $authorization->getClientPHID());
if (!$client) {
unset($authorizations[$key]);
continue;
}
$authorization->attachClient($client);
}
return $authorizations;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->userPHIDs) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->clientPHIDs) {
$where[] = qsprintf(
$conn_r,
'clientPHID IN (%Ls)',
$this->clientPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorOAuthServerApplication';
}
}
diff --git a/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php b/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
index bf22a2a701..b5da9ecd5f 100644
--- a/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
+++ b/src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorOAuthServerClientQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $creatorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorOAuthServerClient();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T client %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->creatorPHIDs) {
$where[] = qsprintf(
$conn_r,
'creatorPHID IN (%Ls)',
$this->creatorPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorOAuthServerApplication';
}
}
diff --git a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
index bdfb6f5a4e..64640c3ab8 100644
--- a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
+++ b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorOwnersPackageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ownerPHIDs;
/**
* Owners are direct owners, and members of owning projects.
*/
public function withOwnerPHIDs(array $phids) {
$this->ownerPHIDs = $phids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorOwnersPackage();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT p.* FROM %T p %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if ($this->ownerPHIDs) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T o ON o.packageID = p.id',
id(new PhabricatorOwnersOwner())->getTableName());
}
return implode(' ', $joins);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'p.phid IN (%Ls)',
$this->phids);
}
if ($this->ownerPHIDs) {
$base_phids = $this->ownerPHIDs;
$query = new PhabricatorProjectQuery();
$query->setViewer($this->getViewer());
$query->withMemberPHIDs($base_phids);
$projects = $query->execute();
$project_phids = mpull($projects, 'getPHID');
$all_phids = array_merge($base_phids, $project_phids);
$where[] = qsprintf(
$conn_r,
'o.userPHID IN (%Ls)',
$all_phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorOwnersApplication';
}
}
diff --git a/src/applications/passphrase/query/PassphraseCredentialQuery.php b/src/applications/passphrase/query/PassphraseCredentialQuery.php
index 29f661397d..9cae8b1f85 100644
--- a/src/applications/passphrase/query/PassphraseCredentialQuery.php
+++ b/src/applications/passphrase/query/PassphraseCredentialQuery.php
@@ -1,163 +1,163 @@
<?php
final class PassphraseCredentialQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $credentialTypes;
private $providesTypes;
private $isDestroyed;
private $allowConduit;
private $nameContains;
private $needSecrets;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCredentialTypes(array $credential_types) {
$this->credentialTypes = $credential_types;
return $this;
}
public function withProvidesTypes(array $provides_types) {
$this->providesTypes = $provides_types;
return $this;
}
public function withIsDestroyed($destroyed) {
$this->isDestroyed = $destroyed;
return $this;
}
public function withAllowConduit($allow_conduit) {
$this->allowConduit = $allow_conduit;
return $this;
}
public function withNameContains($name_contains) {
$this->nameContains = $name_contains;
return $this;
}
public function needSecrets($need_secrets) {
$this->needSecrets = $need_secrets;
return $this;
}
protected function loadPage() {
$table = new PassphraseCredential();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $page) {
if ($this->needSecrets) {
$secret_ids = mpull($page, 'getSecretID');
$secret_ids = array_filter($secret_ids);
$secrets = array();
if ($secret_ids) {
$secret_objects = id(new PassphraseSecret())->loadAllWhere(
'id IN (%Ld)',
$secret_ids);
foreach ($secret_objects as $secret) {
$secret_data = $secret->getSecretData();
$secrets[$secret->getID()] = new PhutilOpaqueEnvelope($secret_data);
}
}
foreach ($page as $key => $credential) {
$secret_id = $credential->getSecretID();
if (!$secret_id) {
$credential->attachSecret(null);
} else if (isset($secrets[$secret_id])) {
$credential->attachSecret($secrets[$secret_id]);
} else {
unset($page[$key]);
}
}
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->credentialTypes) {
$where[] = qsprintf(
$conn_r,
'credentialType in (%Ls)',
$this->credentialTypes);
}
if ($this->providesTypes) {
$where[] = qsprintf(
$conn_r,
'providesType IN (%Ls)',
$this->providesTypes);
}
if ($this->isDestroyed !== null) {
$where[] = qsprintf(
$conn_r,
'isDestroyed = %d',
(int)$this->isDestroyed);
}
if ($this->allowConduit !== null) {
$where[] = qsprintf(
$conn_r,
'allowConduit = %d',
(int)$this->allowConduit);
}
if (strlen($this->nameContains)) {
$where[] = qsprintf(
$conn_r,
'name LIKE %~',
$this->nameContains);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPassphraseApplication';
}
}
diff --git a/src/applications/paste/query/PhabricatorPasteQuery.php b/src/applications/paste/query/PhabricatorPasteQuery.php
index 35c3820311..ae74978510 100644
--- a/src/applications/paste/query/PhabricatorPasteQuery.php
+++ b/src/applications/paste/query/PhabricatorPasteQuery.php
@@ -1,252 +1,252 @@
<?php
final class PhabricatorPasteQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $parentPHIDs;
private $needContent;
private $needRawContent;
private $languages;
private $includeNoLanguage;
private $dateCreatedAfter;
private $dateCreatedBefore;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withParentPHIDs(array $phids) {
$this->parentPHIDs = $phids;
return $this;
}
public function needContent($need_content) {
$this->needContent = $need_content;
return $this;
}
public function needRawContent($need_raw_content) {
$this->needRawContent = $need_raw_content;
return $this;
}
public function withLanguages(array $languages) {
$this->includeNoLanguage = false;
foreach ($languages as $key => $language) {
if ($language === null) {
$languages[$key] = '';
continue;
}
}
$this->languages = $languages;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
protected function loadPage() {
$table = new PhabricatorPaste();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT paste.* FROM %T paste %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$pastes = $table->loadAllFromArray($data);
return $pastes;
}
protected function didFilterPage(array $pastes) {
if ($this->needRawContent) {
$pastes = $this->loadRawContent($pastes);
}
if ($this->needContent) {
$this->loadContent($pastes);
}
return $pastes;
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->parentPHIDs) {
$where[] = qsprintf(
$conn_r,
'parentPHID IN (%Ls)',
$this->parentPHIDs);
}
if ($this->languages) {
$where[] = qsprintf(
$conn_r,
'language IN (%Ls)',
$this->languages);
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn_r,
'dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn_r,
'dateCreated <= %d',
$this->dateCreatedBefore);
}
return $this->formatWhereClause($where);
}
private function getContentCacheKey(PhabricatorPaste $paste) {
return implode(
':',
array(
'P'.$paste->getID(),
$paste->getFilePHID(),
$paste->getLanguage(),
));
}
private function loadRawContent(array $pastes) {
$file_phids = mpull($pastes, 'getFilePHID');
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($pastes as $key => $paste) {
$file = idx($files, $paste->getFilePHID());
if (!$file) {
unset($pastes[$key]);
continue;
}
try {
$paste->attachRawContent($file->loadFileData());
} catch (Exception $ex) {
// We can hit various sorts of file storage issues here. Just drop the
// paste if the file is dead.
unset($pastes[$key]);
continue;
}
}
return $pastes;
}
private function loadContent(array $pastes) {
$cache = new PhabricatorKeyValueDatabaseCache();
$cache = new PhutilKeyValueCacheProfiler($cache);
$cache->setProfiler(PhutilServiceProfiler::getInstance());
$keys = array();
foreach ($pastes as $paste) {
$keys[] = $this->getContentCacheKey($paste);
}
$caches = $cache->getKeys($keys);
$need_raw = array();
foreach ($pastes as $key => $paste) {
$key = $this->getContentCacheKey($paste);
if (isset($caches[$key])) {
$paste->attachContent(phutil_safe_html($caches[$key]));
} else {
$need_raw[$key] = $paste;
}
}
if (!$need_raw) {
return;
}
$write_data = array();
$need_raw = $this->loadRawContent($need_raw);
foreach ($need_raw as $key => $paste) {
$content = $this->buildContent($paste);
$paste->attachContent($content);
$write_data[$this->getContentCacheKey($paste)] = (string)$content;
}
$cache->setKeys($write_data);
}
private function buildContent(PhabricatorPaste $paste) {
$language = $paste->getLanguage();
$source = $paste->getRawContent();
if (empty($language)) {
return PhabricatorSyntaxHighlighter::highlightWithFilename(
$paste->getTitle(),
$source);
} else {
return PhabricatorSyntaxHighlighter::highlightWithLanguage(
$language,
$source);
}
}
public function getQueryApplicationClass() {
return 'PhabricatorPasteApplication';
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleLogQuery.php b/src/applications/people/query/PhabricatorPeopleLogQuery.php
index 3315234d12..9bcdc53f49 100644
--- a/src/applications/people/query/PhabricatorPeopleLogQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleLogQuery.php
@@ -1,113 +1,113 @@
<?php
final class PhabricatorPeopleLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $actorPHIDs;
private $userPHIDs;
private $relatedPHIDs;
private $sessionKeys;
private $actions;
private $remoteAddressPrefix;
public function withActorPHIDs(array $actor_phids) {
$this->actorPHIDs = $actor_phids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withRelatedPHIDs(array $related_phids) {
$this->relatedPHIDs = $related_phids;
return $this;
}
public function withSessionKeys(array $session_keys) {
$this->sessionKeys = $session_keys;
return $this;
}
public function withActions(array $actions) {
$this->actions = $actions;
return $this;
}
public function withRemoteAddressPrefix($remote_address_prefix) {
$this->remoteAddressPrefix = $remote_address_prefix;
return $this;
}
protected function loadPage() {
$table = new PhabricatorUserLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->actorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'actorPHID IN (%Ls)',
$this->actorPHIDs);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->relatedPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'actorPHID IN (%Ls) OR userPHID IN (%Ls)',
$this->relatedPHIDs,
$this->relatedPHIDs);
}
if ($this->sessionKeys !== null) {
$where[] = qsprintf(
$conn_r,
'session IN (%Ls)',
$this->sessionKeys);
}
if ($this->actions !== null) {
$where[] = qsprintf(
$conn_r,
'action IN (%Ls)',
$this->actions);
}
if ($this->remoteAddressPrefix !== null) {
$where[] = qsprintf(
$conn_r,
'remoteAddr LIKE %>',
$this->remoteAddressPrefix);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPeopleApplication';
}
}
diff --git a/src/applications/people/query/PhabricatorPeopleQuery.php b/src/applications/people/query/PhabricatorPeopleQuery.php
index 472e76a8a1..437f764fe9 100644
--- a/src/applications/people/query/PhabricatorPeopleQuery.php
+++ b/src/applications/people/query/PhabricatorPeopleQuery.php
@@ -1,350 +1,350 @@
<?php
final class PhabricatorPeopleQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $usernames;
private $realnames;
private $emails;
private $phids;
private $ids;
private $dateCreatedAfter;
private $dateCreatedBefore;
private $isAdmin;
private $isSystemAgent;
private $isDisabled;
private $isApproved;
private $nameLike;
private $nameTokens;
private $needPrimaryEmail;
private $needProfile;
private $needProfileImage;
private $needStatus;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withEmails(array $emails) {
$this->emails = $emails;
return $this;
}
public function withRealnames(array $realnames) {
$this->realnames = $realnames;
return $this;
}
public function withUsernames(array $usernames) {
$this->usernames = $usernames;
return $this;
}
public function withDateCreatedBefore($date_created_before) {
$this->dateCreatedBefore = $date_created_before;
return $this;
}
public function withDateCreatedAfter($date_created_after) {
$this->dateCreatedAfter = $date_created_after;
return $this;
}
public function withIsAdmin($admin) {
$this->isAdmin = $admin;
return $this;
}
public function withIsSystemAgent($system_agent) {
$this->isSystemAgent = $system_agent;
return $this;
}
public function withIsDisabled($disabled) {
$this->isDisabled = $disabled;
return $this;
}
public function withIsApproved($approved) {
$this->isApproved = $approved;
return $this;
}
public function withNameLike($like) {
$this->nameLike = $like;
return $this;
}
public function withNameTokens(array $tokens) {
$this->nameTokens = array_values($tokens);
return $this;
}
public function needPrimaryEmail($need) {
$this->needPrimaryEmail = $need;
return $this;
}
public function needProfile($need) {
$this->needProfile = $need;
return $this;
}
public function needProfileImage($need) {
$this->needProfileImage = $need;
return $this;
}
public function needStatus($need) {
$this->needStatus = $need;
return $this;
}
protected function loadPage() {
$table = new PhabricatorUser();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T user %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinsClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
if ($this->needPrimaryEmail) {
$table->putInSet(new LiskDAOSet());
}
return $table->loadAllFromArray($data);
}
protected function didFilterPage(array $users) {
if ($this->needProfile) {
$user_list = mpull($users, null, 'getPHID');
$profiles = new PhabricatorUserProfile();
$profiles = $profiles->loadAllWhere('userPHID IN (%Ls)',
array_keys($user_list));
$profiles = mpull($profiles, null, 'getUserPHID');
foreach ($user_list as $user_phid => $user) {
$profile = idx($profiles, $user_phid);
if (!$profile) {
$profile = new PhabricatorUserProfile();
$profile->setUserPHID($user_phid);
}
$user->attachUserProfile($profile);
}
}
if ($this->needProfileImage) {
$user_profile_file_phids = mpull($users, 'getProfileImagePHID');
$user_profile_file_phids = array_filter($user_profile_file_phids);
if ($user_profile_file_phids) {
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($user_profile_file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
} else {
$files = array();
}
foreach ($users as $user) {
$image_phid = $user->getProfileImagePHID();
if (isset($files[$image_phid])) {
$profile_image_uri = $files[$image_phid]->getBestURI();
} else {
$profile_image_uri = PhabricatorUser::getDefaultProfileImageURI();
}
$user->attachProfileImageURI($profile_image_uri);
}
}
if ($this->needStatus) {
$user_list = mpull($users, null, 'getPHID');
$statuses = id(new PhabricatorCalendarEvent())->loadCurrentStatuses(
array_keys($user_list));
foreach ($user_list as $phid => $user) {
$status = idx($statuses, $phid);
if ($status) {
$user->attachStatus($status);
}
}
}
return $users;
}
private function buildGroupClause(AphrontDatabaseConnection $conn) {
if ($this->nameTokens) {
return qsprintf(
$conn,
'GROUP BY user.id');
} else {
return $this->buildApplicationSearchGroupClause($conn);
}
}
private function buildJoinsClause($conn_r) {
$joins = array();
if ($this->emails) {
$email_table = new PhabricatorUserEmail();
$joins[] = qsprintf(
$conn_r,
'JOIN %T email ON email.userPHID = user.PHID',
$email_table->getTableName());
}
if ($this->nameTokens) {
foreach ($this->nameTokens as $key => $token) {
$token_table = 'token_'.$key;
$joins[] = qsprintf(
$conn_r,
'JOIN %T %T ON %T.userID = user.id AND %T.token LIKE %>',
PhabricatorUser::NAMETOKEN_TABLE,
$token_table,
$token_table,
$token_table,
$token);
}
}
$joins[] = $this->buildApplicationSearchJoinClause($conn_r);
$joins = implode(' ', $joins);
return $joins;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->usernames !== null) {
$where[] = qsprintf(
$conn_r,
'user.userName IN (%Ls)',
$this->usernames);
}
if ($this->emails !== null) {
$where[] = qsprintf(
$conn_r,
'email.address IN (%Ls)',
$this->emails);
}
if ($this->realnames !== null) {
$where[] = qsprintf(
$conn_r,
'user.realName IN (%Ls)',
$this->realnames);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'user.phid IN (%Ls)',
$this->phids);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'user.id IN (%Ld)',
$this->ids);
}
if ($this->dateCreatedAfter) {
$where[] = qsprintf(
$conn_r,
'user.dateCreated >= %d',
$this->dateCreatedAfter);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn_r,
'user.dateCreated <= %d',
$this->dateCreatedBefore);
}
if ($this->isAdmin) {
$where[] = qsprintf(
$conn_r,
'user.isAdmin = 1');
}
if ($this->isDisabled !== null) {
$where[] = qsprintf(
$conn_r,
'user.isDisabled = %d',
(int)$this->isDisabled);
}
if ($this->isApproved !== null) {
$where[] = qsprintf(
$conn_r,
'user.isApproved = %d',
(int)$this->isApproved);
}
if ($this->isSystemAgent) {
$where[] = qsprintf(
$conn_r,
'user.isSystemAgent = 1');
}
if (strlen($this->nameLike)) {
$where[] = qsprintf(
$conn_r,
'user.username LIKE %~ OR user.realname LIKE %~',
$this->nameLike,
$this->nameLike);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function getPrimaryTableAlias() {
return 'user';
}
public function getQueryApplicationClass() {
return 'PhabricatorPeopleApplication';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'username' => array(
'table' => 'user',
'column' => 'username',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$user = $this->loadCursorObject($cursor);
return array(
'id' => $user->getID(),
'username' => $user->getUsername(),
);
}
}
diff --git a/src/applications/phame/query/PhameBlogQuery.php b/src/applications/phame/query/PhameBlogQuery.php
index 160749a18f..a3e88e5143 100644
--- a/src/applications/phame/query/PhameBlogQuery.php
+++ b/src/applications/phame/query/PhameBlogQuery.php
@@ -1,80 +1,80 @@
<?php
final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $domain;
private $needBloggers;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withDomain($domain) {
$this->domain = $domain;
return $this;
}
protected function loadPage() {
$table = new PhameBlog();
$conn_r = $table->establishConnection('r');
$where_clause = $this->buildWhereClause($conn_r);
$order_clause = $this->buildOrderClause($conn_r);
$limit_clause = $this->buildLimitClause($conn_r);
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T b %Q %Q %Q',
$table->getTableName(),
$where_clause,
$order_clause,
$limit_clause);
$blogs = $table->loadAllFromArray($data);
return $blogs;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ls)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->domain) {
$where[] = qsprintf(
$conn_r,
'domain = %s',
$this->domain);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Can we set this without breaking public blogs?
return null;
}
}
diff --git a/src/applications/phame/query/PhamePostQuery.php b/src/applications/phame/query/PhamePostQuery.php
index d87c26e35e..2eed8d2960 100644
--- a/src/applications/phame/query/PhamePostQuery.php
+++ b/src/applications/phame/query/PhamePostQuery.php
@@ -1,146 +1,146 @@
<?php
final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $blogPHIDs;
private $bloggerPHIDs;
private $phameTitles;
private $visibility;
private $publishedAfter;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBloggerPHIDs(array $blogger_phids) {
$this->bloggerPHIDs = $blogger_phids;
return $this;
}
public function withBlogPHIDs(array $blog_phids) {
$this->blogPHIDs = $blog_phids;
return $this;
}
public function withPhameTitles(array $phame_titles) {
$this->phameTitles = $phame_titles;
return $this;
}
public function withVisibility($visibility) {
$this->visibility = $visibility;
return $this;
}
public function withPublishedAfter($time) {
$this->publishedAfter = $time;
return $this;
}
protected function loadPage() {
$table = new PhamePost();
$conn_r = $table->establishConnection('r');
$where_clause = $this->buildWhereClause($conn_r);
$order_clause = $this->buildOrderClause($conn_r);
$limit_clause = $this->buildLimitClause($conn_r);
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T p %Q %Q %Q',
$table->getTableName(),
$where_clause,
$order_clause,
$limit_clause);
$posts = $table->loadAllFromArray($data);
if ($posts) {
// We require these to do visibility checks, so load them unconditionally.
$blog_phids = mpull($posts, 'getBlogPHID');
$blogs = id(new PhameBlogQuery())
->setViewer($this->getViewer())
->withPHIDs($blog_phids)
->execute();
$blogs = mpull($blogs, null, 'getPHID');
foreach ($posts as $post) {
if (isset($blogs[$post->getBlogPHID()])) {
$post->setBlog($blogs[$post->getBlogPHID()]);
}
}
}
return $posts;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'p.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'p.phid IN (%Ls)',
$this->phids);
}
if ($this->bloggerPHIDs) {
$where[] = qsprintf(
$conn_r,
'p.bloggerPHID IN (%Ls)',
$this->bloggerPHIDs);
}
if ($this->phameTitles) {
$where[] = qsprintf(
$conn_r,
'p.phameTitle IN (%Ls)',
$this->phameTitles);
}
if ($this->visibility !== null) {
$where[] = qsprintf(
$conn_r,
'p.visibility = %d',
$this->visibility);
}
if ($this->publishedAfter !== null) {
$where[] = qsprintf(
$conn_r,
'p.datePublished > %d',
$this->publishedAfter);
}
if ($this->blogPHIDs) {
$where[] = qsprintf(
$conn_r,
'p.blogPHID in (%Ls)',
$this->blogPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Does setting this break public blogs?
return null;
}
}
diff --git a/src/applications/phlux/query/PhluxVariableQuery.php b/src/applications/phlux/query/PhluxVariableQuery.php
index 3439ee1d8b..82072485d4 100644
--- a/src/applications/phlux/query/PhluxVariableQuery.php
+++ b/src/applications/phlux/query/PhluxVariableQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhluxVariableQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $keys;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
protected function loadPage() {
$table = new PhluxVariable();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->keys !== null) {
$where[] = qsprintf(
$conn_r,
'variableKey IN (%Ls)',
$this->keys);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function getDefaultOrderVector() {
return array('key');
}
public function getOrderableColumns() {
return array(
'key' => array(
'column' => 'variableKey',
'type' => 'string',
'reverse' => true,
'unique' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$object = $this->loadCursorObject($cursor);
return array(
'key' => $object->getVariableKey(),
);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhluxApplication';
}
}
diff --git a/src/applications/pholio/query/PholioImageQuery.php b/src/applications/pholio/query/PholioImageQuery.php
index dd5fb23f3c..2d5057ccdc 100644
--- a/src/applications/pholio/query/PholioImageQuery.php
+++ b/src/applications/pholio/query/PholioImageQuery.php
@@ -1,165 +1,165 @@
<?php
final class PholioImageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $mockIDs;
private $obsolete;
private $needInlineComments;
private $mockCache = array();
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMockIDs(array $mock_ids) {
$this->mockIDs = $mock_ids;
return $this;
}
public function withObsolete($obsolete) {
$this->obsolete = $obsolete;
return $this;
}
public function needInlineComments($need_inline_comments) {
$this->needInlineComments = $need_inline_comments;
return $this;
}
public function setMockCache($mock_cache) {
$this->mockCache = $mock_cache;
return $this;
}
public function getMockCache() {
return $this->mockCache;
}
protected function loadPage() {
$table = new PholioImage();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$images = $table->loadAllFromArray($data);
return $images;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->mockIDs) {
$where[] = qsprintf(
$conn_r,
'mockID IN (%Ld)',
$this->mockIDs);
}
if ($this->obsolete !== null) {
$where[] = qsprintf(
$conn_r,
'isObsolete = %d',
$this->obsolete);
}
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $images) {
assert_instances_of($images, 'PholioImage');
if ($this->getMockCache()) {
$mocks = $this->getMockCache();
} else {
$mock_ids = mpull($images, 'getMockID');
// DO NOT set needImages to true; recursion results!
$mocks = id(new PholioMockQuery())
->setViewer($this->getViewer())
->withIDs($mock_ids)
->execute();
$mocks = mpull($mocks, null, 'getID');
}
foreach ($images as $index => $image) {
$mock = idx($mocks, $image->getMockID());
if ($mock) {
$image->attachMock($mock);
} else {
// mock is missing or we can't see it
unset($images[$index]);
}
}
return $images;
}
protected function didFilterPage(array $images) {
assert_instances_of($images, 'PholioImage');
$file_phids = mpull($images, 'getFilePHID');
$all_files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$all_files = mpull($all_files, null, 'getPHID');
if ($this->needInlineComments) {
$all_inline_comments = id(new PholioTransactionComment())
->loadAllWhere('imageid IN (%Ld)',
mpull($images, 'getID'));
$all_inline_comments = mgroup($all_inline_comments, 'getImageID');
}
foreach ($images as $image) {
$file = idx($all_files, $image->getFilePHID());
if (!$file) {
$file = PhabricatorFile::loadBuiltin($this->getViewer(), 'missing.png');
}
$image->attachFile($file);
if ($this->needInlineComments) {
$inlines = idx($all_inline_comments, $image->getID(), array());
$image->attachInlineComments($inlines);
}
}
return $images;
}
public function getQueryApplicationClass() {
return 'PhabricatorPholioApplication';
}
}
diff --git a/src/applications/pholio/query/PholioMockQuery.php b/src/applications/pholio/query/PholioMockQuery.php
index d80bf57a28..2f6edd313f 100644
--- a/src/applications/pholio/query/PholioMockQuery.php
+++ b/src/applications/pholio/query/PholioMockQuery.php
@@ -1,181 +1,181 @@
<?php
final class PholioMockQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $statuses;
private $needCoverFiles;
private $needImages;
private $needInlineComments;
private $needTokenCounts;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needCoverFiles($need_cover_files) {
$this->needCoverFiles = $need_cover_files;
return $this;
}
public function needImages($need_images) {
$this->needImages = $need_images;
return $this;
}
public function needInlineComments($need_inline_comments) {
$this->needInlineComments = $need_inline_comments;
return $this;
}
public function needTokenCounts($need) {
$this->needTokenCounts = $need;
return $this;
}
protected function loadPage() {
$table = new PholioMock();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$mocks = $table->loadAllFromArray($data);
if ($mocks && $this->needImages) {
self::loadImages($this->getViewer(), $mocks, $this->needInlineComments);
}
if ($mocks && $this->needCoverFiles) {
$this->loadCoverFiles($mocks);
}
if ($mocks && $this->needTokenCounts) {
$this->loadTokenCounts($mocks);
}
return $mocks;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID in (%Ls)',
$this->authorPHIDs);
}
if ($this->statuses) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($where);
}
public static function loadImages(
PhabricatorUser $viewer,
array $mocks,
$need_inline_comments) {
assert_instances_of($mocks, 'PholioMock');
$mock_map = mpull($mocks, null, 'getID');
$all_images = id(new PholioImageQuery())
->setViewer($viewer)
->setMockCache($mock_map)
->withMockIDs(array_keys($mock_map))
->needInlineComments($need_inline_comments)
->execute();
$image_groups = mgroup($all_images, 'getMockID');
foreach ($mocks as $mock) {
$mock_images = idx($image_groups, $mock->getID(), array());
$mock->attachAllImages($mock_images);
$active_images = mfilter($mock_images, 'getIsObsolete', true);
$mock->attachImages(msort($active_images, 'getSequence'));
}
}
private function loadCoverFiles(array $mocks) {
assert_instances_of($mocks, 'PholioMock');
$cover_file_phids = mpull($mocks, 'getCoverPHID');
$cover_files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->withPHIDs($cover_file_phids)
->execute();
$cover_files = mpull($cover_files, null, 'getPHID');
foreach ($mocks as $mock) {
$file = idx($cover_files, $mock->getCoverPHID());
if (!$file) {
$file = PhabricatorFile::loadBuiltin($this->getViewer(), 'missing.png');
}
$mock->attachCoverFile($file);
}
}
private function loadTokenCounts(array $mocks) {
assert_instances_of($mocks, 'PholioMock');
$phids = mpull($mocks, 'getPHID');
$counts = id(new PhabricatorTokenCountQuery())
->withObjectPHIDs($phids)
->execute();
foreach ($mocks as $mock) {
$mock->attachTokenCount(idx($counts, $mock->getPHID(), 0));
}
}
public function getQueryApplicationClass() {
return 'PhabricatorPholioApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneAccountQuery.php b/src/applications/phortune/query/PhortuneAccountQuery.php
index 676badcb0c..a567aa2d38 100644
--- a/src/applications/phortune/query/PhortuneAccountQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountQuery.php
@@ -1,123 +1,123 @@
<?php
final class PhortuneAccountQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
public static function loadAccountsForUser(
PhabricatorUser $user,
PhabricatorContentSource $content_source) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($user)
->withMemberPHIDs(array($user->getPHID()))
->execute();
if (!$accounts) {
$accounts = array(
PhortuneAccount::createNewAccount($user, $content_source),
);
}
$accounts = mpull($accounts, null, 'getPHID');
return $accounts;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMemberPHIDs(array $phids) {
$this->memberPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhortuneAccount();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT a.* FROM %T a %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $accounts) {
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($accounts, 'getPHID'))
->withEdgeTypes(array(PhortuneAccountHasMemberEdgeType::EDGECONST));
$query->execute();
foreach ($accounts as $account) {
$member_phids = $query->getDestinationPHIDs(array($account->getPHID()));
$member_phids = array_reverse($member_phids);
$account->attachMemberPHIDs($member_phids);
}
return $accounts;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids) {
$where[] = qsprintf(
$conn,
'a.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn,
'a.phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs) {
$where[] = qsprintf(
$conn,
'm.dst IN (%Ls)',
$this->memberPHIDs);
}
return $this->formatWhereClause($where);
}
private function buildJoinClause(AphrontDatabaseConnection $conn) {
$joins = array();
if ($this->memberPHIDs) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T m ON a.phid = m.src AND m.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhortuneAccountHasMemberEdgeType::EDGECONST);
}
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneCartQuery.php b/src/applications/phortune/query/PhortuneCartQuery.php
index 4897ad7f22..5009d3a685 100644
--- a/src/applications/phortune/query/PhortuneCartQuery.php
+++ b/src/applications/phortune/query/PhortuneCartQuery.php
@@ -1,223 +1,223 @@
<?php
final class PhortuneCartQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $subscriptionPHIDs;
private $statuses;
private $invoices;
private $needPurchases;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withMerchantPHIDs(array $merchant_phids) {
$this->merchantPHIDs = $merchant_phids;
return $this;
}
public function withSubscriptionPHIDs(array $subscription_phids) {
$this->subscriptionPHIDs = $subscription_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
/**
* Include or exclude carts which represent invoices with payments due.
*
* @param bool `true` to select invoices; `false` to exclude invoices.
* @return this
*/
public function withInvoices($invoices) {
$this->invoices = $invoices;
return $this;
}
public function needPurchases($need_purchases) {
$this->needPurchases = $need_purchases;
return $this;
}
protected function loadPage() {
$table = new PhortuneCart();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT cart.* FROM %T cart %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $carts) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($carts, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($carts as $key => $cart) {
$account = idx($accounts, $cart->getAccountPHID());
if (!$account) {
unset($carts[$key]);
continue;
}
$cart->attachAccount($account);
}
if (!$carts) {
return array();
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($carts, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($carts as $key => $cart) {
$merchant = idx($merchants, $cart->getMerchantPHID());
if (!$merchant) {
unset($carts[$key]);
continue;
}
$cart->attachMerchant($merchant);
}
if (!$carts) {
return array();
}
$implementations = array();
$cart_map = mgroup($carts, 'getCartClass');
foreach ($cart_map as $class => $class_carts) {
$implementations += newv($class, array())->loadImplementationsForCarts(
$this->getViewer(),
$class_carts);
}
foreach ($carts as $key => $cart) {
$implementation = idx($implementations, $key);
if (!$implementation) {
unset($carts[$key]);
continue;
}
$cart->attachImplementation($implementation);
}
return $carts;
}
protected function didFilterPage(array $carts) {
if ($this->needPurchases) {
$purchases = id(new PhortunePurchaseQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withCartPHIDs(mpull($carts, 'getPHID'))
->execute();
$purchases = mgroup($purchases, 'getCartPHID');
foreach ($carts as $cart) {
$cart->attachPurchases(idx($purchases, $cart->getPHID(), array()));
}
}
return $carts;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'cart.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'cart.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->subscriptionPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.subscriptionPHID IN (%Ls)',
$this->subscriptionPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'cart.status IN (%Ls)',
$this->statuses);
}
if ($this->invoices !== null) {
if ($this->invoices) {
$where[] = qsprintf(
$conn,
'cart.status = %s AND cart.isInvoice = 1',
PhortuneCart::STATUS_READY);
} else {
$where[] = qsprintf(
$conn,
'cart.status != %s OR cart.isInvoice = 0',
PhortuneCart::STATUS_READY);
}
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneChargeQuery.php b/src/applications/phortune/query/PhortuneChargeQuery.php
index aba655b4e4..6b11cbe95e 100644
--- a/src/applications/phortune/query/PhortuneChargeQuery.php
+++ b/src/applications/phortune/query/PhortuneChargeQuery.php
@@ -1,144 +1,144 @@
<?php
final class PhortuneChargeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $cartPHIDs;
private $statuses;
private $needCarts;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withCartPHIDs(array $cart_phids) {
$this->cartPHIDs = $cart_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needCarts($need_carts) {
$this->needCarts = $need_carts;
return $this;
}
protected function loadPage() {
$table = new PhortuneCharge();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT charge.* FROM %T charge %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $charges) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($charges, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($charges as $key => $charge) {
$account = idx($accounts, $charge->getAccountPHID());
if (!$account) {
unset($charges[$key]);
continue;
}
$charge->attachAccount($account);
}
return $charges;
}
protected function didFilterPage(array $charges) {
if ($this->needCarts) {
$carts = id(new PhortuneCartQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($charges, 'getCartPHID'))
->execute();
$carts = mpull($carts, null, 'getPHID');
foreach ($charges as $charge) {
$cart = idx($carts, $charge->getCartPHID());
$charge->attachCart($cart);
}
}
return $charges;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'charge.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'charge.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'charge.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->cartPHIDs !== null) {
$where[] = qsprintf(
$conn,
'charge.cartPHID IN (%Ls)',
$this->cartPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'charge.status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneMerchantQuery.php b/src/applications/phortune/query/PhortuneMerchantQuery.php
index 1632797421..41a6f1004d 100644
--- a/src/applications/phortune/query/PhortuneMerchantQuery.php
+++ b/src/applications/phortune/query/PhortuneMerchantQuery.php
@@ -1,103 +1,103 @@
<?php
final class PhortuneMerchantQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMemberPHIDs(array $member_phids) {
$this->memberPHIDs = $member_phids;
return $this;
}
protected function loadPage() {
$table = new PhortuneMerchant();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT m.* FROM %T m %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $merchants) {
$query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($merchants, 'getPHID'))
->withEdgeTypes(array(PhortuneMerchantHasMemberEdgeType::EDGECONST));
$query->execute();
foreach ($merchants as $merchant) {
$member_phids = $query->getDestinationPHIDs(array($merchant->getPHID()));
$member_phids = array_reverse($member_phids);
$merchant->attachMemberPHIDs($member_phids);
}
return $merchants;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn,
'e.dst IN (%Ls)',
$this->memberPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($where);
}
private function buildJoinClause(AphrontDatabaseConnection $conn) {
$joins = array();
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn,
'LEFT JOIN %T e ON m.phid = e.src AND e.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhortuneMerchantHasMemberEdgeType::EDGECONST);
}
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortunePaymentMethodQuery.php b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
index c6b1fd878a..07d49a5909 100644
--- a/src/applications/phortune/query/PhortunePaymentMethodQuery.php
+++ b/src/applications/phortune/query/PhortunePaymentMethodQuery.php
@@ -1,156 +1,156 @@
<?php
final class PhortunePaymentMethodQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $phids) {
$this->accountPHIDs = $phids;
return $this;
}
public function withMerchantPHIDs(array $phids) {
$this->merchantPHIDs = $phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
protected function loadPage() {
$table = new PhortunePaymentMethod();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $methods) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($methods as $key => $method) {
$account = idx($accounts, $method->getAccountPHID());
if (!$account) {
unset($methods[$key]);
continue;
}
$method->attachAccount($account);
}
if (!$methods) {
return $methods;
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($methods as $key => $method) {
$merchant = idx($merchants, $method->getMerchantPHID());
if (!$merchant) {
unset($methods[$key]);
continue;
}
$method->attachMerchant($merchant);
}
if (!$methods) {
return $methods;
}
$provider_configs = id(new PhortunePaymentProviderConfigQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($methods, 'getProviderPHID'))
->execute();
$provider_configs = mpull($provider_configs, null, 'getPHID');
foreach ($methods as $key => $method) {
$provider_config = idx($provider_configs, $method->getProviderPHID());
if (!$provider_config) {
unset($methods[$key]);
continue;
}
$method->attachProviderConfig($provider_config);
}
return $methods;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'status IN (%Ls)',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php b/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
index 748ff7cb64..d80b0e90d0 100644
--- a/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
+++ b/src/applications/phortune/query/PhortunePaymentProviderConfigQuery.php
@@ -1,95 +1,95 @@
<?php
final class PhortunePaymentProviderConfigQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $merchantPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMerchantPHIDs(array $phids) {
$this->merchantPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhortunePaymentProviderConfig();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $provider_configs) {
$merchant_phids = mpull($provider_configs, 'getMerchantPHID');
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($merchant_phids)
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($provider_configs as $key => $config) {
$merchant = idx($merchants, $config->getMerchantPHID());
if (!$merchant) {
$this->didRejectResult($config);
unset($provider_configs[$key]);
continue;
}
$config->attachMerchant($merchant);
}
return $provider_configs;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneProductQuery.php b/src/applications/phortune/query/PhortuneProductQuery.php
index ae824ab914..99ba535585 100644
--- a/src/applications/phortune/query/PhortuneProductQuery.php
+++ b/src/applications/phortune/query/PhortuneProductQuery.php
@@ -1,120 +1,120 @@
<?php
final class PhortuneProductQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $refMap;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withClassAndRef($class, $ref) {
$this->refMap = array($class => array($ref));
return $this;
}
protected function loadPage() {
$table = new PhortuneProduct();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
$page = $table->loadAllFromArray($rows);
// NOTE: We're loading product implementations here, but also creating any
// products which do not yet exist.
$class_map = mgroup($page, 'getProductClass');
if ($this->refMap) {
$class_map += array_fill_keys(array_keys($this->refMap), array());
}
foreach ($class_map as $class => $products) {
$refs = mpull($products, null, 'getProductRef');
if (isset($this->refMap[$class])) {
$refs += array_fill_keys($this->refMap[$class], null);
}
$implementations = newv($class, array())->loadImplementationsForRefs(
$this->getViewer(),
array_keys($refs));
$implementations = mpull($implementations, null, 'getRef');
foreach ($implementations as $ref => $implementation) {
$product = idx($refs, $ref);
if ($product === null) {
// If this product does not exist yet, create it and add it to the
// result page.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$product = PhortuneProduct::initializeNewProduct()
->setProductClass($class)
->setProductRef($ref)
->save();
unset($unguarded);
$page[] = $product;
}
$product->attachImplementation($implementation);
}
}
return $page;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->refMap !== null) {
$sql = array();
foreach ($this->refMap as $class => $refs) {
foreach ($refs as $ref) {
$sql[] = qsprintf(
$conn,
'(productClassKey = %s AND productRefKey = %s)',
PhabricatorHash::digestForIndex($class),
PhabricatorHash::digestForIndex($ref));
}
}
$where[] = implode(' OR ', $sql);
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortunePurchaseQuery.php b/src/applications/phortune/query/PhortunePurchaseQuery.php
index 70aff445a0..6e9e599240 100644
--- a/src/applications/phortune/query/PhortunePurchaseQuery.php
+++ b/src/applications/phortune/query/PhortunePurchaseQuery.php
@@ -1,110 +1,110 @@
<?php
final class PhortunePurchaseQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $cartPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCartPHIDs(array $cart_phids) {
$this->cartPHIDs = $cart_phids;
return $this;
}
protected function loadPage() {
$table = new PhortunePurchase();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT purchase.* FROM %T purchase %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $purchases) {
$carts = id(new PhortuneCartQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($purchases, 'getCartPHID'))
->execute();
$carts = mpull($carts, null, 'getPHID');
foreach ($purchases as $key => $purchase) {
$cart = idx($carts, $purchase->getCartPHID());
if (!$cart) {
unset($purchases[$key]);
continue;
}
$purchase->attachCart($cart);
}
$products = id(new PhortuneProductQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs(mpull($purchases, 'getProductPHID'))
->execute();
$products = mpull($products, null, 'getPHID');
foreach ($purchases as $key => $purchase) {
$product = idx($products, $purchase->getProductPHID());
if (!$product) {
unset($purchases[$key]);
continue;
}
$purchase->attachProduct($product);
}
return $purchases;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'purchase.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'purchase.phid IN (%Ls)',
$this->phids);
}
if ($this->cartPHIDs !== null) {
$where[] = qsprintf(
$conn,
'purchase.cartPHID IN (%Ls)',
$this->cartPHIDs);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phortune/query/PhortuneSubscriptionQuery.php b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
index ba6d7acc73..e8b39c0fee 100644
--- a/src/applications/phortune/query/PhortuneSubscriptionQuery.php
+++ b/src/applications/phortune/query/PhortuneSubscriptionQuery.php
@@ -1,192 +1,192 @@
<?php
final class PhortuneSubscriptionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $accountPHIDs;
private $merchantPHIDs;
private $statuses;
private $needTriggers;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAccountPHIDs(array $account_phids) {
$this->accountPHIDs = $account_phids;
return $this;
}
public function withMerchantPHIDs(array $merchant_phids) {
$this->merchantPHIDs = $merchant_phids;
return $this;
}
public function withStatuses(array $statuses) {
$this->statuses = $statuses;
return $this;
}
public function needTriggers($need_triggers) {
$this->needTriggers = $need_triggers;
return $this;
}
protected function loadPage() {
$table = new PhortuneSubscription();
$conn = $table->establishConnection('r');
$rows = queryfx_all(
$conn,
'SELECT subscription.* FROM %T subscription %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $subscriptions) {
$accounts = id(new PhortuneAccountQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($subscriptions, 'getAccountPHID'))
->execute();
$accounts = mpull($accounts, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$account = idx($accounts, $subscription->getAccountPHID());
if (!$account) {
unset($subscriptions[$key]);
continue;
}
$subscription->attachAccount($account);
}
if (!$subscriptions) {
return $subscriptions;
}
$merchants = id(new PhortuneMerchantQuery())
->setViewer($this->getViewer())
->withPHIDs(mpull($subscriptions, 'getMerchantPHID'))
->execute();
$merchants = mpull($merchants, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$merchant = idx($merchants, $subscription->getMerchantPHID());
if (!$merchant) {
unset($subscriptions[$key]);
continue;
}
$subscription->attachMerchant($merchant);
}
if (!$subscriptions) {
return $subscriptions;
}
$implementations = array();
$subscription_map = mgroup($subscriptions, 'getSubscriptionClass');
foreach ($subscription_map as $class => $class_subscriptions) {
$sub = newv($class, array());
$impl_objects = $sub->loadImplementationsForRefs(
$this->getViewer(),
mpull($class_subscriptions, 'getSubscriptionRef'));
$implementations += mpull($impl_objects, null, 'getRef');
}
foreach ($subscriptions as $key => $subscription) {
$ref = $subscription->getSubscriptionRef();
$implementation = idx($implementations, $ref);
if (!$implementation) {
unset($subscriptions[$key]);
continue;
}
$subscription->attachImplementation($implementation);
}
if (!$subscriptions) {
return $subscriptions;
}
if ($this->needTriggers) {
$trigger_phids = mpull($subscriptions, 'getTriggerPHID');
$triggers = id(new PhabricatorWorkerTriggerQuery())
->setViewer($this->getViewer())
->withPHIDs($trigger_phids)
->needEvents(true)
->execute();
$triggers = mpull($triggers, null, 'getPHID');
foreach ($subscriptions as $key => $subscription) {
$trigger = idx($triggers, $subscription->getTriggerPHID());
if (!$trigger) {
unset($subscriptions[$key]);
continue;
}
$subscription->attachTrigger($trigger);
}
}
return $subscriptions;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
$where[] = $this->buildPagingClause($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'subscription.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'subscription.phid IN (%Ls)',
$this->phids);
}
if ($this->accountPHIDs !== null) {
$where[] = qsprintf(
$conn,
'subscription.accountPHID IN (%Ls)',
$this->accountPHIDs);
}
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'subscription.merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn,
'subscription.status IN (%Ls)',
$this->statuses);
}
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorPhortuneApplication';
}
}
diff --git a/src/applications/phragment/query/PhragmentFragmentQuery.php b/src/applications/phragment/query/PhragmentFragmentQuery.php
index 173acfb1ce..d6dc67609d 100644
--- a/src/applications/phragment/query/PhragmentFragmentQuery.php
+++ b/src/applications/phragment/query/PhragmentFragmentQuery.php
@@ -1,130 +1,130 @@
<?php
final class PhragmentFragmentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $paths;
private $leadingPath;
private $depths;
private $needLatestVersion;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withPaths(array $paths) {
$this->paths = $paths;
return $this;
}
public function withLeadingPath($path) {
$this->leadingPath = $path;
return $this;
}
public function withDepths($depths) {
$this->depths = $depths;
return $this;
}
public function needLatestVersion($need_latest_version) {
$this->needLatestVersion = $need_latest_version;
return $this;
}
protected function loadPage() {
$table = new PhragmentFragment();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->paths) {
$where[] = qsprintf(
$conn_r,
'path IN (%Ls)',
$this->paths);
}
if ($this->leadingPath) {
$where[] = qsprintf(
$conn_r,
'path LIKE %>',
$this->leadingPath);
}
if ($this->depths) {
$where[] = qsprintf(
$conn_r,
'depth IN (%Ld)',
$this->depths);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function didFilterPage(array $page) {
if ($this->needLatestVersion) {
$versions = array();
$version_phids = array_filter(mpull($page, 'getLatestVersionPHID'));
if ($version_phids) {
$versions = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($version_phids)
->setParentQuery($this)
->execute();
$versions = mpull($versions, null, 'getPHID');
}
foreach ($page as $key => $fragment) {
$version_phid = $fragment->getLatestVersionPHID();
if (empty($versions[$version_phid])) {
continue;
}
$fragment->attachLatestVersion($versions[$version_phid]);
}
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}
diff --git a/src/applications/phragment/query/PhragmentFragmentVersionQuery.php b/src/applications/phragment/query/PhragmentFragmentVersionQuery.php
index 4acbd0f636..a874a8be1a 100644
--- a/src/applications/phragment/query/PhragmentFragmentVersionQuery.php
+++ b/src/applications/phragment/query/PhragmentFragmentVersionQuery.php
@@ -1,123 +1,123 @@
<?php
final class PhragmentFragmentVersionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $fragmentPHIDs;
private $sequences;
private $sequenceBefore;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withFragmentPHIDs(array $fragment_phids) {
$this->fragmentPHIDs = $fragment_phids;
return $this;
}
public function withSequences(array $sequences) {
$this->sequences = $sequences;
return $this;
}
public function withSequenceBefore($current) {
$this->sequenceBefore = $current;
return $this;
}
protected function loadPage() {
$table = new PhragmentFragmentVersion();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->fragmentPHIDs) {
$where[] = qsprintf(
$conn_r,
'fragmentPHID IN (%Ls)',
$this->fragmentPHIDs);
}
if ($this->sequences) {
$where[] = qsprintf(
$conn_r,
'sequence IN (%Ld)',
$this->sequences);
}
if ($this->sequenceBefore !== null) {
$where[] = qsprintf(
$conn_r,
'sequence < %d',
$this->sequenceBefore);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $page) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $version) {
$fragment_phid = $version->getFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$version->attachFragment($fragments[$fragment_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}
diff --git a/src/applications/phragment/query/PhragmentSnapshotChildQuery.php b/src/applications/phragment/query/PhragmentSnapshotChildQuery.php
index 8f81beeabe..032fb0c49c 100644
--- a/src/applications/phragment/query/PhragmentSnapshotChildQuery.php
+++ b/src/applications/phragment/query/PhragmentSnapshotChildQuery.php
@@ -1,174 +1,174 @@
<?php
final class PhragmentSnapshotChildQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $snapshotPHIDs;
private $fragmentPHIDs;
private $fragmentVersionPHIDs;
private $needFragments;
private $needFragmentVersions;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withSnapshotPHIDs(array $snapshot_phids) {
$this->snapshotPHIDs = $snapshot_phids;
return $this;
}
public function withFragmentPHIDs(array $fragment_phids) {
$this->fragmentPHIDs = $fragment_phids;
return $this;
}
public function withFragmentVersionPHIDs(array $fragment_version_phids) {
$this->fragmentVersionPHIDs = $fragment_version_phids;
return $this;
}
public function needFragments($need_fragments) {
$this->needFragments = $need_fragments;
return $this;
}
public function needFragmentVersions($need_fragment_versions) {
$this->needFragmentVersions = $need_fragment_versions;
return $this;
}
protected function loadPage() {
$table = new PhragmentSnapshotChild();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->snapshotPHIDs) {
$where[] = qsprintf(
$conn_r,
'snapshotPHID IN (%Ls)',
$this->snapshotPHIDs);
}
if ($this->fragmentPHIDs) {
$where[] = qsprintf(
$conn_r,
'fragmentPHID IN (%Ls)',
$this->fragmentPHIDs);
}
if ($this->fragmentVersionPHIDs) {
$where[] = qsprintf(
$conn_r,
'fragmentVersionPHID IN (%Ls)',
$this->fragmentVersionPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $page) {
$snapshots = array();
$snapshot_phids = array_filter(mpull($page, 'getSnapshotPHID'));
if ($snapshot_phids) {
$snapshots = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($snapshot_phids)
->setParentQuery($this)
->execute();
$snapshots = mpull($snapshots, null, 'getPHID');
}
foreach ($page as $key => $child) {
$snapshot_phid = $child->getSnapshotPHID();
if (empty($snapshots[$snapshot_phid])) {
unset($page[$key]);
continue;
}
$child->attachSnapshot($snapshots[$snapshot_phid]);
}
return $page;
}
protected function didFilterPage(array $page) {
if ($this->needFragments) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $child) {
$fragment_phid = $child->getFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$child->attachFragment($fragments[$fragment_phid]);
}
}
if ($this->needFragmentVersions) {
$fragment_versions = array();
$fragment_version_phids = array_filter(mpull(
$page,
'getFragmentVersionPHID'));
if ($fragment_version_phids) {
$fragment_versions = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_version_phids)
->setParentQuery($this)
->execute();
$fragment_versions = mpull($fragment_versions, null, 'getPHID');
}
foreach ($page as $key => $child) {
$fragment_version_phid = $child->getFragmentVersionPHID();
if (empty($fragment_versions[$fragment_version_phid])) {
continue;
}
$child->attachFragmentVersion(
$fragment_versions[$fragment_version_phid]);
}
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}
diff --git a/src/applications/phragment/query/PhragmentSnapshotQuery.php b/src/applications/phragment/query/PhragmentSnapshotQuery.php
index 81c73441d2..d6f9d3422f 100644
--- a/src/applications/phragment/query/PhragmentSnapshotQuery.php
+++ b/src/applications/phragment/query/PhragmentSnapshotQuery.php
@@ -1,111 +1,111 @@
<?php
final class PhragmentSnapshotQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $primaryFragmentPHIDs;
private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withPrimaryFragmentPHIDs(array $primary_fragment_phids) {
$this->primaryFragmentPHIDs = $primary_fragment_phids;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
protected function loadPage() {
$table = new PhragmentSnapshot();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- protected function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->primaryFragmentPHIDs) {
$where[] = qsprintf(
$conn_r,
'primaryFragmentPHID IN (%Ls)',
$this->primaryFragmentPHIDs);
}
if ($this->names) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $page) {
$fragments = array();
$fragment_phids = array_filter(mpull($page, 'getPrimaryFragmentPHID'));
if ($fragment_phids) {
$fragments = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($fragment_phids)
->setParentQuery($this)
->execute();
$fragments = mpull($fragments, null, 'getPHID');
}
foreach ($page as $key => $snapshot) {
$fragment_phid = $snapshot->getPrimaryFragmentPHID();
if (empty($fragments[$fragment_phid])) {
unset($page[$key]);
continue;
}
$snapshot->attachPrimaryFragment($fragments[$fragment_phid]);
}
return $page;
}
public function getQueryApplicationClass() {
return 'PhabricatorPhragmentApplication';
}
}
diff --git a/src/applications/phrequent/query/PhrequentUserTimeQuery.php b/src/applications/phrequent/query/PhrequentUserTimeQuery.php
index b6e0c85f48..61fa978165 100644
--- a/src/applications/phrequent/query/PhrequentUserTimeQuery.php
+++ b/src/applications/phrequent/query/PhrequentUserTimeQuery.php
@@ -1,333 +1,333 @@
<?php
final class PhrequentUserTimeQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
const ORDER_ID_ASC = 0;
const ORDER_ID_DESC = 1;
const ORDER_STARTED_ASC = 2;
const ORDER_STARTED_DESC = 3;
const ORDER_ENDED_ASC = 4;
const ORDER_ENDED_DESC = 5;
const ENDED_YES = 0;
const ENDED_NO = 1;
const ENDED_ALL = 2;
private $ids;
private $userPHIDs;
private $objectPHIDs;
private $ended = self::ENDED_ALL;
private $needPreemptingEvents;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withEnded($ended) {
$this->ended = $ended;
return $this;
}
public function setOrder($order) {
switch ($order) {
case self::ORDER_ID_ASC:
$this->setOrderVector(array('-id'));
break;
case self::ORDER_ID_DESC:
$this->setOrderVector(array('id'));
break;
case self::ORDER_STARTED_ASC:
$this->setOrderVector(array('-start', '-id'));
break;
case self::ORDER_STARTED_DESC:
$this->setOrderVector(array('start', 'id'));
break;
case self::ORDER_ENDED_ASC:
$this->setOrderVector(array('-end', '-id'));
break;
case self::ORDER_ENDED_DESC:
$this->setOrderVector(array('end', 'id'));
break;
default:
throw new Exception(pht('Unknown order "%s".', $order));
}
return $this;
}
public function needPreemptingEvents($need_events) {
$this->needPreemptingEvents = $need_events;
return $this;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->userPHIDs !== null) {
$where[] = qsprintf(
$conn,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
switch ($this->ended) {
case self::ENDED_ALL:
break;
case self::ENDED_YES:
$where[] = qsprintf(
$conn,
'dateEnded IS NOT NULL');
break;
case self::ENDED_NO:
$where[] = qsprintf(
$conn,
'dateEnded IS NULL');
break;
default:
throw new Exception("Unknown ended '{$this->ended}'!");
}
$where[] = $this->buildPagingClause($conn);
return $this->formatWhereClause($where);
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'start' => array(
'column' => 'dateStarted',
'type' => 'int',
),
'end' => array(
'column' => 'dateEnded',
'type' => 'int',
'null' => 'head',
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$usertime = $this->loadCursorObject($cursor);
return array(
'id' => $usertime->getID(),
'start' => $usertime->getDateStarted(),
'end' => $usertime->getDateEnded(),
);
}
protected function loadPage() {
$usertime = new PhrequentUserTime();
$conn = $usertime->establishConnection('r');
$data = queryfx_all(
$conn,
'SELECT usertime.* FROM %T usertime %Q %Q %Q',
$usertime->getTableName(),
$this->buildWhereClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
return $usertime->loadAllFromArray($data);
}
protected function didFilterPage(array $page) {
if ($this->needPreemptingEvents) {
$usertime = new PhrequentUserTime();
$conn_r = $usertime->establishConnection('r');
$preempt = array();
foreach ($page as $event) {
$preempt[] = qsprintf(
$conn_r,
'(userPHID = %s AND
(dateStarted BETWEEN %d AND %d) AND
(dateEnded IS NULL OR dateEnded > %d))',
$event->getUserPHID(),
$event->getDateStarted(),
nonempty($event->getDateEnded(), PhabricatorTime::getNow()),
$event->getDateStarted());
}
$preempting_events = queryfx_all(
$conn_r,
'SELECT * FROM %T WHERE %Q ORDER BY dateStarted ASC, id ASC',
$usertime->getTableName(),
implode(' OR ', $preempt));
$preempting_events = $usertime->loadAllFromArray($preempting_events);
$preempting_events = mgroup($preempting_events, 'getUserPHID');
foreach ($page as $event) {
$e_start = $event->getDateStarted();
$e_end = $event->getDateEnded();
$select = array();
$user_events = idx($preempting_events, $event->getUserPHID(), array());
foreach ($user_events as $u_event) {
if ($u_event->getID() == $event->getID()) {
// Don't allow an event to preempt itself.
continue;
}
$u_start = $u_event->getDateStarted();
$u_end = $u_event->getDateEnded();
if ($u_start < $e_start) {
// This event started before our event started, so it's not
// preempting us.
continue;
}
if ($u_start == $e_start) {
if ($u_event->getID() < $event->getID()) {
// This event started at the same time as our event started,
// but has a lower ID, so it's not preempting us.
continue;
}
}
if (($e_end !== null) && ($u_start > $e_end)) {
// Our event has ended, and this event started after it ended.
continue;
}
if (($u_end !== null) && ($u_end < $e_start)) {
// This event ended before our event began.
continue;
}
$select[] = $u_event;
}
$event->attachPreemptingEvents($select);
}
}
return $page;
}
/* -( Helper Functions ) --------------------------------------------------- */
public static function getEndedSearchOptions() {
return array(
self::ENDED_ALL => pht('All'),
self::ENDED_NO => pht('No'),
self::ENDED_YES => pht('Yes'),
);
}
public static function getOrderSearchOptions() {
return array(
self::ORDER_STARTED_ASC => pht('by furthest start date'),
self::ORDER_STARTED_DESC => pht('by nearest start date'),
self::ORDER_ENDED_ASC => pht('by furthest end date'),
self::ORDER_ENDED_DESC => pht('by nearest end date'),
);
}
public static function getUserTotalObjectsTracked(
PhabricatorUser $user,
$limit = PHP_INT_MAX) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
$count = queryfx_one(
$conn,
'SELECT COUNT(usertime.id) N FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.dateEnded IS NULL '.
'LIMIT %d',
$usertime_dao->getTableName(),
$user->getPHID(),
$limit);
return $count['N'];
}
public static function isUserTrackingObject(
PhabricatorUser $user,
$phid) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
$count = queryfx_one(
$conn,
'SELECT COUNT(usertime.id) N FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
return $count['N'] > 0;
}
public static function getUserTimeSpentOnObject(
PhabricatorUser $user,
$phid) {
$usertime_dao = new PhrequentUserTime();
$conn = $usertime_dao->establishConnection('r');
// First calculate all the time spent where the
// usertime blocks have ended.
$sum_ended = queryfx_one(
$conn,
'SELECT SUM(usertime.dateEnded - usertime.dateStarted) N '.
'FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NOT NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
// Now calculate the time spent where the usertime
// blocks have not yet ended.
$sum_not_ended = queryfx_one(
$conn,
'SELECT SUM(UNIX_TIMESTAMP() - usertime.dateStarted) N '.
'FROM %T usertime '.
'WHERE usertime.userPHID = %s '.
'AND usertime.objectPHID = %s '.
'AND usertime.dateEnded IS NULL',
$usertime_dao->getTableName(),
$user->getPHID(),
$phid);
return $sum_ended['N'] + $sum_not_ended['N'];
}
public function getQueryApplicationClass() {
return 'PhabricatorPhrequentApplication';
}
}
diff --git a/src/applications/ponder/query/PonderAnswerQuery.php b/src/applications/ponder/query/PonderAnswerQuery.php
index 1b5c66a10c..0fe61bc9e1 100644
--- a/src/applications/ponder/query/PonderAnswerQuery.php
+++ b/src/applications/ponder/query/PonderAnswerQuery.php
@@ -1,125 +1,125 @@
<?php
final class PonderAnswerQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $questionIDs;
private $needViewerVotes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withQuestionIDs(array $ids) {
$this->questionIDs = $ids;
return $this;
}
public function needViewerVotes($need_viewer_votes) {
$this->needViewerVotes = $need_viewer_votes;
return $this;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function loadPage() {
$answer = new PonderAnswer();
$conn_r = $answer->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT a.* FROM %T a %Q %Q %Q',
$answer->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $answer->loadAllFromArray($data);
}
protected function willFilterPage(array $answers) {
$questions = id(new PonderQuestionQuery())
->setViewer($this->getViewer())
->withIDs(mpull($answers, 'getQuestionID'))
->execute();
foreach ($answers as $key => $answer) {
$question = idx($questions, $answer->getQuestionID());
if (!$question) {
unset($answers[$key]);
continue;
}
$answer->attachQuestion($question);
}
if ($this->needViewerVotes) {
$viewer_phid = $this->getViewer()->getPHID();
$etype = PonderAnswerHasVotingUserEdgeType::EDGECONST;
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($answers, 'getPHID'))
->withDestinationPHIDs(array($viewer_phid))
->withEdgeTypes(array($etype))
->needEdgeData(true)
->execute();
foreach ($answers as $answer) {
$user_edge = idx(
$edges[$answer->getPHID()][$etype],
$viewer_phid,
array());
$answer->attachUserVote($viewer_phid, idx($user_edge, 'data', 0));
}
}
return $answers;
}
public function getQueryApplicationClass() {
return 'PhabricatorPonderApplication';
}
}
diff --git a/src/applications/ponder/query/PonderQuestionQuery.php b/src/applications/ponder/query/PonderQuestionQuery.php
index 9cb8c81d40..51081b3203 100644
--- a/src/applications/ponder/query/PonderQuestionQuery.php
+++ b/src/applications/ponder/query/PonderQuestionQuery.php
@@ -1,182 +1,182 @@
<?php
final class PonderQuestionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $answererPHIDs;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
private $needAnswers;
private $needViewerVotes;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withAnswererPHIDs(array $phids) {
$this->answererPHIDs = $phids;
return $this;
}
public function needAnswers($need_answers) {
$this->needAnswers = $need_answers;
return $this;
}
public function needViewerVotes($need_viewer_votes) {
$this->needViewerVotes = $need_viewer_votes;
return $this;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'q.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'q.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'q.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->status) {
switch ($this->status) {
case self::STATUS_ANY:
break;
case self::STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'q.status = %d',
PonderQuestionStatus::STATUS_OPEN);
break;
case self::STATUS_CLOSED:
$where[] = qsprintf(
$conn_r,
'q.status = %d',
PonderQuestionStatus::STATUS_CLOSED);
break;
default:
throw new Exception("Unknown status query '{$this->status}'!");
}
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function loadPage() {
$question = new PonderQuestion();
$conn_r = $question->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT q.* FROM %T q %Q %Q %Q %Q',
$question->getTableName(),
$this->buildJoinsClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $question->loadAllFromArray($data);
}
protected function willFilterPage(array $questions) {
if ($this->needAnswers) {
$aquery = id(new PonderAnswerQuery())
->setViewer($this->getViewer())
->setOrderVector(array('-id'))
->withQuestionIDs(mpull($questions, 'getID'));
if ($this->needViewerVotes) {
$aquery->needViewerVotes($this->needViewerVotes);
}
$answers = $aquery->execute();
$answers = mgroup($answers, 'getQuestionID');
foreach ($questions as $question) {
$question_answers = idx($answers, $question->getID(), array());
$question->attachAnswers(mpull($question_answers, null, 'getPHID'));
}
}
if ($this->needViewerVotes) {
$viewer_phid = $this->getViewer()->getPHID();
$etype = PonderQuestionHasVotingUserEdgeType::EDGECONST;
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($questions, 'getPHID'))
->withDestinationPHIDs(array($viewer_phid))
->withEdgeTypes(array($etype))
->needEdgeData(true)
->execute();
foreach ($questions as $question) {
$user_edge = idx(
$edges[$question->getPHID()][$etype],
$viewer_phid,
array());
$question->attachUserVote($viewer_phid, idx($user_edge, 'data', 0));
}
}
return $questions;
}
private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if ($this->answererPHIDs) {
$answer_table = new PonderAnswer();
$joins[] = qsprintf(
$conn_r,
'JOIN %T a ON a.questionID = q.id AND a.authorPHID IN (%Ls)',
$answer_table->getTableName(),
$this->answererPHIDs);
}
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorPonderApplication';
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
index 87bd87ffd3..3348b4054d 100644
--- a/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnPositionQuery.php
@@ -1,306 +1,306 @@
<?php
final class PhabricatorProjectColumnPositionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $boardPHIDs;
private $objectPHIDs;
private $columns;
private $needColumns;
private $skipImplicitCreate;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withBoardPHIDs(array $board_phids) {
$this->boardPHIDs = $board_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
/**
* Find objects in specific columns.
*
* NOTE: Using this method activates logic which constructs virtual
* column positions for objects not in any column, if you pass a default
* column. Normally these results are not returned.
*
* @param list<PhabricatorProjectColumn> Columns to look for objects in.
* @return this
*/
public function withColumns(array $columns) {
assert_instances_of($columns, 'PhabricatorProjectColumn');
$this->columns = $columns;
return $this;
}
public function needColumns($need_columns) {
$this->needColumns = true;
return $this;
}
/**
* Skip implicit creation of column positions which are implied but do not
* yet exist.
*
* This is primarily useful internally.
*
* @param bool True to skip implicit creation of column positions.
* @return this
*/
public function setSkipImplicitCreate($skip) {
$this->skipImplicitCreate = $skip;
return $this;
}
// NOTE: For now, boards are always attached to projects. However, they might
// not be in the future. This generalization just anticipates a future where
// we let other types of objects (like users) have boards, or let boards
// contain other types of objects.
private function newPositionObject() {
return new PhabricatorProjectColumnPosition();
}
private function newColumnQuery() {
return new PhabricatorProjectColumnQuery();
}
private function getBoardMembershipEdgeTypes() {
return array(
PhabricatorProjectProjectHasObjectEdgeType::EDGECONST,
);
}
private function getBoardMembershipPHIDTypes() {
return array(
ManiphestTaskPHIDType::TYPECONST,
);
}
protected function loadPage() {
$table = $this->newPositionObject();
$conn_r = $table->establishConnection('r');
// We're going to find results by combining two queries: one query finds
// objects on a board column, while the other query finds objects not on
// any board column and virtually puts them on the default column.
$unions = array();
// First, find all the stuff that's actually on a column.
$unions[] = qsprintf(
$conn_r,
'SELECT * FROM %T %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r));
// If we have a default column, find all the stuff that's not in any
// column and put it in the default column.
$must_type_filter = false;
if ($this->columns && !$this->skipImplicitCreate) {
$default_map = array();
foreach ($this->columns as $column) {
if ($column->isDefaultColumn()) {
$default_map[$column->getProjectPHID()] = $column->getPHID();
}
}
if ($default_map) {
$where = array();
// Find the edges attached to the boards we have default columns for.
$where[] = qsprintf(
$conn_r,
'e.src IN (%Ls)',
array_keys($default_map));
// Find only edges which describe a board relationship.
$where[] = qsprintf(
$conn_r,
'e.type IN (%Ld)',
$this->getBoardMembershipEdgeTypes());
if ($this->boardPHIDs !== null) {
// This should normally be redundant, but construct it anyway if
// the caller has told us to.
$where[] = qsprintf(
$conn_r,
'e.src IN (%Ls)',
$this->boardPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'e.dst IN (%Ls)',
$this->objectPHIDs);
}
$where[] = qsprintf(
$conn_r,
'p.id IS NULL');
$where = $this->formatWhereClause($where);
$unions[] = qsprintf(
$conn_r,
'SELECT NULL id, e.src boardPHID, NULL columnPHID, e.dst objectPHID,
0 sequence
FROM %T e LEFT JOIN %T p
ON e.src = p.boardPHID AND e.dst = p.objectPHID
%Q',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
$table->getTableName(),
$where);
$must_type_filter = true;
}
}
$data = queryfx_all(
$conn_r,
'%Q %Q %Q',
implode(' UNION ALL ', $unions),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
// If we've picked up objects not in any column, we need to filter out any
// matched objects which have the wrong edge type.
if ($must_type_filter) {
$allowed_types = array_fuse($this->getBoardMembershipPHIDTypes());
foreach ($data as $id => $row) {
if ($row['columnPHID'] === null) {
$object_phid = $row['objectPHID'];
if (empty($allowed_types[phid_get_type($object_phid)])) {
unset($data[$id]);
}
}
}
}
$positions = $table->loadAllFromArray($data);
// Find the implied positions which don't exist yet. If there are any,
// we're going to create them.
$create = array();
foreach ($positions as $position) {
if ($position->getColumnPHID() === null) {
$column_phid = idx($default_map, $position->getBoardPHID());
$position->setColumnPHID($column_phid);
$create[] = $position;
}
}
if ($create) {
// If we're adding several objects to a column, insert the column
// position objects in object ID order. This means that newly added
// objects float to the top, and when a group of newly added objects
// float up at the same time, the most recently created ones end up
// highest in the list.
$objects = id(new PhabricatorObjectQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(mpull($create, 'getObjectPHID'))
->execute();
$objects = mpull($objects, null, 'getPHID');
$objects = msort($objects, 'getID');
$create = mgroup($create, 'getObjectPHID');
$create = array_select_keys($create, array_keys($objects)) + $create;
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
foreach ($create as $object_phid => $create_positions) {
foreach ($create_positions as $create_position) {
$create_position->save();
}
}
unset($unguarded);
}
return $positions;
}
protected function willFilterPage(array $page) {
if ($this->needColumns) {
$column_phids = mpull($page, 'getColumnPHID');
$columns = $this->newColumnQuery()
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($column_phids)
->execute();
$columns = mpull($columns, null, 'getPHID');
foreach ($page as $key => $position) {
$column = idx($columns, $position->getColumnPHID());
if (!$column) {
unset($page[$key]);
continue;
}
$position->attachColumn($column);
}
}
return $page;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->boardPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'boardPHID IN (%Ls)',
$this->boardPHIDs);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->columns !== null) {
$where[] = qsprintf(
$conn_r,
'columnPHID IN (%Ls)',
mpull($this->columns, 'getPHID'));
}
// NOTE: Explicitly not building the paging clause here, since it won't
// work with the UNION.
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorProjectApplication';
}
}
diff --git a/src/applications/project/query/PhabricatorProjectColumnQuery.php b/src/applications/project/query/PhabricatorProjectColumnQuery.php
index d369161fe3..c486968070 100644
--- a/src/applications/project/query/PhabricatorProjectColumnQuery.php
+++ b/src/applications/project/query/PhabricatorProjectColumnQuery.php
@@ -1,112 +1,112 @@
<?php
final class PhabricatorProjectColumnQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $projectPHIDs;
private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withProjectPHIDs(array $project_phids) {
$this->projectPHIDs = $project_phids;
return $this;
}
public function withStatuses(array $status) {
$this->statuses = $status;
return $this;
}
protected function loadPage() {
$table = new PhabricatorProjectColumn();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $page) {
$projects = array();
$project_phids = array_filter(mpull($page, 'getProjectPHID'));
if ($project_phids) {
$projects = id(new PhabricatorProjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($project_phids)
->execute();
$projects = mpull($projects, null, 'getPHID');
}
foreach ($page as $key => $column) {
$phid = $column->getProjectPHID();
$project = idx($projects, $phid);
if (!$project) {
unset($page[$key]);
continue;
}
$column->attachProject($project);
}
return $page;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->projectPHIDs) {
$where[] = qsprintf(
$conn_r,
'projectPHID IN (%Ls)',
$this->projectPHIDs);
}
if ($this->statuses !== null) {
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
$this->statuses);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorProjectApplication';
}
}
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
index 4b6ad566a7..f743be7295 100644
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -1,393 +1,393 @@
<?php
final class PhabricatorProjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $memberPHIDs;
private $slugs;
private $phrictionSlugs;
private $names;
private $nameTokens;
private $icons;
private $colors;
private $status = 'status-any';
const STATUS_ANY = 'status-any';
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ACTIVE = 'status-active';
const STATUS_ARCHIVED = 'status-archived';
private $needSlugs;
private $needMembers;
private $needWatchers;
private $needImages;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withMemberPHIDs(array $member_phids) {
$this->memberPHIDs = $member_phids;
return $this;
}
public function withSlugs(array $slugs) {
$this->slugs = $slugs;
return $this;
}
public function withPhrictionSlugs(array $slugs) {
$this->phrictionSlugs = $slugs;
return $this;
}
public function withNames(array $names) {
$this->names = $names;
return $this;
}
public function withNameTokens(array $tokens) {
$this->nameTokens = array_values($tokens);
return $this;
}
public function withIcons(array $icons) {
$this->icons = $icons;
return $this;
}
public function withColors(array $colors) {
$this->colors = $colors;
return $this;
}
public function needMembers($need_members) {
$this->needMembers = $need_members;
return $this;
}
public function needWatchers($need_watchers) {
$this->needWatchers = $need_watchers;
return $this;
}
public function needImages($need_images) {
$this->needImages = $need_images;
return $this;
}
public function needSlugs($need_slugs) {
$this->needSlugs = $need_slugs;
return $this;
}
protected function getDefaultOrderVector() {
return array('name');
}
public function getOrderableColumns() {
return array(
'name' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'name',
'reverse' => true,
'type' => 'string',
'unique' => true,
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$project = $this->loadCursorObject($cursor);
return array(
'name' => $project->getName(),
);
}
protected function loadPage() {
$table = new PhabricatorProject();
$conn_r = $table->establishConnection('r');
// NOTE: Because visibility checks for projects depend on whether or not
// the user is a project member, we always load their membership. If we're
// loading all members anyway we can piggyback on that; otherwise we
// do an explicit join.
$select_clause = '';
if (!$this->needMembers) {
$select_clause = ', vm.dst viewerIsMember';
}
$data = queryfx_all(
$conn_r,
'SELECT p.* %Q FROM %T p %Q %Q %Q %Q %Q',
$select_clause,
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$projects = $table->loadAllFromArray($data);
if ($projects) {
$viewer_phid = $this->getViewer()->getPHID();
$project_phids = mpull($projects, 'getPHID');
$member_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
$watcher_type = PhabricatorObjectHasWatcherEdgeType::EDGECONST;
$need_edge_types = array();
if ($this->needMembers) {
$need_edge_types[] = $member_type;
} else {
foreach ($data as $row) {
$projects[$row['id']]->setIsUserMember(
$viewer_phid,
($row['viewerIsMember'] !== null));
}
}
if ($this->needWatchers) {
$need_edge_types[] = $watcher_type;
}
if ($need_edge_types) {
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs($project_phids)
->withEdgeTypes($need_edge_types)
->execute();
if ($this->needMembers) {
foreach ($projects as $project) {
$phid = $project->getPHID();
$project->attachMemberPHIDs(
array_keys($edges[$phid][$member_type]));
$project->setIsUserMember(
$viewer_phid,
isset($edges[$phid][$member_type][$viewer_phid]));
}
}
if ($this->needWatchers) {
foreach ($projects as $project) {
$phid = $project->getPHID();
$project->attachWatcherPHIDs(
array_keys($edges[$phid][$watcher_type]));
$project->setIsUserWatcher(
$viewer_phid,
isset($edges[$phid][$watcher_type][$viewer_phid]));
}
}
}
}
return $projects;
}
protected function didFilterPage(array $projects) {
if ($this->needImages) {
$default = null;
$file_phids = mpull($projects, 'getProfileImagePHID');
$files = id(new PhabricatorFileQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
foreach ($projects as $project) {
$file = idx($files, $project->getProfileImagePHID());
if (!$file) {
if (!$default) {
$default = PhabricatorFile::loadBuiltin(
$this->getViewer(),
'project.png');
}
$file = $default;
}
$project->attachProfileImageFile($file);
}
}
if ($this->needSlugs) {
$slugs = id(new PhabricatorProjectSlug())
->loadAllWhere(
'projectPHID IN (%Ls)',
mpull($projects, 'getPHID'));
$slugs = mgroup($slugs, 'getProjectPHID');
foreach ($projects as $project) {
$project_slugs = idx($slugs, $project->getPHID(), array());
$project->attachSlugs($project_slugs);
}
}
return $projects;
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->status != self::STATUS_ANY) {
switch ($this->status) {
case self::STATUS_OPEN:
case self::STATUS_ACTIVE:
$filter = array(
PhabricatorProjectStatus::STATUS_ACTIVE,
);
break;
case self::STATUS_CLOSED:
case self::STATUS_ARCHIVED:
$filter = array(
PhabricatorProjectStatus::STATUS_ARCHIVED,
);
break;
default:
throw new Exception(
"Unknown project status '{$this->status}'!");
}
$where[] = qsprintf(
$conn_r,
'status IN (%Ld)',
$filter);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->memberPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'e.dst IN (%Ls)',
$this->memberPHIDs);
}
if ($this->slugs !== null) {
$where[] = qsprintf(
$conn_r,
'slug.slug IN (%Ls)',
$this->slugs);
}
if ($this->phrictionSlugs !== null) {
$where[] = qsprintf(
$conn_r,
'phrictionSlug IN (%Ls)',
$this->phrictionSlugs);
}
if ($this->names !== null) {
$where[] = qsprintf(
$conn_r,
'name IN (%Ls)',
$this->names);
}
if ($this->icons !== null) {
$where[] = qsprintf(
$conn_r,
'icon IN (%Ls)',
$this->icons);
}
if ($this->colors !== null) {
$where[] = qsprintf(
$conn_r,
'color IN (%Ls)',
$this->colors);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function buildGroupClause($conn_r) {
if ($this->memberPHIDs || $this->nameTokens) {
return 'GROUP BY p.id';
} else {
return $this->buildApplicationSearchGroupClause($conn_r);
}
}
private function buildJoinClause($conn_r) {
$joins = array();
if (!$this->needMembers !== null) {
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T vm ON vm.src = p.phid AND vm.type = %d AND vm.dst = %s',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectProjectHasMemberEdgeType::EDGECONST,
$this->getViewer()->getPHID());
}
if ($this->memberPHIDs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T e ON e.src = p.phid AND e.type = %d',
PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectProjectHasMemberEdgeType::EDGECONST);
}
if ($this->slugs !== null) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T slug on slug.projectPHID = p.phid',
id(new PhabricatorProjectSlug())->getTableName());
}
if ($this->nameTokens !== null) {
foreach ($this->nameTokens as $key => $token) {
$token_table = 'token_'.$key;
$joins[] = qsprintf(
$conn_r,
'JOIN %T %T ON %T.projectID = p.id AND %T.token LIKE %>',
PhabricatorProject::TABLE_DATASOURCE_TOKEN,
$token_table,
$token_table,
$token_table,
$token);
}
}
$joins[] = $this->buildApplicationSearchJoinClause($conn_r);
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorProjectApplication';
}
protected function getPrimaryTableAlias() {
return 'p';
}
}
diff --git a/src/applications/releeph/query/ReleephBranchQuery.php b/src/applications/releeph/query/ReleephBranchQuery.php
index 43a600fa2d..201c2653d0 100644
--- a/src/applications/releeph/query/ReleephBranchQuery.php
+++ b/src/applications/releeph/query/ReleephBranchQuery.php
@@ -1,152 +1,152 @@
<?php
final class ReleephBranchQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $productPHIDs;
private $productIDs;
const STATUS_ALL = 'status-all';
const STATUS_OPEN = 'status-open';
private $status = self::STATUS_ALL;
private $needCutPointCommits;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function needCutPointCommits($need_commits) {
$this->needCutPointCommits = $need_commits;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withProductPHIDs($product_phids) {
$this->productPHIDs = $product_phids;
return $this;
}
protected function loadPage() {
$table = new ReleephBranch();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willExecute() {
if ($this->productPHIDs !== null) {
$products = id(new ReleephProductQuery())
->setViewer($this->getViewer())
->withPHIDs($this->productPHIDs)
->execute();
if (!$products) {
throw new PhabricatorEmptyQueryException();
}
$this->productIDs = mpull($products, 'getID');
}
}
protected function willFilterPage(array $branches) {
$project_ids = mpull($branches, 'getReleephProjectID');
$projects = id(new ReleephProductQuery())
->withIDs($project_ids)
->setViewer($this->getViewer())
->execute();
foreach ($branches as $key => $branch) {
$project_id = $project_ids[$key];
if (isset($projects[$project_id])) {
$branch->attachProject($projects[$project_id]);
} else {
unset($branches[$key]);
}
}
if ($this->needCutPointCommits) {
$commit_phids = mpull($branches, 'getCutPointCommitPHID');
$commits = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->withPHIDs($commit_phids)
->execute();
$commits = mpull($commits, null, 'getPHID');
foreach ($branches as $branch) {
$commit = idx($commits, $branch->getCutPointCommitPHID());
$branch->attachCutPointCommit($commit);
}
}
return $branches;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->productIDs !== null) {
$where[] = qsprintf(
$conn_r,
'releephProjectID IN (%Ld)',
$this->productIDs);
}
$status = $this->status;
switch ($status) {
case self::STATUS_ALL:
break;
case self::STATUS_OPEN:
$where[] = qsprintf(
$conn_r,
'isActive = 1');
break;
default:
throw new Exception("Unknown status constant '{$status}'!");
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorReleephApplication';
}
}
diff --git a/src/applications/releeph/query/ReleephProductQuery.php b/src/applications/releeph/query/ReleephProductQuery.php
index 2562004a06..6fe2b90db3 100644
--- a/src/applications/releeph/query/ReleephProductQuery.php
+++ b/src/applications/releeph/query/ReleephProductQuery.php
@@ -1,174 +1,174 @@
<?php
final class ReleephProductQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $active;
private $ids;
private $phids;
private $repositoryPHIDs;
private $needArcanistProjects;
const ORDER_ID = 'order-id';
const ORDER_NAME = 'order-name';
public function withActive($active) {
$this->active = $active;
return $this;
}
public function setOrder($order) {
switch ($order) {
case self::ORDER_ID:
$this->setOrderVector(array('id'));
break;
case self::ORDER_NAME:
$this->setOrderVector(array('name'));
break;
default:
throw new Exception(pht('Order "%s" not supported.', $order));
}
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function needArcanistProjects($need) {
$this->needArcanistProjects = $need;
return $this;
}
protected function loadPage() {
$table = new ReleephProject();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
protected function willFilterPage(array $projects) {
assert_instances_of($projects, 'ReleephProject');
$repository_phids = mpull($projects, 'getRepositoryPHID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($projects as $key => $project) {
$repo = idx($repositories, $project->getRepositoryPHID());
if (!$repo) {
unset($projects[$key]);
continue;
}
$project->attachRepository($repo);
}
return $projects;
}
protected function didFilterPage(array $products) {
if ($this->needArcanistProjects) {
$project_ids = array_filter(mpull($products, 'getArcanistProjectID'));
if ($project_ids) {
$projects = id(new PhabricatorRepositoryArcanistProject())
->loadAllWhere('id IN (%Ld)', $project_ids);
$projects = mpull($projects, null, 'getID');
} else {
$projects = array();
}
foreach ($products as $product) {
$project_id = $product->getArcanistProjectID();
$project = idx($projects, $project_id);
$product->attachArcanistProject($project);
}
}
return $products;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->active !== null) {
$where[] = qsprintf(
$conn_r,
'isActive = %d',
(int)$this->active);
}
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ls)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'name' => array(
'column' => 'name',
'unique' => true,
'reverse' => true,
'type' => 'string',
),
);
}
protected function getPagingValueMap($cursor, array $keys) {
$product = $this->loadCursorObject($cursor);
return array(
'id' => $product->getID(),
'name' => $product->getName(),
);
}
public function getQueryApplicationClass() {
return 'PhabricatorReleephApplication';
}
}
diff --git a/src/applications/releeph/query/ReleephRequestQuery.php b/src/applications/releeph/query/ReleephRequestQuery.php
index 84d35d288a..1a5965ad43 100644
--- a/src/applications/releeph/query/ReleephRequestQuery.php
+++ b/src/applications/releeph/query/ReleephRequestQuery.php
@@ -1,247 +1,247 @@
<?php
final class ReleephRequestQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $requestedCommitPHIDs;
private $ids;
private $phids;
private $severities;
private $requestorPHIDs;
private $branchIDs;
private $requestedObjectPHIDs;
const STATUS_ALL = 'status-all';
const STATUS_OPEN = 'status-open';
const STATUS_REQUESTED = 'status-requested';
const STATUS_NEEDS_PULL = 'status-needs-pull';
const STATUS_REJECTED = 'status-rejected';
const STATUS_ABANDONED = 'status-abandoned';
const STATUS_PULLED = 'status-pulled';
const STATUS_NEEDS_REVERT = 'status-needs-revert';
const STATUS_REVERTED = 'status-reverted';
private $status = self::STATUS_ALL;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withBranchIDs(array $branch_ids) {
$this->branchIDs = $branch_ids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withRequestedCommitPHIDs(array $requested_commit_phids) {
$this->requestedCommitPHIDs = $requested_commit_phids;
return $this;
}
public function withRequestorPHIDs(array $phids) {
$this->requestorPHIDs = $phids;
return $this;
}
public function withSeverities(array $severities) {
$this->severities = $severities;
return $this;
}
public function withRequestedObjectPHIDs(array $phids) {
$this->requestedObjectPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new ReleephRequest();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $requests) {
// Load requested objects: you must be able to see an object to see
// requests for it.
$object_phids = mpull($requests, 'getRequestedObjectPHID');
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
foreach ($requests as $key => $request) {
$object_phid = $request->getRequestedObjectPHID();
$object = idx($objects, $object_phid);
if (!$object) {
unset($requests[$key]);
continue;
}
$request->attachRequestedObject($object);
}
if ($this->severities) {
$severities = array_fuse($this->severities);
foreach ($requests as $key => $request) {
// NOTE: Facebook uses a custom field here.
if (ReleephDefaultFieldSelector::isFacebook()) {
$severity = $request->getDetail('severity');
} else {
$severity = $request->getDetail('releeph:severity');
}
if (empty($severities[$severity])) {
unset($requests[$key]);
}
}
}
$branch_ids = array_unique(mpull($requests, 'getBranchID'));
$branches = id(new ReleephBranchQuery())
->withIDs($branch_ids)
->setViewer($this->getViewer())
->execute();
$branches = mpull($branches, null, 'getID');
foreach ($requests as $key => $request) {
$branch = idx($branches, $request->getBranchID());
if (!$branch) {
unset($requests[$key]);
continue;
}
$request->attachBranch($branch);
}
// TODO: These should be serviced by the query, but are not currently
// denormalized anywhere. For now, filter them here instead. Note that
// we must perform this filtering *after* querying and attaching branches,
// because request status depends on the product.
$keep_status = array_fuse($this->getKeepStatusConstants());
if ($keep_status) {
foreach ($requests as $key => $request) {
if (empty($keep_status[$request->getStatus()])) {
unset($requests[$key]);
}
}
}
return $requests;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->branchIDs !== null) {
$where[] = qsprintf(
$conn_r,
'branchID IN (%Ld)',
$this->branchIDs);
}
if ($this->requestedCommitPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'requestCommitPHID IN (%Ls)',
$this->requestedCommitPHIDs);
}
if ($this->requestorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'requestUserPHID IN (%Ls)',
$this->requestorPHIDs);
}
if ($this->requestedObjectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'requestedObjectPHID IN (%Ls)',
$this->requestedObjectPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function getKeepStatusConstants() {
switch ($this->status) {
case self::STATUS_ALL:
return array();
case self::STATUS_OPEN:
return array(
ReleephRequestStatus::STATUS_REQUESTED,
ReleephRequestStatus::STATUS_NEEDS_PICK,
ReleephRequestStatus::STATUS_NEEDS_REVERT,
);
case self::STATUS_REQUESTED:
return array(
ReleephRequestStatus::STATUS_REQUESTED,
);
case self::STATUS_NEEDS_PULL:
return array(
ReleephRequestStatus::STATUS_NEEDS_PICK,
);
case self::STATUS_REJECTED:
return array(
ReleephRequestStatus::STATUS_REJECTED,
);
case self::STATUS_ABANDONED:
return array(
ReleephRequestStatus::STATUS_ABANDONED,
);
case self::STATUS_PULLED:
return array(
ReleephRequestStatus::STATUS_PICKED,
);
case self::STATUS_NEEDS_REVERT:
return array(
ReleephRequestStatus::NEEDS_REVERT,
);
case self::STATUS_REVERTED:
return array(
ReleephRequestStatus::REVERTED,
);
default:
throw new Exception("Unknown status '{$this->status}'!");
}
}
public function getQueryApplicationClass() {
return 'PhabricatorReleephApplication';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php b/src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php
index 5cbc730075..901f58cbdf 100644
--- a/src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php
@@ -1,87 +1,87 @@
<?php
final class PhabricatorRepositoryArcanistProjectQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $needRepositories;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function needRepositories($need_repositories) {
$this->needRepositories = $need_repositories;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepositoryArcanistProject();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $projects) {
assert_instances_of($projects, 'PhabricatorRepositoryArcanistProject');
if ($this->needRepositories) {
$repository_ids = mpull($projects, 'getRepositoryID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withIDs($repository_ids)
->execute();
foreach ($projects as $project) {
$repo = idx($repositories, $project->getRepositoryID());
$project->attachRepository($repo);
}
}
return $projects;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Diffusion? Differential?
return null;
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryMirrorQuery.php b/src/applications/repository/query/PhabricatorRepositoryMirrorQuery.php
index f6e7d22950..84c5ef74ce 100644
--- a/src/applications/repository/query/PhabricatorRepositoryMirrorQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryMirrorQuery.php
@@ -1,99 +1,99 @@
<?php
final class PhabricatorRepositoryMirrorQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepositoryMirror();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $mirrors) {
assert_instances_of($mirrors, 'PhabricatorRepositoryMirror');
$repository_phids = mpull($mirrors, 'getRepositoryPHID');
if ($repository_phids) {
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
} else {
$repositories = array();
}
foreach ($mirrors as $key => $mirror) {
$phid = $mirror->getRepositoryPHID();
if (empty($repositories[$phid])) {
unset($mirrors[$key]);
continue;
}
$mirror->attachRepository($repositories[$phid]);
}
return $mirrors;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn_r,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
index 14b4e4d596..a3bed7abd3 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushEventQuery.php
@@ -1,131 +1,131 @@
<?php
final class PhabricatorRepositoryPushEventQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $pusherPHIDs;
private $needLogs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withPusherPHIDs(array $pusher_phids) {
$this->pusherPHIDs = $pusher_phids;
return $this;
}
public function needLogs($need_logs) {
$this->needLogs = $need_logs;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepositoryPushEvent();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $events) {
$repository_phids = mpull($events, 'getRepositoryPHID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($events as $key => $event) {
$phid = $event->getRepositoryPHID();
if (empty($repositories[$phid])) {
unset($events[$key]);
continue;
}
$event->attachRepository($repositories[$phid]);
}
return $events;
}
protected function didFilterPage(array $events) {
$phids = mpull($events, 'getPHID');
if ($this->needLogs) {
$logs = id(new PhabricatorRepositoryPushLogQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPushEventPHIDs($phids)
->execute();
$logs = mgroup($logs, 'getPushEventPHID');
foreach ($events as $key => $event) {
$event_logs = idx($logs, $event->getPHID(), array());
$event->attachLogs($event_logs);
}
}
return $events;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn_r,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->pusherPHIDs) {
$where[] = qsprintf(
$conn_r,
'pusherPHID in (%Ls)',
$this->pusherPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
index 7812f77abd..94a0b6922e 100644
--- a/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryPushLogQuery.php
@@ -1,146 +1,146 @@
<?php
final class PhabricatorRepositoryPushLogQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $repositoryPHIDs;
private $pusherPHIDs;
private $refTypes;
private $newRefs;
private $pushEventPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withRepositoryPHIDs(array $repository_phids) {
$this->repositoryPHIDs = $repository_phids;
return $this;
}
public function withPusherPHIDs(array $pusher_phids) {
$this->pusherPHIDs = $pusher_phids;
return $this;
}
public function withRefTypes(array $ref_types) {
$this->refTypes = $ref_types;
return $this;
}
public function withNewRefs(array $new_refs) {
$this->newRefs = $new_refs;
return $this;
}
public function withPushEventPHIDs(array $phids) {
$this->pushEventPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepositoryPushLog();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $logs) {
$event_phids = mpull($logs, 'getPushEventPHID');
$events = id(new PhabricatorObjectQuery())
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($event_phids)
->execute();
$events = mpull($events, null, 'getPHID');
foreach ($logs as $key => $log) {
$event = idx($events, $log->getPushEventPHID());
if (!$event) {
unset($logs[$key]);
continue;
}
$log->attachPushEvent($event);
}
return $logs;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->repositoryPHIDs) {
$where[] = qsprintf(
$conn_r,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->pusherPHIDs) {
$where[] = qsprintf(
$conn_r,
'pusherPHID in (%Ls)',
$this->pusherPHIDs);
}
if ($this->pushEventPHIDs) {
$where[] = qsprintf(
$conn_r,
'pushEventPHID in (%Ls)',
$this->pushEventPHIDs);
}
if ($this->refTypes) {
$where[] = qsprintf(
$conn_r,
'refType IN (%Ls)',
$this->refTypes);
}
if ($this->newRefs) {
$where[] = qsprintf(
$conn_r,
'refNew IN (%Ls)',
$this->newRefs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryQuery.php b/src/applications/repository/query/PhabricatorRepositoryQuery.php
index 1b4e90fb22..d9ea26433f 100644
--- a/src/applications/repository/query/PhabricatorRepositoryQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryQuery.php
@@ -1,552 +1,552 @@
<?php
final class PhabricatorRepositoryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $callsigns;
private $types;
private $uuids;
private $nameContains;
private $remoteURIs;
private $anyProjectPHIDs;
private $datasourceQuery;
private $numericIdentifiers;
private $callsignIdentifiers;
private $phidIdentifiers;
private $identifierMap;
const STATUS_OPEN = 'status-open';
const STATUS_CLOSED = 'status-closed';
const STATUS_ALL = 'status-all';
private $status = self::STATUS_ALL;
const HOSTED_PHABRICATOR = 'hosted-phab';
const HOSTED_REMOTE = 'hosted-remote';
const HOSTED_ALL = 'hosted-all';
private $hosted = self::HOSTED_ALL;
private $needMostRecentCommits;
private $needCommitCounts;
private $needProjectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withCallsigns(array $callsigns) {
$this->callsigns = $callsigns;
return $this;
}
public function withIdentifiers(array $identifiers) {
$ids = array(); $callsigns = array(); $phids = array();
foreach ($identifiers as $identifier) {
if (ctype_digit($identifier)) {
$ids[$identifier] = $identifier;
} else {
$repository_type = PhabricatorRepositoryRepositoryPHIDType::TYPECONST;
if (phid_get_type($identifier) === $repository_type) {
$phids[$identifier] = $identifier;
} else {
$callsigns[$identifier] = $identifier;
}
}
}
$this->numericIdentifiers = $ids;
$this->callsignIdentifiers = $callsigns;
$this->phidIdentifiers = $phids;
return $this;
}
public function withStatus($status) {
$this->status = $status;
return $this;
}
public function withHosted($hosted) {
$this->hosted = $hosted;
return $this;
}
public function withTypes(array $types) {
$this->types = $types;
return $this;
}
public function withUUIDs(array $uuids) {
$this->uuids = $uuids;
return $this;
}
public function withNameContains($contains) {
$this->nameContains = $contains;
return $this;
}
public function withRemoteURIs(array $uris) {
$this->remoteURIs = $uris;
return $this;
}
public function withAnyProjects(array $projects) {
$this->anyProjectPHIDs = $projects;
return $this;
}
public function withDatasourceQuery($query) {
$this->datasourceQuery = $query;
return $this;
}
public function needCommitCounts($need_counts) {
$this->needCommitCounts = $need_counts;
return $this;
}
public function needMostRecentCommits($need_commits) {
$this->needMostRecentCommits = $need_commits;
return $this;
}
public function needProjectPHIDs($need_phids) {
$this->needProjectPHIDs = $need_phids;
return $this;
}
public function getBuiltinOrders() {
return array(
'committed' => array(
'vector' => array('committed', 'id'),
'name' => pht('Most Recent Commit'),
),
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Name'),
),
'callsign' => array(
'vector' => array('callsign'),
'name' => pht('Callsign'),
),
'size' => array(
'vector' => array('size', 'id'),
'name' => pht('Size'),
),
) + parent::getBuiltinOrders();
}
public function getIdentifierMap() {
if ($this->identifierMap === null) {
throw new Exception(
'You must execute() the query before accessing the identifier map.');
}
return $this->identifierMap;
}
protected function willExecute() {
$this->identifierMap = array();
}
protected function loadPage() {
$table = new PhabricatorRepository();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T r %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinsClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$repositories = $table->loadAllFromArray($data);
if ($this->needCommitCounts) {
$sizes = ipull($data, 'size', 'id');
foreach ($repositories as $id => $repository) {
$repository->attachCommitCount(nonempty($sizes[$id], 0));
}
}
if ($this->needMostRecentCommits) {
$commit_ids = ipull($data, 'lastCommitID', 'id');
$commit_ids = array_filter($commit_ids);
if ($commit_ids) {
$commits = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
->withIDs($commit_ids)
->execute();
} else {
$commits = array();
}
foreach ($repositories as $id => $repository) {
$commit = null;
if (idx($commit_ids, $id)) {
$commit = idx($commits, $commit_ids[$id]);
}
$repository->attachMostRecentCommit($commit);
}
}
return $repositories;
}
protected function willFilterPage(array $repositories) {
assert_instances_of($repositories, 'PhabricatorRepository');
// TODO: Denormalize repository status into the PhabricatorRepository
// table so we can do this filtering in the database.
foreach ($repositories as $key => $repo) {
$status = $this->status;
switch ($status) {
case self::STATUS_OPEN:
if (!$repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_CLOSED:
if ($repo->isTracked()) {
unset($repositories[$key]);
}
break;
case self::STATUS_ALL:
break;
default:
throw new Exception("Unknown status '{$status}'!");
}
// TODO: This should also be denormalized.
$hosted = $this->hosted;
switch ($hosted) {
case self::HOSTED_PHABRICATOR:
if (!$repo->isHosted()) {
unset($repositories[$key]);
}
break;
case self::HOSTED_REMOTE:
if ($repo->isHosted()) {
unset($repositories[$key]);
}
break;
case self::HOSTED_ALL:
break;
default:
throw new Exception("Uknown hosted failed '${hosted}'!");
}
}
// TODO: Denormalize this, too.
if ($this->remoteURIs) {
$try_uris = $this->getNormalizedPaths();
$try_uris = array_fuse($try_uris);
foreach ($repositories as $key => $repository) {
if (!isset($try_uris[$repository->getNormalizedPath()])) {
unset($repositories[$key]);
}
}
}
// Build the identifierMap
if ($this->numericIdentifiers) {
foreach ($this->numericIdentifiers as $id) {
if (isset($repositories[$id])) {
$this->identifierMap[$id] = $repositories[$id];
}
}
}
if ($this->callsignIdentifiers) {
$repository_callsigns = mpull($repositories, null, 'getCallsign');
foreach ($this->callsignIdentifiers as $callsign) {
if (isset($repository_callsigns[$callsign])) {
$this->identifierMap[$callsign] = $repository_callsigns[$callsign];
}
}
}
if ($this->phidIdentifiers) {
$repository_phids = mpull($repositories, null, 'getPHID');
foreach ($this->phidIdentifiers as $phid) {
if (isset($repository_phids[$phid])) {
$this->identifierMap[$phid] = $repository_phids[$phid];
}
}
}
return $repositories;
}
protected function didFilterPage(array $repositories) {
if ($this->needProjectPHIDs) {
$type_project = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
$edge_query = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(mpull($repositories, 'getPHID'))
->withEdgeTypes(array($type_project));
$edge_query->execute();
foreach ($repositories as $repository) {
$project_phids = $edge_query->getDestinationPHIDs(
array(
$repository->getPHID(),
));
$repository->attachProjectPHIDs($project_phids);
}
}
return $repositories;
}
protected function getPrimaryTableAlias() {
return 'r';
}
public function getOrderableColumns() {
return parent::getOrderableColumns() + array(
'committed' => array(
'table' => 's',
'column' => 'epoch',
'type' => 'int',
'null' => 'tail',
),
'callsign' => array(
'table' => 'r',
'column' => 'callsign',
'type' => 'string',
'unique' => true,
'reverse' => true,
),
'name' => array(
'table' => 'r',
'column' => 'name',
'type' => 'string',
'reverse' => true,
),
'size' => array(
'table' => 's',
'column' => 'size',
'type' => 'int',
'null' => 'tail',
),
);
}
protected function willExecuteCursorQuery(
PhabricatorCursorPagedPolicyAwareQuery $query) {
$vector = $this->getOrderVector();
if ($vector->containsKey('committed')) {
$query->needMostRecentCommits(true);
}
if ($vector->containsKey('size')) {
$query->needCommitCounts(true);
}
}
protected function getPagingValueMap($cursor, array $keys) {
$repository = $this->loadCursorObject($cursor);
$map = array(
'id' => $repository->getID(),
'callsign' => $repository->getCallsign(),
'name' => $repository->getName(),
);
foreach ($keys as $key) {
switch ($key) {
case 'committed':
$commit = $repository->getMostRecentCommit();
if ($commit) {
$map[$key] = $commit->getEpoch();
} else {
$map[$key] = null;
}
break;
case 'size':
$count = $repository->getCommitCount();
if ($count) {
$map[$key] = $count;
} else {
$map[$key] = null;
}
break;
}
}
return $map;
}
private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
$join_summary_table = $this->needCommitCounts ||
$this->needMostRecentCommits;
$vector = $this->getOrderVector();
if ($vector->containsKey('committed') ||
$vector->containsKey('size')) {
$join_summary_table = true;
}
if ($join_summary_table) {
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T s ON r.id = s.repositoryID',
PhabricatorRepository::TABLE_SUMMARY);
}
if ($this->anyProjectPHIDs) {
$joins[] = qsprintf(
$conn_r,
'JOIN edge e ON e.src = r.phid');
}
return implode(' ', $joins);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'r.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'r.phid IN (%Ls)',
$this->phids);
}
if ($this->callsigns) {
$where[] = qsprintf(
$conn_r,
'r.callsign IN (%Ls)',
$this->callsigns);
}
if ($this->numericIdentifiers ||
$this->callsignIdentifiers ||
$this->phidIdentifiers) {
$identifier_clause = array();
if ($this->numericIdentifiers) {
$identifier_clause[] = qsprintf(
$conn_r,
'r.id IN (%Ld)',
$this->numericIdentifiers);
}
if ($this->callsignIdentifiers) {
$identifier_clause[] = qsprintf(
$conn_r,
'r.callsign IN (%Ls)',
$this->callsignIdentifiers);
}
if ($this->phidIdentifiers) {
$identifier_clause[] = qsprintf(
$conn_r,
'r.phid IN (%Ls)',
$this->phidIdentifiers);
}
$where = array('('.implode(' OR ', $identifier_clause).')');
}
if ($this->types) {
$where[] = qsprintf(
$conn_r,
'r.versionControlSystem IN (%Ls)',
$this->types);
}
if ($this->uuids) {
$where[] = qsprintf(
$conn_r,
'r.uuid IN (%Ls)',
$this->uuids);
}
if (strlen($this->nameContains)) {
$where[] = qsprintf(
$conn_r,
'name LIKE %~',
$this->nameContains);
}
if ($this->anyProjectPHIDs) {
$where[] = qsprintf(
$conn_r,
'e.dst IN (%Ls)',
$this->anyProjectPHIDs);
}
if (strlen($this->datasourceQuery)) {
// This handles having "rP" match callsigns starting with "P...".
$query = trim($this->datasourceQuery);
if (preg_match('/^r/', $query)) {
$callsign = substr($query, 1);
} else {
$callsign = $query;
}
$where[] = qsprintf(
$conn_r,
'r.name LIKE %> OR r.callsign LIKE %>',
$query,
$callsign);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
private function getNormalizedPaths() {
$normalized_uris = array();
// Since we don't know which type of repository this URI is in the general
// case, just generate all the normalizations. We could refine this in some
// cases: if the query specifies VCS types, or the URI is a git-style URI
// or an `svn+ssh` URI, we could deduce how to normalize it. However, this
// would be more complicated and it's not clear if it matters in practice.
foreach ($this->remoteURIs as $uri) {
$normalized_uris[] = new PhabricatorRepositoryURINormalizer(
PhabricatorRepositoryURINormalizer::TYPE_GIT,
$uri);
$normalized_uris[] = new PhabricatorRepositoryURINormalizer(
PhabricatorRepositoryURINormalizer::TYPE_SVN,
$uri);
$normalized_uris[] = new PhabricatorRepositoryURINormalizer(
PhabricatorRepositoryURINormalizer::TYPE_MERCURIAL,
$uri);
}
return array_unique(mpull($normalized_uris, 'getNormalizedPath'));
}
}
diff --git a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
index b75a8aa31e..c4c48c713c 100644
--- a/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
+++ b/src/applications/repository/query/PhabricatorRepositoryRefCursorQuery.php
@@ -1,100 +1,100 @@
<?php
final class PhabricatorRepositoryRefCursorQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $repositoryPHIDs;
private $refTypes;
private $refNames;
public function withRepositoryPHIDs(array $phids) {
$this->repositoryPHIDs = $phids;
return $this;
}
public function withRefTypes(array $types) {
$this->refTypes = $types;
return $this;
}
public function withRefNames(array $names) {
$this->refNames = $names;
return $this;
}
protected function loadPage() {
$table = new PhabricatorRepositoryRefCursor();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T r %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $refs) {
$repository_phids = mpull($refs, 'getRepositoryPHID');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($repository_phids)
->execute();
$repositories = mpull($repositories, null, 'getPHID');
foreach ($refs as $key => $ref) {
$repository = idx($repositories, $ref->getRepositoryPHID());
if (!$repository) {
unset($refs[$key]);
continue;
}
$ref->attachRepository($repository);
}
return $refs;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->repositoryPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'repositoryPHID IN (%Ls)',
$this->repositoryPHIDs);
}
if ($this->refTypes !== null) {
$where[] = qsprintf(
$conn_r,
'refType IN (%Ls)',
$this->refTypes);
}
if ($this->refNames !== null) {
$name_hashes = array();
foreach ($this->refNames as $name) {
$name_hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn_r,
'refNameHash IN (%Ls)',
$name_hashes);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorDiffusionApplication';
}
}
diff --git a/src/applications/search/query/PhabricatorNamedQueryQuery.php b/src/applications/search/query/PhabricatorNamedQueryQuery.php
index 413811771d..ce54ae9a84 100644
--- a/src/applications/search/query/PhabricatorNamedQueryQuery.php
+++ b/src/applications/search/query/PhabricatorNamedQueryQuery.php
@@ -1,86 +1,86 @@
<?php
final class PhabricatorNamedQueryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $engineClassNames;
private $userPHIDs;
private $queryKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withUserPHIDs(array $user_phids) {
$this->userPHIDs = $user_phids;
return $this;
}
public function withEngineClassNames(array $engine_class_names) {
$this->engineClassNames = $engine_class_names;
return $this;
}
public function withQueryKeys(array $query_keys) {
$this->queryKeys = $query_keys;
return $this;
}
protected function loadPage() {
$table = new PhabricatorNamedQuery();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->engineClassNames) {
$where[] = qsprintf(
$conn_r,
'engineClassName IN (%Ls)',
$this->engineClassNames);
}
if ($this->userPHIDs) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->userPHIDs);
}
if ($this->queryKeys) {
$where[] = qsprintf(
$conn_r,
'queryKey IN (%Ls)',
$this->queryKeys);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorSearchApplication';
}
}
diff --git a/src/applications/search/query/PhabricatorSavedQueryQuery.php b/src/applications/search/query/PhabricatorSavedQueryQuery.php
index 168342fdf2..623b001662 100644
--- a/src/applications/search/query/PhabricatorSavedQueryQuery.php
+++ b/src/applications/search/query/PhabricatorSavedQueryQuery.php
@@ -1,73 +1,73 @@
<?php
final class PhabricatorSavedQueryQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $engineClassNames;
private $queryKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withEngineClassNames(array $engine_class_names) {
$this->engineClassNames = $engine_class_names;
return $this;
}
public function withQueryKeys(array $query_keys) {
$this->queryKeys = $query_keys;
return $this;
}
protected function loadPage() {
$table = new PhabricatorSavedQuery();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->engineClassNames !== null) {
$where[] = qsprintf(
$conn_r,
'engineClassName IN (%Ls)',
$this->engineClassNames);
}
if ($this->queryKeys !== null) {
$where[] = qsprintf(
$conn_r,
'queryKey IN (%Ls)',
$this->queryKeys);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorSearchApplication';
}
}
diff --git a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
index d17672b5e3..b7449d06a9 100644
--- a/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
+++ b/src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
@@ -1,185 +1,185 @@
<?php
final class PhabricatorSlowvoteQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $authorPHIDs;
private $withVotesByViewer;
private $isClosed;
private $needOptions;
private $needChoices;
private $needViewerChoices;
public function withIDs($ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs($phids) {
$this->phids = $phids;
return $this;
}
public function withAuthorPHIDs($author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withVotesByViewer($with_vote) {
$this->withVotesByViewer = $with_vote;
return $this;
}
public function withIsClosed($with_closed) {
$this->isClosed = $with_closed;
return $this;
}
public function needOptions($need_options) {
$this->needOptions = $need_options;
return $this;
}
public function needChoices($need_choices) {
$this->needChoices = $need_choices;
return $this;
}
public function needViewerChoices($need_viewer_choices) {
$this->needViewerChoices = $need_viewer_choices;
return $this;
}
protected function loadPage() {
$table = new PhabricatorSlowvotePoll();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT p.* FROM %T p %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinsClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
protected function willFilterPage(array $polls) {
assert_instances_of($polls, 'PhabricatorSlowvotePoll');
$ids = mpull($polls, 'getID');
$viewer = $this->getViewer();
if ($this->needOptions) {
$options = id(new PhabricatorSlowvoteOption())->loadAllWhere(
'pollID IN (%Ld)',
$ids);
$options = mgroup($options, 'getPollID');
foreach ($polls as $poll) {
$poll->attachOptions(idx($options, $poll->getID(), array()));
}
}
if ($this->needChoices) {
$choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
'pollID IN (%Ld)',
$ids);
$choices = mgroup($choices, 'getPollID');
foreach ($polls as $poll) {
$poll->attachChoices(idx($choices, $poll->getID(), array()));
}
// If we need the viewer's choices, we can just fill them from the data
// we already loaded.
if ($this->needViewerChoices) {
foreach ($polls as $poll) {
$poll->attachViewerChoices(
$viewer,
idx(
mgroup($poll->getChoices(), 'getAuthorPHID'),
$viewer->getPHID(),
array()));
}
}
} else if ($this->needViewerChoices) {
$choices = id(new PhabricatorSlowvoteChoice())->loadAllWhere(
'pollID IN (%Ld) AND authorPHID = %s',
$ids,
$viewer->getPHID());
$choices = mgroup($choices, 'getPollID');
foreach ($polls as $poll) {
$poll->attachViewerChoices(
$viewer,
idx($choices, $poll->getID(), array()));
}
}
return $polls;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'p.id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'p.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'p.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->isClosed !== null) {
$where[] = qsprintf(
$conn_r,
'p.isClosed = %d',
(int)$this->isClosed);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
private function buildJoinsClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if ($this->withVotesByViewer) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T vv ON vv.pollID = p.id AND vv.authorPHID = %s',
id(new PhabricatorSlowvoteChoice())->getTableName(),
$this->getViewer()->getPHID());
}
return implode(' ', $joins);
}
protected function getPrimaryTableAlias() {
return 'p';
}
public function getQueryApplicationClass() {
return 'PhabricatorSlowvoteApplication';
}
}
diff --git a/src/applications/tokens/query/PhabricatorTokenCountQuery.php b/src/applications/tokens/query/PhabricatorTokenCountQuery.php
index cc333109a2..d942f22ce4 100644
--- a/src/applications/tokens/query/PhabricatorTokenCountQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenCountQuery.php
@@ -1,40 +1,40 @@
<?php
final class PhabricatorTokenCountQuery
extends PhabricatorOffsetPagedQuery {
private $objectPHIDs;
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
final public function execute() {
$table = new PhabricatorTokenCount();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT objectPHID, tokenCount FROM %T %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildLimitClause($conn_r));
return ipull($rows, 'tokenCount', 'objectPHID');
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
return $this->formatWhereClause($where);
}
}
diff --git a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
index 896b4532c9..c16eaa2168 100644
--- a/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
+++ b/src/applications/tokens/query/PhabricatorTokenGivenQuery.php
@@ -1,96 +1,96 @@
<?php
final class PhabricatorTokenGivenQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $authorPHIDs;
private $objectPHIDs;
private $tokenPHIDs;
public function withTokenPHIDs(array $token_phids) {
$this->tokenPHIDs = $token_phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorTokenGiven();
$conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($rows);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->tokenPHIDs) {
$where[] = qsprintf(
$conn_r,
'tokenPHID IN (%Ls)',
$this->tokenPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
protected function willFilterPage(array $results) {
$object_phids = array_filter(mpull($results, 'getObjectPHID'));
if (!$object_phids) {
return array();
}
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->withPHIDs($object_phids)
->execute();
foreach ($results as $key => $result) {
$phid = $result->getObjectPHID();
if (empty($objects[$phid])) {
unset($results[$key]);
} else {
$result->attachObject($objects[$phid]);
}
}
return $results;
}
public function getQueryApplicationClass() {
return 'PhabricatorTokensApplication';
}
}
diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
index cd61c0fd30..f79de81ba3 100644
--- a/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
+++ b/src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
@@ -1,125 +1,125 @@
<?php
abstract class PhabricatorApplicationTransactionCommentQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $authorPHIDs;
private $phids;
private $transactionPHIDs;
private $isDeleted;
private $hasTransaction;
abstract protected function getTemplate();
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withTransactionPHIDs(array $transaction_phids) {
$this->transactionPHIDs = $transaction_phids;
return $this;
}
public function withAuthorPHIDs(array $phids) {
$this->authorPHIDs = $phids;
return $this;
}
public function withIsDeleted($deleted) {
$this->isDeleted = $deleted;
return $this;
}
public function withHasTransaction($has_transaction) {
$this->hasTransaction = $has_transaction;
return $this;
}
protected function loadPage() {
$table = $this->getTemplate();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T xcomment %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
return $table->loadAllFromArray($data);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
return $this->formatWhereClause($this->buildWhereClauseComponents($conn_r));
}
protected function buildWhereClauseComponents(
AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'xcomment.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
'xcomment.phid IN (%Ls)',
$this->phids);
}
if ($this->authorPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'xcomment.authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->transactionPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'xcomment.transactionPHID IN (%Ls)',
$this->transactionPHIDs);
}
if ($this->isDeleted !== null) {
$where[] = qsprintf(
$conn_r,
'xcomment.isDeleted = %d',
(int)$this->isDeleted);
}
if ($this->hasTransaction !== null) {
if ($this->hasTransaction) {
$where[] = qsprintf(
$conn_r,
'xcomment.transactionPHID IS NOT NULL');
} else {
$where[] = qsprintf(
$conn_r,
'xcomment.transactionPHID IS NULL');
}
}
return $where;
}
public function getQueryApplicationClass() {
// TODO: Figure out the app via the template?
return null;
}
}
diff --git a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
index 5da8411277..ac6f713eeb 100644
--- a/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
+++ b/src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
@@ -1,191 +1,191 @@
<?php
abstract class PhabricatorApplicationTransactionQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $objectPHIDs;
private $authorPHIDs;
private $transactionTypes;
private $needComments = true;
private $needHandles = true;
abstract public function getTemplateApplicationTransaction();
protected function buildMoreWhereClauses(AphrontDatabaseConnection $conn_r) {
return array();
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function withAuthorPHIDs(array $author_phids) {
$this->authorPHIDs = $author_phids;
return $this;
}
public function withTransactionTypes(array $transaction_types) {
$this->transactionTypes = $transaction_types;
return $this;
}
public function needComments($need) {
$this->needComments = $need;
return $this;
}
public function needHandles($need) {
$this->needHandles = $need;
return $this;
}
protected function loadPage() {
$table = $this->getTemplateApplicationTransaction();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT * FROM %T x %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$xactions = $table->loadAllFromArray($data);
foreach ($xactions as $xaction) {
$xaction->attachViewer($this->getViewer());
}
if ($this->needComments) {
$comment_phids = array_filter(mpull($xactions, 'getCommentPHID'));
$comments = array();
if ($comment_phids) {
$comments =
id(new PhabricatorApplicationTransactionTemplatedCommentQuery())
->setTemplate($table->getApplicationTransactionCommentObject())
->setViewer($this->getViewer())
->withPHIDs($comment_phids)
->execute();
$comments = mpull($comments, null, 'getPHID');
}
foreach ($xactions as $xaction) {
if ($xaction->getCommentPHID()) {
$comment = idx($comments, $xaction->getCommentPHID());
if ($comment) {
$xaction->attachComment($comment);
}
}
}
} else {
foreach ($xactions as $xaction) {
$xaction->setCommentNotLoaded(true);
}
}
return $xactions;
}
protected function willFilterPage(array $xactions) {
$object_phids = array_keys(mpull($xactions, null, 'getObjectPHID'));
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
foreach ($xactions as $key => $xaction) {
$object_phid = $xaction->getObjectPHID();
if (empty($objects[$object_phid])) {
unset($xactions[$key]);
continue;
}
$xaction->attachObject($objects[$object_phid]);
}
// NOTE: We have to do this after loading objects, because the objects
// may help determine which handles are required (for example, in the case
// of custom fields).
if ($this->needHandles) {
$phids = array();
foreach ($xactions as $xaction) {
$phids[$xaction->getPHID()] = $xaction->getRequiredHandlePHIDs();
}
$handles = array();
$merged = array_mergev($phids);
if ($merged) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($merged)
->execute();
}
foreach ($xactions as $xaction) {
$xaction->setHandles(
array_select_keys(
$handles,
$phids[$xaction->getPHID()]));
}
}
return $xactions;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
if ($this->objectPHIDs) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->authorPHIDs) {
$where[] = qsprintf(
$conn_r,
'authorPHID IN (%Ls)',
$this->authorPHIDs);
}
if ($this->transactionTypes) {
$where[] = qsprintf(
$conn_r,
'transactionType IN (%Ls)',
$this->transactionTypes);
}
foreach ($this->buildMoreWhereClauses($conn_r) as $clause) {
$where[] = $clause;
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Sort this out?
return null;
}
}
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php
index eb46857a4f..7dfafa16cc 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerArchiveTaskQuery.php
@@ -1,94 +1,94 @@
<?php
final class PhabricatorWorkerArchiveTaskQuery
extends PhabricatorQuery {
private $ids;
private $dateModifiedSince;
private $dateCreatedBefore;
private $objectPHIDs;
private $limit;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withDateModifiedSince($timestamp) {
$this->dateModifiedSince = $timestamp;
return $this;
}
public function withDateCreatedBefore($timestamp) {
$this->dateCreatedBefore = $timestamp;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function execute() {
$task_table = new PhabricatorWorkerArchiveTask();
$conn_r = $task_table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q ORDER BY id DESC %Q',
$task_table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildLimitClause($conn_r));
return $task_table->loadAllFromArray($rows);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
'id in (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
if ($this->dateModifiedSince) {
$where[] = qsprintf(
$conn_r,
'dateModified > %d',
$this->dateModifiedSince);
}
if ($this->dateCreatedBefore) {
$where[] = qsprintf(
$conn_r,
'dateCreated < %d',
$this->dateCreatedBefore);
}
return $this->formatWhereClause($where);
}
private function buildLimitClause(AphrontDatabaseConnection $conn_r) {
$clause = '';
if ($this->limit) {
$clause = qsprintf($conn_r, 'LIMIT %d', $this->limit);
}
return $clause;
}
}
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php
index 456a042776..07c3460494 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php
@@ -1,332 +1,335 @@
<?php
/**
* Select and lease tasks from the worker task queue.
*/
final class PhabricatorWorkerLeaseQuery extends PhabricatorQuery {
const PHASE_LEASED = 'leased';
const PHASE_UNLEASED = 'unleased';
const PHASE_EXPIRED = 'expired';
private $ids;
private $objectPHIDs;
private $limit;
private $skipLease;
private $leased = false;
public static function getDefaultWaitBeforeRetry() {
return phutil_units('5 minutes in seconds');
}
public static function getDefaultLeaseDuration() {
return phutil_units('2 hours in seconds');
}
/**
* Set this flag to select tasks from the top of the queue without leasing
* them.
*
* This can be used to show which tasks are coming up next without altering
* the queue's behavior.
*
* @param bool True to skip the lease acquisition step.
*/
public function setSkipLease($skip) {
$this->skipLease = $skip;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $phids) {
$this->objectPHIDs = $phids;
return $this;
}
/**
* Select only leased tasks, only unleased tasks, or both types of task.
*
* By default, queries select only unleased tasks (equivalent to passing
* `false` to this method). You can pass `true` to select only leased tasks,
* or `null` to ignore the lease status of tasks.
*
* If your result set potentially includes leased tasks, you must disable
* leasing using @{method:setSkipLease}. These options are intended for use
* when displaying task status information.
*
* @param mixed `true` to select only leased tasks, `false` to select only
* unleased tasks (default), or `null` to select both.
* @return this
*/
public function withLeasedTasks($leased) {
$this->leased = $leased;
return $this;
}
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function execute() {
if (!$this->limit) {
throw new Exception(
pht('You must setLimit() when leasing tasks.'));
}
if ($this->leased !== false) {
if (!$this->skipLease) {
throw new Exception(
pht(
'If you potentially select leased tasks using withLeasedTasks(), '.
'you MUST disable lease acquisition by calling setSkipLease().'));
}
}
$task_table = new PhabricatorWorkerActiveTask();
$taskdata_table = new PhabricatorWorkerTaskData();
$lease_ownership_name = $this->getLeaseOwnershipName();
$conn_w = $task_table->establishConnection('w');
// Try to satisfy the request from new, unleased tasks first. If we don't
// find enough tasks, try tasks with expired leases (i.e., tasks which have
// previously failed).
// If we're selecting leased tasks, look for them first.
$phases = array();
if ($this->leased !== false) {
$phases[] = self::PHASE_LEASED;
}
if ($this->leased !== true) {
$phases[] = self::PHASE_UNLEASED;
$phases[] = self::PHASE_EXPIRED;
}
$limit = $this->limit;
$leased = 0;
$task_ids = array();
foreach ($phases as $phase) {
// NOTE: If we issue `UPDATE ... WHERE ... ORDER BY id ASC`, the query
// goes very, very slowly. The `ORDER BY` triggers this, although we get
// the same apparent results without it. Without the ORDER BY, binary
// read slaves complain that the query isn't repeatable. To avoid both
// problems, do a SELECT and then an UPDATE.
$rows = queryfx_all(
$conn_w,
'SELECT id, leaseOwner FROM %T %Q %Q %Q',
$task_table->getTableName(),
- $this->buildWhereClause($conn_w, $phase),
+ $this->buildCustomWhereClause($conn_w, $phase),
$this->buildOrderClause($conn_w, $phase),
$this->buildLimitClause($conn_w, $limit - $leased));
// NOTE: Sometimes, we'll race with another worker and they'll grab
// this task before we do. We could reduce how often this happens by
// selecting more tasks than we need, then shuffling them and trying
// to lock only the number we're actually after. However, the amount
// of time workers spend here should be very small relative to their
// total runtime, so keep it simple for the moment.
if ($rows) {
if ($this->skipLease) {
$leased += count($rows);
$task_ids += array_fuse(ipull($rows, 'id'));
} else {
queryfx(
$conn_w,
'UPDATE %T task
SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + %d
%Q',
$task_table->getTableName(),
$lease_ownership_name,
self::getDefaultLeaseDuration(),
$this->buildUpdateWhereClause($conn_w, $phase, $rows));
$leased += $conn_w->getAffectedRows();
}
if ($leased == $limit) {
break;
}
}
}
if (!$leased) {
return array();
}
if ($this->skipLease) {
$selection_condition = qsprintf(
$conn_w,
'task.id IN (%Ld)',
$task_ids);
} else {
$selection_condition = qsprintf(
$conn_w,
'task.leaseOwner = %s AND leaseExpires > UNIX_TIMESTAMP()',
$lease_ownership_name);
}
$data = queryfx_all(
$conn_w,
'SELECT task.*, taskdata.data _taskData, UNIX_TIMESTAMP() _serverTime
FROM %T task LEFT JOIN %T taskdata
ON taskdata.id = task.dataID
WHERE %Q %Q %Q',
$task_table->getTableName(),
$taskdata_table->getTableName(),
$selection_condition,
$this->buildOrderClause($conn_w, $phase),
$this->buildLimitClause($conn_w, $limit));
$tasks = $task_table->loadAllFromArray($data);
$tasks = mpull($tasks, null, 'getID');
foreach ($data as $row) {
$tasks[$row['id']]->setServerTime($row['_serverTime']);
if ($row['_taskData']) {
$task_data = json_decode($row['_taskData'], true);
} else {
$task_data = null;
}
$tasks[$row['id']]->setData($task_data);
}
if ($this->skipLease) {
// Reorder rows into the original phase order if this is a status query.
$tasks = array_select_keys($tasks, $task_ids);
}
return $tasks;
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_w, $phase) {
+ protected function buildCustomWhereClause(
+ AphrontDatabaseConnection $conn_w,
+ $phase) {
+
$where = array();
switch ($phase) {
case self::PHASE_LEASED:
$where[] = 'leaseOwner IS NOT NULL';
$where[] = 'leaseExpires >= UNIX_TIMESTAMP()';
break;
case self::PHASE_UNLEASED:
$where[] = 'leaseOwner IS NULL';
break;
case self::PHASE_EXPIRED:
$where[] = 'leaseExpires < UNIX_TIMESTAMP()';
break;
default:
throw new Exception("Unknown phase '{$phase}'!");
}
if ($this->ids !== null) {
$where[] = qsprintf($conn_w, 'id IN (%Ld)', $this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf($conn_w, 'objectPHID IN (%Ls)', $this->objectPHIDs);
}
return $this->formatWhereClause($where);
}
private function buildUpdateWhereClause(
AphrontDatabaseConnection $conn_w,
$phase,
array $rows) {
$where = array();
// NOTE: This is basically working around the MySQL behavior that
// `IN (NULL)` doesn't match NULL.
switch ($phase) {
case self::PHASE_LEASED:
throw new Exception(
pht(
'Trying to lease tasks selected in the leased phase! This is '.
'intended to be imposssible.'));
case self::PHASE_UNLEASED:
$where[] = qsprintf($conn_w, 'leaseOwner IS NULL');
$where[] = qsprintf($conn_w, 'id IN (%Ld)', ipull($rows, 'id'));
break;
case self::PHASE_EXPIRED:
$in = array();
foreach ($rows as $row) {
$in[] = qsprintf(
$conn_w,
'(id = %d AND leaseOwner = %s)',
$row['id'],
$row['leaseOwner']);
}
$where[] = qsprintf($conn_w, '(%Q)', implode(' OR ', $in));
break;
default:
throw new Exception("Unknown phase '{$phase}'!");
}
return $this->formatWhereClause($where);
}
private function buildOrderClause(AphrontDatabaseConnection $conn_w, $phase) {
switch ($phase) {
case self::PHASE_LEASED:
// Ideally we'd probably order these by lease acquisition time, but
// we don't have that handy and this is a good approximation.
return qsprintf($conn_w, 'ORDER BY priority ASC, id ASC');
case self::PHASE_UNLEASED:
// When selecting new tasks, we want to consume them in order of
// increasing priority (and then FIFO).
return qsprintf($conn_w, 'ORDER BY priority ASC, id ASC');
case self::PHASE_EXPIRED:
// When selecting failed tasks, we want to consume them in roughly
// FIFO order of their failures, which is not necessarily their original
// queue order.
// Particularly, this is important for tasks which use soft failures to
// indicate that they are waiting on other tasks to complete: we need to
// push them to the end of the queue after they fail, at least on
// average, so we don't deadlock retrying the same blocked task over
// and over again.
return qsprintf($conn_w, 'ORDER BY leaseExpires ASC');
default:
throw new Exception(pht('Unknown phase "%s"!', $phase));
}
}
private function buildLimitClause(AphrontDatabaseConnection $conn_w, $limit) {
return qsprintf($conn_w, 'LIMIT %d', $limit);
}
private function getLeaseOwnershipName() {
static $sequence = 0;
// TODO: If the host name is very long, this can overflow the 64-character
// column, so we pick just the first part of the host name. It might be
// useful to just use a random hash as the identifier instead and put the
// pid / time / host (which are somewhat useful diagnostically) elsewhere.
// Likely, we could store a daemon ID instead and use that to identify
// when and where code executed. See T6742.
$host = php_uname('n');
$host = id(new PhutilUTF8StringTruncator())
->setMaximumBytes(32)
->setTerminator('...')
->truncateString($host);
$parts = array(
getmypid(),
time(),
$host,
++$sequence,
);
return implode(':', $parts);
}
}
diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php
index 679a5236a7..eb9441aa8f 100644
--- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php
+++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php
@@ -1,233 +1,233 @@
<?php
final class PhabricatorWorkerTriggerQuery
extends PhabricatorPolicyAwareQuery {
// NOTE: This is a PolicyAware query so it can work with other infrastructure
// like handles; triggers themselves are low-level and do not have
// meaninguful policies.
const ORDER_ID = 'id';
const ORDER_EXECUTION = 'execution';
const ORDER_VERSION = 'version';
private $ids;
private $phids;
private $versionMin;
private $versionMax;
private $nextEpochMin;
private $nextEpochMax;
private $needEvents;
private $order = self::ORDER_ID;
public function getQueryApplicationClass() {
return null;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withVersionBetween($min, $max) {
$this->versionMin = $min;
$this->versionMax = $max;
return $this;
}
public function withNextEventBetween($min, $max) {
$this->nextEpochMin = $min;
$this->nextEpochMax = $max;
return $this;
}
public function needEvents($need_events) {
$this->needEvents = $need_events;
return $this;
}
/**
* Set the result order.
*
* Note that using `ORDER_EXECUTION` will also filter results to include only
* triggers which have been scheduled to execute. You should not use this
* ordering when querying for specific triggers, e.g. by ID or PHID.
*
* @param const Result order.
* @return this
*/
public function setOrder($order) {
$this->order = $order;
return $this;
}
protected function nextPage(array $page) {
// NOTE: We don't implement paging because we don't currently ever need
// it and paging ORDER_EXCUTION is a hassle.
throw new PhutilMethodNotImplementedException();
}
protected function loadPage() {
$task_table = new PhabricatorWorkerTrigger();
$conn_r = $task_table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT t.* FROM %T t %Q %Q %Q %Q',
$task_table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$triggers = $task_table->loadAllFromArray($rows);
if ($triggers) {
if ($this->needEvents) {
$ids = mpull($triggers, 'getID');
$events = id(new PhabricatorWorkerTriggerEvent())->loadAllWhere(
'triggerID IN (%Ld)',
$ids);
$events = mpull($events, null, 'getTriggerID');
foreach ($triggers as $key => $trigger) {
$event = idx($events, $trigger->getID());
$trigger->attachEvent($event);
}
}
foreach ($triggers as $key => $trigger) {
$clock_class = $trigger->getClockClass();
if (!is_subclass_of($clock_class, 'PhabricatorTriggerClock')) {
unset($triggers[$key]);
continue;
}
try {
$argv = array($trigger->getClockProperties());
$clock = newv($clock_class, $argv);
} catch (Exception $ex) {
unset($triggers[$key]);
continue;
}
$trigger->attachClock($clock);
}
foreach ($triggers as $key => $trigger) {
$action_class = $trigger->getActionClass();
if (!is_subclass_of($action_class, 'PhabricatorTriggerAction')) {
unset($triggers[$key]);
continue;
}
try {
$argv = array($trigger->getActionProperties());
$action = newv($action_class, $argv);
} catch (Exception $ex) {
unset($triggers[$key]);
continue;
}
$trigger->attachAction($action);
}
}
return $triggers;
}
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
$joins = array();
if (($this->nextEpochMin !== null) ||
($this->nextEpochMax !== null) ||
($this->order == PhabricatorWorkerTriggerQuery::ORDER_EXECUTION)) {
$joins[] = qsprintf(
$conn_r,
'JOIN %T e ON e.triggerID = t.id',
id(new PhabricatorWorkerTriggerEvent())->getTableName());
}
return implode(' ', $joins);
}
- private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
't.id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
't.phid IN (%Ls)',
$this->phids);
}
if ($this->versionMin !== null) {
$where[] = qsprintf(
$conn_r,
't.triggerVersion >= %d',
$this->versionMin);
}
if ($this->versionMax !== null) {
$where[] = qsprintf(
$conn_r,
't.triggerVersion <= %d',
$this->versionMax);
}
if ($this->nextEpochMin !== null) {
$where[] = qsprintf(
$conn_r,
'e.nextEventEpoch >= %d',
$this->nextEpochMin);
}
if ($this->nextEpochMax !== null) {
$where[] = qsprintf(
$conn_r,
'e.nextEventEpoch <= %d',
$this->nextEpochMax);
}
return $this->formatWhereClause($where);
}
private function buildOrderClause(AphrontDatabaseConnection $conn_r) {
switch ($this->order) {
case self::ORDER_ID:
return qsprintf(
$conn_r,
'ORDER BY id DESC');
case self::ORDER_EXECUTION:
return qsprintf(
$conn_r,
'ORDER BY e.nextEventEpoch ASC, e.id ASC');
case self::ORDER_VERSION:
return qsprintf(
$conn_r,
'ORDER BY t.triggerVersion ASC');
default:
throw new Exception(
pht(
'Unsupported order "%s".',
$this->order));
}
}
}
diff --git a/src/infrastructure/edges/query/PhabricatorEdgeQuery.php b/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
index 17f1660b33..3ea7eb998e 100644
--- a/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
+++ b/src/infrastructure/edges/query/PhabricatorEdgeQuery.php
@@ -1,332 +1,332 @@
<?php
/**
* 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 $destPHIDs;
private $edgeTypes;
private $resultSet;
const ORDER_OLDEST_FIRST = 'order:oldest';
const ORDER_NEWEST_FIRST = 'order:newest';
private $order = self::ORDER_NEWEST_FIRST;
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 terminating at one or more destination PHIDs.
*
* @param list List of destination PHIDs.
* @return this
*
*/
public function withDestinationPHIDs(array $dest_phids) {
$this->destPHIDs = $dest_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;
}
/**
* Configure the order edge results are returned in.
*
* @param const Order constant.
* @return this
*
* @task config
*/
public function setOrder($order) {
$this->order = $order;
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]);
}
/**
* Convenience method for loading a single edge's metadata for
* a given source, destination, and edge type. Returns null
* if the edge does not exist or does not have metadata. Builds
* and immediately executes a full query.
*
* @param phid Source PHID.
* @param const Edge type.
* @param phid Destination PHID.
* @return wild Edge annotation (or null).
*/
public static function loadSingleEdgeData($src_phid, $edge_type, $dest_phid) {
$edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array($src_phid))
->withEdgeTypes(array($edge_type))
->withDestinationPHIDs(array($dest_phid))
->needEdgeData(true)
->execute();
if (isset($edges[$src_phid][$edge_type][$dest_phid]['data'])) {
return $edges[$src_phid][$edge_type][$dest_phid]['data'];
}
return null;
}
/**
* 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.
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'], array());
}
}
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->setViewer($viewer);
* $query->withSourcePHIDs(mpull($objects, 'getPHID'));
* $query->withEdgeTypes(array($some_type));
* $query->execute();
*
* // Gets all of the destinations.
* $all_phids = $query->getDestinationPHIDs();
* $handles = id(new PhabricatorHandleQuery())
* ->setViewer($viewer)
* ->withPHIDs($all_phids)
* ->execute();
*
* 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().');
}
$result_phids = array();
$set = $this->resultSet;
if ($src_phids) {
$set = array_select_keys($set, $src_phids);
}
foreach ($set as $src => $edges_by_type) {
if ($types) {
$edges_by_type = array_select_keys($edges_by_type, $types);
}
foreach ($edges_by_type as $edges) {
foreach ($edges as $edge_phid => $edge) {
$result_phids[$edge_phid] = true;
}
}
}
return array_keys($result_phids);
}
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
- private function buildWhereClause($conn_r) {
+ protected function buildWhereClause(AphrontDatabaseConnection $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);
}
if ($this->destPHIDs) {
// potentially complain if $this->edgeType was not set
$where[] = qsprintf(
$conn_r,
'edge.dst IN (%Ls)',
$this->destPHIDs);
}
return $this->formatWhereClause($where);
}
/**
* @task internal
*/
private function buildOrderClause($conn_r) {
if ($this->order == self::ORDER_NEWEST_FIRST) {
return 'ORDER BY edge.dateCreated DESC, edge.seq DESC';
} else {
return 'ORDER BY edge.dateCreated ASC, edge.seq ASC';
}
}
}
diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
index 7e7bfc2d35..d532d1cf0f 100644
--- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
+++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
@@ -1,1108 +1,1148 @@
<?php
/**
* A query class which uses cursor-based paging. This paging is much more
* performant than offset-based paging in the presence of policy filtering.
*
+ * @task clauses Building Query Clauses
* @task appsearch Integration with ApplicationSearch
+ * @task customfield Integration with CustomField
* @task paging Paging
* @task order Result Ordering
*/
abstract class PhabricatorCursorPagedPolicyAwareQuery
extends PhabricatorPolicyAwareQuery {
private $afterID;
private $beforeID;
private $applicationSearchConstraints = array();
protected $applicationSearchOrders = array();
private $internalPaging;
private $orderVector;
private $builtinOrder;
protected function getPageCursors(array $page) {
return array(
$this->getResultCursor(head($page)),
$this->getResultCursor(last($page)),
);
}
protected function getResultCursor($object) {
if (!is_object($object)) {
throw new Exception(
pht(
'Expected object, got "%s".',
gettype($object)));
}
return $object->getID();
}
protected function nextPage(array $page) {
// See getPagingViewer() for a description of this flag.
$this->internalPaging = true;
if ($this->beforeID !== null) {
$page = array_reverse($page, $preserve_keys = true);
list($before, $after) = $this->getPageCursors($page);
$this->beforeID = $before;
} else {
list($before, $after) = $this->getPageCursors($page);
$this->afterID = $after;
}
}
final public function setAfterID($object_id) {
$this->afterID = $object_id;
return $this;
}
final protected function getAfterID() {
return $this->afterID;
}
final public function setBeforeID($object_id) {
$this->beforeID = $object_id;
return $this;
}
final protected function getBeforeID() {
return $this->beforeID;
}
/**
* Get the viewer for making cursor paging queries.
*
* NOTE: You should ONLY use this viewer to load cursor objects while
* building paging queries.
*
* Cursor paging can happen in two ways. First, the user can request a page
* like `/stuff/?after=33`, which explicitly causes paging. Otherwise, we
* can fall back to implicit paging if we filter some results out of a
* result list because the user can't see them and need to go fetch some more
* results to generate a large enough result list.
*
* In the first case, want to use the viewer's policies to load the object.
* This prevents an attacker from figuring out information about an object
* they can't see by executing queries like `/stuff/?after=33&order=name`,
* which would otherwise give them a hint about the name of the object.
* Generally, if a user can't see an object, they can't use it to page.
*
* In the second case, we need to load the object whether the user can see
* it or not, because we need to examine new results. For example, if a user
* loads `/stuff/` and we run a query for the first 100 items that they can
* see, but the first 100 rows in the database aren't visible, we need to
* be able to issue a query for the next 100 results. If we can't load the
* cursor object, we'll fail or issue the same query over and over again.
* So, generally, internal paging must bypass policy controls.
*
* This method returns the appropriate viewer, based on the context in which
* the paging is occuring.
*
* @return PhabricatorUser Viewer for executing paging queries.
*/
final protected function getPagingViewer() {
if ($this->internalPaging) {
return PhabricatorUser::getOmnipotentUser();
} else {
return $this->getViewer();
}
}
final protected function buildLimitClause(AphrontDatabaseConnection $conn_r) {
if ($this->getRawResultLimit()) {
return qsprintf($conn_r, 'LIMIT %d', $this->getRawResultLimit());
} else {
return '';
}
}
final protected function didLoadResults(array $results) {
if ($this->beforeID) {
$results = array_reverse($results, $preserve_keys = true);
}
return $results;
}
final public function executeWithCursorPager(AphrontCursorPagerView $pager) {
$limit = $pager->getPageSize();
$this->setLimit($limit + 1);
if ($pager->getAfterID()) {
$this->setAfterID($pager->getAfterID());
} else if ($pager->getBeforeID()) {
$this->setBeforeID($pager->getBeforeID());
}
$results = $this->execute();
$count = count($results);
$sliced_results = $pager->sliceResults($results);
if ($sliced_results) {
list($before, $after) = $this->getPageCursors($sliced_results);
if ($pager->getBeforeID() || ($count > $limit)) {
$pager->setNextPageID($after);
}
if ($pager->getAfterID() ||
($pager->getBeforeID() && ($count > $limit))) {
$pager->setPrevPageID($before);
}
}
return $sliced_results;
}
/**
* Return the alias this query uses to identify the primary table.
*
* Some automatic query constructions may need to be qualified with a table
* alias if the query performs joins which make column names ambiguous. If
* this is the case, return the alias for the primary table the query
* uses; generally the object table which has `id` and `phid` columns.
*
* @return string Alias for the primary table.
*/
protected function getPrimaryTableAlias() {
return null;
}
protected function newResultObject() {
return null;
}
+/* -( Building Query Clauses )--------------------------------------------- */
+
+
+ /**
+ * @task clauses
+ */
+ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
+ throw new PhutilMethodNotImplementedException();
+ }
+
+
/* -( Paging )------------------------------------------------------------- */
+ /**
+ * @task paging
+ */
protected function buildPagingClause(AphrontDatabaseConnection $conn) {
$orderable = $this->getOrderableColumns();
$vector = $this->getOrderVector();
if ($this->beforeID !== null) {
$cursor = $this->beforeID;
$reversed = true;
} else if ($this->afterID !== null) {
$cursor = $this->afterID;
$reversed = false;
} else {
// No paging is being applied to this query so we do not need to
// construct a paging clause.
return '';
}
$keys = array();
foreach ($vector as $order) {
$keys[] = $order->getOrderKey();
}
$value_map = $this->getPagingValueMap($cursor, $keys);
$columns = array();
foreach ($vector as $order) {
$key = $order->getOrderKey();
if (!array_key_exists($key, $value_map)) {
throw new Exception(
pht(
'Query "%s" failed to return a value from getPagingValueMap() '.
'for column "%s".',
get_class($this),
$key));
}
$column = $orderable[$key];
$column['value'] = $value_map[$key];
$columns[] = $column;
}
return $this->buildPagingClauseFromMultipleColumns(
$conn,
$columns,
array(
'reversed' => $reversed,
));
}
+
+ /**
+ * @task paging
+ */
protected function getPagingValueMap($cursor, array $keys) {
- // TODO: This is a hack to make this work with existing classes for now.
return array(
'id' => $cursor,
);
}
+
+ /**
+ * @task paging
+ */
protected function loadCursorObject($cursor) {
$query = newv(get_class($this), array())
->setViewer($this->getPagingViewer())
->withIDs(array((int)$cursor));
$this->willExecuteCursorQuery($query);
$object = $query->executeOne();
if (!$object) {
throw new Exception(
pht(
'Cursor "%s" does not identify a valid object.',
$cursor));
}
return $object;
}
+
+ /**
+ * @task paging
+ */
protected function willExecuteCursorQuery(
PhabricatorCursorPagedPolicyAwareQuery $query) {
return;
}
/**
* Simplifies the task of constructing a paging clause across multiple
* columns. In the general case, this looks like:
*
* A > a OR (A = a AND B > b) OR (A = a AND B = b AND C > c)
*
* To build a clause, specify the name, type, and value of each column
* to include:
*
* $this->buildPagingClauseFromMultipleColumns(
* $conn_r,
* array(
* array(
* 'table' => 't',
* 'column' => 'title',
* 'type' => 'string',
* 'value' => $cursor->getTitle(),
* 'reverse' => true,
* ),
* array(
* 'table' => 't',
* 'column' => 'id',
* 'type' => 'int',
* 'value' => $cursor->getID(),
* ),
* ),
* array(
* 'reversed' => $is_reversed,
* ));
*
* This method will then return a composable clause for inclusion in WHERE.
*
* @param AphrontDatabaseConnection Connection query will execute on.
* @param list<map> Column description dictionaries.
* @param map Additional constuction options.
* @return string Query clause.
+ * @task paging
*/
final protected function buildPagingClauseFromMultipleColumns(
AphrontDatabaseConnection $conn,
array $columns,
array $options) {
foreach ($columns as $column) {
PhutilTypeSpec::checkMap(
$column,
array(
'table' => 'optional string|null',
'column' => 'string',
'value' => 'wild',
'type' => 'string',
'reverse' => 'optional bool',
'unique' => 'optional bool',
'null' => 'optional string|null',
));
}
PhutilTypeSpec::checkMap(
$options,
array(
'reversed' => 'optional bool',
));
$is_query_reversed = idx($options, 'reversed', false);
$clauses = array();
$accumulated = array();
$last_key = last_key($columns);
foreach ($columns as $key => $column) {
$type = $column['type'];
$null = idx($column, 'null');
if ($column['value'] === null) {
if ($null) {
$value = null;
} else {
throw new Exception(
pht(
'Column "%s" has null value, but does not specify a null '.
'behavior.',
$key));
}
} else {
switch ($type) {
case 'int':
$value = qsprintf($conn, '%d', $column['value']);
break;
case 'float':
$value = qsprintf($conn, '%f', $column['value']);
break;
case 'string':
$value = qsprintf($conn, '%s', $column['value']);
break;
default:
throw new Exception(
pht(
'Column "%s" has unknown column type "%s".',
$column['column'],
$type));
}
}
$is_column_reversed = idx($column, 'reverse', false);
$reverse = ($is_query_reversed xor $is_column_reversed);
$clause = $accumulated;
$table_name = idx($column, 'table');
$column_name = $column['column'];
if ($table_name !== null) {
$field = qsprintf($conn, '%T.%T', $table_name, $column_name);
} else {
$field = qsprintf($conn, '%T', $column_name);
}
$parts = array();
if ($null) {
$can_page_if_null = ($null === 'head');
$can_page_if_nonnull = ($null === 'tail');
if ($reverse) {
$can_page_if_null = !$can_page_if_null;
$can_page_if_nonnull = !$can_page_if_nonnull;
}
$subclause = null;
if ($can_page_if_null && $value === null) {
$parts[] = qsprintf(
$conn,
'(%Q IS NOT NULL)',
$field);
} else if ($can_page_if_nonnull && $value !== null) {
$parts[] = qsprintf(
$conn,
'(%Q IS NULL)',
$field);
}
}
if ($value !== null) {
$parts[] = qsprintf(
$conn,
'%Q %Q %Q',
$field,
$reverse ? '>' : '<',
$value);
}
if ($parts) {
if (count($parts) > 1) {
$clause[] = '('.implode(') OR (', $parts).')';
} else {
$clause[] = head($parts);
}
}
if ($clause) {
if (count($clause) > 1) {
$clauses[] = '('.implode(') AND (', $clause).')';
} else {
$clauses[] = head($clause);
}
}
if ($value === null) {
$accumulated[] = qsprintf(
$conn,
'%Q IS NULL',
$field);
} else {
$accumulated[] = qsprintf(
$conn,
'%Q = %Q',
$field,
$value);
}
}
return '('.implode(') OR (', $clauses).')';
}
/* -( Result Ordering )---------------------------------------------------- */
/**
* Select a result ordering.
*
* This is a high-level method which selects an ordering from a predefined
* list of builtin orders, as provided by @{method:getBuiltinOrders}. These
* options are user-facing and not exhaustive, but are generally convenient
* and meaningful.
*
* You can also use @{method:setOrderVector} to specify a low-level ordering
* across individual orderable columns. This offers greater control but is
* also more involved.
*
* @param string Key of a builtin order supported by this query.
* @return this
* @task order
*/
public function setOrder($order) {
$orders = $this->getBuiltinOrders();
if (empty($orders[$order])) {
throw new Exception(
pht(
'Query "%s" does not support a builtin order "%s". Supported orders '.
'are: %s.',
get_class($this),
$order,
implode(', ', array_keys($orders))));
}
$this->builtinOrder = $order;
$this->orderVector = null;
return $this;
}
/**
* Get builtin orders for this class.
*
* In application UIs, we want to be able to present users with a small
* selection of meaningful order options (like "Order by Title") rather than
* an exhaustive set of column ordering options.
*
* Meaningful user-facing orders are often really orders across multiple
* columns: for example, a "title" ordering is usually implemented as a
* "title, id" ordering under the hood.
*
* Builtin orders provide a mapping from convenient, understandable
* user-facing orders to implementations.
*
* A builtin order should provide these keys:
*
* - `vector` (`list<string>`): The actual order vector to use.
* - `name` (`string`): Human-readable order name.
*
* @return map<string, wild> Map from builtin order keys to specification.
* @task order
*/
public function getBuiltinOrders() {
$orders = array(
'newest' => array(
'vector' => array('id'),
'name' => pht('Creation (Newest First)'),
'aliases' => array('created'),
),
'oldest' => array(
'vector' => array('-id'),
'name' => pht('Creation (Oldest First)'),
),
);
$object = $this->newResultObject();
if ($object instanceof PhabricatorCustomFieldInterface) {
$list = PhabricatorCustomField::getObjectFields(
$object,
PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
foreach ($list->getFields() as $field) {
$index = $field->buildOrderIndex();
if (!$index) {
continue;
}
$key = $field->getFieldKey();
$digest = $field->getFieldIndex();
$full_key = 'custom:'.$key;
$orders[$full_key] = array(
'vector' => array($full_key, 'id'),
'name' => $field->getFieldName(),
);
}
}
return $orders;
}
/**
* Set a low-level column ordering.
*
* This is a low-level method which offers granular control over column
* ordering. In most cases, applications can more easily use
* @{method:setOrder} to choose a high-level builtin order.
*
* To set an order vector, specify a list of order keys as provided by
* @{method:getOrderableColumns}.
*
* @param PhabricatorQueryOrderVector|list<string> List of order keys.
* @return this
* @task order
*/
public function setOrderVector($vector) {
$vector = PhabricatorQueryOrderVector::newFromVector($vector);
$orderable = $this->getOrderableColumns();
// Make sure that all the components identify valid columns.
$unique = array();
foreach ($vector as $order) {
$key = $order->getOrderKey();
if (empty($orderable[$key])) {
$valid = implode(', ', array_keys($orderable));
throw new Exception(
pht(
'This query ("%s") does not support sorting by order key "%s". '.
'Supported orders are: %s.',
get_class($this),
$key,
$valid));
}
$unique[$key] = idx($orderable[$key], 'unique', false);
}
// Make sure that the last column is unique so that this is a strong
// ordering which can be used for paging.
$last = last($unique);
if ($last !== true) {
throw new Exception(
pht(
'Order vector "%s" is invalid: the last column in an order must '.
'be a column with unique values, but "%s" is not unique.',
$vector->getAsString(),
last_key($unique)));
}
// Make sure that other columns are not unique; an ordering like "id, name"
// does not make sense because only "id" can ever have an effect.
array_pop($unique);
foreach ($unique as $key => $is_unique) {
if ($is_unique) {
throw new Exception(
pht(
'Order vector "%s" is invalid: only the last column in an order '.
'may be unique, but "%s" is a unique column and not the last '.
'column in the order.',
$vector->getAsString(),
$key));
}
}
$this->orderVector = $vector;
return $this;
}
/**
* Get the effective order vector.
*
* @return PhabricatorQueryOrderVector Effective vector.
* @task order
*/
protected function getOrderVector() {
if (!$this->orderVector) {
if ($this->builtinOrder !== null) {
$builtin_order = idx($this->getBuiltinOrders(), $this->builtinOrder);
$vector = $builtin_order['vector'];
} else {
$vector = $this->getDefaultOrderVector();
}
$vector = PhabricatorQueryOrderVector::newFromVector($vector);
// We call setOrderVector() here to apply checks to the default vector.
// This catches any errors in the implementation.
$this->setOrderVector($vector);
}
return $this->orderVector;
}
/**
* @task order
*/
protected function getDefaultOrderVector() {
return array('id');
}
/**
* @task order
*/
public function getOrderableColumns() {
$columns = array(
'id' => array(
'table' => $this->getPrimaryTableAlias(),
'column' => 'id',
'reverse' => false,
'type' => 'int',
'unique' => true,
),
);
$object = $this->newResultObject();
if ($object instanceof PhabricatorCustomFieldInterface) {
$list = PhabricatorCustomField::getObjectFields(
$object,
PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
foreach ($list->getFields() as $field) {
$index = $field->buildOrderIndex();
if (!$index) {
continue;
}
$key = $field->getFieldKey();
$digest = $field->getFieldIndex();
$full_key = 'custom:'.$key;
$columns[$full_key] = array(
'table' => 'appsearch_order_'.$digest,
'column' => 'indexValue',
'type' => $index->getIndexValueType(),
'null' => 'tail',
);
}
}
return $columns;
}
/**
* @task order
*/
final protected function buildOrderClause(AphrontDatabaseConnection $conn) {
$orderable = $this->getOrderableColumns();
$vector = $this->getOrderVector();
$parts = array();
foreach ($vector as $order) {
$part = $orderable[$order->getOrderKey()];
if ($order->getIsReversed()) {
$part['reverse'] = !idx($part, 'reverse', false);
}
$parts[] = $part;
}
return $this->formatOrderClause($conn, $parts);
}
/**
* @task order
*/
protected function formatOrderClause(
AphrontDatabaseConnection $conn,
array $parts) {
$is_query_reversed = false;
if ($this->getBeforeID()) {
$is_query_reversed = !$is_query_reversed;
}
$sql = array();
foreach ($parts as $key => $part) {
$is_column_reversed = !empty($part['reverse']);
$descending = true;
if ($is_query_reversed) {
$descending = !$descending;
}
if ($is_column_reversed) {
$descending = !$descending;
}
$table = idx($part, 'table');
$column = $part['column'];
if ($table !== null) {
$field = qsprintf($conn, '%T.%T', $table, $column);
} else {
$field = qsprintf($conn, '%T', $column);
}
$null = idx($part, 'null');
if ($null) {
switch ($null) {
case 'head':
$null_field = qsprintf($conn, '(%Q IS NULL)', $field);
break;
case 'tail':
$null_field = qsprintf($conn, '(%Q IS NOT NULL)', $field);
break;
default:
throw new Exception(
pht(
'NULL value "%s" is invalid. Valid values are "head" and '.
'"tail".',
$null));
}
if ($descending) {
$sql[] = qsprintf($conn, '%Q DESC', $null_field);
} else {
$sql[] = qsprintf($conn, '%Q ASC', $null_field);
}
}
if ($descending) {
$sql[] = qsprintf($conn, '%Q DESC', $field);
} else {
$sql[] = qsprintf($conn, '%Q ASC', $field);
}
}
return qsprintf($conn, 'ORDER BY %Q', implode(', ', $sql));
}
/* -( Application Search )------------------------------------------------- */
/**
* Constrain the query with an ApplicationSearch index, requiring field values
* contain at least one of the values in a set.
*
* This constraint can build the most common types of queries, like:
*
* - Find users with shirt sizes "X" or "XL".
* - Find shoes with size "13".
*
* @param PhabricatorCustomFieldIndexStorage Table where the index is stored.
* @param string|list<string> One or more values to filter by.
* @return this
* @task appsearch
*/
public function withApplicationSearchContainsConstraint(
PhabricatorCustomFieldIndexStorage $index,
$value) {
$this->applicationSearchConstraints[] = array(
'type' => $index->getIndexValueType(),
'cond' => '=',
'table' => $index->getTableName(),
'index' => $index->getIndexKey(),
'value' => $value,
);
return $this;
}
/**
* Constrain the query with an ApplicationSearch index, requiring values
* exist in a given range.
*
* This constraint is useful for expressing date ranges:
*
* - Find events between July 1st and July 7th.
*
* The ends of the range are inclusive, so a `$min` of `3` and a `$max` of
* `5` will match fields with values `3`, `4`, or `5`. Providing `null` for
* either end of the range will leave that end of the constraint open.
*
* @param PhabricatorCustomFieldIndexStorage Table where the index is stored.
* @param int|null Minimum permissible value, inclusive.
* @param int|null Maximum permissible value, inclusive.
* @return this
* @task appsearch
*/
public function withApplicationSearchRangeConstraint(
PhabricatorCustomFieldIndexStorage $index,
$min,
$max) {
$index_type = $index->getIndexValueType();
if ($index_type != 'int') {
throw new Exception(
pht(
'Attempting to apply a range constraint to a field with index type '.
'"%s", expected type "%s".',
$index_type,
'int'));
}
$this->applicationSearchConstraints[] = array(
'type' => $index->getIndexValueType(),
'cond' => 'range',
'table' => $index->getTableName(),
'index' => $index->getIndexKey(),
'value' => array($min, $max),
);
return $this;
}
/**
* Order the results by an ApplicationSearch index.
*
* @param PhabricatorCustomField Field to which the index belongs.
* @param PhabricatorCustomFieldIndexStorage Table where the index is stored.
* @param bool True to sort ascending.
* @return this
* @task appsearch
*/
public function withApplicationSearchOrder(
PhabricatorCustomField $field,
PhabricatorCustomFieldIndexStorage $index,
$ascending) {
$this->applicationSearchOrders[] = array(
'key' => $field->getFieldKey(),
'type' => $index->getIndexValueType(),
'table' => $index->getTableName(),
'index' => $index->getIndexKey(),
'ascending' => $ascending,
);
return $this;
}
/**
* Get the name of the query's primary object PHID column, for constructing
* JOIN clauses. Normally (and by default) this is just `"phid"`, but it may
* be something more exotic.
*
* See @{method:getPrimaryTableAlias} if the column needs to be qualified with
* a table alias.
*
* @return string Column name.
* @task appsearch
*/
protected function getApplicationSearchObjectPHIDColumn() {
if ($this->getPrimaryTableAlias()) {
$prefix = $this->getPrimaryTableAlias().'.';
} else {
$prefix = '';
}
return $prefix.'phid';
}
/**
* Determine if the JOINs built by ApplicationSearch might cause each primary
* object to return multiple result rows. Generally, this means the query
* needs an extra GROUP BY clause.
*
* @return bool True if the query may return multiple rows for each object.
* @task appsearch
*/
protected function getApplicationSearchMayJoinMultipleRows() {
foreach ($this->applicationSearchConstraints as $constraint) {
$type = $constraint['type'];
$value = $constraint['value'];
$cond = $constraint['cond'];
switch ($cond) {
case '=':
switch ($type) {
case 'string':
case 'int':
if (count((array)$value) > 1) {
return true;
}
break;
default:
throw new Exception(pht('Unknown index type "%s"!', $type));
}
break;
case 'range':
// NOTE: It's possible to write a custom field where multiple rows
// match a range constraint, but we don't currently ship any in the
// upstream and I can't immediately come up with cases where this
// would make sense.
break;
default:
throw new Exception(pht('Unknown constraint condition "%s"!', $cond));
}
}
return false;
}
/**
* Construct a GROUP BY clause appropriate for ApplicationSearch constraints.
*
* @param AphrontDatabaseConnection Connection executing the query.
* @return string Group clause.
* @task appsearch
*/
protected function buildApplicationSearchGroupClause(
AphrontDatabaseConnection $conn_r) {
if ($this->getApplicationSearchMayJoinMultipleRows()) {
return qsprintf(
$conn_r,
'GROUP BY %Q',
$this->getApplicationSearchObjectPHIDColumn());
} else {
return '';
}
}
/**
* Construct a JOIN clause appropriate for applying ApplicationSearch
* constraints.
*
* @param AphrontDatabaseConnection Connection executing the query.
* @return string Join clause.
* @task appsearch
*/
protected function buildApplicationSearchJoinClause(
AphrontDatabaseConnection $conn_r) {
$joins = array();
foreach ($this->applicationSearchConstraints as $key => $constraint) {
$table = $constraint['table'];
$alias = 'appsearch_'.$key;
$index = $constraint['index'];
$cond = $constraint['cond'];
$phid_column = $this->getApplicationSearchObjectPHIDColumn();
switch ($cond) {
case '=':
$type = $constraint['type'];
switch ($type) {
case 'string':
$constraint_clause = qsprintf(
$conn_r,
'%T.indexValue IN (%Ls)',
$alias,
(array)$constraint['value']);
break;
case 'int':
$constraint_clause = qsprintf(
$conn_r,
'%T.indexValue IN (%Ld)',
$alias,
(array)$constraint['value']);
break;
default:
throw new Exception(pht('Unknown index type "%s"!', $type));
}
$joins[] = qsprintf(
$conn_r,
'JOIN %T %T ON %T.objectPHID = %Q
AND %T.indexKey = %s
AND (%Q)',
$table,
$alias,
$alias,
$phid_column,
$alias,
$index,
$constraint_clause);
break;
case 'range':
list($min, $max) = $constraint['value'];
if (($min === null) && ($max === null)) {
// If there's no actual range constraint, just move on.
break;
}
if ($min === null) {
$constraint_clause = qsprintf(
$conn_r,
'%T.indexValue <= %d',
$alias,
$max);
} else if ($max === null) {
$constraint_clause = qsprintf(
$conn_r,
'%T.indexValue >= %d',
$alias,
$min);
} else {
$constraint_clause = qsprintf(
$conn_r,
'%T.indexValue BETWEEN %d AND %d',
$alias,
$min,
$max);
}
$joins[] = qsprintf(
$conn_r,
'JOIN %T %T ON %T.objectPHID = %Q
AND %T.indexKey = %s
AND (%Q)',
$table,
$alias,
$alias,
$phid_column,
$alias,
$index,
$constraint_clause);
break;
default:
throw new Exception(pht('Unknown constraint condition "%s"!', $cond));
}
}
foreach ($this->applicationSearchOrders as $key => $order) {
$table = $order['table'];
$index = $order['index'];
$alias = 'appsearch_order_'.$index;
$phid_column = $this->getApplicationSearchObjectPHIDColumn();
$joins[] = qsprintf(
$conn_r,
'LEFT JOIN %T %T ON %T.objectPHID = %Q
AND %T.indexKey = %s',
$table,
$alias,
$alias,
$phid_column,
$alias,
$index);
}
return implode(' ', $joins);
}
+
+/* -( Integration with CustomField )--------------------------------------- */
+
+
+ /**
+ * @task customfield
+ */
protected function getPagingValueMapForCustomFields(
PhabricatorCustomFieldInterface $object) {
// We have to get the current field values on the cursor object.
$fields = PhabricatorCustomField::getObjectFields(
$object,
PhabricatorCustomField::ROLE_APPLICATIONSEARCH);
$fields->setViewer($this->getViewer());
$fields->readFieldsFromStorage($object);
$map = array();
foreach ($fields->getFields() as $field) {
$map['custom:'.$field->getFieldKey()] = $field->getValueForStorage();
}
return $map;
}
+
+ /**
+ * @task customfield
+ */
protected function isCustomFieldOrderKey($key) {
$prefix = 'custom:';
return !strncmp($key, $prefix, strlen($prefix));
}
+
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jul 3, 7:57 PM (5 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
166322
Default Alt Text
(534 KB)
Attached To
Mode
R1 hydra
Attached
Detach File
Event Timeline
Log In to Comment