1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-24 06:20:56 +01:00

Expose modern *.search Conduit endpoints in Almanac

Summary: Fixes T10411. Ref T10246. There are probably still some rough edges with this, but replace the old-school endpoints with modern ones so we don't unprototype with deprecated stuff.

Test Plan:
  - Made a bunch of calls to the new endpoints with various constraints/attachments.
  - Created and edited services, devices, interfaces, bindings, and properties on everything.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10246, T10411

Differential Revision: https://secure.phabricator.com/D15329
This commit is contained in:
epriestley 2016-02-22 12:53:40 -08:00
parent 023cfbb23a
commit f7d5904e4b
24 changed files with 403 additions and 111 deletions

View file

@ -20,6 +20,7 @@ phutil_register_library_map(array(
'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php',
'AlmanacBindingTransactionQuery' => 'applications/almanac/query/AlmanacBindingTransactionQuery.php',
'AlmanacBindingViewController' => 'applications/almanac/controller/AlmanacBindingViewController.php',
'AlmanacBindingsSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php',
'AlmanacClusterDatabaseServiceType' => 'applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php',
'AlmanacClusterRepositoryServiceType' => 'applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php',
'AlmanacClusterServiceType' => 'applications/almanac/servicetype/AlmanacClusterServiceType.php',
@ -42,6 +43,7 @@ phutil_register_library_map(array(
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php',
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
'AlmanacDeviceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php',
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
@ -90,6 +92,7 @@ phutil_register_library_map(array(
'AlmanacNetworkTransactionQuery' => 'applications/almanac/query/AlmanacNetworkTransactionQuery.php',
'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php',
'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php',
'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php',
'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php',
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
'AlmanacPropertyDeleteController' => 'applications/almanac/controller/AlmanacPropertyDeleteController.php',
@ -101,6 +104,7 @@ phutil_register_library_map(array(
'AlmanacQueryDevicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryDevicesConduitAPIMethod.php',
'AlmanacQueryServicesConduitAPIMethod' => 'applications/almanac/conduit/AlmanacQueryServicesConduitAPIMethod.php',
'AlmanacSchemaSpec' => 'applications/almanac/storage/AlmanacSchemaSpec.php',
'AlmanacSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacSearchEngineAttachment.php',
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
'AlmanacServiceDatasource' => 'applications/almanac/typeahead/AlmanacServiceDatasource.php',
@ -111,6 +115,7 @@ phutil_register_library_map(array(
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php',
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
'AlmanacServiceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacServiceSearchConduitAPIMethod.php',
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
@ -4007,6 +4012,7 @@ phutil_register_library_map(array(
'AlmanacBindingTransaction' => 'AlmanacTransaction',
'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacBindingViewController' => 'AlmanacServiceController',
'AlmanacBindingsSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType',
'AlmanacClusterRepositoryServiceType' => 'AlmanacClusterServiceType',
'AlmanacClusterServiceType' => 'AlmanacServiceType',
@ -4029,6 +4035,7 @@ phutil_register_library_map(array(
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorNgramsInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacDeviceController' => 'AlmanacController',
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
@ -4038,6 +4045,7 @@ phutil_register_library_map(array(
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacDeviceQuery' => 'AlmanacQuery',
'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacDeviceTransaction' => 'AlmanacTransaction',
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
@ -4052,7 +4060,7 @@ phutil_register_library_map(array(
'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacInterfaceEditController' => 'AlmanacDeviceController',
'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType',
'AlmanacInterfaceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacInterfaceQuery' => 'AlmanacQuery',
'AlmanacInterfaceTableView' => 'AphrontView',
'AlmanacKeys' => 'Phobject',
'AlmanacManagementLockWorkflow' => 'AlmanacManagementWorkflow',
@ -4098,25 +4106,27 @@ phutil_register_library_map(array(
'AlmanacNetworkListController' => 'AlmanacNetworkController',
'AlmanacNetworkNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacNetworkPHIDType' => 'PhabricatorPHIDType',
'AlmanacNetworkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacNetworkQuery' => 'AlmanacQuery',
'AlmanacNetworkSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacNetworkTransaction' => 'PhabricatorApplicationTransaction',
'AlmanacNetworkTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacNetworkViewController' => 'AlmanacNetworkController',
'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
'AlmanacProperty' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
),
'AlmanacPropertyController' => 'AlmanacController',
'AlmanacPropertyDeleteController' => 'AlmanacDeviceController',
'AlmanacPropertyEditController' => 'AlmanacDeviceController',
'AlmanacPropertyDeleteController' => 'AlmanacPropertyController',
'AlmanacPropertyEditController' => 'AlmanacPropertyController',
'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine',
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQueryDevicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
'AlmanacQueryServicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
'AlmanacSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'AlmanacSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'AlmanacService' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
@ -4125,6 +4135,7 @@ phutil_register_library_map(array(
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorNgramsInterface',
'PhabricatorConduitResultInterface',
),
'AlmanacServiceController' => 'AlmanacController',
'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource',
@ -4135,6 +4146,7 @@ phutil_register_library_map(array(
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacServiceQuery' => 'AlmanacQuery',
'AlmanacServiceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacServiceTransaction' => 'AlmanacTransaction',
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',

View file

@ -8,7 +8,7 @@ abstract class AlmanacConduitAPIMethod extends ConduitAPIMethod {
}
public function getMethodStatus() {
return self::METHOD_STATUS_UNSTABLE;
return self::METHOD_STATUS_DEPRECATED;
}
public function getMethodStatusDescription() {

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacDeviceSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.device.search';
}
public function newSearchEngine() {
return new AlmanacDeviceSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac devices.');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class AlmanacServiceSearchConduitAPIMethod
extends PhabricatorSearchEngineAPIMethod {
public function getAPIMethodName() {
return 'almanac.service.search';
}
public function newSearchEngine() {
return new AlmanacServiceSearchEngine();
}
public function getMethodSummary() {
return pht('Read information about Almanac services.');
}
}

View file

@ -15,6 +15,7 @@ final class AlmanacBindingViewController
$binding = id(new AlmanacBindingQuery())
->setViewer($viewer)
->withIDs(array($id))
->needProperties(true)
->executeOne();
if (!$binding) {
return new Aphront404Response();

View file

@ -15,6 +15,7 @@ final class AlmanacDeviceViewController
$device = id(new AlmanacDeviceQuery())
->setViewer($viewer)
->withNames(array($name))
->needProperties(true)
->executeOne();
if (!$device) {
return new Aphront404Response();

View file

@ -1,3 +1,56 @@
<?php
abstract class AlmanacPropertyController extends AlmanacController {}
abstract class AlmanacPropertyController extends AlmanacController {
private $propertyObject;
public function getPropertyObject() {
return $this->propertyObject;
}
protected function loadPropertyObject() {
$viewer = $this->getViewer();
$request = $this->getRequest();
$object_phid = $request->getStr('objectPHID');
switch (phid_get_type($object_phid)) {
case AlmanacBindingPHIDType::TYPECONST:
$query = new AlmanacBindingQuery();
break;
case AlmanacDevicePHIDType::TYPECONST:
$query = new AlmanacDeviceQuery();
break;
case AlmanacServicePHIDType::TYPECONST:
$query = new AlmanacServiceQuery();
break;
default:
return new Aphront404Response();
}
$object = $query
->setViewer($viewer)
->withPHIDs(array($object_phid))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->needProperties(true)
->executeOne();
if (!$object) {
return new Aphront404Response();
}
if (!($object instanceof AlmanacPropertyInterface)) {
return new Aphront404Response();
}
$this->propertyObject = $object;
return null;
}
}

View file

@ -1,27 +1,17 @@
<?php
final class AlmanacPropertyDeleteController
extends AlmanacDeviceController {
extends AlmanacPropertyController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($request->getStr('objectPHID')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$object) {
return new Aphront404Response();
$response = $this->loadPropertyObject();
if ($response) {
return $response;
}
if (!($object instanceof AlmanacPropertyInterface)) {
return new Aphront404Response();
}
$object = $this->getPropertyObject();
$key = $request->getStr('key');
if (!strlen($key)) {

View file

@ -1,27 +1,17 @@
<?php
final class AlmanacPropertyEditController
extends AlmanacDeviceController {
extends AlmanacPropertyController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($request->getStr('objectPHID')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$object) {
return new Aphront404Response();
$response = $this->loadPropertyObject();
if ($response) {
return $response;
}
if (!($object instanceof AlmanacPropertyInterface)) {
return new Aphront404Response();
}
$object = $this->getPropertyObject();
$cancel_uri = $object->getURI();
$property_key = $request->getStr('key');

View file

@ -15,6 +15,7 @@ final class AlmanacServiceViewController
$service = id(new AlmanacServiceQuery())
->setViewer($viewer)
->withNames(array($name))
->needProperties(true)
->executeOne();
if (!$service) {
return new Aphront404Response();

View file

@ -0,0 +1,30 @@
<?php
final class AlmanacBindingsSearchEngineAttachment
extends AlmanacSearchEngineAttachment {
public function getAttachmentName() {
return pht('Almanac Bindings');
}
public function getAttachmentDescription() {
return pht('Get Almanac bindings for the service.');
}
public function willLoadAttachmentData($query, $spec) {
$query->needProperties(true);
$query->needBindings(true);
}
public function getAttachmentForObject($object, $data, $spec) {
$bindings = array();
foreach ($object->getBindings() as $binding) {
$bindings[] = $this->getAlmanacBindingDictionary($binding);
}
return array(
'bindings' => $bindings,
);
}
}

View file

@ -0,0 +1,26 @@
<?php
final class AlmanacPropertiesSearchEngineAttachment
extends AlmanacSearchEngineAttachment {
public function getAttachmentName() {
return pht('Almanac Properties');
}
public function getAttachmentDescription() {
return pht('Get Almanac properties for the object.');
}
public function willLoadAttachmentData($query, $spec) {
$query->needProperties(true);
}
public function getAttachmentForObject($object, $data, $spec) {
$properties = $this->getAlmanacPropertyList($object);
return array(
'properties' => $properties,
);
}
}

View file

@ -0,0 +1,64 @@
<?php
abstract class AlmanacSearchEngineAttachment
extends PhabricatorSearchEngineAttachment {
protected function getAlmanacPropertyList($object) {
$builtins = $object->getAlmanacPropertyFieldSpecifications();
$properties = array();
foreach ($object->getAlmanacProperties() as $key => $property) {
$is_builtin = isset($builtins[$key]);
$properties[] = array(
'key' => $key,
'value' => $property->getFieldValue(),
'builtin' => $is_builtin,
);
}
return $properties;
}
protected function getAlmanacBindingDictionary(AlmanacBinding $binding) {
$interface = $binding->getInterface();
return array(
'id' => (int)$binding->getID(),
'phid' => $binding->getPHID(),
'properties' => $this->getAlmanacPropertyList($binding),
'interface' => $this->getAlmanacInterfaceDictionary($interface),
);
}
protected function getAlmanacInterfaceDictionary(
AlmanacInterface $interface) {
return array(
'id' => (int)$interface->getID(),
'phid' => $interface->getPHID(),
'address' => $interface->getAddress(),
'port' => (int)$interface->getPort(),
'device' => $this->getAlmanacDeviceDictionary($interface->getDevice()),
'network' => $this->getAlmanacNetworkDictionary($interface->getNetwork()),
);
}
protected function getAlmanacDeviceDictionary(AlmanacDevice $device) {
return array(
'id' => (int)$device->getID(),
'phid' => $device->getPHID(),
'name' => $device->getName(),
'properties' => $this->getAlmanacPropertyList($device),
);
}
protected function getAlmanacNetworkDictionary(AlmanacNetwork $network) {
return array(
'id' => (int)$network->getID(),
'phid' => $network->getPHID(),
'name' => $network->getName(),
);
}
}

View file

@ -34,19 +34,12 @@ final class AlmanacBindingQuery
return $this;
}
public function newResultObject() {
return new AlmanacBinding();
}
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);
return $this->loadStandardPage($this->newResultObject());
}
protected function willFilterPage(array $bindings) {
@ -58,6 +51,7 @@ final class AlmanacBindingQuery
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($service_phids)
->needProperties($this->getNeedProperties())
->execute();
$services = mpull($services, null, 'getPHID');
@ -65,6 +59,7 @@ final class AlmanacBindingQuery
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($device_phids)
->needProperties($this->getNeedProperties())
->execute();
$devices = mpull($devices, null, 'getPHID');
@ -72,6 +67,7 @@ final class AlmanacBindingQuery
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($interface_phids)
->needProperties($this->getNeedProperties())
->execute();
$interfaces = mpull($interfaces, null, 'getPHID');
@ -93,47 +89,45 @@ final class AlmanacBindingQuery
return $bindings;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->servicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'servicePHID IN (%Ls)',
$this->servicePHIDs);
}
if ($this->devicePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'devicePHID IN (%Ls)',
$this->devicePHIDs);
}
if ($this->interfacePHIDs !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'interfacePHID IN (%Ls)',
$this->interfacePHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
return $where;
}
}

View file

@ -21,6 +21,10 @@ final class AlmanacDeviceSearchEngine
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for devices by name substring.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Exact Names'))
->setKey('names')
->setDescription(pht('Search for devices with specific names.')),
);
}
@ -31,6 +35,10 @@ final class AlmanacDeviceSearchEngine
$query->withNameNgrams($map['match']);
}
if ($map['names']) {
$query->withNames($map['names']);
}
return $query;
}

View file

@ -1,7 +1,7 @@
<?php
final class AlmanacInterfaceQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
extends AlmanacQuery {
private $ids;
private $phids;
@ -50,6 +50,7 @@ final class AlmanacInterfaceQuery
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($network_phids)
->needProperties($this->getNeedProperties())
->execute();
$networks = mpull($networks, null, 'getPHID');
@ -57,6 +58,7 @@ final class AlmanacInterfaceQuery
->setParentQuery($this)
->setViewer($this->getViewer())
->withPHIDs($device_phids)
->needProperties($this->getNeedProperties())
->execute();
$devices = mpull($devices, null, 'getPHID');

View file

@ -1,7 +1,7 @@
<?php
final class AlmanacNetworkQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
extends AlmanacQuery {
private $ids;
private $phids;

View file

@ -5,8 +5,8 @@ final class AlmanacPropertyQuery
private $ids;
private $objectPHIDs;
private $objects;
private $names;
private $disablePolicyFilteringAndAttachment;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -18,45 +18,46 @@ final class AlmanacPropertyQuery
return $this;
}
public function withObjects(array $objects) {
$this->objects = mpull($objects, null, 'getPHID');
$this->objectPHIDs = array_keys($this->objects);
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;
public function newResultObject() {
return new AlmanacProperty();
}
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);
return $this->loadStandardPage($this->newResultObject());
}
protected function willFilterPage(array $properties) {
if (!$this->disablePolicyFilteringAndAttachment) {
$object_phids = mpull($properties, 'getObjectPHID');
$object_phids = array_fuse($object_phids);
if ($this->objects !== null) {
$object_phids = array_diff_key($object_phids, $this->objects);
}
if ($object_phids) {
$objects = id(new PhabricatorObjectQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withPHIDs($object_phids)
->execute();
$objects = mpull($objects, null, 'getPHID');
} else {
$objects = array();
}
$objects += $this->objects;
foreach ($properties as $key => $property) {
$object = idx($objects, $property->getObjectPHID());
@ -66,24 +67,23 @@ final class AlmanacPropertyQuery
}
$property->attachObject($object);
}
}
return $properties;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn_r,
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
@ -94,14 +94,12 @@ final class AlmanacPropertyQuery
$hashes[] = PhabricatorHash::digestForIndex($name);
}
$where[] = qsprintf(
$conn_r,
$conn,
'fieldIndex IN (%Ls)',
$hashes);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
return $where;
}
public function getQueryApplicationClass() {

View file

@ -3,21 +3,25 @@
abstract class AlmanacQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
protected function didFilterPage(array $objects) {
if (head($objects) instanceof AlmanacPropertyInterface) {
// NOTE: We load properties for obsolete historical reasons. It may make
// sense to re-examine that assumption shortly.
private $needProperties;
public function needProperties($need_properties) {
$this->needProperties = $need_properties;
return $this;
}
protected function getNeedProperties() {
return $this->needProperties;
}
protected function didFilterPage(array $objects) {
$has_properties = (head($objects) instanceof AlmanacPropertyInterface);
if ($has_properties && $this->needProperties) {
$property_query = id(new AlmanacPropertyQuery())
->setViewer($this->getViewer())
->setParentQuery($this)
->withObjectPHIDs(mpull($objects, 'getPHID'));
// NOTE: We disable policy filtering and object attachment to avoid
// a cyclic dependency where objects need their properties and properties
// need their objects. We'll attach the objects below, and have already
// implicitly checked the necessary policies.
$property_query->setDisablePolicyFilteringAndAttachment(true);
->withObjects($objects);
$properties = $property_query->execute();

View file

@ -65,8 +65,12 @@ final class AlmanacServiceQuery
return $this;
}
public function newResultObject() {
return new AlmanacService();
}
protected function loadPage() {
return $this->loadStandardPage(new AlmanacService());
return $this->loadStandardPage($this->newResultObject());
}
protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) {
@ -172,6 +176,7 @@ final class AlmanacServiceQuery
$bindings = id(new AlmanacBindingQuery())
->setViewer($this->getViewer())
->withServicePHIDs($service_phids)
->needProperties($this->getNeedProperties())
->execute();
$bindings = mgroup($bindings, 'getServicePHID');

View file

@ -26,6 +26,14 @@ final class AlmanacServiceSearchEngine
$query->withNameNgrams($map['match']);
}
if ($map['names']) {
$query->withNames($map['names']);
}
if ($map['devicePHIDs']) {
$query->withDevicePHIDs($map['devicePHIDs']);
}
return $query;
}
@ -36,6 +44,15 @@ final class AlmanacServiceSearchEngine
->setLabel(pht('Name Contains'))
->setKey('match')
->setDescription(pht('Search for services by name substring.')),
id(new PhabricatorSearchStringListField())
->setLabel(pht('Exact Names'))
->setKey('names')
->setDescription(pht('Search for services with specific names.')),
id(new PhabricatorPHIDsSearchField())
->setLabel(pht('Devices'))
->setKey('devicePHIDs')
->setDescription(
pht('Search for services bound to particular devices.')),
);
}

View file

@ -9,7 +9,8 @@ final class AlmanacDevice
PhabricatorSSHPublicKeyInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
PhabricatorNgramsInterface,
PhabricatorConduitResultInterface {
protected $name;
protected $nameIndex;
@ -243,4 +244,30 @@ final class AlmanacDevice
);
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of the device.')),
);
}
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
);
}
public function getConduitSearchAttachments() {
return array(
id(new AlmanacPropertiesSearchEngineAttachment())
->setAttachmentKey('properties'),
);
}
}

View file

@ -8,7 +8,8 @@ final class AlmanacService
PhabricatorProjectInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface,
PhabricatorNgramsInterface {
PhabricatorNgramsInterface,
PhabricatorConduitResultInterface {
protected $name;
protected $nameIndex;
@ -224,4 +225,32 @@ final class AlmanacService
);
}
/* -( PhabricatorConduitResultInterface )---------------------------------- */
public function getFieldSpecificationsForConduit() {
return array(
id(new PhabricatorConduitSearchFieldSpecification())
->setKey('name')
->setType('string')
->setDescription(pht('The name of the service.')),
);
}
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
);
}
public function getConduitSearchAttachments() {
return array(
id(new AlmanacPropertiesSearchEngineAttachment())
->setAttachmentKey('properties'),
id(new AlmanacBindingsSearchEngineAttachment())
->setAttachmentKey('bindings'),
);
}
}

View file

@ -15,4 +15,8 @@ final class PhabricatorSearchTextField
return new AphrontFormTextControl();
}
protected function newConduitParameterType() {
return new ConduitStringParameterType();
}
}