Page MenuHomePhabricator

D15327.diff
No OneTemporary

D15327.diff

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

Mime Type
text/plain
Expires
Sun, May 12, 5:03 AM (1 w, 4 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/jh/3j/ebeiybboseern4jy
Default Alt Text
D15327.diff (60 KB)

Event Timeline