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 @@ -2069,6 +2069,7 @@ 'PhabricatorApplicationTransactionWarningException' => 'applications/transactions/exception/PhabricatorApplicationTransactionWarningException.php', 'PhabricatorApplicationTransactionWarningResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionWarningResponse.php', 'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php', + 'PhabricatorApplicationUninstallTransaction' => 'applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php', 'PhabricatorApplicationsApplication' => 'applications/meta/application/PhabricatorApplicationsApplication.php', 'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php', 'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php', @@ -7533,6 +7534,7 @@ 'PhabricatorApplicationTransactionWarningException' => 'Exception', 'PhabricatorApplicationTransactionWarningResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController', + 'PhabricatorApplicationUninstallTransaction' => 'PhabricatorApplicationTransactionType', 'PhabricatorApplicationsApplication' => 'PhabricatorApplication', 'PhabricatorApplicationsController' => 'PhabricatorController', 'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController', diff --git a/src/applications/meta/controller/PhabricatorApplicationUninstallController.php b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php --- a/src/applications/meta/controller/PhabricatorApplicationUninstallController.php +++ b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php @@ -3,17 +3,15 @@ final class PhabricatorApplicationUninstallController extends PhabricatorApplicationsController { - private $application; - private $action; - public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); - $this->action = $request->getURIData('action'); - $this->application = $request->getURIData('application'); + $user = $request->getUser(); + $action = $request->getURIData('action'); + $application_name = $request->getURIData('application'); - $selected = id(new PhabricatorApplicationQuery()) + $application = id(new PhabricatorApplicationQuery()) ->setViewer($viewer) - ->withClasses(array($this->application)) + ->withClasses(array($application_name)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, @@ -21,11 +19,11 @@ )) ->executeOne(); - if (!$selected) { + if (!$application) { return new Aphront404Response(); } - $view_uri = $this->getApplicationURI('view/'.$this->application); + $view_uri = $this->getApplicationURI('view/'.$application_name); $prototypes_enabled = PhabricatorEnv::getEnvConfig( 'phabricator.show-prototypes'); @@ -34,7 +32,7 @@ ->setUser($viewer) ->addCancelButton($view_uri); - if ($selected->isPrototype() && !$prototypes_enabled) { + if ($application->isPrototype() && !$prototypes_enabled) { $dialog ->setTitle(pht('Prototypes Not Enabled')) ->appendChild( @@ -46,18 +44,40 @@ } if ($request->isDialogFormPost()) { - $this->manageApplication(); - return id(new AphrontRedirectResponse())->setURI($view_uri); + $xactions = array(); + $template = $application->getApplicationTransactionTemplate(); + $xactions[] = id(clone $template) + ->setTransactionType( + PhabricatorApplicationUninstallTransaction::TRANSACTIONTYPE) + ->setNewValue($action); + + $editor = id(new PhabricatorApplicationEditor()) + ->setActor($user) + ->setContentSourceFromRequest($request) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true); + + try { + $editor->applyTransactions($application, $xactions); + return id(new AphrontRedirectResponse())->setURI($view_uri); + } catch (PhabricatorApplicationTransactionValidationException $ex) { + $validation_exception = $ex; + } + + return $this->newDialog() + ->setTitle(pht('Validation Failed')) + ->setValidationException($validation_exception) + ->addCancelButton($view_uri); } - if ($this->action == 'install') { - if ($selected->canUninstall()) { + if ($action == 'install') { + if ($application->canUninstall()) { $dialog ->setTitle(pht('Confirmation')) ->appendChild( pht( 'Install %s application?', - $selected->getName())) + $application->getName())) ->addSubmitButton(pht('Install')); } else { @@ -66,10 +86,10 @@ ->appendChild(pht('You cannot install an installed application.')); } } else { - if ($selected->canUninstall()) { + if ($application->canUninstall()) { $dialog->setTitle(pht('Really Uninstall Application?')); - if ($selected instanceof PhabricatorHomeApplication) { + if ($application instanceof PhabricatorHomeApplication) { $dialog ->appendParagraph( pht( @@ -86,7 +106,7 @@ ->appendParagraph( pht( 'Really uninstall the %s application?', - $selected->getName())) + $application->getName())) ->addSubmitButton(pht('Uninstall')); } } else { @@ -101,23 +121,4 @@ return id(new AphrontDialogResponse())->setDialog($dialog); } - public function manageApplication() { - $key = 'phabricator.uninstalled-applications'; - $config_entry = PhabricatorConfigEntry::loadConfigEntry($key); - $list = $config_entry->getValue(); - $uninstalled = PhabricatorEnv::getEnvConfig($key); - - if (isset($uninstalled[$this->application])) { - unset($list[$this->application]); - } else { - $list[$this->application] = true; - } - - PhabricatorConfigEditor::storeNewValue( - $this->getViewer(), - $config_entry, - $list, - PhabricatorContentSource::newFromRequest($this->getRequest())); - } - } diff --git a/src/applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php b/src/applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php --- a/src/applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php +++ b/src/applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php @@ -14,7 +14,7 @@ return $application->getPolicy($capability); } - public function applyInternalEffects($object, $value) { + public function applyExternalEffects($object, $value) { $application = $object; $user = $this->getActor(); diff --git a/src/applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php b/src/applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php new file mode 100644 --- /dev/null +++ b/src/applications/meta/xactions/PhabricatorApplicationUninstallTransaction.php @@ -0,0 +1,79 @@ +getValue(); + $uninstalled = PhabricatorEnv::getEnvConfig($key); + + if (isset($uninstalled[get_class($object)])) { + return 'uninstalled'; + } else { + return 'installed'; + } + } + + public function generateNewValue($object, $value) { + if ($value === 'uninstall') { + return 'uninstalled'; + } else { + return 'installed'; + } + } + + public function applyExternalEffects($object, $value) { + $application = $object; + $user = $this->getActor(); + + $key = 'phabricator.uninstalled-applications'; + $config_entry = PhabricatorConfigEntry::loadConfigEntry($key); + $list = $config_entry->getValue(); + $uninstalled = PhabricatorEnv::getEnvConfig($key); + + if (isset($uninstalled[get_class($application)])) { + unset($list[get_class($application)]); + } else { + $list[get_class($application)] = true; + } + + $editor = $this->getEditor(); + $content_source = $editor->getContentSource(); + PhabricatorConfigEditor::storeNewValue( + $user, + $config_entry, + $list, + $content_source); + } + + public function getTitle() { + if ($this->getNewValue() === 'uninstalled') { + return pht( + '%s uninstalled this application.', + $this->renderAuthor()); + } else { + return pht( + '%s installed this application.', + $this->renderAuthor()); + } + } + + public function getTitleForFeed() { + if ($this->getNewValue() === 'uninstalled') { + return pht( + '%s uninstalled %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s installed %s.', + $this->renderAuthor(), + $this->renderObject()); + } + } + +}