Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15331287
D14453.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
63 KB
Referenced Files
None
Subscribers
None
D14453.diff
View Options
diff --git a/resources/sql/autopatches/20151106.editengine.1.table.sql b/resources/sql/autopatches/20151106.editengine.1.table.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20151106.editengine.1.table.sql
@@ -0,0 +1,17 @@
+CREATE TABLE {$NAMESPACE}_search.search_editengineconfiguration (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ engineKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
+ builtinKey VARCHAR(64) COLLATE {$COLLATE_TEXT},
+ name VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ properties LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ isDisabled BOOL NOT NULL DEFAULT 0,
+ isDefault BOOL NOT NULL DEFAULT 0,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (phid),
+ UNIQUE KEY `key_engine` (engineKey, builtinKey),
+ KEY `key_default` (engineKey, isDefault, isDisabled)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20151106.editengine.2.xactions.sql b/resources/sql/autopatches/20151106.editengine.2.xactions.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20151106.editengine.2.xactions.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_search.search_editengineconfigurationtransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64) DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
+ oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
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
@@ -1579,8 +1579,6 @@
'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php',
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
- 'PhabricatorApplicationEditEngine' => 'applications/transactions/editengine/PhabricatorApplicationEditEngine.php',
- 'PhabricatorApplicationEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php',
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php',
@@ -2110,6 +2108,24 @@
'PhabricatorEdgeTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeTestCase.php',
'PhabricatorEdgeType' => 'infrastructure/edges/type/PhabricatorEdgeType.php',
'PhabricatorEdgeTypeTestCase' => 'infrastructure/edges/type/__tests__/PhabricatorEdgeTypeTestCase.php',
+ 'PhabricatorEditEngine' => 'applications/transactions/editengine/PhabricatorEditEngine.php',
+ 'PhabricatorEditEngineAPIMethod' => 'applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php',
+ 'PhabricatorEditEngineConfiguration' => 'applications/transactions/storage/PhabricatorEditEngineConfiguration.php',
+ 'PhabricatorEditEngineConfigurationEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php',
+ 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php',
+ 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php',
+ 'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php',
+ 'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php',
+ 'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php',
+ 'PhabricatorEditEngineConfigurationSaveController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php',
+ 'PhabricatorEditEngineConfigurationSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php',
+ 'PhabricatorEditEngineConfigurationTransaction' => 'applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php',
+ 'PhabricatorEditEngineConfigurationTransactionQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php',
+ 'PhabricatorEditEngineConfigurationViewController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php',
+ 'PhabricatorEditEngineController' => 'applications/transactions/controller/PhabricatorEditEngineController.php',
+ 'PhabricatorEditEngineListController' => 'applications/transactions/controller/PhabricatorEditEngineListController.php',
+ 'PhabricatorEditEngineQuery' => 'applications/transactions/query/PhabricatorEditEngineQuery.php',
+ 'PhabricatorEditEngineSearchEngine' => 'applications/transactions/query/PhabricatorEditEngineSearchEngine.php',
'PhabricatorEditField' => 'applications/transactions/editfield/PhabricatorEditField.php',
'PhabricatorEditType' => 'applications/transactions/edittype/PhabricatorEditType.php',
'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php',
@@ -2294,6 +2310,7 @@
'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php',
'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php',
'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php',
+ 'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php',
'PhabricatorInternationalizationManagementExtractWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementExtractWorkflow.php',
'PhabricatorInternationalizationManagementWorkflow' => 'infrastructure/internationalization/management/PhabricatorInternationalizationManagementWorkflow.php',
'PhabricatorInvalidConfigSetupCheck' => 'applications/config/check/PhabricatorInvalidConfigSetupCheck.php',
@@ -5500,7 +5517,7 @@
'PasteCreateMailReceiver' => 'PhabricatorMailReceiver',
'PasteDefaultEditCapability' => 'PhabricatorPolicyCapability',
'PasteDefaultViewCapability' => 'PhabricatorPolicyCapability',
- 'PasteEditConduitAPIMethod' => 'PhabricatorApplicationEditEngineAPIMethod',
+ 'PasteEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
'PasteEmbedView' => 'AphrontView',
'PasteInfoConduitAPIMethod' => 'PasteConduitAPIMethod',
'PasteMailReceiver' => 'PhabricatorObjectMailReceiver',
@@ -5544,8 +5561,6 @@
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
- 'PhabricatorApplicationEditEngine' => 'Phobject',
- 'PhabricatorApplicationEditEngineAPIMethod' => 'ConduitAPIMethod',
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationLaunchView' => 'AphrontTagView',
@@ -6172,6 +6187,31 @@
'PhabricatorEdgeTestCase' => 'PhabricatorTestCase',
'PhabricatorEdgeType' => 'Phobject',
'PhabricatorEdgeTypeTestCase' => 'PhabricatorTestCase',
+ 'PhabricatorEditEngine' => array(
+ 'Phobject',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorEditEngineAPIMethod' => 'ConduitAPIMethod',
+ 'PhabricatorEditEngineConfiguration' => array(
+ 'PhabricatorSearchDAO',
+ 'PhabricatorApplicationTransactionInterface',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorEditEngineConfigurationEditController' => 'PhabricatorEditEngineController',
+ 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine',
+ 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController',
+ 'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorEditEngineConfigurationSaveController' => 'PhabricatorEditEngineController',
+ 'PhabricatorEditEngineConfigurationSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'PhabricatorEditEngineConfigurationTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorEditEngineConfigurationTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'PhabricatorEditEngineConfigurationViewController' => 'PhabricatorEditEngineController',
+ 'PhabricatorEditEngineController' => 'PhabricatorApplicationTransactionController',
+ 'PhabricatorEditEngineListController' => 'PhabricatorEditEngineController',
+ 'PhabricatorEditEngineQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'PhabricatorEditEngineSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorEditField' => 'Phobject',
'PhabricatorEditType' => 'Phobject',
'PhabricatorEditor' => 'Phobject',
@@ -6392,6 +6432,7 @@
'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface',
'PhabricatorInlineCommentPreviewController' => 'PhabricatorController',
'PhabricatorInlineSummaryView' => 'AphrontView',
+ 'PhabricatorInstructionsEditField' => 'PhabricatorEditField',
'PhabricatorInternationalizationManagementExtractWorkflow' => 'PhabricatorInternationalizationManagementWorkflow',
'PhabricatorInternationalizationManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorInvalidConfigSetupCheck' => 'PhabricatorSetupCheck',
@@ -6710,7 +6751,7 @@
'PhabricatorPasteController' => 'PhabricatorController',
'PhabricatorPasteDAO' => 'PhabricatorLiskDAO',
'PhabricatorPasteEditController' => 'PhabricatorPasteController',
- 'PhabricatorPasteEditEngine' => 'PhabricatorApplicationEditEngine',
+ 'PhabricatorPasteEditEngine' => 'PhabricatorEditEngine',
'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorPasteListController' => 'PhabricatorPasteController',
'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType',
diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php
--- a/src/applications/base/PhabricatorApplication.php
+++ b/src/applications/base/PhabricatorApplication.php
@@ -635,8 +635,12 @@
return array();
}
- protected function getEditRoutePattern($base) {
+ protected function getEditRoutePattern($base = null) {
return $base.'(?:(?P<id>[0-9]\d*)/)?(?:(?P<editAction>parameters)/)?';
}
+ protected function getQueryRoutePattern($base = null) {
+ return $base.'(?:query/(?P<queryKey>[^/]+)/)?';
+ }
+
}
diff --git a/src/applications/paste/conduit/PasteEditConduitAPIMethod.php b/src/applications/paste/conduit/PasteEditConduitAPIMethod.php
--- a/src/applications/paste/conduit/PasteEditConduitAPIMethod.php
+++ b/src/applications/paste/conduit/PasteEditConduitAPIMethod.php
@@ -1,7 +1,7 @@
<?php
final class PasteEditConduitAPIMethod
- extends PhabricatorApplicationEditEngineAPIMethod {
+ extends PhabricatorEditEngineAPIMethod {
public function getAPIMethodName() {
return 'paste.edit';
diff --git a/src/applications/paste/editor/PhabricatorPasteEditEngine.php b/src/applications/paste/editor/PhabricatorPasteEditEngine.php
--- a/src/applications/paste/editor/PhabricatorPasteEditEngine.php
+++ b/src/applications/paste/editor/PhabricatorPasteEditEngine.php
@@ -1,7 +1,13 @@
<?php
final class PhabricatorPasteEditEngine
- extends PhabricatorApplicationEditEngine {
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'paste.paste';
+
+ public function getEngineName() {
+ return pht('Pastes');
+ }
protected function newEditableObject() {
return PhabricatorPaste::initializeNewPaste($this->getViewer());
@@ -24,7 +30,7 @@
return $object->getMonogram();
}
- protected function getObjectCreateShortText($object) {
+ protected function getObjectCreateShortText() {
return pht('Create Paste');
}
diff --git a/src/applications/transactions/application/PhabricatorTransactionsApplication.php b/src/applications/transactions/application/PhabricatorTransactionsApplication.php
--- a/src/applications/transactions/application/PhabricatorTransactionsApplication.php
+++ b/src/applications/transactions/application/PhabricatorTransactionsApplication.php
@@ -33,6 +33,20 @@
=> 'PhabricatorApplicationTransactionShowOlderController',
'(?P<value>old|new)/(?<phid>[^/]+)/'
=> 'PhabricatorApplicationTransactionValueController',
+ 'editengine/' => array(
+ $this->getQueryRoutePattern()
+ => 'PhabricatorEditEngineListController',
+ '(?P<engineKey>[^/]+)/' => array(
+ $this->getQueryRoutePattern() =>
+ 'PhabricatorEditEngineConfigurationListController',
+ $this->getEditRoutePattern('edit/') =>
+ 'PhabricatorEditEngineConfigurationEditController',
+ 'view/(?P<key>[^/]+)/' =>
+ 'PhabricatorEditEngineConfigurationViewController',
+ 'save/(?P<key>[^/]+)/' =>
+ 'PhabricatorEditEngineConfigurationSaveController',
+ ),
+ ),
),
);
}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php
@@ -0,0 +1,26 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationEditController
+ extends PhabricatorEditEngineController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+
+ $target_engine_key = $request->getURIData('engineKey');
+
+ $target_engine = PhabricatorEditEngine::getByKey(
+ $viewer,
+ $target_engine_key);
+ if (!$target_engine) {
+ return new Aphront404Response();
+ }
+
+ $this->setEngineKey($target_engine->getEngineKey());
+
+ return id(new PhabricatorEditEngineConfigurationEditEngine())
+ ->setTargetEngine($target_engine)
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php
@@ -0,0 +1,34 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationListController
+ extends PhabricatorEditEngineController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $this->setEngineKey($request->getURIData('engineKey'));
+
+ return id(new PhabricatorEditEngineConfigurationSearchEngine())
+ ->setController($this)
+ ->setEngineKey($this->getEngineKey())
+ ->buildResponse();
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $engine_key = $this->getEngineKey();
+ $edit_uri = "/transactions/editengine/{$engine_key}/edit/";
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('New Form'))
+ ->setHref($edit_uri)
+ ->setIcon('fa-plus-square'));
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationSaveController.php
@@ -0,0 +1,55 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationSaveController
+ extends PhabricatorEditEngineController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $engine_key = $request->getURIData('engineKey');
+ $this->setEngineKey($engine_key);
+
+ $key = $request->getURIData('key');
+ $viewer = $this->getViewer();
+
+ $config = id(new PhabricatorEditEngineConfigurationQuery())
+ ->setViewer($viewer)
+ ->withEngineKeys(array($engine_key))
+ ->withIdentifiers(array($key))
+ ->executeOne();
+ if (!$config) {
+ return id(new Aphront404Response());
+ }
+
+ $view_uri = $config->getURI();
+
+ if ($config->getID()) {
+ return $this->newDialog()
+ ->setTitle(pht('Already Editable'))
+ ->appendParagraph(
+ pht('This form configuration is already editable.'))
+ ->addCancelButton($view_uri);
+ }
+
+ if ($request->isFormPost()) {
+ $editor = id(new PhabricatorEditEngineConfigurationEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true);
+
+ $editor->applyTransactions($config, array());
+
+ return id(new AphrontRedirectResponse())
+ ->setURI($config->getURI());
+ }
+
+ // TODO: Explain what this means in more detail once the implications are
+ // more clear, or just link to some docs or something.
+
+ return $this->newDialog()
+ ->setTitle(pht('Make Builtin Editable'))
+ ->appendParagraph(
+ pht('Make this builtin form editable?'))
+ ->addSubmitButton(pht('Make Editable'))
+ ->addCancelButton($view_uri);
+ }
+
+}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php
@@ -0,0 +1,125 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationViewController
+ extends PhabricatorEditEngineController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $engine_key = $request->getURIData('engineKey');
+ $this->setEngineKey($engine_key);
+
+ $key = $request->getURIData('key');
+ $viewer = $this->getViewer();
+
+ $config = id(new PhabricatorEditEngineConfigurationQuery())
+ ->setViewer($viewer)
+ ->withEngineKeys(array($engine_key))
+ ->withIdentifiers(array($key))
+ ->executeOne();
+ if (!$config) {
+ return id(new Aphront404Response());
+ }
+
+ $is_concrete = (bool)$config->getID();
+
+ $actions = $this->buildActionView($config);
+
+ $properties = $this->buildPropertyView($config)
+ ->setActionList($actions);
+
+ $header = id(new PHUIHeaderView())
+ ->setUser($viewer)
+ ->setPolicyObject($config)
+ ->setHeader(pht('Edit Form: %s', $config->getDisplayName()));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($properties);
+
+ $crumbs = $this->buildApplicationCrumbs();
+
+ if ($is_concrete) {
+ $crumbs->addTextCrumb(pht('Form %d', $config->getID()));
+ } else {
+ $crumbs->addTextCrumb(pht('Builtin'));
+ }
+
+ if ($is_concrete) {
+ $timeline = $this->buildTransactionTimeline(
+ $config,
+ new PhabricatorEditEngineConfigurationTransactionQuery());
+
+ $timeline->setShouldTerminate(true);
+ } else {
+ $timeline = null;
+ }
+
+ return $this->newPage()
+ ->setCrumbs($crumbs)
+ ->appendChild(
+ array(
+ $box,
+ $timeline,
+ ));
+ }
+
+ private function buildActionView(
+ PhabricatorEditEngineConfiguration $config) {
+ $viewer = $this->getViewer();
+ $engine_key = $this->getEngineKey();
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $config,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $view = id(new PhabricatorActionListView())
+ ->setUser($viewer);
+
+ $key = $config->getIdentifier();
+
+ $base_uri = "/transactions/editengine/{$engine_key}";
+
+ $is_concrete = (bool)$config->getID();
+ if (!$is_concrete) {
+ $save_uri = "{$base_uri}/save/{$key}/";
+
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Make Editable'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(true)
+ ->setHref($save_uri));
+
+ $can_edit = false;
+ } else {
+ $edit_uri = "{$base_uri}/edit/{$key}/";
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Form Configuration'))
+ ->setIcon('fa-pencil')
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit)
+ ->setHref($edit_uri));
+ }
+
+ return $view;
+ }
+
+ private function buildPropertyView(
+ PhabricatorEditEngineConfiguration $config) {
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer)
+ ->setObject($config);
+
+ return $properties;
+ }
+
+
+}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineController.php b/src/applications/transactions/controller/PhabricatorEditEngineController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineController.php
@@ -0,0 +1,37 @@
+<?php
+
+abstract class PhabricatorEditEngineController
+ extends PhabricatorApplicationTransactionController {
+
+ private $engineKey;
+
+ public function setEngineKey($engine_key) {
+ $this->engineKey = $engine_key;
+ return $this;
+ }
+
+ public function getEngineKey() {
+ return $this->engineKey;
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $crumbs->addTextCrumb(pht('Edit Engines'), '/transactions/editengine/');
+
+ $engine_key = $this->getEngineKey();
+ if ($engine_key !== null) {
+ $engine = PhabricatorEditEngine::getByKey(
+ $this->getViewer(),
+ $engine_key);
+ if ($engine) {
+ $crumbs->addTextCrumb(
+ $engine->getEngineName(),
+ "/transactions/editengine/{$engine_key}/");
+ }
+ }
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/transactions/controller/PhabricatorEditEngineListController.php b/src/applications/transactions/controller/PhabricatorEditEngineListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/controller/PhabricatorEditEngineListController.php
@@ -0,0 +1,16 @@
+<?php
+
+final class PhabricatorEditEngineListController
+ extends PhabricatorEditEngineController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ return id(new PhabricatorEditEngineSearchEngine())
+ ->setController($this)
+ ->buildResponse();
+ }
+
+}
diff --git a/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php b/src/applications/transactions/editengine/PhabricatorEditEngine.php
rename from src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php
rename to src/applications/transactions/editengine/PhabricatorEditEngine.php
--- a/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngine.php
@@ -4,6 +4,7 @@
/**
* @task fields Managing Fields
* @task text Display Text
+ * @task config Edit Engine Configuration
* @task uri Managing URIs
* @task load Creating and Loading Objects
* @task web Responding to Web Requests
@@ -11,11 +12,16 @@
* @task http Responding to HTTP Parameter Requests
* @task conduit Responding to Conduit Requests
*/
-abstract class PhabricatorApplicationEditEngine extends Phobject {
+abstract class PhabricatorEditEngine
+ extends Phobject
+ implements PhabricatorPolicyInterface {
+
+ const EDITENGINECONFIG_DEFAULT = 'default';
private $viewer;
private $controller;
private $isCreate;
+ private $editEngineConfiguration;
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@@ -36,6 +42,10 @@
return $this->controller;
}
+ final public function getEngineKey() {
+ return $this->getPhobjectClassConstant('ENGINECONST', 64);
+ }
+
/* -( Managing Fields )---------------------------------------------------- */
@@ -184,6 +194,9 @@
}
}
+ $config = $this->getEditEngineConfiguration();
+ $fields = $config->applyConfigurationToFields($this, $fields);
+
foreach ($fields as $field) {
$field
->setViewer($viewer)
@@ -200,6 +213,12 @@
/**
* @task text
*/
+ abstract public function getEngineName();
+
+
+ /**
+ * @task text
+ */
abstract protected function getObjectCreateTitleText($object);
@@ -212,7 +231,7 @@
/**
* @task text
*/
- abstract protected function getObjectCreateShortText($object);
+ abstract protected function getObjectCreateShortText();
/**
@@ -237,6 +256,121 @@
}
+/* -( Edit Engine Configuration )------------------------------------------ */
+
+
+ protected function supportsEditEngineConfiguration() {
+ return true;
+ }
+
+ final protected function getEditEngineConfiguration() {
+ return $this->editEngineConfiguration;
+ }
+
+ private function loadEditEngineConfiguration($key) {
+ if ($key === null) {
+ $key = self::EDITENGINECONFIG_DEFAULT;
+ }
+
+ $config = id(new PhabricatorEditEngineConfigurationQuery())
+ ->setViewer($this->getViewer())
+ ->withEngineKeys(array($this->getEngineKey()))
+ ->withIdentifiers(array($key))
+ ->executeOne();
+ if (!$config) {
+ return null;
+ }
+
+ $this->editEngineConfiguration = $config;
+
+ return $config;
+ }
+
+ final public function getBuiltinEngineConfigurations() {
+ $configurations = $this->newBuiltinEngineConfigurations();
+
+ if (!$configurations) {
+ throw new Exception(
+ pht(
+ 'EditEngine ("%s") returned no builtin engine configurations, but '.
+ 'an edit engine must have at least one configuration.',
+ get_class($this)));
+ }
+
+ assert_instances_of($configurations, 'PhabricatorEditEngineConfiguration');
+
+ $has_default = false;
+ foreach ($configurations as $config) {
+ if ($config->getBuiltinKey() == self::EDITENGINECONFIG_DEFAULT) {
+ $has_default = true;
+ }
+ }
+
+ if (!$has_default) {
+ $first = head($configurations);
+ if (!$first->getBuiltinKey()) {
+ $first->setBuiltinKey(self::EDITENGINECONFIG_DEFAULT);
+
+ if (!strlen($first->getName())) {
+ $first->setName($this->getObjectCreateShortText());
+ }
+ } else {
+ throw new Exception(
+ pht(
+ 'EditEngine ("%s") returned builtin engine configurations, '.
+ 'but none are marked as default and the first configuration has '.
+ 'a different builtin key already. Mark a builtin as default or '.
+ 'omit the key from the first configuration',
+ get_class($this)));
+ }
+ }
+
+ $builtins = array();
+ foreach ($configurations as $key => $config) {
+ $builtin_key = $config->getBuiltinKey();
+
+ if ($builtin_key === null) {
+ throw new Exception(
+ pht(
+ 'EditEngine ("%s") returned builtin engine configurations, '.
+ 'but one (with key "%s") is missing a builtin key. Provide a '.
+ 'builtin key for each configuration (you can omit it from the '.
+ 'first configuration in the list to automatically assign the '.
+ 'default key).',
+ get_class($this),
+ $key));
+ }
+
+ if (isset($builtins[$builtin_key])) {
+ throw new Exception(
+ pht(
+ 'EditEngine ("%s") returned builtin engine configurations, '.
+ 'but at least two specify the same builtin key ("%s"). Engines '.
+ 'must have unique builtin keys.',
+ get_class($this),
+ $builtin_key));
+ }
+
+ $builtins[$builtin_key] = $config;
+ }
+
+
+ return $builtins;
+ }
+
+ protected function newBuiltinEngineConfigurations() {
+ return array(
+ $this->newConfiguration(),
+ );
+ }
+
+ final protected function newConfiguration() {
+ return PhabricatorEditEngineConfiguration::initializeNewConfiguration(
+ $this->getViewer(),
+ $this);
+ }
+
+
/* -( Managing URIs )------------------------------------------------------ */
@@ -317,7 +451,7 @@
* @return bool True if a new object is being created.
* @task load
*/
- final protected function getIsCreate() {
+ final public function getIsCreate() {
return $this->isCreate;
}
@@ -391,6 +525,35 @@
}
+ /**
+ * Verify that an object is appropriate for editing.
+ *
+ * @param wild Loaded value.
+ * @return void
+ * @task load
+ */
+ private function validateObject($object) {
+ if (!$object || !is_object($object)) {
+ throw new Exception(
+ pht(
+ 'EditEngine "%s" created or loaded an invalid object: object must '.
+ 'actually be an object, but is of some other type ("%s").',
+ get_class($this),
+ gettype($object)));
+ }
+
+ if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
+ throw new Exception(
+ pht(
+ 'EditEngine "%s" created or loaded an invalid object: object (of '.
+ 'class "%s") must implement "%s", but does not.',
+ get_class($this),
+ get_class($object),
+ 'PhabricatorApplicationTransactionInterface'));
+ }
+ }
+
+
/* -( Responding to Web Requests )----------------------------------------- */
@@ -399,6 +562,11 @@
$controller = $this->getController();
$request = $controller->getRequest();
+ $config = $this->loadEditEngineConfiguration($request->getURIData('form'));
+ if (!$config) {
+ return new Aphront404Response();
+ }
+
$id = $request->getURIData('id');
if ($id) {
$this->setIsCreate(false);
@@ -411,6 +579,8 @@
$object = $this->newEditableObject();
}
+ $this->validateObject($object);
+
$action = $request->getURIData('editAction');
switch ($action) {
case 'parameters':
@@ -425,7 +595,7 @@
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
if ($this->getIsCreate()) {
- $create_text = $this->getObjectCreateShortText($object);
+ $create_text = $this->getObjectCreateShortText();
if ($final) {
$crumbs->addTextCrumb($create_text);
} else {
@@ -570,6 +740,20 @@
private function buildEditFormActions($object) {
$actions = array();
+ if ($this->supportsEditEngineConfiguration()) {
+ $engine_key = $this->getEngineKey();
+ $config = $this->getEditEngineConfiguration();
+
+ $actions[] = id(new PhabricatorActionView())
+ ->setName(pht('Manage Form Configurations'))
+ ->setIcon('fa-list-ul')
+ ->setHref("/transactions/editengine/{$engine_key}/");
+ $actions[] = id(new PhabricatorActionView())
+ ->setName(pht('Edit Form Configuration'))
+ ->setIcon('fa-pencil')
+ ->setHref($config->getURI());
+ }
+
$actions[] = id(new PhabricatorActionView())
->setName(pht('Show HTTP Parameters'))
->setIcon('fa-crosshairs')
@@ -601,7 +785,7 @@
$header_text = pht(
'HTTP Parameters: %s',
- $this->getObjectCreateShortText($object));
+ $this->getObjectCreateShortText());
$header = id(new PHUIHeaderView())
->setHeader($header_text);
@@ -637,6 +821,14 @@
final public function buildConduitResponse(ConduitAPIRequest $request) {
$viewer = $this->getViewer();
+ $config = $this->loadEditEngineConfiguration(null);
+ if (!$config) {
+ throw new Exception(
+ pht(
+ 'Unable to load configuration for this EditEngine ("%s").',
+ get_class($this)));
+ }
+
$phid = $request->getValue('objectPHID');
if ($phid) {
$this->setIsCreate(false);
@@ -649,6 +841,8 @@
$object = $this->newEditableObject();
}
+ $this->validateObject($object);
+
$fields = $this->buildEditFields($object);
$types = $this->getAllEditTypesFromFields($fields);
@@ -772,5 +966,46 @@
return $this->getAllEditTypesFromFields($fields);
}
+ final public static function getAllEditEngines() {
+ return id(new PhutilClassMapQuery())
+ ->setAncestorClass(__CLASS__)
+ ->setUniqueMethod('getEngineKey')
+ ->execute();
+ }
+
+ final public static function getByKey(PhabricatorUser $viewer, $key) {
+ return id(new PhabricatorEditEngineQuery())
+ ->setViewer($viewer)
+ ->withEngineKeys(array($key))
+ ->executeOne();
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getPHID() {
+ return get_class($this);
+ }
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+ public function getPolicy($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return PhabricatorPolicies::getMostOpenPolicy();
+ }
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
}
diff --git a/src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php
rename from src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php
rename to src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php
--- a/src/applications/transactions/editengine/PhabricatorApplicationEditEngineAPIMethod.php
+++ b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php
@@ -1,6 +1,6 @@
<?php
-abstract class PhabricatorApplicationEditEngineAPIMethod
+abstract class PhabricatorEditEngineAPIMethod
extends ConduitAPIMethod {
abstract public function newEditEngine();
diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php
--- a/src/applications/transactions/editfield/PhabricatorEditField.php
+++ b/src/applications/transactions/editfield/PhabricatorEditField.php
@@ -13,7 +13,7 @@
private $metadata = array();
private $description;
private $editTypeKey;
-
+ private $isLocked;
public function setKey($key) {
$this->key = $key;
@@ -69,7 +69,18 @@
return $this->description;
}
- abstract protected function newControl();
+ public function setIsLocked($is_locked) {
+ $this->isLocked = $is_locked;
+ return $this;
+ }
+
+ public function getIsLocked() {
+ return $this->isLocked;
+ }
+
+ protected function newControl() {
+ throw new PhutilMethodNotImplementedException();
+ }
protected function renderControl() {
$control = $this->newControl();
@@ -85,6 +96,10 @@
$control->setLabel($this->getLabel());
}
+ if ($this->getIsLocked()) {
+ $control->setDisabled(true);
+ }
+
return $control;
}
@@ -166,6 +181,15 @@
return $this;
}
+ public function readDefaultValueFromConfiguration($value) {
+ $this->value = $this->getDefaultValueFromConfiguration($value);
+ return $this;
+ }
+
+ protected function getDefaultValueFromConfiguration($value) {
+ return $value;
+ }
+
protected function getValueFromObject($object) {
if ($this->hasValue) {
return $this->value;
diff --git a/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php b/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/editfield/PhabricatorInstructionsEditField.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorInstructionsEditField
+ extends PhabricatorEditField {
+
+ public function appendToForm(AphrontFormView $form) {
+ return $form->appendRemarkupInstructions($this->getValue());
+ }
+
+}
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -815,18 +815,6 @@
$xactions = $this->filterTransactions($object, $xactions);
- if (!$xactions) {
- if ($read_locking) {
- $object->endReadLocking();
- $read_locking = false;
- }
- if ($transaction_open) {
- $object->killTransaction();
- $transaction_open = false;
- }
- return array();
- }
-
// Now that we've merged, filtered, and combined transactions, check for
// required capabilities.
foreach ($xactions as $xaction) {
diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
@@ -0,0 +1,78 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationEditEngine
+ extends PhabricatorEditEngine {
+
+ const ENGINECONST = 'transactions.editengine.config';
+
+ private $targetEngine;
+
+ public function setTargetEngine(PhabricatorEditEngine $target_engine) {
+ $this->targetEngine = $target_engine;
+ return $this;
+ }
+
+ public function getTargetEngine() {
+ return $this->targetEngine;
+ }
+
+ public function getEngineName() {
+ return pht('Edit Configurations');
+ }
+
+ protected function newEditableObject() {
+ return PhabricatorEditEngineConfiguration::initializeNewConfiguration(
+ $this->getViewer(),
+ $this->getTargetEngine());
+ }
+
+ protected function newObjectQuery() {
+ return id(new PhabricatorEditEngineConfigurationQuery());
+ }
+
+ protected function getObjectCreateTitleText($object) {
+ return pht('Create New Form');
+ }
+
+ protected function getObjectEditTitleText($object) {
+ return pht('Edit Form %d: %s', $object->getID(), $object->getDisplayName());
+ }
+
+ protected function getObjectEditShortText($object) {
+ return pht('Form %d', $object->getID());
+ }
+
+ protected function getObjectCreateShortText() {
+ return pht('Create Form');
+ }
+
+ protected function getObjectViewURI($object) {
+ $engine_key = $this->getTargetEngine()->getEngineKey();
+ $id = $object->getID();
+ return "/transactions/editengine/{$engine_key}/view/{$id}/";
+ }
+
+ protected function getObjectEditURI($object) {
+ $engine_key = $this->getTargetEngine()->getEngineKey();
+ $id = $object->getID();
+ return "/transactions/editengine/{$engine_key}/edit/{$id}/";
+ }
+
+ protected function getObjectCreateCancelURI($object) {
+ $engine_key = $this->getTargetEngine()->getEngineKey();
+ return "/transactions/editengine/{$engine_key}/";
+ }
+
+ protected function buildCustomEditFields($object) {
+ return array(
+ id(new PhabricatorTextEditField())
+ ->setKey('name')
+ ->setLabel(pht('Name'))
+ ->setDescription(pht('Name of the form.'))
+ ->setTransactionType(
+ PhabricatorEditEngineConfigurationTransaction::TYPE_NAME)
+ ->setValue($object->getName()),
+ );
+ }
+
+}
diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
@@ -0,0 +1,98 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Edit Configurations');
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
+ $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_NAME;
+
+ return $types;
+ }
+
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+ switch ($type) {
+ case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME:
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('Form name is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ }
+ break;
+ }
+
+ return $errors;
+ }
+
+ protected function getCustomTransactionOldValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME:
+ return $object->getName();
+ }
+ }
+
+ protected function getCustomTransactionNewValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME:
+ return $xaction->getNewValue();
+ }
+ }
+
+ protected function applyCustomInternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME:
+ $object->setName($xaction->getNewValue());
+ return;
+ }
+
+ return parent::applyCustomInternalTransaction($object, $xaction);
+ }
+
+ protected function applyCustomExternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME:
+ return;
+ }
+
+ return parent::applyCustomExternalTransaction($object, $xaction);
+ }
+
+}
diff --git a/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php b/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php
@@ -0,0 +1,43 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationPHIDType
+ extends PhabricatorPHIDType {
+
+ const TYPECONST = 'FORM';
+
+ public function getTypeName() {
+ return pht('Edit Configuration');
+ }
+
+ public function newObject() {
+ return new PhabricatorEditEngineConfiguration();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $object_query,
+ array $phids) {
+ return id(new PhabricatorEditEngineConfigurationQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $config = $objects[$phid];
+
+ $id = $config->getID();
+ $name = $config->getName();
+
+ $handle->setName($name);
+ $handle->setURI($config->getURI());
+ }
+ }
+
+}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php
@@ -0,0 +1,183 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $engineKeys;
+ private $builtinKeys;
+ private $identifiers;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withEngineKeys(array $engine_keys) {
+ $this->engineKeys = $engine_keys;
+ return $this;
+ }
+
+ public function withBuiltinKeys(array $builtin_keys) {
+ $this->builtinKeys = $builtin_keys;
+ return $this;
+ }
+
+ public function withIdentifiers(array $identifiers) {
+ $this->identifiers = $identifiers;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorEditEngineConfiguration();
+ }
+
+ protected function loadPage() {
+ // TODO: The logic here is a little flimsy and won't survive pagination.
+ // For now, I'm just not bothering with pagination since I believe it will
+ // take some time before any install manages to produce a large enough
+ // number of edit forms for any particular engine for the lack of UI
+ // pagination to become a problem.
+
+ $page = $this->loadStandardPage($this->newResultObject());
+
+ // Now that we've loaded the real results from the database, we're going
+ // to load builtins from the edit engines and add them to the list.
+
+ $engines = PhabricatorEditEngine::getAllEditEngines();
+
+ if ($this->engineKeys) {
+ $engines = array_select_keys($engines, $this->engineKeys);
+ }
+
+ foreach ($engines as $engine) {
+ $engine->setViewer($this->getViewer());
+ }
+
+ // List all the builtins which have already been saved to the database as
+ // real objects.
+ $concrete = array();
+ foreach ($page as $config) {
+ $builtin_key = $config->getBuiltinKey();
+ if ($builtin_key !== null) {
+ $engine_key = $config->getEngineKey();
+ $concrete[$engine_key][$builtin_key] = $config;
+ }
+ }
+
+ $builtins = array();
+ foreach ($engines as $engine_key => $engine) {
+ $engine_builtins = $engine->getBuiltinEngineConfigurations();
+ foreach ($engine_builtins as $engine_builtin) {
+ $builtin_key = $engine_builtin->getBuiltinKey();
+ if (isset($concrete[$engine_key][$builtin_key])) {
+ continue;
+ } else {
+ $builtins[] = $engine_builtin;
+ }
+ }
+ }
+
+ foreach ($builtins as $builtin) {
+ $page[] = $builtin;
+ }
+
+ // Now we have to do some extra filtering to make sure everything we're
+ // about to return really satisfies the query.
+
+ if ($this->ids !== null) {
+ $ids = array_fuse($this->ids);
+ foreach ($page as $key => $config) {
+ if (empty($ids[$config->getID()])) {
+ unset($page[$key]);
+ }
+ }
+ }
+
+ if ($this->phids !== null) {
+ $phids = array_fuse($this->phids);
+ foreach ($page as $key => $config) {
+ if (empty($phids[$config->getPHID()])) {
+ unset($page[$key]);
+ }
+ }
+ }
+
+ if ($this->builtinKeys !== null) {
+ $builtin_keys = array_fuse($this->builtinKeys);
+ foreach ($page as $key => $config) {
+ if (empty($builtin_keys[$config->getBuiltinKey()])) {
+ unset($page[$key]);
+ }
+ }
+ }
+
+ if ($this->identifiers !== null) {
+ $identifiers = array_fuse($this->identifiers);
+ foreach ($page as $key => $config) {
+ if (isset($identifiers[$config->getBuiltinKey()])) {
+ continue;
+ }
+ if (isset($identifiers[$config->getID()])) {
+ continue;
+ }
+ unset($page[$key]);
+ }
+ }
+
+ return $page;
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->engineKeys !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'engineKey IN (%Ls)',
+ $this->engineKeys);
+ }
+
+ if ($this->builtinKeys !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'builtinKey IN (%Ls)',
+ $this->builtinKeys);
+ }
+
+ if ($this->identifiers !== null) {
+ $where[] = qsprintf(
+ $conn,
+ '(id IN (%Ls) OR builtinKey IN (%Ls))',
+ $this->identifiers,
+ $this->identifiers);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php
@@ -0,0 +1,102 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ private $engineKey;
+
+ public function setEngineKey($engine_key) {
+ $this->engineKey = $engine_key;
+ return $this;
+ }
+
+ public function getEngineKey() {
+ return $this->engineKey;
+ }
+
+ public function canUseInPanelContext() {
+ return false;
+ }
+
+ public function getResultTypeDescription() {
+ return pht('Forms');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+ public function newQuery() {
+ return id(new PhabricatorEditEngineConfigurationQuery())
+ ->withEngineKeys(array($this->getEngineKey()));
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+ return $query;
+ }
+
+ protected function buildCustomSearchFields() {
+ return array();
+ }
+
+ protected function getDefaultFieldOrder() {
+ return array();
+ }
+
+ protected function getURI($path) {
+ return '/transactions/editengine/'.$this->getEngineKey().'/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Forms'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $configs,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($configs, 'PhabricatorEditEngineConfiguration');
+ $viewer = $this->requireViewer();
+ $engine_key = $this->getEngineKey();
+
+ $list = id(new PHUIObjectItemListView())
+ ->setUser($viewer);
+ foreach ($configs as $config) {
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($config->getDisplayName());
+
+ $id = $config->getID();
+ if ($id) {
+ $item->setObjectName(pht('Form %d', $id));
+ $key = $id;
+ } else {
+ $item->setObjectName(pht('Builtin'));
+ $key = $config->getBuiltinKey();
+ }
+ $item->setHref("/transactions/editengine/{$engine_key}/view/{$key}/");
+
+
+ $list->addItem($item);
+ }
+
+ return id(new PhabricatorApplicationSearchResultView())
+ ->setObjectList($list);
+ }
+}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorEditEngineConfigurationTransaction();
+ }
+
+}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineQuery.php b/src/applications/transactions/query/PhabricatorEditEngineQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/query/PhabricatorEditEngineQuery.php
@@ -0,0 +1,31 @@
+<?php
+
+final class PhabricatorEditEngineQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $engineKeys;
+
+ public function withEngineKeys(array $keys) {
+ $this->engineKeys = $keys;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $engines = PhabricatorEditEngine::getAllEditEngines();
+
+ if ($this->engineKeys !== null) {
+ $engines = array_select_keys($engines, $this->engineKeys);
+ }
+
+ return $engines;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+ protected function getResultCursor($object) {
+ return null;
+ }
+
+}
diff --git a/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php b/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/query/PhabricatorEditEngineSearchEngine.php
@@ -0,0 +1,78 @@
+<?php
+
+final class PhabricatorEditEngineSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Edit Engines');
+ }
+
+ public function getApplicationClassName() {
+ return 'PhabricatorTransactionsApplication';
+ }
+
+ public function newQuery() {
+ return id(new PhabricatorEditEngineQuery());
+ }
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+ return $query;
+ }
+
+ protected function buildCustomSearchFields() {
+ return array();
+ }
+
+ protected function getDefaultFieldOrder() {
+ return array();
+ }
+
+ protected function getURI($path) {
+ return '/transactions/editengine/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Edit Engines'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function renderResultList(
+ array $engines,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($engines, 'PhabricatorEditEngine');
+ $viewer = $this->requireViewer();
+
+ $list = id(new PHUIObjectItemListView())
+ ->setUser($viewer);
+ foreach ($engines as $engine) {
+ $engine_key = $engine->getEngineKey();
+ $query_uri = "/transactions/editengine/{$engine_key}/";
+
+ $item = id(new PHUIObjectItemView())
+ ->setHeader($engine->getEngineName())
+ ->setHref($query_uri);
+
+ $list->addItem($item);
+ }
+
+ return id(new PhabricatorApplicationSearchResultView())
+ ->setObjectList($list);
+ }
+}
diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php
@@ -0,0 +1,211 @@
+<?php
+
+final class PhabricatorEditEngineConfiguration
+ extends PhabricatorSearchDAO
+ implements
+ PhabricatorApplicationTransactionInterface,
+ PhabricatorPolicyInterface {
+
+ protected $engineKey;
+ protected $builtinKey;
+ protected $name;
+ protected $viewPolicy;
+ protected $editPolicy;
+ protected $properties = array();
+ protected $isDisabled = 0;
+ protected $isDefault = 0;
+
+ private $engine = self::ATTACHABLE;
+
+ public function getTableName() {
+ return 'search_editengineconfiguration';
+ }
+
+ public static function initializeNewConfiguration(
+ PhabricatorUser $actor,
+ PhabricatorEditEngine $engine) {
+
+ // TODO: This should probably be controlled by a new defualt capability.
+ $edit_policy = PhabricatorPolicies::POLICY_ADMIN;
+
+ return id(new PhabricatorEditEngineConfiguration())
+ ->setEngineKey($engine->getEngineKey())
+ ->attachEngine($engine)
+ ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())
+ ->setEditPolicy($edit_policy);
+ }
+
+ public function generatePHID() {
+ return PhabricatorPHID::generateNewPHID(
+ PhabricatorEditEngineConfigurationPHIDType::TYPECONST);
+ }
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_SERIALIZATION => array(
+ 'properties' => self::SERIALIZATION_JSON,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'engineKey' => 'text64',
+ 'builtinKey' => 'text64?',
+ 'name' => 'text255',
+ 'isDisabled' => 'bool',
+ 'isDefault' => 'bool',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_engine' => array(
+ 'columns' => array('engineKey', 'builtinKey'),
+ 'unique' => true,
+ ),
+ 'key_default' => array(
+ 'columns' => array('engineKey', 'isDefault', 'isDisabled'),
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getProperty($key, $default = null) {
+ return idx($this->properties, $key, $default);
+ }
+
+ public function setProperty($key, $value) {
+ $this->properties[$key] = $value;
+ return $this;
+ }
+
+ public function attachEngine(PhabricatorEditEngine $engine) {
+ $this->engine = $engine;
+ return $this;
+ }
+
+ public function getEngine() {
+ return $this->assertAttached($this->engine);
+ }
+
+ public function applyConfigurationToFields(
+ PhabricatorEditEngine $engine,
+ array $fields) {
+ $fields = mpull($fields, null, 'getKey');
+
+ $values = $this->getProperty('defaults', array());
+ foreach ($fields as $key => $field) {
+ if ($engine->getIsCreate()) {
+ if (array_key_exists($key, $values)) {
+ $field->readDefaultValueFromConfiguration($values[$key]);
+ }
+ }
+ }
+
+ $fields = $this->reorderFields($fields);
+
+ $head_instructions = $this->getProperty('instructions.head');
+ if (strlen($head_instructions)) {
+ $fields = array(
+ 'config.instructions.head' => id(new PhabricatorInstructionsEditField())
+ ->setKey('config.instructions.head')
+ ->setValue($head_instructions),
+ ) + $fields;
+ }
+
+ return $fields;
+ }
+
+ private function reorderFields(array $fields) {
+ $keys = array();
+ $fields = array_select_keys($fields, $keys) + $fields;
+
+ // Now, move locked fields to the bottom.
+ $head = array();
+ $tail = array();
+ foreach ($fields as $key => $field) {
+ if (!$field->getIsLocked()) {
+ $head[$key] = $field;
+ } else {
+ $tail[$key] = $field;
+ }
+ }
+
+ return $head + $tail;
+ }
+
+ public function getURI() {
+ $engine_key = $this->getEngineKey();
+ $key = $this->getIdentifier();
+
+ return "/transactions/editengine/{$engine_key}/view/{$key}/";
+ }
+
+ public function getIdentifier() {
+ $key = $this->getID();
+ if (!$key) {
+ $key = $this->getBuiltinKey();
+ }
+ return $key;
+ }
+
+ public function getDisplayName() {
+ $name = $this->getName();
+ if (strlen($name)) {
+ return $name;
+ }
+
+ $builtin = $this->getBuiltinKey();
+ if ($builtin !== null) {
+ return pht('Builtin Form "%s"', $builtin);
+ }
+
+ return pht('Untitled Form');
+ }
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ );
+ }
+
+ public function getPolicy($capability) {
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
+ }
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return null;
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorEditEngineConfigurationEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorEditEngineConfigurationTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+ return $timeline;
+ }
+
+}
diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php
@@ -0,0 +1,20 @@
+<?php
+
+final class PhabricatorEditEngineConfigurationTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_NAME = 'editengine.config.name';
+
+ public function getApplicationName() {
+ return 'search';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorEditEngineConfigurationPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+}
diff --git a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php
--- a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php
+++ b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php
@@ -4,7 +4,7 @@
* Renders the "HTTP Parameters" help page for edit engines.
*
* This page has a ton of text and specialized rendering on it, this class
- * just pulls it out of the main @{class:PhabricatorApplicationEditEngine}.
+ * just pulls it out of the main @{class:PhabricatorEditEngine}.
*/
final class PhabricatorApplicationEditHTTPParameterHelpView
extends AphrontView {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 8, 8:37 AM (2 w, 2 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/yv/gl/csmaf7nuroqtgokg
Default Alt Text
D14453.diff (63 KB)
Attached To
Mode
D14453: Allow ApplicationEditor forms to be reconfigured
Attached
Detach File
Event Timeline
Log In to Comment