diff --git a/src/applications/almanac/editor/AlmanacBindingEditEngine.php b/src/applications/almanac/editor/AlmanacBindingEditEngine.php index dfcd9dedcd..07a9e36e9e 100644 --- a/src/applications/almanac/editor/AlmanacBindingEditEngine.php +++ b/src/applications/almanac/editor/AlmanacBindingEditEngine.php @@ -1,158 +1,171 @@ 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()), + id(new PhabricatorBoolEditField()) + ->setKey('disabled') + ->setLabel(pht('Disabled')) + ->setIsConduitOnly(true) + ->setTransactionType( + AlmanacBindingDisableTransaction::TRANSACTIONTYPE) + ->setDescription(pht('Disable or enable the binding.')) + ->setConduitDescription(pht('Disable or enable the binding.')) + ->setConduitTypeDescription(pht('True to disable the binding.')) + ->setValue($object->getIsDisabled()) + ->setOptions( + pht('Enable Binding'), + pht('Disable Binding')), ); } } diff --git a/src/applications/almanac/storage/AlmanacBinding.php b/src/applications/almanac/storage/AlmanacBinding.php index 1641120900..be70a5ecdc 100644 --- a/src/applications/almanac/storage/AlmanacBinding.php +++ b/src/applications/almanac/storage/AlmanacBinding.php @@ -1,262 +1,270 @@ setServicePHID($service->getPHID()) ->attachService($service) ->attachAlmanacProperties(array()) ->setIsDisabled(0); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'mailKey' => 'bytes20', 'isDisabled' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_service' => array( 'columns' => array('servicePHID', 'interfacePHID'), 'unique' => true, ), 'key_device' => array( 'columns' => array('devicePHID'), ), 'key_interface' => array( 'columns' => array('interfacePHID'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID(AlmanacBindingPHIDType::TYPECONST); } public function save() { if (!$this->mailKey) { $this->mailKey = Filesystem::readRandomCharacters(20); } return parent::save(); } public function getName() { return pht('Binding %s', $this->getID()); } public function getURI() { return '/almanac/binding/'.$this->getID().'/'; } public function getService() { return $this->assertAttached($this->service); } public function attachService(AlmanacService $service) { $this->service = $service; return $this; } public function getDevice() { return $this->assertAttached($this->device); } public function attachDevice(AlmanacDevice $device) { $this->device = $device; return $this; } public function getInterface() { return $this->assertAttached($this->interface); } public function attachInterface(AlmanacInterface $interface) { $this->interface = $interface; return $this; } /* -( AlmanacPropertyInterface )------------------------------------------- */ public function attachAlmanacProperties(array $properties) { assert_instances_of($properties, 'AlmanacProperty'); $this->almanacProperties = mpull($properties, null, 'getFieldName'); return $this; } public function getAlmanacProperties() { return $this->assertAttached($this->almanacProperties); } public function hasAlmanacProperty($key) { $this->assertAttached($this->almanacProperties); return isset($this->almanacProperties[$key]); } public function getAlmanacProperty($key) { return $this->assertAttachedKey($this->almanacProperties, $key); } public function getAlmanacPropertyValue($key, $default = null) { if ($this->hasAlmanacProperty($key)) { return $this->getAlmanacProperty($key)->getFieldValue(); } else { return $default; } } public function getAlmanacPropertyFieldSpecifications() { return array(); } public function newAlmanacPropertyEditEngine() { return new AlmanacBindingPropertyEditEngine(); } public function getAlmanacPropertySetTransactionType() { return AlmanacBindingSetPropertyTransaction::TRANSACTIONTYPE; } public function getAlmanacPropertyDeleteTransactionType() { return AlmanacBindingDeletePropertyTransaction::TRANSACTIONTYPE; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { return $this->getService()->getPolicy($capability); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return $this->getService()->hasAutomaticCapability($capability, $viewer); } public function describeAutomaticCapability($capability) { $notes = array( pht('A binding inherits the policies of its service.'), pht( 'To view a binding, you must also be able to view its device and '. 'interface.'), ); return $notes; } /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ public function getExtendedPolicy($capability, PhabricatorUser $viewer) { switch ($capability) { case PhabricatorPolicyCapability::CAN_EDIT: if ($this->getService()->isClusterService()) { return array( array( new PhabricatorAlmanacApplication(), AlmanacManageClusterServicesCapability::CAPABILITY, ), ); } break; } return array(); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new AlmanacBindingEditor(); } public function getApplicationTransactionObject() { return $this; } public function getApplicationTransactionTemplate() { return new AlmanacBindingTransaction(); } public function willRenderTimeline( PhabricatorApplicationTransactionView $timeline, AphrontRequest $request) { return $timeline; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->delete(); } /* -( 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.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('disabled') + ->setType('bool') + ->setDescription(pht('Interface status.')), ); } public function getFieldValuesForConduit() { return array( 'servicePHID' => $this->getServicePHID(), 'devicePHID' => $this->getDevicePHID(), 'interfacePHID' => $this->getInterfacePHID(), + 'disabled' => (bool)$this->getIsDisabled(), ); } public function getConduitSearchAttachments() { - return array(); + return array( + id(new AlmanacPropertiesSearchEngineAttachment()) + ->setAttachmentKey('properties'), + ); } }