Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15401709
D19340.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D19340.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D19340: Provide "almanac.binding.search" and "almanac.binding.edit"
Attached
Detach File
Event Timeline
Log In to Comment