Page MenuHomePhabricator

D19340.diff
No OneTemporary

D19340.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -14,12 +14,17 @@
'AlmanacBindingDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingDeletePropertyTransaction.php',
'AlmanacBindingDisableController' => 'applications/almanac/controller/AlmanacBindingDisableController.php',
'AlmanacBindingDisableTransaction' => 'applications/almanac/xaction/AlmanacBindingDisableTransaction.php',
+ 'AlmanacBindingEditConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php',
'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php',
+ 'AlmanacBindingEditEngine' => 'applications/almanac/editor/AlmanacBindingEditEngine.php',
'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php',
'AlmanacBindingInterfaceTransaction' => 'applications/almanac/xaction/AlmanacBindingInterfaceTransaction.php',
'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php',
'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php',
'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php',
+ 'AlmanacBindingSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php',
+ 'AlmanacBindingSearchEngine' => 'applications/almanac/query/AlmanacBindingSearchEngine.php',
+ 'AlmanacBindingServiceTransaction' => 'applications/almanac/xaction/AlmanacBindingServiceTransaction.php',
'AlmanacBindingSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacBindingSetPropertyTransaction.php',
'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php',
'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php',
@@ -5206,16 +5211,22 @@
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorExtendedPolicyInterface',
+ 'PhabricatorConduitResultInterface',
),
'AlmanacBindingDeletePropertyTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingDisableController' => 'AlmanacServiceController',
'AlmanacBindingDisableTransaction' => 'AlmanacBindingTransactionType',
+ 'AlmanacBindingEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'AlmanacBindingEditController' => 'AlmanacServiceController',
+ 'AlmanacBindingEditEngine' => 'PhabricatorEditEngine',
'AlmanacBindingEditor' => 'AlmanacEditor',
'AlmanacBindingInterfaceTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingPHIDType' => 'PhabricatorPHIDType',
'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacBindingQuery' => 'AlmanacQuery',
+ 'AlmanacBindingSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
+ 'AlmanacBindingSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'AlmanacBindingServiceTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingSetPropertyTransaction' => 'AlmanacBindingTransactionType',
'AlmanacBindingTableView' => 'AphrontView',
'AlmanacBindingTransaction' => 'AlmanacModularTransaction',
diff --git a/src/applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php b/src/applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/conduit/AlmanacBindingEditConduitAPIMethod.php
@@ -0,0 +1,19 @@
+<?php
+
+final class AlmanacBindingEditConduitAPIMethod
+ extends PhabricatorEditEngineAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'almanac.binding.edit';
+ }
+
+ public function newEditEngine() {
+ return new AlmanacBindingEditEngine();
+ }
+
+ public function getMethodSummary() {
+ return pht(
+ 'Apply transactions to create a new binding or edit an existing one.');
+ }
+
+}
diff --git a/src/applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php b/src/applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/conduit/AlmanacBindingSearchConduitAPIMethod.php
@@ -0,0 +1,18 @@
+<?php
+
+final class AlmanacBindingSearchConduitAPIMethod
+ extends PhabricatorSearchEngineAPIMethod {
+
+ public function getAPIMethodName() {
+ return 'almanac.binding.search';
+ }
+
+ public function newSearchEngine() {
+ return new AlmanacBindingSearchEngine();
+ }
+
+ public function getMethodSummary() {
+ return pht('Read information about Almanac bindings.');
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacBindingEditEngine.php b/src/applications/almanac/editor/AlmanacBindingEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacBindingEditEngine.php
@@ -0,0 +1,158 @@
+<?php
+
+final class AlmanacBindingEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'almanac.binding';
+
+ private $service;
+
+ public function setService(AlmanacService $service) {
+ $this->service = $service;
+ return $this;
+ }
+
+ public function getService() {
+ if (!$this->service) {
+ throw new PhutilInvalidStateException('setService');
+ }
+ return $this->service;
+ }
+
+ public function isEngineConfigurable() {
+ return false;
+ }
+
+ public function getEngineName() {
+ return pht('Almanac Bindings');
+ }
+
+ public function getSummaryHeader() {
+ return pht('Edit Almanac Binding Configurations');
+ }
+
+ public function getSummaryText() {
+ return pht('This engine is used to edit Almanac bindings.');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+ protected function newEditableObject() {
+ $service = $this->getService();
+ return AlmanacBinding::initializeNewBinding($service);
+ }
+
+ protected function newEditableObjectForDocumentation() {
+ $service_type = AlmanacCustomServiceType::SERVICETYPE;
+ $service = AlmanacService::initializeNewService($service_type);
+ $this->setService($service);
+ return $this->newEditableObject();
+ }
+
+ protected function newEditableObjectFromConduit(array $raw_xactions) {
+ $service_phid = null;
+ foreach ($raw_xactions as $raw_xaction) {
+ if ($raw_xaction['type'] !== 'service') {
+ continue;
+ }
+
+ $service_phid = $raw_xaction['value'];
+ }
+
+ if ($service_phid === null) {
+ throw new Exception(
+ pht(
+ 'When creating a new Almanac binding via the Conduit API, you '.
+ 'must provide a "service" transaction to select a service to bind.'));
+ }
+
+ $service = id(new AlmanacServiceQuery())
+ ->setViewer($this->getViewer())
+ ->withPHIDs(array($service_phid))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$service) {
+ throw new Exception(
+ pht(
+ 'Service "%s" is unrecognized, restricted, or you do not have '.
+ 'permission to edit it.',
+ $service_phid));
+ }
+
+ $this->setService($service);
+
+ return $this->newEditableObject();
+ }
+
+ protected function newObjectQuery() {
+ return new AlmanacBindingQuery();
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create Binding');
+ }
+
+ protected function getObjectCreateButtonText($object) {
+ return pht('Create Binding');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Binding');
+ }
+
+ protected function getObjectEditShortText($object) {
+ return pht('Edit Binding');
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Binding');
+ }
+
+ protected function getObjectName() {
+ return pht('Binding');
+ }
+
+ protected function getEditorURI() {
+ return '/almanac/binding/edit/';
+ }
+
+ protected function getObjectCreateCancelURI($object) {
+ return '/almanac/binding/';
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+ protected function buildCustomEditFields($object) {
+ return array(
+ id(new PhabricatorTextEditField())
+ ->setKey('service')
+ ->setLabel(pht('Service'))
+ ->setIsConduitOnly(true)
+ ->setTransactionType(
+ AlmanacBindingServiceTransaction::TRANSACTIONTYPE)
+ ->setDescription(pht('Service to create a binding for.'))
+ ->setConduitDescription(pht('Select the service to bind.'))
+ ->setConduitTypeDescription(pht('Service PHID.'))
+ ->setValue($object->getServicePHID()),
+ id(new PhabricatorTextEditField())
+ ->setKey('interface')
+ ->setLabel(pht('Interface'))
+ ->setIsConduitOnly(true)
+ ->setTransactionType(
+ AlmanacBindingInterfaceTransaction::TRANSACTIONTYPE)
+ ->setDescription(pht('Interface to bind the service to.'))
+ ->setConduitDescription(pht('Set the interface to bind.'))
+ ->setConduitTypeDescription(pht('Interface PHID.'))
+ ->setValue($object->getInterfacePHID()),
+ );
+ }
+
+}
diff --git a/src/applications/almanac/query/AlmanacBindingSearchEngine.php b/src/applications/almanac/query/AlmanacBindingSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/query/AlmanacBindingSearchEngine.php
@@ -0,0 +1,80 @@
+<?php
+
+final class AlmanacBindingSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Almanac Bindings');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+ public function newQuery() {
+ return new AlmanacBindingQuery();
+ }
+
+ protected function buildCustomSearchFields() {
+ return array(
+ id(new PhabricatorPHIDsSearchField())
+ ->setLabel(pht('Services'))
+ ->setKey('servicePHIDs')
+ ->setAliases(array('service', 'servicePHID', 'services'))
+ ->setDescription(pht('Search for bindings on particular services.')),
+ id(new PhabricatorPHIDsSearchField())
+ ->setLabel(pht('Devices'))
+ ->setKey('devicePHIDs')
+ ->setAliases(array('device', 'devicePHID', 'devices'))
+ ->setDescription(pht('Search for bindings on particular devices.')),
+ );
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ if ($map['servicePHIDs']) {
+ $query->withServicePHIDs($map['servicePHIDs']);
+ }
+
+ if ($map['devicePHIDs']) {
+ $query->withDevicePHIDs($map['devicePHIDs']);
+ }
+
+ return $query;
+ }
+
+ protected function getURI($path) {
+ return '/almanac/binding/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Bindings'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $devices,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+
+ // For now, this SearchEngine just supports API access via Conduit.
+ throw new PhutilMethodNotImplementedException();
+ }
+
+}
diff --git a/src/applications/almanac/storage/AlmanacBinding.php b/src/applications/almanac/storage/AlmanacBinding.php
--- a/src/applications/almanac/storage/AlmanacBinding.php
+++ b/src/applications/almanac/storage/AlmanacBinding.php
@@ -7,7 +7,8 @@
PhabricatorApplicationTransactionInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface,
- PhabricatorExtendedPolicyInterface {
+ PhabricatorExtendedPolicyInterface,
+ PhabricatorConduitResultInterface {
protected $servicePHID;
protected $devicePHID;
@@ -23,6 +24,7 @@
public static function initializeNewBinding(AlmanacService $service) {
return id(new AlmanacBinding())
->setServicePHID($service->getPHID())
+ ->attachService($service)
->attachAlmanacProperties(array())
->setIsDisabled(0);
}
@@ -225,4 +227,36 @@
}
+/* -( PhabricatorConduitResultInterface )---------------------------------- */
+
+
+ public function getFieldSpecificationsForConduit() {
+ return array(
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('servicePHID')
+ ->setType('phid')
+ ->setDescription(pht('The bound service.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('devicePHID')
+ ->setType('phid')
+ ->setDescription(pht('The device the service is bound to.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('interfacePHID')
+ ->setType('phid')
+ ->setDescription(pht('The interface the service is bound to.')),
+ );
+ }
+
+ public function getFieldValuesForConduit() {
+ return array(
+ 'servicePHID' => $this->getServicePHID(),
+ 'devicePHID' => $this->getDevicePHID(),
+ 'interfacePHID' => $this->getInterfacePHID(),
+ );
+ }
+
+ public function getConduitSearchAttachments() {
+ return array();
+ }
+
}
diff --git a/src/applications/almanac/xaction/AlmanacBindingServiceTransaction.php b/src/applications/almanac/xaction/AlmanacBindingServiceTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacBindingServiceTransaction.php
@@ -0,0 +1,64 @@
+<?php
+
+final class AlmanacBindingServiceTransaction
+ extends AlmanacBindingTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:binding:service';
+
+ public function generateOldValue($object) {
+ return $object->getServicePHID();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setServicePHID($value);
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ $service_phid = $object->getServicePHID();
+ if ($this->isEmptyTextTransaction($service_phid, $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Bindings must have a service.'));
+ }
+
+ foreach ($xactions as $xaction) {
+ if (!$this->isNewObject()) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'The service for a binding can not be changed once it has '.
+ 'been created.'),
+ $xaction);
+ continue;
+ }
+
+ $service_phid = $xaction->getNewValue();
+ $services = id(new AlmanacServiceQuery())
+ ->setViewer($this->getActor())
+ ->withPHIDs(array($service_phid))
+ ->execute();
+ if (!$services) {
+ $errors[] = $this->newInvalidError(
+ pht('You can not bind a nonexistent or restricted service.'),
+ $xaction);
+ continue;
+ }
+
+ $service = head($services);
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $this->getActor(),
+ $service,
+ PhabricatorPolicyCapability::CAN_EDIT);
+ if (!$can_edit) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'You can not bind a service which you do not have permission '.
+ 'to edit.'));
+ continue;
+ }
+ }
+
+ return $errors;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 18, 6:57 PM (3 d, 19 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7710267
Default Alt Text
D19340.diff (15 KB)

Event Timeline