From 5017c80b31036039bb4c8ffd286f2fd2f5110c36 Mon Sep 17 00:00:00 2001 From: Afaque Hussain Date: Tue, 29 Jan 2013 09:14:03 -0800 Subject: [PATCH] Installation & Uninstallion of Applications Summary: Created Applications application which allows uninstallation & installation of application. Test Plan: In "Applications" application, clicked on uninstalled the application by cliking Uninstall and chekcing whether they are really uninstalled(Disabling URI & in appearance in the side pane). Then Clicked on the install button of the uninstalled application to check whether they are installed. Reviewers: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D4715 --- conf/default.conf.php | 3 + src/__phutil_library_map__.php | 2 + .../PhabricatorApplicationAuth.php | 4 + .../base/PhabricatorApplication.php | 63 +++++++++++-- .../PhabricatorApplicationConfig.php | 4 + .../option/PhabricatorCoreConfigOptions.php | 5 + .../PhabricatorApplicationDaemons.php | 4 + .../PhabricatorApplicationFeed.php | 4 + .../PhabricatorApplicationFiles.php | 4 + .../PhabricatorApplicationApplications.php | 7 +- ...ricatorApplicationDetailViewController.php | 76 +++++++++------ ...bricatorApplicationUninstallController.php | 93 +++++++++++++++++++ .../PhabricatorApplicationsListController.php | 2 +- .../PhabricatorApplicationMetaMTA.php | 4 + .../PhabricatorApplicationPeople.php | 4 + .../PhabricatorApplicationSettings.php | 4 + .../PhabricatorApplicationSubscriptions.php | 4 + .../PhabricatorApplicationTransactions.php | 4 + 18 files changed, 253 insertions(+), 38 deletions(-) create mode 100644 src/applications/meta/controller/PhabricatorApplicationUninstallController.php diff --git a/conf/default.conf.php b/conf/default.conf.php index 1217dc6238..6cc166c323 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -839,6 +839,9 @@ return array( // Should Phabricator show beta applications on the homepage 'phabricator.show-beta-applications' => false, + // Contains a list of uninstalled applications + 'phabricator.uninstalled-applications' => array(), + // -- Files ----------------------------------------------------------------- // // Lists which uploaded file types may be viewed in the browser. If a file diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5090f256e3..c900d24f47 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -673,6 +673,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionView' => 'applications/transactions/view/PhabricatorApplicationTransactionView.php', 'PhabricatorApplicationTransactions' => 'applications/transactions/application/PhabricatorApplicationTransactions.php', 'PhabricatorApplicationUIExamples' => 'applications/uiexample/application/PhabricatorApplicationUIExamples.php', + 'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php', 'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php', 'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php', 'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php', @@ -2103,6 +2104,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionView' => 'AphrontView', 'PhabricatorApplicationTransactions' => 'PhabricatorApplication', 'PhabricatorApplicationUIExamples' => 'PhabricatorApplication', + 'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationsController' => 'PhabricatorController', 'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController', 'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController', diff --git a/src/applications/auth/application/PhabricatorApplicationAuth.php b/src/applications/auth/application/PhabricatorApplicationAuth.php index 18819a9410..acd98344ea 100644 --- a/src/applications/auth/application/PhabricatorApplicationAuth.php +++ b/src/applications/auth/application/PhabricatorApplicationAuth.php @@ -6,6 +6,10 @@ final class PhabricatorApplicationAuth extends PhabricatorApplication { return false; } + public function canUninstall() { + return false; + } + public function buildMainMenuItems( PhabricatorUser $user, PhabricatorController $controller = null) { diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 9642a57fba..6bed54389a 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -62,10 +62,25 @@ abstract class PhabricatorApplication { return true; } + public function isInstalled() { + $uninstalled = + PhabricatorEnv::getEnvConfig('phabricator.uninstalled-applications'); + + if (isset($uninstalled[get_class($this)])) { + return false; + } else { + return true; + } + } + public function isBeta() { return false; } + public function canUninstall() { + return true; + } + public function getPHID() { return 'PHID-APPS-'.get_class($this); } @@ -212,6 +227,22 @@ abstract class PhabricatorApplication { /* -( Application Management )--------------------------------------------- */ + public static function getAllApplications() { + + $classes = id(new PhutilSymbolLoader()) + ->setAncestorClass(__CLASS__) + ->setConcreteOnly(true) + ->selectAndLoadSymbols(); + + $apps = array(); + + foreach ($classes as $class) { + $app = newv($class['name'], array()); + $apps[] = $app; + } + + return $apps; + } public static function getAllInstalledApplications() { static $applications; @@ -219,6 +250,11 @@ abstract class PhabricatorApplication { $show_beta = PhabricatorEnv::getEnvConfig('phabricator.show-beta-applications'); + $uninstalled = + PhabricatorEnv::getEnvConfig('phabricator.uninstalled-applications'); + + + if (empty($applications)) { $classes = id(new PhutilSymbolLoader()) ->setAncestorClass(__CLASS__) @@ -227,22 +263,29 @@ abstract class PhabricatorApplication { $apps = array(); foreach ($classes as $class) { - $app = newv($class['name'], array()); - if (!$app->isEnabled()) { - continue; - } - if (!$show_beta && $app->isBeta()) { - continue; - } - - $apps[] = $app; + if (isset($uninstalled[$class['name']])) { + continue; } + + $app = newv($class['name'], array()); + + if (!$app->isEnabled()) { + continue; + } + + if (!$show_beta && $app->isBeta()) { + continue; + } + + $apps[] = $app; + } + $applications = $apps; } return $applications; } - } + diff --git a/src/applications/config/application/PhabricatorApplicationConfig.php b/src/applications/config/application/PhabricatorApplicationConfig.php index 70c542c217..5c78cef272 100644 --- a/src/applications/config/application/PhabricatorApplicationConfig.php +++ b/src/applications/config/application/PhabricatorApplicationConfig.php @@ -18,6 +18,10 @@ final class PhabricatorApplicationConfig extends PhabricatorApplication { return self::GROUP_ADMIN; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/config/' => array( diff --git a/src/applications/config/option/PhabricatorCoreConfigOptions.php b/src/applications/config/option/PhabricatorCoreConfigOptions.php index c1dddac3d1..6dadb5c816 100644 --- a/src/applications/config/option/PhabricatorCoreConfigOptions.php +++ b/src/applications/config/option/PhabricatorCoreConfigOptions.php @@ -128,6 +128,11 @@ final class PhabricatorCoreConfigOptions $this->newOption('test.value', 'wild', null) ->setLocked(true) ->setDescription(pht('Unit test value.')), + $this->newOption('phabricator.uninstalled-applications', 'set', array()) + ->setLocked(true) + ->setDescription( + pht('Array containing list of Uninstalled applications.') + ), ); } diff --git a/src/applications/daemon/application/PhabricatorApplicationDaemons.php b/src/applications/daemon/application/PhabricatorApplicationDaemons.php index 4d02d15680..344a80ebcd 100644 --- a/src/applications/daemon/application/PhabricatorApplicationDaemons.php +++ b/src/applications/daemon/application/PhabricatorApplicationDaemons.php @@ -26,6 +26,10 @@ final class PhabricatorApplicationDaemons extends PhabricatorApplication { return self::GROUP_ADMIN; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/daemon/' => array( diff --git a/src/applications/feed/application/PhabricatorApplicationFeed.php b/src/applications/feed/application/PhabricatorApplicationFeed.php index 2c089ac344..d1c0e0cf3e 100644 --- a/src/applications/feed/application/PhabricatorApplicationFeed.php +++ b/src/applications/feed/application/PhabricatorApplicationFeed.php @@ -14,6 +14,10 @@ final class PhabricatorApplicationFeed extends PhabricatorApplication { return 'feed'; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/feed/' => array( diff --git a/src/applications/files/application/PhabricatorApplicationFiles.php b/src/applications/files/application/PhabricatorApplicationFiles.php index 9c8491a4ca..2d79ac1003 100644 --- a/src/applications/files/application/PhabricatorApplicationFiles.php +++ b/src/applications/files/application/PhabricatorApplicationFiles.php @@ -30,6 +30,10 @@ final class PhabricatorApplicationFiles extends PhabricatorApplication { return $this->getBaseURI().'upload/'; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/F(?P[1-9]\d*)' => 'PhabricatorFileShortcutController', diff --git a/src/applications/meta/application/PhabricatorApplicationApplications.php b/src/applications/meta/application/PhabricatorApplicationApplications.php index 6139945b6f..58a50e4cbe 100644 --- a/src/applications/meta/application/PhabricatorApplicationApplications.php +++ b/src/applications/meta/application/PhabricatorApplicationApplications.php @@ -2,6 +2,10 @@ final class PhabricatorApplicationApplications extends PhabricatorApplication { + public function canUninstall() { + return false; + } + public function getBaseURI() { return '/applications/'; } @@ -28,7 +32,8 @@ final class PhabricatorApplicationApplications extends PhabricatorApplication { '' => 'PhabricatorApplicationsListController', 'view/(?P\w+)/' => 'PhabricatorApplicationDetailViewController', - + '(?P\w+)/(?Pinstall|uninstall)/' => + 'PhabricatorApplicationUninstallController', ), ); diff --git a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php index db9cd66199..460dd6b0f1 100644 --- a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php +++ b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php @@ -14,12 +14,12 @@ final class PhabricatorApplicationDetailViewController $user = $request->getUser(); $selected = null; - $applications = PhabricatorApplication::getAllInstalledApplications(); + $applications = PhabricatorApplication::getAllApplications(); foreach ($applications as $application) { if (get_class($application) == $this->application) { - $selected = $application; - break; + $selected = $application; + break; } } @@ -35,27 +35,33 @@ final class PhabricatorApplicationDetailViewController ->setName(pht('Applications')) ->setHref($this->getApplicationURI())); - $properties = $this->buildPropertyView($selected); - $actions = $this->buildActionView($user); + $properties = $this->buildPropertyView($selected); + $actions = $this->buildActionView($user, $selected); - return $this->buildApplicationPage( - array( - $crumbs, - id(new PhabricatorHeaderView())->setHeader($title), - $actions, - $properties, - ), - array( - 'title' => $title, - 'device' => true, - )); + return $this->buildApplicationPage( + array( + $crumbs, + id(new PhabricatorHeaderView())->setHeader($title), + $actions, + $properties, + ), + array( + 'title' => $title, + 'device' => true, + )); } private function buildPropertyView(PhabricatorApplication $selected) { $properties = new PhabricatorPropertyListView(); - $properties->addProperty( - pht('Status'), pht('Installed')); + if ($selected->isInstalled()) { + $properties->addProperty( + pht('Status'), pht('Installed')); + + } else { + $properties->addProperty( + pht('Status'), pht('Uninstalled')); + } $properties->addProperty( pht('Description'), $selected->getShortDescription()); @@ -63,15 +69,33 @@ final class PhabricatorApplicationDetailViewController return $properties; } - private function buildActionView(PhabricatorUser $user) { + private function buildActionView( + PhabricatorUser $user, PhabricatorApplication $selected) { - return id(new PhabricatorActionListView()) - ->setUser($user) - ->addAction( - id(new PhabricatorActionView()) - ->setName(pht('Uninstall')) - ->setIcon('delete') - ); + if ($selected->canUninstall()) { + if ($selected->isInstalled()) { + + return id(new PhabricatorActionListView()) + ->setUser($user) + ->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Uninstall')) + ->setIcon('delete') + ->setHref( + $this->getApplicationURI(get_class($selected).'/uninstall/')) + ); + } else { + return id(new PhabricatorActionListView()) + ->setUser($user) + ->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Install')) + ->setIcon('new') + ->setHref( + $this->getApplicationURI(get_class($selected).'/install/')) + ); + } + } } } diff --git a/src/applications/meta/controller/PhabricatorApplicationUninstallController.php b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php new file mode 100644 index 0000000000..7ba660d3cf --- /dev/null +++ b/src/applications/meta/controller/PhabricatorApplicationUninstallController.php @@ -0,0 +1,93 @@ +application = $data['application']; + $this->action = $data['action']; + } + + public function processRequest() { + $request = $this->getRequest(); + $user = $request->getUser(); + $app_name = substr($this->application, strlen('PhabricatorApplication')); + + if ($request->isDialogFormPost()) { + $this->manageApplication(); + return id(new AphrontRedirectResponse())->setURI('/applications/'); + } + + if ($this->action == 'install') { + + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle('Confirmation') + ->appendChild('Install '. $app_name. ' application ?') + ->addSubmitButton('Install') + ->addCancelButton('/applications/view/'.$this->application); + } else { + $dialog = id(new AphrontDialogView()) + ->setUser($user) + ->setTitle('Confirmation') + ->appendChild('Really Uninstall '. $app_name. ' application ?') + ->addSubmitButton('Uninstall') + ->addCancelButton('/applications/view/'.$this->application); + } + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + + public function manageApplication() { + $key = 'phabricator.uninstalled-applications'; + + $config_entry = id(new PhabricatorConfigEntry()) + ->loadOneWhere( + 'configKey = %s AND namespace = %s', + $key, + 'default'); + + if (!$config_entry) { + $config_entry = id(new PhabricatorConfigEntry()) + ->setConfigKey($key) + ->setNamespace('default'); + } + + $list = $config_entry->getValue(); + + $uninstalled = PhabricatorEnv::getEnvConfig($key); + + if ($uninstalled[$this->application]) { + unset($list[$this->application]); + } else { + $list[$this->application] = true; + } + + $xaction = id(new PhabricatorConfigTransaction()) + ->setTransactionType(PhabricatorConfigTransaction::TYPE_EDIT) + ->setNewValue( + array( + 'deleted' => false, + 'value' => $list + )); + + $editor = id(new PhabricatorConfigEditor()) + ->setActor($this->getRequest()->getUser()) + ->setContinueOnNoEffect(true) + ->setContentSource( + PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_WEB, + array( + 'ip' => $this->getRequest()->getRemoteAddr(), + ))); + + + $editor->applyTransactions($config_entry, array($xaction)); + + } + +} + diff --git a/src/applications/meta/controller/PhabricatorApplicationsListController.php b/src/applications/meta/controller/PhabricatorApplicationsListController.php index 3ef64b24bd..a6b3ef1fce 100644 --- a/src/applications/meta/controller/PhabricatorApplicationsListController.php +++ b/src/applications/meta/controller/PhabricatorApplicationsListController.php @@ -10,7 +10,7 @@ final class PhabricatorApplicationsListController $nav = $this->buildSideNavView(); $nav->selectFilter('/'); - $applications = PhabricatorApplication::getAllInstalledApplications(); + $applications = PhabricatorApplication::getAllApplications(); $list = $this->buildInstalledApplicationsList($applications); diff --git a/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php b/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php index 6aed7502c8..0ac2afd146 100644 --- a/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php +++ b/src/applications/metamta/application/PhabricatorApplicationMetaMTA.php @@ -22,6 +22,10 @@ final class PhabricatorApplicationMetaMTA extends PhabricatorApplication { return self::GROUP_ADMIN; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( $this->getBaseURI() => array( diff --git a/src/applications/people/application/PhabricatorApplicationPeople.php b/src/applications/people/application/PhabricatorApplicationPeople.php index ad9754bc1c..0f0f05385e 100644 --- a/src/applications/people/application/PhabricatorApplicationPeople.php +++ b/src/applications/people/application/PhabricatorApplicationPeople.php @@ -26,6 +26,10 @@ final class PhabricatorApplicationPeople extends PhabricatorApplication { return self::GROUP_ADMIN; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/people/' => array( diff --git a/src/applications/settings/application/PhabricatorApplicationSettings.php b/src/applications/settings/application/PhabricatorApplicationSettings.php index 36abbb47c4..613ec7168a 100644 --- a/src/applications/settings/application/PhabricatorApplicationSettings.php +++ b/src/applications/settings/application/PhabricatorApplicationSettings.php @@ -14,6 +14,10 @@ final class PhabricatorApplicationSettings extends PhabricatorApplication { return 'settings'; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/settings/' => array( diff --git a/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php b/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php index 21543d4eb9..ad4b4eea15 100644 --- a/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php +++ b/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php @@ -6,6 +6,10 @@ final class PhabricatorApplicationSubscriptions extends PhabricatorApplication { return false; } + public function canUninstall() { + return false; + } + public function getEventListeners() { return array( new PhabricatorSubscriptionsUIEventListener(), diff --git a/src/applications/transactions/application/PhabricatorApplicationTransactions.php b/src/applications/transactions/application/PhabricatorApplicationTransactions.php index b597b394dd..ac0b4e1bc9 100644 --- a/src/applications/transactions/application/PhabricatorApplicationTransactions.php +++ b/src/applications/transactions/application/PhabricatorApplicationTransactions.php @@ -6,6 +6,10 @@ final class PhabricatorApplicationTransactions extends PhabricatorApplication { return false; } + public function canUninstall() { + return false; + } + public function getRoutes() { return array( '/transactions/' => array(