From f7d5904e4b53a17e44f79c760f10a8d87af00093 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 22 Feb 2016 12:53:40 -0800 Subject: [PATCH] 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 --- src/__phutil_library_map__.php | 20 ++++-- .../conduit/AlmanacConduitAPIMethod.php | 2 +- .../AlmanacDeviceSearchConduitAPIMethod.php | 18 +++++ .../AlmanacServiceSearchConduitAPIMethod.php | 18 +++++ .../AlmanacBindingViewController.php | 1 + .../AlmanacDeviceViewController.php | 1 + .../controller/AlmanacPropertyController.php | 55 +++++++++++++- .../AlmanacPropertyDeleteController.php | 20 ++---- .../AlmanacPropertyEditController.php | 20 ++---- .../AlmanacServiceViewController.php | 1 + .../AlmanacBindingsSearchEngineAttachment.php | 30 ++++++++ ...lmanacPropertiesSearchEngineAttachment.php | 26 +++++++ .../AlmanacSearchEngineAttachment.php | 64 +++++++++++++++++ .../almanac/query/AlmanacBindingQuery.php | 38 +++++----- .../query/AlmanacDeviceSearchEngine.php | 8 +++ .../almanac/query/AlmanacInterfaceQuery.php | 4 +- .../almanac/query/AlmanacNetworkQuery.php | 2 +- .../almanac/query/AlmanacPropertyQuery.php | 72 +++++++++---------- .../almanac/query/AlmanacQuery.php | 26 ++++--- .../almanac/query/AlmanacServiceQuery.php | 7 +- .../query/AlmanacServiceSearchEngine.php | 17 +++++ .../almanac/storage/AlmanacDevice.php | 29 +++++++- .../almanac/storage/AlmanacService.php | 31 +++++++- .../field/PhabricatorSearchTextField.php | 4 ++ 24 files changed, 403 insertions(+), 111 deletions(-) create mode 100644 src/applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php create mode 100644 src/applications/almanac/conduit/AlmanacServiceSearchConduitAPIMethod.php create mode 100644 src/applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php create mode 100644 src/applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php create mode 100644 src/applications/almanac/engineextension/AlmanacSearchEngineAttachment.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 29c34e45cc..4de280e4f9 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/applications/almanac/conduit/AlmanacConduitAPIMethod.php b/src/applications/almanac/conduit/AlmanacConduitAPIMethod.php index 974d888917..b7eec60cb4 100644 --- a/src/applications/almanac/conduit/AlmanacConduitAPIMethod.php +++ b/src/applications/almanac/conduit/AlmanacConduitAPIMethod.php @@ -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() { diff --git a/src/applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php b/src/applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php new file mode 100644 index 0000000000..af674428a5 --- /dev/null +++ b/src/applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php @@ -0,0 +1,18 @@ +setViewer($viewer) ->withIDs(array($id)) + ->needProperties(true) ->executeOne(); if (!$binding) { return new Aphront404Response(); diff --git a/src/applications/almanac/controller/AlmanacDeviceViewController.php b/src/applications/almanac/controller/AlmanacDeviceViewController.php index c7756c5b25..89ec7198e3 100644 --- a/src/applications/almanac/controller/AlmanacDeviceViewController.php +++ b/src/applications/almanac/controller/AlmanacDeviceViewController.php @@ -15,6 +15,7 @@ final class AlmanacDeviceViewController $device = id(new AlmanacDeviceQuery()) ->setViewer($viewer) ->withNames(array($name)) + ->needProperties(true) ->executeOne(); if (!$device) { return new Aphront404Response(); diff --git a/src/applications/almanac/controller/AlmanacPropertyController.php b/src/applications/almanac/controller/AlmanacPropertyController.php index 73d47431fd..deb2709ddd 100644 --- a/src/applications/almanac/controller/AlmanacPropertyController.php +++ b/src/applications/almanac/controller/AlmanacPropertyController.php @@ -1,3 +1,56 @@ 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; + } + + +} diff --git a/src/applications/almanac/controller/AlmanacPropertyDeleteController.php b/src/applications/almanac/controller/AlmanacPropertyDeleteController.php index 2bdaa5f35c..93ec4ced64 100644 --- a/src/applications/almanac/controller/AlmanacPropertyDeleteController.php +++ b/src/applications/almanac/controller/AlmanacPropertyDeleteController.php @@ -1,27 +1,17 @@ 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)) { diff --git a/src/applications/almanac/controller/AlmanacPropertyEditController.php b/src/applications/almanac/controller/AlmanacPropertyEditController.php index 46d609af86..ef587e5b05 100644 --- a/src/applications/almanac/controller/AlmanacPropertyEditController.php +++ b/src/applications/almanac/controller/AlmanacPropertyEditController.php @@ -1,27 +1,17 @@ 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'); diff --git a/src/applications/almanac/controller/AlmanacServiceViewController.php b/src/applications/almanac/controller/AlmanacServiceViewController.php index 113722bf06..debc1bc063 100644 --- a/src/applications/almanac/controller/AlmanacServiceViewController.php +++ b/src/applications/almanac/controller/AlmanacServiceViewController.php @@ -15,6 +15,7 @@ final class AlmanacServiceViewController $service = id(new AlmanacServiceQuery()) ->setViewer($viewer) ->withNames(array($name)) + ->needProperties(true) ->executeOne(); if (!$service) { return new Aphront404Response(); diff --git a/src/applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php b/src/applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php new file mode 100644 index 0000000000..a3afaf3251 --- /dev/null +++ b/src/applications/almanac/engineextension/AlmanacBindingsSearchEngineAttachment.php @@ -0,0 +1,30 @@ +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, + ); + } + +} diff --git a/src/applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php b/src/applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php new file mode 100644 index 0000000000..35c7deae74 --- /dev/null +++ b/src/applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php @@ -0,0 +1,26 @@ +needProperties(true); + } + + public function getAttachmentForObject($object, $data, $spec) { + $properties = $this->getAlmanacPropertyList($object); + + return array( + 'properties' => $properties, + ); + } + +} diff --git a/src/applications/almanac/engineextension/AlmanacSearchEngineAttachment.php b/src/applications/almanac/engineextension/AlmanacSearchEngineAttachment.php new file mode 100644 index 0000000000..0875294bff --- /dev/null +++ b/src/applications/almanac/engineextension/AlmanacSearchEngineAttachment.php @@ -0,0 +1,64 @@ +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(), + ); + } + +} diff --git a/src/applications/almanac/query/AlmanacBindingQuery.php b/src/applications/almanac/query/AlmanacBindingQuery.php index 0b6d7cda3a..5d51d2ba35 100644 --- a/src/applications/almanac/query/AlmanacBindingQuery.php +++ b/src/applications/almanac/query/AlmanacBindingQuery.php @@ -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; } } diff --git a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php index d9e13fba33..a85c38e188 100644 --- a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php +++ b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php @@ -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; } diff --git a/src/applications/almanac/query/AlmanacInterfaceQuery.php b/src/applications/almanac/query/AlmanacInterfaceQuery.php index 353ce34a49..bb6fc2f9d9 100644 --- a/src/applications/almanac/query/AlmanacInterfaceQuery.php +++ b/src/applications/almanac/query/AlmanacInterfaceQuery.php @@ -1,7 +1,7 @@ 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'); diff --git a/src/applications/almanac/query/AlmanacNetworkQuery.php b/src/applications/almanac/query/AlmanacNetworkQuery.php index a1391ff916..a09da0093b 100644 --- a/src/applications/almanac/query/AlmanacNetworkQuery.php +++ b/src/applications/almanac/query/AlmanacNetworkQuery.php @@ -1,7 +1,7 @@ ids = $ids; @@ -18,72 +18,72 @@ 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 = 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(); + } - foreach ($properties as $key => $property) { - $object = idx($objects, $property->getObjectPHID()); - if (!$object) { - unset($properties[$key]); - continue; - } - $property->attachObject($object); + $objects += $this->objects; + + foreach ($properties as $key => $property) { + $object = idx($objects, $property->getObjectPHID()); + if (!$object) { + unset($properties[$key]); + continue; } + $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() { diff --git a/src/applications/almanac/query/AlmanacQuery.php b/src/applications/almanac/query/AlmanacQuery.php index af28e60e30..b046171d32 100644 --- a/src/applications/almanac/query/AlmanacQuery.php +++ b/src/applications/almanac/query/AlmanacQuery.php @@ -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(); diff --git a/src/applications/almanac/query/AlmanacServiceQuery.php b/src/applications/almanac/query/AlmanacServiceQuery.php index f1e6630736..2cfb7edb8f 100644 --- a/src/applications/almanac/query/AlmanacServiceQuery.php +++ b/src/applications/almanac/query/AlmanacServiceQuery.php @@ -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'); diff --git a/src/applications/almanac/query/AlmanacServiceSearchEngine.php b/src/applications/almanac/query/AlmanacServiceSearchEngine.php index 2f7d6cf58f..4011d4fbc5 100644 --- a/src/applications/almanac/query/AlmanacServiceSearchEngine.php +++ b/src/applications/almanac/query/AlmanacServiceSearchEngine.php @@ -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.')), ); } diff --git a/src/applications/almanac/storage/AlmanacDevice.php b/src/applications/almanac/storage/AlmanacDevice.php index 54ba92b4be..7ef17bbc2b 100644 --- a/src/applications/almanac/storage/AlmanacDevice.php +++ b/src/applications/almanac/storage/AlmanacDevice.php @@ -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'), + ); + } + } diff --git a/src/applications/almanac/storage/AlmanacService.php b/src/applications/almanac/storage/AlmanacService.php index 39c8c56e60..48eee1700b 100644 --- a/src/applications/almanac/storage/AlmanacService.php +++ b/src/applications/almanac/storage/AlmanacService.php @@ -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'), + ); + } + } diff --git a/src/applications/search/field/PhabricatorSearchTextField.php b/src/applications/search/field/PhabricatorSearchTextField.php index e3cf1f845c..915f22a6e9 100644 --- a/src/applications/search/field/PhabricatorSearchTextField.php +++ b/src/applications/search/field/PhabricatorSearchTextField.php @@ -15,4 +15,8 @@ final class PhabricatorSearchTextField return new AphrontFormTextControl(); } + protected function newConduitParameterType() { + return new ConduitStringParameterType(); + } + }