Skip to content

Commit 6f179a3

Browse files
authored
Merge pull request #17030 from craftcms/feature/cms-1386-plugin-cli-improvements
`plugin/install` & `plugin/uninstall` improvements
2 parents 4bafd19 + 03808cd commit 6f179a3

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

CHANGELOG-WIP.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
### Administration
1010
- Added the `db/repair` command. ([#16812](https://github.com/craftcms/cms/pull/16812))
1111
- Added the `--batch-size` option for `resave/*` commands. ([#16586](https://github.com/craftcms/cms/issues/16586))
12+
- The `plugin/install` command now accepts an `edition` argument, and prompts for the default edition if none is specified. ([#17030](https://github.com/craftcms/cms/pull/17030))
13+
- The `plugin/uninstall` command now reports if no plugin is installed with the provided handle. ([#17030](https://github.com/craftcms/cms/pull/17030))
1214
- The `users/create` command now prompts to send an activation email, or outputs an activation URL. ([#16794](https://github.com/craftcms/cms/pull/16794))
1315
- Dragging headings within the Customize Sources modal now also drags any subsequent sources. ([#16737](https://github.com/craftcms/cms/issues/16737))
1416
- When switching field types, any field settings which are defined by the same base class are now preserved. ([#16783](https://github.com/craftcms/cms/pull/16783))

src/console/controllers/PluginController.php

+58-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
namespace craft\console\controllers;
99

1010
use Craft;
11+
use craft\base\PluginInterface;
1112
use craft\console\Controller;
13+
use craft\errors\InvalidPluginException;
1214
use craft\helpers\ArrayHelper;
1315
use craft\helpers\Console;
1416
use Throwable;
@@ -118,11 +120,13 @@ public function actionList(): int
118120
* @param string|null $handle The plugin handle (omitted if --all provided).
119121
* @return int
120122
*/
121-
public function actionInstall(?string $handle = null): int
123+
public function actionInstall(?string $handle = null, ?string $edition = null): int
122124
{
125+
$pluginsService = Craft::$app->getPlugins();
126+
123127
if ($this->all) {
124128
// get all plugins’ info
125-
$pluginInfo = Craft::$app->getPlugins()->getAllPluginInfo();
129+
$pluginInfo = $pluginsService->getAllPluginInfo();
126130

127131
// filter out the ones that are already installed
128132
$pluginInfo = array_filter($pluginInfo, function(array $info) {
@@ -140,7 +144,47 @@ public function actionInstall(?string $handle = null): int
140144
$this->_installPluginByHandle($handle);
141145
}
142146
} else {
143-
$this->_installPluginByHandle($handle);
147+
if ($pluginsService->isPluginInstalled($handle)) {
148+
$plugin = $pluginsService->getPlugin($handle);
149+
if ($edition === null || $edition === $plugin->edition) {
150+
$this->stderr(sprintf("%s%s is already installed.\n", $plugin->name, $edition !== null ? " ($edition)" : ''), Console::FG_YELLOW);
151+
return ExitCode::UNSPECIFIED_ERROR;
152+
}
153+
try {
154+
$pluginsService->switchEdition($handle, $edition);
155+
} catch (Throwable $e) {
156+
$this->stderr("{$e->getMessage()}\n", Console::FG_RED);
157+
return ExitCode::UNSPECIFIED_ERROR;
158+
}
159+
$this->stdout($this->markdownToAnsi("$plugin->name switched to the `$edition` edition.") . "\n");
160+
return ExitCode::OK;
161+
}
162+
163+
if ($edition === null && $this->interactive) {
164+
// see if it's a multi-edition plugin
165+
try {
166+
$info = $pluginsService->getPluginInfo($handle);
167+
} catch (InvalidPluginException $e) {
168+
$this->stderr("{$e->getMessage()}\n", Console::FG_RED);
169+
return ExitCode::UNSPECIFIED_ERROR;
170+
}
171+
172+
/** @var class-string<PluginInterface> $class */
173+
$class = $info['class'];
174+
$editions = $class::editions();
175+
if (count($editions) > 1) {
176+
$this->stdout("Which edition?\n");
177+
foreach ($editions as $edition) {
178+
$this->stdout($this->markdownToAnsi("- `$edition`") . "\n");
179+
}
180+
$edition = $this->prompt('Choose:', [
181+
'default' => reset($editions),
182+
'validate' => fn($input) => in_array($input, $editions),
183+
]);
184+
}
185+
}
186+
187+
$this->_installPluginByHandle($handle, $edition);
144188
}
145189

146190
return ExitCode::OK;
@@ -154,9 +198,11 @@ public function actionInstall(?string $handle = null): int
154198
*/
155199
public function actionUninstall(?string $handle = null): int
156200
{
201+
$pluginsService = Craft::$app->getPlugins();
202+
157203
if ($this->all) {
158204
// get all plugins’ info
159-
$pluginInfo = Craft::$app->getPlugins()->getAllPluginInfo();
205+
$pluginInfo = $pluginsService->getAllPluginInfo();
160206

161207
// filter out the ones that are uninstalled/disabled
162208
$pluginInfo = array_filter($pluginInfo, function(array $info) {
@@ -178,6 +224,12 @@ public function actionUninstall(?string $handle = null): int
178224
$this->_uninstallPluginByHandle($handle);
179225
}
180226
} else {
227+
$plugin = $pluginsService->isPluginInstalled($handle);
228+
if (!$plugin) {
229+
$this->stderr($this->markdownToAnsi("No plugin is installed with the handle `$handle`.") . "\n");
230+
return ExitCode::OK;
231+
}
232+
181233
$this->_uninstallPluginByHandle($handle);
182234
}
183235

@@ -258,7 +310,7 @@ public function actionDisable(?string $handle = null): int
258310
* @param null|string $handle
259311
* @return int
260312
*/
261-
private function _installPluginByHandle(?string $handle = null): int
313+
private function _installPluginByHandle(?string $handle, ?string $edition = null): int
262314
{
263315
if ($handle === null) {
264316
$handle = $this->_pluginPrompt(
@@ -278,7 +330,7 @@ function(array $info) {
278330
$start = microtime(true);
279331

280332
try {
281-
$success = Craft::$app->getPlugins()->installPlugin($handle);
333+
$success = Craft::$app->getPlugins()->installPlugin($handle, $edition);
282334
} catch (Throwable $e) {
283335
$success = false;
284336
} finally {

0 commit comments

Comments
 (0)