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 @@ -2135,6 +2135,7 @@ 'PhabricatorEditEngineConfigurationEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationEditController.php', 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php', 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php', + 'PhabricatorEditEngineConfigurationIsEditController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationIsEditController.php', 'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php', 'PhabricatorEditEngineConfigurationLockController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php', 'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php', @@ -6263,6 +6264,7 @@ 'PhabricatorEditEngineConfigurationEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor', + 'PhabricatorEditEngineConfigurationIsEditController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationLockController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType', 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 @@ -53,6 +53,8 @@ 'PhabricatorEditEngineConfigurationLockController', 'defaultcreate/(?P[^/]+)/' => 'PhabricatorEditEngineConfigurationDefaultCreateController', + 'defaultedit/(?P[^/]+)/' => + 'PhabricatorEditEngineConfigurationIsEditController', 'disable/(?P[^/]+)/' => 'PhabricatorEditEngineConfigurationDisableController', ), diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationIsEditController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationIsEditController.php new file mode 100644 --- /dev/null +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationIsEditController.php @@ -0,0 +1,60 @@ +getViewer(); + + $config = $this->loadConfigForEdit(); + if (!$config) { + return id(new Aphront404Response()); + } + + $engine_key = $config->getEngineKey(); + $key = $config->getIdentifier(); + $cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/"; + + $type = PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT; + + if ($request->isFormPost()) { + $xactions = array(); + + $xactions[] = id(new PhabricatorEditEngineConfigurationTransaction()) + ->setTransactionType($type) + ->setNewValue(!$config->getIsEdit()); + + $editor = id(new PhabricatorEditEngineConfigurationEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($config, $xactions); + + return id(new AphrontRedirectResponse()) + ->setURI($cancel_uri); + } + + if ($config->getIsEdit()) { + $title = pht('Unmark as Edit Form'); + $body = pht( + 'Unmark this form as an edit form? It will no longer be able to be '. + 'used to edit objects.'); + $button = pht('Unmark Form'); + } else { + $title = pht('Mark as Edit Form'); + $body = pht( + 'Mark this form as an edit form? Users who can view it will be able '. + 'to use it to edit objects.'); + $button = pht('Mark Form'); + } + + return $this->newDialog() + ->setTitle($title) + ->appendParagraph($body) + ->addSubmitButton($button) + ->addCancelbutton($cancel_uri); + } + +} diff --git a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php --- a/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php +++ b/src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php @@ -177,6 +177,24 @@ ->setWorkflow(true) ->setDisabled(!$can_edit)); + if ($config->getIsEdit()) { + $isedit_name = pht('Unmark as "Edit" Form'); + $isedit_icon = 'fa-minus'; + } else { + $isedit_name = pht('Mark as "Edit" Form'); + $isedit_icon = 'fa-plus'; + } + + $isedit_uri = "{$base_uri}/defaultedit/{$form_key}/"; + + $view->addAction( + id(new PhabricatorActionView()) + ->setName($isedit_name) + ->setIcon($isedit_icon) + ->setHref($isedit_uri) + ->setWorkflow(true) + ->setDisabled(!$can_edit)); + return $view; } 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 @@ -198,59 +198,68 @@ return $this->editEngineConfiguration; } - - /** - * Load the default configuration, ignoring customization in the database - * (which means we implicitly ignore policies). - * - * This is used from places like Conduit, where the fields available in the - * API should not be affected by configuration changes. - * - * @return PhabricatorEditEngineConfiguration Default configuration, ignoring - * customization. - */ - private function loadDefaultEditEngineConfiguration() { - return $this->loadEditEngineConfigurationWithOptions( - self::EDITENGINECONFIG_DEFAULT, - true); + private function newConfigurationQuery() { + return id(new PhabricatorEditEngineConfigurationQuery()) + ->setViewer($this->getViewer()) + ->withEngineKeys(array($this->getEngineKey())); } + private function loadEditEngineConfigurationWithQuery( + PhabricatorEditEngineConfigurationQuery $query, + $sort_method) { - /** - * Load a named configuration, respecting database customization and policies. - * - * @param string Configuration key, or null to load the default. - * @return PhabricatorEditEngineConfiguration Default configuration, - * respecting customization. - */ - private function loadEditEngineConfiguration($key) { - if (!strlen($key)) { - $key = self::EDITENGINECONFIG_DEFAULT; + if ($sort_method) { + $results = $query->execute(); + $results = msort($results, $sort_method); + $result = head($results); + } else { + $result = $query->executeOne(); } - return $this->loadEditEngineConfigurationWithOptions( - $key, - false); + if (!$result) { + return null; + } + + $this->editEngineConfiguration = $result; + return $result; } - private function loadEditEngineConfigurationWithOptions( - $key, - $ignore_database) { - $viewer = $this->getViewer(); + private function loadEditEngineConfigurationWithIdentifier($identifier) { + $query = $this->newConfigurationQuery() + ->withIdentifiers(array($identifier)); - $config = id(new PhabricatorEditEngineConfigurationQuery()) - ->setViewer($viewer) - ->withEngineKeys(array($this->getEngineKey())) - ->withIdentifiers(array($key)) - ->withIgnoreDatabaseConfigurations($ignore_database) - ->executeOne(); - if (!$config) { - return null; - } + return $this->loadEditEngineConfigurationWithQuery($query, null); + } - $this->editEngineConfiguration = $config; + private function loadDefaultConfiguration() { + $query = $this->newConfigurationQuery() + ->withIdentifiers( + array( + self::EDITENGINECONFIG_DEFAULT, + )) + ->withIgnoreDatabaseConfigurations(true); + + return $this->loadEditEngineConfigurationWithQuery($query, null); + } + + private function loadDefaultCreateConfiguration() { + $query = $this->newConfigurationQuery() + ->withIsDefault(true) + ->withIsDisabled(false); + + return $this->loadEditEngineConfigurationWithQuery( + $query, + 'getCreateSortKey'); + } + + private function loadDefaultEditConfiguration() { + $query = $this->newConfigurationQuery() + ->withIsEdit(true) + ->withIsDisabled(false); - return $config; + return $this->loadEditEngineConfigurationWithQuery( + $query, + 'getEditSortKey'); } final public function getBuiltinEngineConfigurations() { @@ -278,7 +287,8 @@ if (!$first->getBuiltinKey()) { $first ->setBuiltinKey(self::EDITENGINECONFIG_DEFAULT) - ->setIsDefault(true); + ->setIsDefault(true) + ->setIsEdit(true); if (!strlen($first->getName())) { $first->setName($this->getObjectCreateShortText()); @@ -648,18 +658,8 @@ break; } - if ($use_default) { - $config = $this->loadDefaultEditEngineConfiguration(); - } else { - $form_key = $request->getURIData('formKey'); - $config = $this->loadEditEngineConfiguration($form_key); - } - - if (!$config) { - return new Aphront404Response(); - } - $id = $request->getURIData('id'); + if ($id) { $this->setIsCreate(false); $object = $this->newObjectFromID($id, $capabilities); @@ -679,6 +679,42 @@ $this->validateObject($object); + if ($use_default) { + $config = $this->loadDefaultConfiguration(); + if (!$config) { + return new Aphront404Response(); + } + } else { + $form_key = $request->getURIData('formKey'); + if (strlen($form_key)) { + $config = $this->loadEditEngineConfigurationWithIdentifier($form_key); + + if (!$config) { + return new Aphront404Response(); + } + + if ($id && !$config->getIsEdit()) { + return $this->buildNotEditFormRespose($object, $config); + } + } else { + if ($id) { + $config = $this->loadDefaultEditConfiguration(); + if (!$config) { + return $this->buildNoEditResponse($object); + } + } else { + $config = $this->loadDefaultCreateConfiguration(); + if (!$config) { + return $this->buildNoCreateResponse($object); + } + } + } + } + + if ($config->getIsDisabled()) { + return $this->buildFormDisabledResponse($object, $config); + } + switch ($action) { case 'parameters': return $this->buildParametersResponse($object); @@ -1032,7 +1068,7 @@ } final public function buildEditEngineCommentView($object) { - $config = $this->loadDefaultEditEngineConfiguration(); + $config = $this->loadDefaultConfiguration(); $viewer = $this->getViewer(); $object_phid = $object->getPHID(); @@ -1146,42 +1182,68 @@ } - private function buildNoDefaultResponse($object) { + private function buildError($object, $title, $body) { $cancel_uri = $this->getObjectCreateCancelURI($object); return $this->getController() ->newDialog() - ->setTitle(pht('No Default Create Forms')) - ->appendParagraph( - pht( - 'This application is not configured with any visible, enabled '. - 'forms for creating objects.')) + ->setTitle($title) + ->appendParagraph($body) ->addCancelButton($cancel_uri); } - private function buildNoCreateResponse($object) { - $cancel_uri = $this->getObjectCreateCancelURI($object); - return $this->getController() - ->newDialog() - ->setTitle(pht('No Create Permission')) - ->appendParagraph( - pht( - 'You do not have permission to create these objects.')) - ->addCancelButton($cancel_uri); + private function buildNoDefaultResponse($object) { + return $this->buildError( + $object, + pht('No Default Create Forms'), + pht( + 'This application is not configured with any forms for creating '. + 'objects that are visible to you and enabled.')); } - private function buildNoManageResponse($object) { - $cancel_uri = $this->getObjectCreateCancelURI($object); + private function buildNoCreateResponse($object) { + return $this->buildError( + $object, + pht('No Create Permission'), + pht('You do not have permission to create these objects.')); + } - return $this->getController() - ->newDialog() - ->setTitle(pht('No Manage Permission')) - ->appendParagraph( - pht( - 'You do not have permission to configure forms for this '. - 'application.')) - ->addCancelButton($cancel_uri); + private function buildNoManageResponse($object) { + return $this->buildError( + $object, + pht('No Manage Permission'), + pht( + 'You do not have permission to configure forms for this '. + 'application.')); + } + + private function buildNoEditResponse($object) { + return $this->buildError( + $object, + pht('No Edit Forms'), + pht( + 'You do not have access to any forms which are enabled and marked '. + 'as edit forms.')); + } + + private function buildNotEditFormRespose($object, $config) { + return $this->buildError( + $object, + pht('Not an Edit Form'), + pht( + 'This form ("%s") is not marked as an edit form, so '. + 'it can not be used to edit objects.', + $config->getName())); + } + + private function buildDisabledFormResponse($object, $config) { + return $this->buildError( + $object, + pht('Form Disabled'), + pht( + 'This form ("%s") has been disabled, so it can not be used.', + $config->getName())); } private function buildCommentResponse($object) { @@ -1198,7 +1260,7 @@ return new Aphront400Response(); } - $config = $this->loadDefaultEditEngineConfiguration(); + $config = $this->loadDefaultConfiguration(); $fields = $this->buildEditFields($object); $is_preview = $request->isPreviewRequest(); @@ -1328,7 +1390,7 @@ final public function buildConduitResponse(ConduitAPIRequest $request) { $viewer = $this->getViewer(); - $config = $this->loadDefaultEditEngineConfiguration(); + $config = $this->loadDefaultConfiguration(); if (!$config) { throw new Exception( pht( @@ -1476,7 +1538,7 @@ } public function getConduitEditTypes() { - $config = $this->loadDefaultEditEngineConfiguration(); + $config = $this->loadDefaultConfiguration(); if (!$config) { return array(); } diff --git a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php --- a/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php +++ b/src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php @@ -23,6 +23,7 @@ $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE; + $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE; @@ -75,6 +76,8 @@ return $object->getFieldLocks(); case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: return (int)$object->getIsDefault(); + case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: + return (int)$object->getIsEdit(); case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE: return (int)$object->getIsDisabled(); } @@ -92,6 +95,7 @@ case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: return $xaction->getNewValue(); case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: + case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE: return (int)$xaction->getNewValue(); } @@ -121,6 +125,9 @@ case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: $object->setIsDefault($xaction->getNewValue()); return; + case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: + $object->setIsEdit($xaction->getNewValue()); + return; case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE: $object->setIsDisabled($xaction->getNewValue()); return; @@ -138,6 +145,7 @@ case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: + case PhabricatorEditEngineConfigurationTransaction::TYPE_ISEDIT: case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULTCREATE: case PhabricatorEditEngineConfigurationTransaction::TYPE_DISABLE: diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php --- a/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php +++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php @@ -9,6 +9,7 @@ private $builtinKeys; private $identifiers; private $default; + private $isEdit; private $disabled; private $ignoreDatabaseConfigurations; @@ -42,6 +43,11 @@ return $this; } + public function withIsEdit($edit) { + $this->isEdit = $edit; + return $this; + } + public function withIsDisabled($disabled) { $this->disabled = $disabled; return $this; @@ -148,6 +154,14 @@ } } + if ($this->isEdit !== null) { + foreach ($page as $key => $config) { + if ($config->getIsEdit() != $this->isEdit) { + unset($page[$key]); + } + } + } + if ($this->disabled !== null) { foreach ($page as $key => $config) { if ($config->getIsDisabled() != $this->disabled) { diff --git a/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php --- a/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php +++ b/src/applications/transactions/query/PhabricatorEditEngineConfigurationSearchEngine.php @@ -33,11 +33,37 @@ protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); + + $is_create = $map['isCreate']; + if ($is_create !== null) { + $query->withIsDefault($is_create); + } + + $is_edit = $map['isEdit']; + if ($is_edit !== null) { + $query->withIsEdit($is_edit); + } + return $query; } protected function buildCustomSearchFields() { - return array(); + return array( + id(new PhabricatorSearchThreeStateField()) + ->setLabel(pht('Create')) + ->setKey('isCreate') + ->setOptions( + pht('Show All'), + pht('Hide Create Forms'), + pht('Show Only Create Forms')), + id(new PhabricatorSearchThreeStateField()) + ->setLabel(pht('Edit')) + ->setKey('isEdit') + ->setOptions( + pht('Show All'), + pht('Hide Edit Forms'), + pht('Show Only Edit Forms')), + ); } protected function getDefaultFieldOrder() { @@ -51,6 +77,8 @@ protected function getBuiltinQueryNames() { $names = array( 'all' => pht('All Forms'), + 'create' => pht('Create Forms'), + 'modify' => pht('Edit Forms'), ); return $names; @@ -63,6 +91,10 @@ switch ($query_key) { case 'all': return $query; + case 'create': + return $query->setParameter('isCreate', true); + case 'modify': + return $query->setParameter('isEdit', true); } return parent::buildSavedQueryFromBuiltin($query_key); @@ -96,6 +128,10 @@ $item->addIcon('fa-plus', pht('Default')); } + if ($config->getIsEdit()) { + $item->addIcon('fa-pencil', pht('Edit Form')); + } + if ($config->getIsDisabled()) { $item->addIcon('fa-ban', pht('Disabled')); } diff --git a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php --- a/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorEditEngineConfigurationTransaction.php @@ -9,6 +9,7 @@ const TYPE_DEFAULT = 'editengine.config.default'; const TYPE_LOCKS = 'editengine.config.locks'; const TYPE_DEFAULTCREATE = 'editengine.config.default.create'; + const TYPE_ISEDIT = 'editengine.config.isedit'; const TYPE_DISABLE = 'editengine.config.disable'; public function getApplicationName() { @@ -72,6 +73,16 @@ '%s removed this form from the "Create" menu.', $this->renderHandleLink($author_phid)); } + case self::TYPE_ISEDIT: + if ($new) { + return pht( + '%s marked this form as an edit form.', + $this->renderHandleLink($author_phid)); + } else { + return pht( + '%s unmarked this form as an edit form.', + $this->renderHandleLink($author_phid)); + } case self::TYPE_DISABLE: if ($new) { return pht(