1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

Allow Almanac properties to be set and deleted via Conduit

Summary:
Depends on D19342. Ref T12414. Ref T13120. This adds an EditEngine extension for editing Almanac properties.

The actual wire format is a little weird. Normally, we'd have a transaction for each property, but since you can pick any property names you want we can't really do that (we'd have to generate infinite transactions).

The transaction wire format anticipates that transactions may eventually get some kind of metadata -- each transaction looks like this:

```
{
  "type": "title",
  "value": "Example title"
}
```

...and we can add more keys there. For example, I could have made this transaction look like this:

```
{
  "type": "property.set",
  "almanac.property.key": "some-key",
  "value": "some-value"
}
```

However, I don't want to just accept any possible key freely, and it might be a decent chunk of work to formalize this better. It also doesn't feel great.

I just built special transaction types intead, so you:

```
{
  "type": "property.set",
  "value": {
   "some-key": "some-value",
   ...
  }
}
```

Internally, we may generate more than one transaction as a result (if the "value" has more than one key).

This feels a bit more natural and is probably easier for clients to use anyway.

Test Plan: Set and deleted Service, Device and Binding properties via the API.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13120, T12414

Differential Revision: https://secure.phabricator.com/D19343
This commit is contained in:
epriestley 2018-04-11 09:02:11 -07:00
parent c1558031c2
commit ea9187ea92
9 changed files with 168 additions and 3 deletions

View file

@ -44,6 +44,8 @@ phutil_register_library_map(array(
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php',
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
'AlmanacDeletePropertyEditField' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditField.php',
'AlmanacDeletePropertyEditType' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditType.php',
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php',
'AlmanacDeviceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceDeletePropertyTransaction.php',
@ -129,6 +131,7 @@ phutil_register_library_map(array(
'AlmanacNetworkTransactionType' => 'applications/almanac/xaction/AlmanacNetworkTransactionType.php',
'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php',
'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php',
'AlmanacPropertiesEditEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesEditEngineExtension.php',
'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php',
'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php',
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
@ -165,6 +168,8 @@ phutil_register_library_map(array(
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
'AlmanacServiceTypeTransaction' => 'applications/almanac/xaction/AlmanacServiceTypeTransaction.php',
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
'AlmanacSetPropertyEditField' => 'applications/almanac/engineextension/AlmanacSetPropertyEditField.php',
'AlmanacSetPropertyEditType' => 'applications/almanac/engineextension/AlmanacSetPropertyEditType.php',
'AlmanacTransactionType' => 'applications/almanac/xaction/AlmanacTransactionType.php',
'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php',
'Aphront304Response' => 'aphront/response/Aphront304Response.php',
@ -5246,6 +5251,8 @@ phutil_register_library_map(array(
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCustomServiceType' => 'AlmanacServiceType',
'AlmanacDAO' => 'PhabricatorLiskDAO',
'AlmanacDeletePropertyEditField' => 'PhabricatorEditField',
'AlmanacDeletePropertyEditType' => 'PhabricatorEditType',
'AlmanacDevice' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
@ -5365,6 +5372,7 @@ phutil_register_library_map(array(
'AlmanacNetworkTransactionType' => 'AlmanacTransactionType',
'AlmanacNetworkViewController' => 'AlmanacNetworkController',
'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'AlmanacPropertiesEditEngineExtension' => 'PhabricatorEditEngineExtension',
'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment',
'AlmanacProperty' => array(
'AlmanacDAO',
@ -5413,6 +5421,8 @@ phutil_register_library_map(array(
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
'AlmanacServiceTypeTransaction' => 'AlmanacServiceTransactionType',
'AlmanacServiceViewController' => 'AlmanacServiceController',
'AlmanacSetPropertyEditField' => 'PhabricatorEditField',
'AlmanacSetPropertyEditType' => 'PhabricatorEditType',
'AlmanacTransactionType' => 'PhabricatorModularTransactionType',
'AphlictDropdownDataQuery' => 'Phobject',
'Aphront304Response' => 'AphrontResponse',

View file

@ -91,7 +91,8 @@ final class AlmanacBindingEditEngine
}
protected function newObjectQuery() {
return new AlmanacBindingQuery();
return id(new AlmanacBindingQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {

View file

@ -30,7 +30,8 @@ final class AlmanacDeviceEditEngine
}
protected function newObjectQuery() {
return new AlmanacDeviceQuery();
return id(new AlmanacDeviceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {

View file

@ -79,7 +79,8 @@ final class AlmanacServiceEditEngine
}
protected function newObjectQuery() {
return new AlmanacServiceQuery();
return id(new AlmanacServiceQuery())
->needProperties(true);
}
protected function getObjectCreateTitleText($object) {

View file

@ -0,0 +1,22 @@
<?php
final class AlmanacDeletePropertyEditField
extends PhabricatorEditField {
protected function newControl() {
return null;
}
protected function newHTTPParameterType() {
return null;
}
protected function newConduitParameterType() {
return new ConduitStringListParameterType();
}
protected function newEditType() {
return new AlmanacDeletePropertyEditType();
}
}

View file

@ -0,0 +1,36 @@
<?php
final class AlmanacDeletePropertyEditType
extends PhabricatorEditType {
public function generateTransactions(
PhabricatorApplicationTransaction $template,
array $spec) {
$value = idx($spec, 'value');
if (!is_array($value)) {
throw new Exception(
pht(
'Transaction value when deleting Almanac properties must be a list '.
'of property names.'));
}
$xactions = array();
foreach ($value as $idx => $property_key) {
if (!is_string($property_key)) {
throw new Exception(
pht(
'When deleting Almanac properties, each property name must '.
'be a string. The value at index "%s" is not a string.',
$idx));
}
$xactions[] = $this->newTransaction($template)
->setMetadataValue('almanac.property', $property_key)
->setNewValue(true);
}
return $xactions;
}
}

View file

@ -0,0 +1,44 @@
<?php
final class AlmanacPropertiesEditEngineExtension
extends PhabricatorEditEngineExtension {
const EXTENSIONKEY = 'almanac.properties';
public function isExtensionEnabled() {
return true;
}
public function getExtensionName() {
return pht('Almanac Properties');
}
public function supportsObject(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
return ($object instanceof AlmanacPropertyInterface);
}
public function buildCustomEditFields(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
return array(
id(new AlmanacSetPropertyEditField())
->setKey('property.set')
->setTransactionType($object->getAlmanacPropertySetTransactionType())
->setConduitDescription(
pht('Pass a map of values to set one or more properties.'))
->setConduitTypeDescription(pht('Map of property names to values.'))
->setIsConduitOnly(true),
id(new AlmanacDeletePropertyEditField())
->setKey('property.delete')
->setTransactionType($object->getAlmanacPropertyDeleteTransactionType())
->setConduitDescription(
pht('Pass a list of property names to delete properties.'))
->setConduitTypeDescription(pht('List of property names.'))
->setIsConduitOnly(true),
);
}
}

View file

@ -0,0 +1,22 @@
<?php
final class AlmanacSetPropertyEditField
extends PhabricatorEditField {
protected function newControl() {
return null;
}
protected function newHTTPParameterType() {
return null;
}
protected function newConduitParameterType() {
return new ConduitWildParameterType();
}
protected function newEditType() {
return new AlmanacSetPropertyEditType();
}
}

View file

@ -0,0 +1,28 @@
<?php
final class AlmanacSetPropertyEditType
extends PhabricatorEditType {
public function generateTransactions(
PhabricatorApplicationTransaction $template,
array $spec) {
$value = idx($spec, 'value');
if (!is_array($value)) {
throw new Exception(
pht(
'Transaction value when setting Almanac properties must be a map '.
'with property names as keys.'));
}
$xactions = array();
foreach ($value as $property_key => $property_value) {
$xactions[] = $this->newTransaction($template)
->setMetadataValue('almanac.property', $property_key)
->setNewValue($property_value);
}
return $xactions;
}
}