Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14772146
D15327.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
60 KB
Referenced Files
None
Subscribers
None
D15327.diff
View Options
diff --git a/resources/sql/autopatches/20160222.almanac.1.properties.php b/resources/sql/autopatches/20160222.almanac.1.properties.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20160222.almanac.1.properties.php
@@ -0,0 +1,28 @@
+<?php
+
+$table = new AlmanacProperty();
+$conn_w = $table->establishConnection('w');
+
+// We're going to JSON-encode the value in each row: previously rows stored
+// plain strings, but now they store JSON, so we need to update them.
+
+foreach (new LiskMigrationIterator($table) as $property) {
+ $key = $property->getFieldName();
+
+ $current_row = queryfx_one(
+ $conn_w,
+ 'SELECT fieldValue FROM %T WHERE id = %d',
+ $table->getTableName(),
+ $property->getID());
+
+ if (!$current_row) {
+ continue;
+ }
+
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET fieldValue = %s WHERE id = %d',
+ $table->getTableName(),
+ phutil_json_encode($current_row['fieldValue']),
+ $property->getID());
+}
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,6 +14,7 @@
'AlmanacBindingEditController' => 'applications/almanac/controller/AlmanacBindingEditController.php',
'AlmanacBindingEditor' => 'applications/almanac/editor/AlmanacBindingEditor.php',
'AlmanacBindingPHIDType' => 'applications/almanac/phid/AlmanacBindingPHIDType.php',
+ 'AlmanacBindingPropertyEditEngine' => 'applications/almanac/editor/AlmanacBindingPropertyEditEngine.php',
'AlmanacBindingQuery' => 'applications/almanac/query/AlmanacBindingQuery.php',
'AlmanacBindingTableView' => 'applications/almanac/view/AlmanacBindingTableView.php',
'AlmanacBindingTransaction' => 'applications/almanac/storage/AlmanacBindingTransaction.php',
@@ -25,13 +26,11 @@
'AlmanacConduitAPIMethod' => 'applications/almanac/conduit/AlmanacConduitAPIMethod.php',
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
- 'AlmanacCoreCustomField' => 'applications/almanac/customfield/AlmanacCoreCustomField.php',
'AlmanacCreateClusterServicesCapability' => 'applications/almanac/capability/AlmanacCreateClusterServicesCapability.php',
'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
'AlmanacCreateNamespacesCapability' => 'applications/almanac/capability/AlmanacCreateNamespacesCapability.php',
'AlmanacCreateNetworksCapability' => 'applications/almanac/capability/AlmanacCreateNetworksCapability.php',
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
- 'AlmanacCustomField' => 'applications/almanac/customfield/AlmanacCustomField.php',
'AlmanacCustomServiceType' => 'applications/almanac/servicetype/AlmanacCustomServiceType.php',
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
@@ -41,12 +40,14 @@
'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
'AlmanacDeviceNameNgrams' => 'applications/almanac/storage/AlmanacDeviceNameNgrams.php',
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
+ 'AlmanacDevicePropertyEditEngine' => 'applications/almanac/editor/AlmanacDevicePropertyEditEngine.php',
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php',
'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php',
+ 'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php',
'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php',
'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php',
'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php',
@@ -92,6 +93,7 @@
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
'AlmanacPropertyDeleteController' => 'applications/almanac/controller/AlmanacPropertyDeleteController.php',
'AlmanacPropertyEditController' => 'applications/almanac/controller/AlmanacPropertyEditController.php',
+ 'AlmanacPropertyEditEngine' => 'applications/almanac/editor/AlmanacPropertyEditEngine.php',
'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php',
'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php',
'AlmanacQuery' => 'applications/almanac/query/AlmanacQuery.php',
@@ -106,6 +108,7 @@
'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php',
'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php',
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
+ 'AlmanacServicePropertyEditEngine' => 'applications/almanac/editor/AlmanacServicePropertyEditEngine.php',
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
@@ -113,6 +116,7 @@
'AlmanacServiceType' => 'applications/almanac/servicetype/AlmanacServiceType.php',
'AlmanacServiceTypeTestCase' => 'applications/almanac/servicetype/__tests__/AlmanacServiceTypeTestCase.php',
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
+ 'AlmanacTransaction' => 'applications/almanac/storage/AlmanacTransaction.php',
'AphlictDropdownDataQuery' => 'applications/aphlict/query/AphlictDropdownDataQuery.php',
'Aphront304Response' => 'aphront/response/Aphront304Response.php',
'Aphront400Response' => 'aphront/response/Aphront400Response.php',
@@ -3989,17 +3993,17 @@
'AlmanacBinding' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
- 'PhabricatorCustomFieldInterface',
'PhabricatorApplicationTransactionInterface',
'AlmanacPropertyInterface',
'PhabricatorDestructibleInterface',
),
'AlmanacBindingEditController' => 'AlmanacServiceController',
- 'AlmanacBindingEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'AlmanacBindingEditor' => 'AlmanacEditor',
'AlmanacBindingPHIDType' => 'PhabricatorPHIDType',
+ 'AlmanacBindingPropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacBindingQuery' => 'AlmanacQuery',
'AlmanacBindingTableView' => 'AphrontView',
- 'AlmanacBindingTransaction' => 'PhabricatorApplicationTransaction',
+ 'AlmanacBindingTransaction' => 'AlmanacTransaction',
'AlmanacBindingTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacBindingViewController' => 'AlmanacServiceController',
'AlmanacClusterDatabaseServiceType' => 'AlmanacClusterServiceType',
@@ -4008,22 +4012,16 @@
'AlmanacConduitAPIMethod' => 'ConduitAPIMethod',
'AlmanacConsoleController' => 'AlmanacController',
'AlmanacController' => 'PhabricatorController',
- 'AlmanacCoreCustomField' => array(
- 'AlmanacCustomField',
- 'PhabricatorStandardCustomFieldInterface',
- ),
'AlmanacCreateClusterServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCreateNamespacesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCreateNetworksCapability' => 'PhabricatorPolicyCapability',
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
- 'AlmanacCustomField' => 'PhabricatorCustomField',
'AlmanacCustomServiceType' => 'AlmanacServiceType',
'AlmanacDAO' => 'PhabricatorLiskDAO',
'AlmanacDevice' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
- 'PhabricatorCustomFieldInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorProjectInterface',
'PhabricatorSSHPublicKeyInterface',
@@ -4033,16 +4031,18 @@
),
'AlmanacDeviceController' => 'AlmanacController',
'AlmanacDeviceEditController' => 'AlmanacDeviceController',
- 'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'AlmanacDeviceEditor' => 'AlmanacEditor',
'AlmanacDeviceListController' => 'AlmanacDeviceController',
'AlmanacDeviceNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
+ 'AlmanacDevicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacDeviceQuery' => 'AlmanacQuery',
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
- 'AlmanacDeviceTransaction' => 'PhabricatorApplicationTransaction',
+ 'AlmanacDeviceTransaction' => 'AlmanacTransaction',
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacDeviceViewController' => 'AlmanacDeviceController',
'AlmanacDrydockPoolServiceType' => 'AlmanacServiceType',
+ 'AlmanacEditor' => 'PhabricatorApplicationTransactionEditor',
'AlmanacInterface' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
@@ -4065,7 +4065,6 @@
'AlmanacNamespace' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
- 'PhabricatorCustomFieldInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorProjectInterface',
'AlmanacPropertyInterface',
@@ -4104,12 +4103,13 @@
'AlmanacNetworkViewController' => 'AlmanacNetworkController',
'AlmanacPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'AlmanacProperty' => array(
- 'PhabricatorCustomFieldStorage',
+ 'AlmanacDAO',
'PhabricatorPolicyInterface',
),
'AlmanacPropertyController' => 'AlmanacController',
'AlmanacPropertyDeleteController' => 'AlmanacDeviceController',
'AlmanacPropertyEditController' => 'AlmanacDeviceController',
+ 'AlmanacPropertyEditEngine' => 'PhabricatorEditEngine',
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacQueryDevicesConduitAPIMethod' => 'AlmanacConduitAPIMethod',
@@ -4118,7 +4118,6 @@
'AlmanacService' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
- 'PhabricatorCustomFieldInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorProjectInterface',
'AlmanacPropertyInterface',
@@ -4128,17 +4127,19 @@
'AlmanacServiceController' => 'AlmanacController',
'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacServiceEditController' => 'AlmanacServiceController',
- 'AlmanacServiceEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'AlmanacServiceEditor' => 'AlmanacEditor',
'AlmanacServiceListController' => 'AlmanacServiceController',
'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams',
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
+ 'AlmanacServicePropertyEditEngine' => 'AlmanacPropertyEditEngine',
'AlmanacServiceQuery' => 'AlmanacQuery',
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
- 'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction',
+ 'AlmanacServiceTransaction' => 'AlmanacTransaction',
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacServiceType' => 'Phobject',
'AlmanacServiceTypeTestCase' => 'PhabricatorTestCase',
'AlmanacServiceViewController' => 'AlmanacServiceController',
+ 'AlmanacTransaction' => 'PhabricatorApplicationTransaction',
'AphlictDropdownDataQuery' => 'Phobject',
'Aphront304Response' => 'AphrontResponse',
'Aphront400Response' => 'AphrontResponse',
diff --git a/src/applications/almanac/application/PhabricatorAlmanacApplication.php b/src/applications/almanac/application/PhabricatorAlmanacApplication.php
--- a/src/applications/almanac/application/PhabricatorAlmanacApplication.php
+++ b/src/applications/almanac/application/PhabricatorAlmanacApplication.php
@@ -43,12 +43,12 @@
return array(
'/almanac/' => array(
'' => 'AlmanacConsoleController',
- 'service/' => array(
+ '(?P<objectType>service)/' => array(
$this->getQueryRoutePattern() => 'AlmanacServiceListController',
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController',
'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController',
),
- 'device/' => array(
+ '(?P<objectType>device)/' => array(
$this->getQueryRoutePattern() => 'AlmanacDeviceListController',
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacDeviceEditController',
'view/(?P<name>[^/]+)/' => 'AlmanacDeviceViewController',
@@ -65,16 +65,16 @@
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacNetworkEditController',
'(?P<id>\d+)/' => 'AlmanacNetworkViewController',
),
- 'property/' => array(
- 'edit/' => 'AlmanacPropertyEditController',
- 'delete/' => 'AlmanacPropertyDeleteController',
- ),
'namespace/' => array(
$this->getQueryRoutePattern() => 'AlmanacNamespaceListController',
$this->getEditRoutePattern('edit/')
=> 'AlmanacNamespaceEditController',
'(?P<id>\d+)/' => 'AlmanacNamespaceViewController',
),
+ 'property/' => array(
+ 'delete/' => 'AlmanacPropertyDeleteController',
+ 'update/' => 'AlmanacPropertyEditController',
+ ),
),
);
}
diff --git a/src/applications/almanac/controller/AlmanacController.php b/src/applications/almanac/controller/AlmanacController.php
--- a/src/applications/almanac/controller/AlmanacController.php
+++ b/src/applications/almanac/controller/AlmanacController.php
@@ -10,27 +10,14 @@
$properties = $object->getAlmanacProperties();
$this->requireResource('almanac-css');
+ Javelin::initBehavior('phabricator-tooltips', array());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$object,
PhabricatorPolicyCapability::CAN_EDIT);
- $field_list = PhabricatorCustomField::getObjectFields(
- $object,
- PhabricatorCustomField::ROLE_DEFAULT);
-
- // Before reading values from the object, read defaults.
- $defaults = mpull(
- $field_list->getFields(),
- 'getValueForStorage',
- 'getFieldKey');
-
- $field_list
- ->setViewer($viewer)
- ->readFieldsFromStorage($object);
-
- Javelin::initBehavior('phabricator-tooltips', array());
+ $properties = $object->getAlmanacProperties();
$icon_builtin = id(new PHUIIconView())
->setIcon('fa-circle')
@@ -51,45 +38,46 @@
));
$builtins = $object->getAlmanacPropertyFieldSpecifications();
+ $defaults = mpull($builtins, null, 'getValueForTransaction');
// Sort fields so builtin fields appear first, then fields are ordered
// alphabetically.
- $fields = $field_list->getFields();
- $fields = msort($fields, 'getFieldKey');
+ $properties = msort($properties, 'getFieldName');
$head = array();
$tail = array();
- foreach ($fields as $field) {
- $key = $field->getFieldKey();
+ foreach ($properties as $property) {
+ $key = $property->getFieldName();
if (isset($builtins[$key])) {
- $head[$key] = $field;
+ $head[$key] = $property;
} else {
- $tail[$key] = $field;
+ $tail[$key] = $property;
}
}
- $fields = $head + $tail;
+ $properties = $head + $tail;
+
+ $delete_base = $this->getApplicationURI('property/delete/');
+ $edit_base = $this->getApplicationURI('property/update/');
$rows = array();
- foreach ($fields as $key => $field) {
- $value = $field->getValueForStorage();
+ foreach ($properties as $key => $property) {
+ $value = $property->getFieldValue();
$is_builtin = isset($builtins[$key]);
- $delete_uri = $this->getApplicationURI('property/delete/');
- $delete_uri = id(new PhutilURI($delete_uri))
+ $delete_uri = id(new PhutilURI($delete_base))
->setQueryParams(
array(
- 'objectPHID' => $object->getPHID(),
'key' => $key,
+ 'objectPHID' => $object->getPHID(),
));
- $edit_uri = $this->getApplicationURI('property/edit/');
- $edit_uri = id(new PhutilURI($edit_uri))
+ $edit_uri = id(new PhutilURI($edit_base))
->setQueryParams(
array(
- 'objectPHID' => $object->getPHID(),
'key' => $key,
+ 'objectPHID' => $object->getPHID(),
));
$delete = javelin_tag(
@@ -153,7 +141,8 @@
));
$phid = $object->getPHID();
- $add_uri = $this->getApplicationURI("property/edit/?objectPHID={$phid}");
+ $add_uri = id(new PhutilURI($edit_base))
+ ->setQueryParam('objectPHID', $object->getPHID());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
@@ -196,4 +185,12 @@
$box->setInfoView($error_view);
}
+ protected function getPropertyDeleteURI($object) {
+ return null;
+ }
+
+ protected function getPropertyUpdateURI($object) {
+ return null;
+ }
+
}
diff --git a/src/applications/almanac/controller/AlmanacPropertyDeleteController.php b/src/applications/almanac/controller/AlmanacPropertyDeleteController.php
--- a/src/applications/almanac/controller/AlmanacPropertyDeleteController.php
+++ b/src/applications/almanac/controller/AlmanacPropertyDeleteController.php
@@ -34,53 +34,24 @@
$is_builtin = isset($builtins[$key]);
if ($is_builtin) {
- // This is a builtin property, so we're going to reset it to the
- // default value.
- $field_list = PhabricatorCustomField::getObjectFields(
- $object,
- PhabricatorCustomField::ROLE_DEFAULT);
-
- // Note that we're NOT loading field values from the object: we just want
- // to get the field's default value so we can reset it.
-
- $fields = $field_list->getFields();
- $field = $fields[$key];
-
- $is_delete = false;
- $new_value = $field->getValueForStorage();
-
- // Now, load the field to get the old value.
-
- $field_list
- ->setViewer($viewer)
- ->readFieldsFromStorage($object);
-
- $old_value = $field->getValueForStorage();
-
$title = pht('Reset Property');
- $body = pht('Reset this property to its default value?');
- $submit_text = pht('Reset');
+ $body = pht(
+ 'Reset property "%s" to its default value?',
+ $key);
+ $submit_text = pht('Reset Property');
} else {
- // This is a custom property, so we're going to delete it outright.
- $is_delete = true;
- $old_value = $object->getAlmanacPropertyValue($key);
- $new_value = null;
-
$title = pht('Delete Property');
- $body = pht('Delete this property? TODO: DOES NOT WORK YET');
- $submit_text = pht('Delete');
+ $body = pht(
+ 'Delete property "%s"?',
+ $key);
+ $submit_text = pht('Delete Property');
}
$validation_exception = null;
if ($request->isFormPost()) {
$xaction = $object->getApplicationTransactionTemplate()
- ->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
- ->setMetadataValue('customfield:key', $key)
- ->setOldValue($old_value)
- ->setNewValue($new_value);
-
- // TODO: We aren't really deleting properties that we claim to delete
- // yet, but that needs to be specialized a little bit.
+ ->setTransactionType(AlmanacTransaction::TYPE_PROPERTY_REMOVE)
+ ->setMetadataValue('almanac.property', $key);
$editor = $object->getApplicationTransactionEditor()
->setActor($viewer)
diff --git a/src/applications/almanac/controller/AlmanacPropertyEditController.php b/src/applications/almanac/controller/AlmanacPropertyEditController.php
--- a/src/applications/almanac/controller/AlmanacPropertyEditController.php
+++ b/src/applications/almanac/controller/AlmanacPropertyEditController.php
@@ -24,133 +24,81 @@
}
$cancel_uri = $object->getURI();
+ $property_key = $request->getStr('key');
- $key = $request->getStr('key');
- if ($key) {
- $property_key = $key;
-
- $is_new = false;
- $title = pht('Edit Property');
- $save_button = pht('Save Changes');
+ if (!strlen($property_key)) {
+ return $this->buildPropertyKeyResponse($cancel_uri, null);
} else {
- $property_key = null;
-
- $is_new = true;
- $title = pht('Add Property');
- $save_button = pht('Add Property');
- }
-
- if ($is_new) {
- $errors = array();
- $property = null;
+ $error = null;
+ try {
+ AlmanacNames::validateName($property_key);
+ } catch (Exception $ex) {
+ $error = $ex->getMessage();
+ }
- $v_name = null;
- $e_name = true;
+ // NOTE: If you enter an existing name, we're just treating it as an
+ // edit operation. This might be a little confusing.
- if ($request->isFormPost()) {
- $name = $request->getStr('name');
- if (!strlen($name)) {
- $e_name = pht('Required');
- $errors[] = pht('You must provide a property name.');
+ if ($error !== null) {
+ if ($request->isFormPost()) {
+ // The user is creating a new property and picked a bad name. Give
+ // them an opportunity to fix it.
+ return $this->buildPropertyKeyResponse($cancel_uri, $error);
} else {
- $caught = null;
- try {
- AlmanacNames::validateName($name);
- } catch (Exception $ex) {
- $caught = $ex;
- }
- if ($caught) {
- $e_name = pht('Invalid');
- $errors[] = $caught->getMessage();
- }
- }
-
- if (!$errors) {
- $property_key = $name;
+ // The user is editing an invalid property.
+ return $this->newDialog()
+ ->setTitle(pht('Invalid Property'))
+ ->appendParagraph(
+ pht(
+ 'The property name "%s" is invalid. This property can not '.
+ 'be edited.',
+ $property_key))
+ ->appendParagraph($error)
+ ->addCancelButton($cancel_uri);
}
}
-
- if ($property_key === null) {
- $form = id(new AphrontFormView())
- ->setUser($viewer)
- ->appendChild(
- id(new AphrontFormTextControl())
- ->setName('name')
- ->setLabel(pht('Name'))
- ->setValue($v_name)
- ->setError($e_name));
-
- return $this->newDialog()
- ->setTitle($title)
- ->setErrors($errors)
- ->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
- ->appendForm($form)
- ->addSubmitButton(pht('Continue'))
- ->addCancelButton($cancel_uri);
- }
}
- // Make sure property key is appropriate.
- // TODO: It would be cleaner to put this safety check in the Editor.
- AlmanacNames::validateName($property_key);
-
- // If we're adding a new property, put a placeholder on the object so
- // that we can build a CustomField for it.
- if (!$object->hasAlmanacProperty($property_key)) {
- $temporary_property = id(new AlmanacProperty())
- ->setObjectPHID($object->getPHID())
- ->setFieldName($property_key);
-
- $object->attachAlmanacProperties(array($temporary_property));
- }
-
- $field_list = PhabricatorCustomField::getObjectFields(
- $object,
- PhabricatorCustomField::ROLE_DEFAULT);
-
- // Select only the field being edited.
- $fields = $field_list->getFields();
- $fields = array_select_keys($fields, array($property_key));
- $field_list = new PhabricatorCustomFieldList($fields);
-
- $field_list
- ->setViewer($viewer)
- ->readFieldsFromStorage($object);
-
- $validation_exception = null;
- if ($request->isFormPost() && $request->getStr('isValueEdit')) {
- $xactions = $field_list->buildFieldTransactionsFromRequest(
- $object->getApplicationTransactionTemplate(),
- $request);
+ return $object->newAlmanacPropertyEditEngine()
+ ->addContextParameter('objectPHID')
+ ->addContextParameter('key')
+ ->setTargetObject($object)
+ ->setPropertyKey($property_key)
+ ->setController($this)
+ ->buildResponse();
+ }
- $editor = $object->getApplicationTransactionEditor()
- ->setActor($viewer)
- ->setContentSourceFromRequest($request)
- ->setContinueOnNoEffect(true)
- ->setContinueOnMissingFields(true);
+ private function buildPropertyKeyResponse($cancel_uri, $error) {
+ $viewer = $this->getViewer();
+ $request = $this->getRequest();
+ $v_key = $request->getStr('key');
- try {
- $editor->applyTransactions($object, $xactions);
- return id(new AphrontRedirectResponse())->setURI($cancel_uri);
- } catch (PhabricatorApplicationTransactionValidationException $ex) {
- $validation_exception = $ex;
- }
+ if ($error !== null) {
+ $e_key = pht('Invalid');
+ } else {
+ $e_key = true;
}
$form = id(new AphrontFormView())
->setUser($viewer)
- ->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
- ->addHiddenInput('key', $request->getStr('key'))
- ->addHiddenInput('name', $property_key)
- ->addHiddenInput('isValueEdit', true);
-
- $field_list->appendFieldsToForm($form);
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('key')
+ ->setLabel(pht('Name'))
+ ->setValue($v_key)
+ ->setError($e_key));
+
+ $errors = array();
+ if ($error !== null) {
+ $errors[] = $error;
+ }
return $this->newDialog()
- ->setTitle($title)
- ->setValidationException($validation_exception)
+ ->setTitle(pht('Add Property'))
+ ->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
+ ->setErrors($errors)
->appendForm($form)
- ->addSubmitButton($save_button)
+ ->addSubmitButton(pht('Continue'))
->addCancelButton($cancel_uri);
}
diff --git a/src/applications/almanac/controller/AlmanacServiceController.php b/src/applications/almanac/controller/AlmanacServiceController.php
--- a/src/applications/almanac/controller/AlmanacServiceController.php
+++ b/src/applications/almanac/controller/AlmanacServiceController.php
@@ -11,4 +11,14 @@
return $crumbs;
}
+ protected function getPropertyDeleteURI($object) {
+ $id = $object->getID();
+ return "/almanac/service/delete/{$id}/";
+ }
+
+ protected function getPropertyUpdateURI($object) {
+ $id = $object->getID();
+ return "/almanac/service/property/{$id}/";
+ }
+
}
diff --git a/src/applications/almanac/customfield/AlmanacCoreCustomField.php b/src/applications/almanac/customfield/AlmanacCoreCustomField.php
deleted file mode 100644
--- a/src/applications/almanac/customfield/AlmanacCoreCustomField.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-
-final class AlmanacCoreCustomField
- extends AlmanacCustomField
- implements PhabricatorStandardCustomFieldInterface {
-
- public function getStandardCustomFieldNamespace() {
- return 'almanac:core';
- }
-
- public function getFieldKey() {
- return $this->getProxy()->getRawStandardFieldKey();
- }
-
- public function getFieldName() {
- return $this->getFieldKey();
- }
-
- public function createFields($object) {
- if (!$object->getID()) {
- return array();
- }
-
- $specs = $object->getAlmanacPropertyFieldSpecifications();
-
- $default_specs = array();
- foreach ($object->getAlmanacProperties() as $property) {
- $default_specs[$property->getFieldName()] = array(
- 'name' => $property->getFieldName(),
- 'type' => 'text',
- );
- }
-
- return PhabricatorStandardCustomField::buildStandardFields(
- $this,
- $specs + $default_specs);
- }
-
- public function shouldUseStorage() {
- return false;
- }
-
- public function readValueFromObject(PhabricatorCustomFieldInterface $object) {
- $key = $this->getFieldKey();
-
- if ($object->hasAlmanacProperty($key)) {
- $this->setValueFromStorage($object->getAlmanacPropertyValue($key));
- }
- }
-
- public function applyApplicationTransactionInternalEffects(
- PhabricatorApplicationTransaction $xaction) {
- return;
- }
-
- public function applyApplicationTransactionExternalEffects(
- PhabricatorApplicationTransaction $xaction) {
-
- $object = $this->getObject();
- $phid = $object->getPHID();
- $key = $this->getFieldKey();
-
- $property = id(new AlmanacPropertyQuery())
- ->setViewer($this->getViewer())
- ->withObjectPHIDs(array($phid))
- ->withNames(array($key))
- ->executeOne();
- if (!$property) {
- $property = id(new AlmanacProperty())
- ->setObjectPHID($phid)
- ->setFieldIndex(PhabricatorHash::digestForIndex($key))
- ->setFieldName($key);
- }
-
- $property
- ->setFieldValue($xaction->getNewValue())
- ->save();
- }
-
-}
diff --git a/src/applications/almanac/customfield/AlmanacCustomField.php b/src/applications/almanac/customfield/AlmanacCustomField.php
deleted file mode 100644
--- a/src/applications/almanac/customfield/AlmanacCustomField.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-
-abstract class AlmanacCustomField
- extends PhabricatorCustomField {}
diff --git a/src/applications/almanac/editor/AlmanacBindingEditor.php b/src/applications/almanac/editor/AlmanacBindingEditor.php
--- a/src/applications/almanac/editor/AlmanacBindingEditor.php
+++ b/src/applications/almanac/editor/AlmanacBindingEditor.php
@@ -1,11 +1,7 @@
<?php
final class AlmanacBindingEditor
- extends PhabricatorApplicationTransactionEditor {
-
- public function getEditorApplicationClass() {
- return 'PhabricatorAlmanacApplication';
- }
+ extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Binding');
diff --git a/src/applications/almanac/editor/AlmanacBindingPropertyEditEngine.php b/src/applications/almanac/editor/AlmanacBindingPropertyEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacBindingPropertyEditEngine.php
@@ -0,0 +1,16 @@
+<?php
+
+final class AlmanacBindingPropertyEditEngine
+ extends AlmanacPropertyEditEngine {
+
+ const ENGINECONST = 'almanac.binding.property';
+
+ protected function newObjectQuery() {
+ return new AlmanacBindingQuery();
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacDeviceEditor.php b/src/applications/almanac/editor/AlmanacDeviceEditor.php
--- a/src/applications/almanac/editor/AlmanacDeviceEditor.php
+++ b/src/applications/almanac/editor/AlmanacDeviceEditor.php
@@ -1,20 +1,12 @@
<?php
final class AlmanacDeviceEditor
- extends PhabricatorApplicationTransactionEditor {
-
- public function getEditorApplicationClass() {
- return 'PhabricatorAlmanacApplication';
- }
+ extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Device');
}
- protected function supportsSearch() {
- return true;
- }
-
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
diff --git a/src/applications/almanac/editor/AlmanacDevicePropertyEditEngine.php b/src/applications/almanac/editor/AlmanacDevicePropertyEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacDevicePropertyEditEngine.php
@@ -0,0 +1,16 @@
+<?php
+
+final class AlmanacDevicePropertyEditEngine
+ extends AlmanacPropertyEditEngine {
+
+ const ENGINECONST = 'almanac.device.property';
+
+ protected function newObjectQuery() {
+ return new AlmanacDeviceQuery();
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacEditor.php b/src/applications/almanac/editor/AlmanacEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacEditor.php
@@ -0,0 +1,156 @@
+<?php
+
+abstract class AlmanacEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+ protected function supportsSearch() {
+ return true;
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
+ $types[] = AlmanacTransaction::TYPE_PROPERTY_REMOVE;
+
+ return $types;
+ }
+
+ protected function getCustomTransactionOldValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+ switch ($xaction->getTransactionType()) {
+ case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
+ case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
+ $property_key = $xaction->getMetadataValue('almanac.property');
+ $exists = $object->hasAlmanacProperty($property_key);
+ $value = $object->getAlmanacPropertyValue($property_key);
+ return array(
+ 'existed' => $exists,
+ 'value' => $value,
+ );
+ }
+
+ return parent::getCustomTransactionOldValue($object, $xaction);
+ }
+
+ protected function getCustomTransactionNewValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
+ case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
+ return $xaction->getNewValue();
+ }
+
+ return parent::getCustomTransactionNewValue($object, $xaction);
+ }
+
+ protected function applyCustomInternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
+ case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
+ return;
+ }
+
+ return parent::applyCustomInternalTransaction($object, $xaction);
+ }
+
+ protected function applyCustomExternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
+ $property_key = $xaction->getMetadataValue('almanac.property');
+ if ($object->hasAlmanacProperty($property_key)) {
+ $property = $object->getAlmanacProperty($property_key);
+ } else {
+ $property = id(new AlmanacProperty())
+ ->setObjectPHID($object->getPHID())
+ ->setFieldName($property_key);
+ }
+ $property
+ ->setFieldValue($xaction->getNewValue())
+ ->save();
+ return;
+ case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
+ $property_key = $xaction->getMetadataValue('almanac.property');
+ if ($object->hasAlmanacProperty($property_key)) {
+ $property = $object->getAlmanacProperty($property_key);
+ $property->delete();
+ }
+ return;
+ }
+
+ return parent::applyCustomExternalTransaction($object, $xaction);
+ }
+
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+
+ switch ($type) {
+ case AlmanacTransaction::TYPE_PROPERTY_UPDATE:
+ foreach ($xactions as $xaction) {
+ $property_key = $xaction->getMetadataValue('almanac.property');
+
+ $message = null;
+ try {
+ AlmanacNames::validateName($property_key);
+ } catch (Exception $ex) {
+ $message = $ex->getMessage();
+ }
+
+ if ($message !== null) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Invalid'),
+ $message,
+ $xaction);
+ $errors[] = $error;
+ continue;
+ }
+
+ $new_value = $xaction->getNewValue();
+ try {
+ phutil_json_encode($new_value);
+ } catch (Exception $ex) {
+ $message = pht(
+ 'Almanac property values must be representable in JSON. %s',
+ $ex->getMessage());
+ }
+
+ if ($message !== null) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Invalid'),
+ $message,
+ $xaction);
+ $errors[] = $error;
+ continue;
+ }
+ }
+ break;
+
+ case AlmanacTransaction::TYPE_PROPERTY_REMOVE:
+ // NOTE: No name validation on removals since it's OK to delete
+ // an invalid property that somehow came into existence.
+ break;
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacPropertyEditEngine.php b/src/applications/almanac/editor/AlmanacPropertyEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacPropertyEditEngine.php
@@ -0,0 +1,79 @@
+<?php
+
+abstract class AlmanacPropertyEditEngine
+ extends PhabricatorEditEngine {
+
+ private $propertyKey;
+
+ public function setPropertyKey($property_key) {
+ $this->propertyKey = $property_key;
+ return $this;
+ }
+
+ public function getPropertyKey() {
+ return $this->propertyKey;
+ }
+
+ public function isEngineConfigurable() {
+ return false;
+ }
+
+ public function isEngineExtensible() {
+ return false;
+ }
+
+ public function getEngineName() {
+ return pht('Almanac Properties');
+ }
+
+ public function getSummaryHeader() {
+ return pht('Edit Almanac Property Configurations');
+ }
+
+ public function getSummaryText() {
+ return pht('This engine is used to edit Almanac properties.');
+ }
+
+ public function getEngineApplicationClass() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+ protected function newEditableObject() {
+ throw new PhutilMethodNotImplementedException();
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create Property');
+ }
+
+ protected function getObjectCreateButtonText($object) {
+ return pht('Create Property');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Property: %s', $object->getName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return pht('Edit Property');
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Property');
+ }
+
+ protected function buildCustomEditFields($object) {
+ $property_key = $this->getPropertyKey();
+ $xaction_type = AlmanacTransaction::TYPE_PROPERTY_UPDATE;
+
+ return array(
+ id(new PhabricatorTextEditField())
+ ->setKey('value')
+ ->setMetadataValue('almanac.property', $property_key)
+ ->setLabel($property_key)
+ ->setTransactionType($xaction_type)
+ ->setValue($object->getAlmanacPropertyValue($property_key)),
+ );
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacServiceEditor.php b/src/applications/almanac/editor/AlmanacServiceEditor.php
--- a/src/applications/almanac/editor/AlmanacServiceEditor.php
+++ b/src/applications/almanac/editor/AlmanacServiceEditor.php
@@ -1,20 +1,12 @@
<?php
final class AlmanacServiceEditor
- extends PhabricatorApplicationTransactionEditor {
-
- public function getEditorApplicationClass() {
- return 'PhabricatorAlmanacApplication';
- }
+ extends AlmanacEditor {
public function getEditorObjectsDescription() {
return pht('Almanac Service');
}
- protected function supportsSearch() {
- return true;
- }
-
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
@@ -185,6 +177,4 @@
return $errors;
}
-
-
}
diff --git a/src/applications/almanac/editor/AlmanacServicePropertyEditEngine.php b/src/applications/almanac/editor/AlmanacServicePropertyEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacServicePropertyEditEngine.php
@@ -0,0 +1,16 @@
+<?php
+
+final class AlmanacServicePropertyEditEngine
+ extends AlmanacPropertyEditEngine {
+
+ const ENGINECONST = 'almanac.service.property';
+
+ protected function newObjectQuery() {
+ return new AlmanacServiceQuery();
+ }
+
+ protected function getObjectViewURI($object) {
+ return $object->getURI();
+ }
+
+}
diff --git a/src/applications/almanac/property/AlmanacPropertyInterface.php b/src/applications/almanac/property/AlmanacPropertyInterface.php
--- a/src/applications/almanac/property/AlmanacPropertyInterface.php
+++ b/src/applications/almanac/property/AlmanacPropertyInterface.php
@@ -8,5 +8,6 @@
public function getAlmanacProperty($key);
public function getAlmanacPropertyValue($key, $default = null);
public function getAlmanacPropertyFieldSpecifications();
+ public function newAlmanacPropertyEditEngine();
}
diff --git a/src/applications/almanac/query/AlmanacQuery.php b/src/applications/almanac/query/AlmanacQuery.php
--- a/src/applications/almanac/query/AlmanacQuery.php
+++ b/src/applications/almanac/query/AlmanacQuery.php
@@ -5,9 +5,8 @@
protected function didFilterPage(array $objects) {
if (head($objects) instanceof AlmanacPropertyInterface) {
- // NOTE: We load properties unconditionally because CustomField assumes
- // it can always generate a list of fields on an object. It may make
- // sense to re-examine that assumption eventually.
+ // NOTE: We load properties for obsolete historical reasons. It may make
+ // sense to re-examine that assumption shortly.
$property_query = id(new AlmanacPropertyQuery())
->setViewer($this->getViewer())
@@ -25,9 +24,23 @@
$properties = mgroup($properties, 'getObjectPHID');
foreach ($objects as $object) {
$object_properties = idx($properties, $object->getPHID(), array());
+ $object_properties = mpull($object_properties, null, 'getFieldName');
+
+ // Create synthetic properties for defaults on the object itself.
+ $specs = $object->getAlmanacPropertyFieldSpecifications();
+ foreach ($specs as $key => $spec) {
+ if (empty($object_properties[$key])) {
+ $object_properties[$key] = id(new AlmanacProperty())
+ ->setObjectPHID($object->getPHID())
+ ->setFieldName($key)
+ ->setFieldValue($spec->getValueForTransaction());
+ }
+ }
+
foreach ($object_properties as $property) {
$property->attachObject($object);
}
+
$object->attachAlmanacProperties($object_properties);
}
}
diff --git a/src/applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php b/src/applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php
--- a/src/applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php
+++ b/src/applications/almanac/servicetype/AlmanacClusterDatabaseServiceType.php
@@ -16,8 +16,4 @@
'Defines a database service for use in a Phabricator cluster.');
}
- public function getFieldSpecifications() {
- return array();
- }
-
}
diff --git a/src/applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php b/src/applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php
--- a/src/applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php
+++ b/src/applications/almanac/servicetype/AlmanacClusterRepositoryServiceType.php
@@ -18,16 +18,7 @@
public function getFieldSpecifications() {
return array(
- 'closed' => array(
- 'type' => 'bool',
- 'name' => pht('Closed'),
- 'default' => false,
- 'strings' => array(
- 'edit.checkbox' => pht(
- 'Prevent new repositories from being allocated on this '.
- 'service.'),
- ),
- ),
+ 'closed' => id(new PhabricatorTextEditField()),
);
}
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
@@ -4,7 +4,6 @@
extends AlmanacDAO
implements
PhabricatorPolicyInterface,
- PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
AlmanacPropertyInterface,
PhabricatorDestructibleInterface {
@@ -17,7 +16,6 @@
private $service = self::ATTACHABLE;
private $device = self::ATTACHABLE;
private $interface = self::ATTACHABLE;
- private $customFields = self::ATTACHABLE;
private $almanacProperties = self::ATTACHABLE;
public static function initializeNewBinding(AlmanacService $service) {
@@ -58,6 +56,10 @@
return parent::save();
}
+ public function getName() {
+ return pht('Binding %s', $this->getID());
+ }
+
public function getURI() {
return '/almanac/binding/'.$this->getID().'/';
}
@@ -124,6 +126,10 @@
return array();
}
+ public function newAlmanacPropertyEditEngine() {
+ return new AlmanacBindingPropertyEditEngine();
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -162,27 +168,6 @@
}
-/* -( PhabricatorCustomFieldInterface )------------------------------------ */
-
-
- public function getCustomFieldSpecificationForRole($role) {
- return array();
- }
-
- public function getCustomFieldBaseClass() {
- return 'AlmanacCustomField';
- }
-
- public function getCustomFields() {
- return $this->assertAttached($this->customFields);
- }
-
- public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
- $this->customFields = $fields;
- return $this;
- }
-
-
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
diff --git a/src/applications/almanac/storage/AlmanacBindingTransaction.php b/src/applications/almanac/storage/AlmanacBindingTransaction.php
--- a/src/applications/almanac/storage/AlmanacBindingTransaction.php
+++ b/src/applications/almanac/storage/AlmanacBindingTransaction.php
@@ -1,7 +1,7 @@
<?php
final class AlmanacBindingTransaction
- extends PhabricatorApplicationTransaction {
+ extends AlmanacTransaction {
const TYPE_INTERFACE = 'almanac:binding:interface';
diff --git a/src/applications/almanac/storage/AlmanacDevice.php b/src/applications/almanac/storage/AlmanacDevice.php
--- a/src/applications/almanac/storage/AlmanacDevice.php
+++ b/src/applications/almanac/storage/AlmanacDevice.php
@@ -4,7 +4,6 @@
extends AlmanacDAO
implements
PhabricatorPolicyInterface,
- PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorProjectInterface,
PhabricatorSSHPublicKeyInterface,
@@ -19,7 +18,6 @@
protected $editPolicy;
protected $isLocked;
- private $customFields = self::ATTACHABLE;
private $almanacProperties = self::ATTACHABLE;
public static function initializeNewDevice() {
@@ -137,6 +135,10 @@
return array();
}
+ public function newAlmanacPropertyEditEngine() {
+ return new AlmanacDevicePropertyEditEngine();
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -178,27 +180,6 @@
}
-/* -( PhabricatorCustomFieldInterface )------------------------------------ */
-
-
- public function getCustomFieldSpecificationForRole($role) {
- return array();
- }
-
- public function getCustomFieldBaseClass() {
- return 'AlmanacCustomField';
- }
-
- public function getCustomFields() {
- return $this->assertAttached($this->customFields);
- }
-
- public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
- $this->customFields = $fields;
- return $this;
- }
-
-
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
diff --git a/src/applications/almanac/storage/AlmanacDeviceTransaction.php b/src/applications/almanac/storage/AlmanacDeviceTransaction.php
--- a/src/applications/almanac/storage/AlmanacDeviceTransaction.php
+++ b/src/applications/almanac/storage/AlmanacDeviceTransaction.php
@@ -1,7 +1,7 @@
<?php
final class AlmanacDeviceTransaction
- extends PhabricatorApplicationTransaction {
+ extends AlmanacTransaction {
const TYPE_NAME = 'almanac:device:name';
const TYPE_INTERFACE = 'almanac:device:interface';
diff --git a/src/applications/almanac/storage/AlmanacNamespace.php b/src/applications/almanac/storage/AlmanacNamespace.php
--- a/src/applications/almanac/storage/AlmanacNamespace.php
+++ b/src/applications/almanac/storage/AlmanacNamespace.php
@@ -4,7 +4,6 @@
extends AlmanacDAO
implements
PhabricatorPolicyInterface,
- PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorProjectInterface,
AlmanacPropertyInterface,
@@ -17,7 +16,6 @@
protected $viewPolicy;
protected $editPolicy;
- private $customFields = self::ATTACHABLE;
private $almanacProperties = self::ATTACHABLE;
public static function initializeNewNamespace() {
@@ -148,6 +146,10 @@
return array();
}
+ public function newAlmanacPropertyEditEngine() {
+ throw new PhutilMethodNotImplementedException();
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -177,27 +179,6 @@
}
-/* -( PhabricatorCustomFieldInterface )------------------------------------ */
-
-
- public function getCustomFieldSpecificationForRole($role) {
- return array();
- }
-
- public function getCustomFieldBaseClass() {
- return 'AlmanacCustomField';
- }
-
- public function getCustomFields() {
- return $this->assertAttached($this->customFields);
- }
-
- public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
- $this->customFields = $fields;
- return $this;
- }
-
-
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
diff --git a/src/applications/almanac/storage/AlmanacProperty.php b/src/applications/almanac/storage/AlmanacProperty.php
--- a/src/applications/almanac/storage/AlmanacProperty.php
+++ b/src/applications/almanac/storage/AlmanacProperty.php
@@ -1,25 +1,33 @@
<?php
final class AlmanacProperty
- extends PhabricatorCustomFieldStorage
+ extends AlmanacDAO
implements PhabricatorPolicyInterface {
+ protected $objectPHID;
+ protected $fieldIndex;
protected $fieldName;
+ protected $fieldValue;
private $object = self::ATTACHABLE;
- public function getApplicationName() {
- return 'almanac';
- }
-
protected function getConfiguration() {
- $config = parent::getConfiguration();
-
- $config[self::CONFIG_COLUMN_SCHEMA] += array(
- 'fieldName' => 'text128',
- );
-
- return $config;
+ return array(
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_SERIALIZATION => array(
+ 'fieldValue' => self::SERIALIZATION_JSON,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'fieldIndex' => 'bytes12',
+ 'fieldName' => 'text128',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'objectPHID' => array(
+ 'columns' => array('objectPHID', 'fieldIndex'),
+ 'unique' => true,
+ ),
+ ),
+ ) + parent::getConfiguration();
}
public function getObject() {
@@ -31,37 +39,11 @@
return $this;
}
- public static function buildTransactions(
- AlmanacPropertyInterface $object,
- array $properties) {
-
- $template = $object->getApplicationTransactionTemplate();
-
- $attached_properties = $object->getAlmanacProperties();
- foreach ($properties as $key => $value) {
- if (empty($attached_properties[$key])) {
- $attached_properties[] = id(new AlmanacProperty())
- ->setObjectPHID($object->getPHID())
- ->setFieldName($key);
- }
- }
- $object->attachAlmanacProperties($attached_properties);
-
- $field_list = PhabricatorCustomField::getObjectFields(
- $object,
- PhabricatorCustomField::ROLE_DEFAULT);
- $fields = $field_list->getFields();
-
- $xactions = array();
- foreach ($properties as $name => $property) {
- $xactions[] = id(clone $template)
- ->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
- ->setMetadataValue('customfield:key', $name)
- ->setOldValue($object->getAlmanacPropertyValue($name))
- ->setNewValue($property);
- }
-
- return $xactions;
+ public function save() {
+ $hash = PhabricatorHash::digestForIndex($this->getFieldName());
+ $this->setFieldIndex($hash);
+
+ return parent::save();
}
diff --git a/src/applications/almanac/storage/AlmanacService.php b/src/applications/almanac/storage/AlmanacService.php
--- a/src/applications/almanac/storage/AlmanacService.php
+++ b/src/applications/almanac/storage/AlmanacService.php
@@ -4,7 +4,6 @@
extends AlmanacDAO
implements
PhabricatorPolicyInterface,
- PhabricatorCustomFieldInterface,
PhabricatorApplicationTransactionInterface,
PhabricatorProjectInterface,
AlmanacPropertyInterface,
@@ -19,7 +18,6 @@
protected $serviceClass;
protected $isLocked;
- private $customFields = self::ATTACHABLE;
private $almanacProperties = self::ATTACHABLE;
private $bindings = self::ATTACHABLE;
private $serviceType = self::ATTACHABLE;
@@ -130,6 +128,10 @@
return $this->getServiceType()->getFieldSpecifications();
}
+ public function newAlmanacPropertyEditEngine() {
+ return new AlmanacServicePropertyEditEngine();
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -171,27 +173,6 @@
}
-/* -( PhabricatorCustomFieldInterface )------------------------------------ */
-
-
- public function getCustomFieldSpecificationForRole($role) {
- return array();
- }
-
- public function getCustomFieldBaseClass() {
- return 'AlmanacCustomField';
- }
-
- public function getCustomFields() {
- return $this->assertAttached($this->customFields);
- }
-
- public function attachCustomFields(PhabricatorCustomFieldAttachment $fields) {
- $this->customFields = $fields;
- return $this;
- }
-
-
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
diff --git a/src/applications/almanac/storage/AlmanacServiceTransaction.php b/src/applications/almanac/storage/AlmanacServiceTransaction.php
--- a/src/applications/almanac/storage/AlmanacServiceTransaction.php
+++ b/src/applications/almanac/storage/AlmanacServiceTransaction.php
@@ -1,23 +1,15 @@
<?php
final class AlmanacServiceTransaction
- extends PhabricatorApplicationTransaction {
+ extends AlmanacTransaction {
const TYPE_NAME = 'almanac:service:name';
const TYPE_LOCK = 'almanac:service:lock';
- public function getApplicationName() {
- return 'almanac';
- }
-
public function getApplicationTransactionType() {
return AlmanacServicePHIDType::TYPECONST;
}
- public function getApplicationTransactionCommentObject() {
- return null;
- }
-
public function getTitle() {
$author_phid = $this->getAuthorPHID();
diff --git a/src/applications/almanac/storage/AlmanacTransaction.php b/src/applications/almanac/storage/AlmanacTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/storage/AlmanacTransaction.php
@@ -0,0 +1,38 @@
+<?php
+
+abstract class AlmanacTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_PROPERTY_UPDATE = 'almanac:property:update';
+ const TYPE_PROPERTY_REMOVE = 'almanac:property:remove';
+
+ public function getApplicationName() {
+ return 'almanac';
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ public function getTitle() {
+ $author_phid = $this->getAuthorPHID();
+
+ switch ($this->getTransactionType()) {
+ case self::TYPE_PROPERTY_UPDATE:
+ $property_key = $this->getMetadataValue('almanac.property');
+ return pht(
+ '%s updated the property "%s".',
+ $this->renderHandleLink($author_phid),
+ $property_key);
+ case self::TYPE_PROPERTY_REMOVE:
+ $property_key = $this->getMetadataValue('almanac.property');
+ return pht(
+ '%s deleted the property "%s".',
+ $this->renderHandleLink($author_phid),
+ $property_key);
+ }
+
+ return parent::getTitle();
+ }
+
+}
diff --git a/src/applications/transactions/editengine/PhabricatorEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php
--- a/src/applications/transactions/editengine/PhabricatorEditEngine.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php
@@ -23,6 +23,7 @@
private $isCreate;
private $editEngineConfiguration;
private $contextParameters = array();
+ private $targetObject;
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@@ -61,6 +62,22 @@
return true;
}
+ public function isEngineExtensible() {
+ return true;
+ }
+
+ /**
+ * Force the engine to edit a particular object.
+ */
+ public function setTargetObject($target_object) {
+ $this->targetObject = $target_object;
+ return $this;
+ }
+
+ public function getTargetObject() {
+ return $this->targetObject;
+ }
+
/* -( Managing Fields )---------------------------------------------------- */
@@ -94,7 +111,12 @@
$fields = mpull($fields, null, 'getKey');
- $extensions = PhabricatorEditEngineExtension::getAllEnabledExtensions();
+ if ($this->isEngineExtensible()) {
+ $extensions = PhabricatorEditEngineExtension::getAllEnabledExtensions();
+ } else {
+ $extensions = array();
+ }
+
foreach ($extensions as $extension) {
$extension->setViewer($viewer);
@@ -720,23 +742,28 @@
break;
}
- $id = $request->getURIData('id');
+ $object = $this->getTargetObject();
+ if (!$object) {
+ $id = $request->getURIData('id');
+
+ if ($id) {
+ $this->setIsCreate(false);
+ $object = $this->newObjectFromID($id, $capabilities);
+ if (!$object) {
+ return new Aphront404Response();
+ }
+ } else {
+ // Make sure the viewer has permission to create new objects of
+ // this type if we're going to create a new object.
+ if ($require_create) {
+ $this->requireCreateCapability();
+ }
- if ($id) {
- $this->setIsCreate(false);
- $object = $this->newObjectFromID($id, $capabilities);
- if (!$object) {
- return new Aphront404Response();
+ $this->setIsCreate(true);
+ $object = $this->newEditableObject();
}
} else {
- // Make sure the viewer has permission to create new objects of
- // this type if we're going to create a new object.
- if ($require_create) {
- $this->requireCreateCapability();
- }
-
- $this->setIsCreate(true);
- $object = $this->newEditableObject();
+ $id = $object->getID();
}
$this->validateObject($object);
@@ -831,7 +858,7 @@
$template = $object->getApplicationTransactionTemplate();
$validation_exception = null;
- if ($request->isFormPost()) {
+ if ($request->isFormPost() && $request->getBool('editEngine')) {
$submit_fields = $fields;
foreach ($submit_fields as $key => $field) {
@@ -1044,7 +1071,8 @@
$request = $controller->getRequest();
$form = id(new AphrontFormView())
- ->setUser($viewer);
+ ->setUser($viewer)
+ ->addHiddenInput('editEngine', 'true');
foreach ($this->contextParameters as $param) {
$form->addHiddenInput($param, $request->getStr($param));
diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
--- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
+++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php
@@ -456,8 +456,14 @@
return null;
}
+ $object = $this->getObject();
+
+ if (!($object instanceof PhabricatorCustomFieldInterface)) {
+ return null;
+ }
+
$field = PhabricatorCustomField::getObjectField(
- $this->getObject(),
+ $object,
PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS,
$key);
if (!$field) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 24, 11:06 PM (20 h, 16 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7044664
Default Alt Text
D15327.diff (60 KB)
Attached To
Mode
D15327: Allow Almanac properties to be deleted, use EditEngine instead of CustomField
Attached
Detach File
Event Timeline
Log In to Comment