@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+168 -3
+10
src/__phutil_library_map__.php
··· 44 44 'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php', 45 45 'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php', 46 46 'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php', 47 + 'AlmanacDeletePropertyEditField' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditField.php', 48 + 'AlmanacDeletePropertyEditType' => 'applications/almanac/engineextension/AlmanacDeletePropertyEditType.php', 47 49 'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php', 48 50 'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php', 49 51 'AlmanacDeviceDeletePropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceDeletePropertyTransaction.php', ··· 129 131 'AlmanacNetworkTransactionType' => 'applications/almanac/xaction/AlmanacNetworkTransactionType.php', 130 132 'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php', 131 133 'AlmanacPropertiesDestructionEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesDestructionEngineExtension.php', 134 + 'AlmanacPropertiesEditEngineExtension' => 'applications/almanac/engineextension/AlmanacPropertiesEditEngineExtension.php', 132 135 'AlmanacPropertiesSearchEngineAttachment' => 'applications/almanac/engineextension/AlmanacPropertiesSearchEngineAttachment.php', 133 136 'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php', 134 137 'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php', ··· 165 168 'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php', 166 169 'AlmanacServiceTypeTransaction' => 'applications/almanac/xaction/AlmanacServiceTypeTransaction.php', 167 170 'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php', 171 + 'AlmanacSetPropertyEditField' => 'applications/almanac/engineextension/AlmanacSetPropertyEditField.php', 172 + 'AlmanacSetPropertyEditType' => 'applications/almanac/engineextension/AlmanacSetPropertyEditType.php', 168 173 'AlmanacTransactionType' => 'applications/almanac/xaction/AlmanacTransactionType.php', 169 174 'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php', 170 175 'Aphront304Response' => 'aphront/response/Aphront304Response.php', ··· 5246 5251 'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability', 5247 5252 'AlmanacCustomServiceType' => 'AlmanacServiceType', 5248 5253 'AlmanacDAO' => 'PhabricatorLiskDAO', 5254 + 'AlmanacDeletePropertyEditField' => 'PhabricatorEditField', 5255 + 'AlmanacDeletePropertyEditType' => 'PhabricatorEditType', 5249 5256 'AlmanacDevice' => array( 5250 5257 'AlmanacDAO', 5251 5258 'PhabricatorPolicyInterface', ··· 5365 5372 'AlmanacNetworkTransactionType' => 'AlmanacTransactionType', 5366 5373 'AlmanacNetworkViewController' => 'AlmanacNetworkController', 5367 5374 'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 5375 + 'AlmanacPropertiesEditEngineExtension' => 'PhabricatorEditEngineExtension', 5368 5376 'AlmanacPropertiesSearchEngineAttachment' => 'AlmanacSearchEngineAttachment', 5369 5377 'AlmanacProperty' => array( 5370 5378 'AlmanacDAO', ··· 5413 5421 'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase', 5414 5422 'AlmanacServiceTypeTransaction' => 'AlmanacServiceTransactionType', 5415 5423 'AlmanacServiceViewController' => 'AlmanacServiceController', 5424 + 'AlmanacSetPropertyEditField' => 'PhabricatorEditField', 5425 + 'AlmanacSetPropertyEditType' => 'PhabricatorEditType', 5416 5426 'AlmanacTransactionType' => 'PhabricatorModularTransactionType', 5417 5427 'AphlictDropdownDataQuery' => 'Phobject', 5418 5428 'Aphront304Response' => 'AphrontResponse',
+2 -1
src/applications/almanac/editor/AlmanacBindingEditEngine.php
··· 91 91 } 92 92 93 93 protected function newObjectQuery() { 94 - return new AlmanacBindingQuery(); 94 + return id(new AlmanacBindingQuery()) 95 + ->needProperties(true); 95 96 } 96 97 97 98 protected function getObjectCreateTitleText($object) {
+2 -1
src/applications/almanac/editor/AlmanacDeviceEditEngine.php
··· 30 30 } 31 31 32 32 protected function newObjectQuery() { 33 - return new AlmanacDeviceQuery(); 33 + return id(new AlmanacDeviceQuery()) 34 + ->needProperties(true); 34 35 } 35 36 36 37 protected function getObjectCreateTitleText($object) {
+2 -1
src/applications/almanac/editor/AlmanacServiceEditEngine.php
··· 79 79 } 80 80 81 81 protected function newObjectQuery() { 82 - return new AlmanacServiceQuery(); 82 + return id(new AlmanacServiceQuery()) 83 + ->needProperties(true); 83 84 } 84 85 85 86 protected function getObjectCreateTitleText($object) {
+22
src/applications/almanac/engineextension/AlmanacDeletePropertyEditField.php
··· 1 + <?php 2 + 3 + final class AlmanacDeletePropertyEditField 4 + extends PhabricatorEditField { 5 + 6 + protected function newControl() { 7 + return null; 8 + } 9 + 10 + protected function newHTTPParameterType() { 11 + return null; 12 + } 13 + 14 + protected function newConduitParameterType() { 15 + return new ConduitStringListParameterType(); 16 + } 17 + 18 + protected function newEditType() { 19 + return new AlmanacDeletePropertyEditType(); 20 + } 21 + 22 + }
+36
src/applications/almanac/engineextension/AlmanacDeletePropertyEditType.php
··· 1 + <?php 2 + 3 + final class AlmanacDeletePropertyEditType 4 + extends PhabricatorEditType { 5 + 6 + public function generateTransactions( 7 + PhabricatorApplicationTransaction $template, 8 + array $spec) { 9 + 10 + $value = idx($spec, 'value'); 11 + if (!is_array($value)) { 12 + throw new Exception( 13 + pht( 14 + 'Transaction value when deleting Almanac properties must be a list '. 15 + 'of property names.')); 16 + } 17 + 18 + $xactions = array(); 19 + foreach ($value as $idx => $property_key) { 20 + if (!is_string($property_key)) { 21 + throw new Exception( 22 + pht( 23 + 'When deleting Almanac properties, each property name must '. 24 + 'be a string. The value at index "%s" is not a string.', 25 + $idx)); 26 + } 27 + 28 + $xactions[] = $this->newTransaction($template) 29 + ->setMetadataValue('almanac.property', $property_key) 30 + ->setNewValue(true); 31 + } 32 + 33 + return $xactions; 34 + } 35 + 36 + }
+44
src/applications/almanac/engineextension/AlmanacPropertiesEditEngineExtension.php
··· 1 + <?php 2 + 3 + final class AlmanacPropertiesEditEngineExtension 4 + extends PhabricatorEditEngineExtension { 5 + 6 + const EXTENSIONKEY = 'almanac.properties'; 7 + 8 + public function isExtensionEnabled() { 9 + return true; 10 + } 11 + 12 + public function getExtensionName() { 13 + return pht('Almanac Properties'); 14 + } 15 + 16 + public function supportsObject( 17 + PhabricatorEditEngine $engine, 18 + PhabricatorApplicationTransactionInterface $object) { 19 + return ($object instanceof AlmanacPropertyInterface); 20 + } 21 + 22 + public function buildCustomEditFields( 23 + PhabricatorEditEngine $engine, 24 + PhabricatorApplicationTransactionInterface $object) { 25 + 26 + return array( 27 + id(new AlmanacSetPropertyEditField()) 28 + ->setKey('property.set') 29 + ->setTransactionType($object->getAlmanacPropertySetTransactionType()) 30 + ->setConduitDescription( 31 + pht('Pass a map of values to set one or more properties.')) 32 + ->setConduitTypeDescription(pht('Map of property names to values.')) 33 + ->setIsConduitOnly(true), 34 + id(new AlmanacDeletePropertyEditField()) 35 + ->setKey('property.delete') 36 + ->setTransactionType($object->getAlmanacPropertyDeleteTransactionType()) 37 + ->setConduitDescription( 38 + pht('Pass a list of property names to delete properties.')) 39 + ->setConduitTypeDescription(pht('List of property names.')) 40 + ->setIsConduitOnly(true), 41 + ); 42 + } 43 + 44 + }
+22
src/applications/almanac/engineextension/AlmanacSetPropertyEditField.php
··· 1 + <?php 2 + 3 + final class AlmanacSetPropertyEditField 4 + extends PhabricatorEditField { 5 + 6 + protected function newControl() { 7 + return null; 8 + } 9 + 10 + protected function newHTTPParameterType() { 11 + return null; 12 + } 13 + 14 + protected function newConduitParameterType() { 15 + return new ConduitWildParameterType(); 16 + } 17 + 18 + protected function newEditType() { 19 + return new AlmanacSetPropertyEditType(); 20 + } 21 + 22 + }
+28
src/applications/almanac/engineextension/AlmanacSetPropertyEditType.php
··· 1 + <?php 2 + 3 + final class AlmanacSetPropertyEditType 4 + extends PhabricatorEditType { 5 + 6 + public function generateTransactions( 7 + PhabricatorApplicationTransaction $template, 8 + array $spec) { 9 + 10 + $value = idx($spec, 'value'); 11 + if (!is_array($value)) { 12 + throw new Exception( 13 + pht( 14 + 'Transaction value when setting Almanac properties must be a map '. 15 + 'with property names as keys.')); 16 + } 17 + 18 + $xactions = array(); 19 + foreach ($value as $property_key => $property_value) { 20 + $xactions[] = $this->newTransaction($template) 21 + ->setMetadataValue('almanac.property', $property_key) 22 + ->setNewValue($property_value); 23 + } 24 + 25 + return $xactions; 26 + } 27 + 28 + }