setName("uninstall")
->addOption(
'all-yes',
'y',
InputOption::VALUE_NONE,
'Assumes yes (or best approach) instead of prompting'
)
->addArgument(
'package',
InputArgument::IS_ARRAY | InputArgument::REQUIRED,
'The package(s) that are desired to be removed. Use the "index" command for a list of packages'
)
->setDescription("Performs the uninstallation of plugins and themes")
->setHelp('The uninstall command allows to uninstall plugins and themes');
}
/**
* @return int|null|void
*/
protected function serve()
{
$this->gpm = new GPM();
$this->all_yes = $this->input->getOption('all-yes');
$packages = array_map('strtolower', $this->input->getArgument('package'));
$this->data = ['total' => 0, 'not_found' => []];
foreach ($packages as $package) {
$plugin = $this->gpm->getInstalledPlugin($package);
$theme = $this->gpm->getInstalledTheme($package);
if ($plugin || $theme) {
$this->data[strtolower($package)] = $plugin ?: $theme;
$this->data['total']++;
} else {
$this->data['not_found'][] = $package;
}
}
$this->output->writeln('');
if (!$this->data['total']) {
$this->output->writeln("Nothing to uninstall.");
$this->output->writeln('');
exit;
}
if (count($this->data['not_found'])) {
$this->output->writeln("These packages were not found installed: " . implode(', ',
$this->data['not_found']) . "");
}
unset($this->data['not_found']);
unset($this->data['total']);
foreach ($this->data as $slug => $package) {
$this->output->writeln("Preparing to uninstall " . $package->name . " [v" . $package->version . "]");
$this->output->write(" |- Checking destination... ");
$checks = $this->checkDestination($slug, $package);
if (!$checks) {
$this->output->writeln(" '- Installation failed or aborted.");
$this->output->writeln('');
} else {
$uninstall = $this->uninstallPackage($slug, $package);
if (!$uninstall) {
$this->output->writeln(" '- Uninstallation failed or aborted.");
} else {
$this->output->writeln(" '- Success! ");
}
}
}
// clear cache after successful upgrade
$this->clearCache();
}
/**
* @param $slug
* @param $package
*
* @return bool
*/
private function uninstallPackage($slug, $package, $is_dependency = false)
{
if (!$slug) {
return false;
}
//check if there are packages that have this as a dependency. Abort and show list
$dependent_packages = $this->gpm->getPackagesThatDependOnPackage($slug);
if (count($dependent_packages) > ($is_dependency ? 1 : 0)) {
$this->output->writeln('');
$this->output->writeln('');
$this->output->writeln("Uninstallation failed.");
$this->output->writeln('');
if (count($dependent_packages) > ($is_dependency ? 2 : 1)) {
$this->output->writeln("The installed packages " . implode(', ', $dependent_packages) . " depends on this package. Please remove those first.");
} else {
$this->output->writeln("The installed package " . implode(', ', $dependent_packages) . " depends on this package. Please remove it first.");
}
$this->output->writeln('');
return false;
}
if (isset($package->dependencies)) {
$dependencies = $package->dependencies;
if ($is_dependency) {
foreach ($dependencies as $key => $dependency) {
if (in_array($dependency['name'], $this->dependencies)) {
unset($dependencies[$key]);
}
}
} else {
if (count($dependencies) > 0) {
$this->output->writeln(' `- Dependencies found...');
$this->output->writeln('');
}
}
$questionHelper = $this->getHelper('question');
foreach ($dependencies as $dependency) {
$this->dependencies[] = $dependency['name'];
if (is_array($dependency)) {
$dependency = $dependency['name'];
}
if ($dependency === 'grav') {
continue;
}
$dependencyPackage = $this->gpm->findPackage($dependency);
$dependency_exists = $this->packageExists($dependency, $dependencyPackage);
if ($dependency_exists == Installer::EXISTS) {
$this->output->writeln("A dependency on " . $dependencyPackage->name . " [v" . $dependencyPackage->version . "] was found");
$question = new ConfirmationQuestion(" |- Uninstall " . $dependencyPackage->name . "? [y|N] ", false);
$answer = $this->all_yes ? true : $questionHelper->ask($this->input, $this->output, $question);
if ($answer) {
$uninstall = $this->uninstallPackage($dependency, $dependencyPackage, true);
if (!$uninstall) {
$this->output->writeln(" '- Uninstallation failed or aborted.");
} else {
$this->output->writeln(" '- Success! ");
}
$this->output->writeln('');
} else {
$this->output->writeln(" '- You decided not to uninstall " . $dependencyPackage->name . ".");
$this->output->writeln('');
}
}
}
}
$locator = Grav::instance()['locator'];
$path = $locator->findResource($package->package_type . '://' . $slug);
Installer::uninstall($path);
$errorCode = Installer::lastErrorCode();
if ($errorCode && $errorCode !== Installer::IS_LINK && $errorCode !== Installer::EXISTS) {
$this->output->writeln(" |- Uninstalling " . $package->name . " package... error ");
$this->output->writeln(" | '- " . Installer::lastErrorMsg()."");
return false;
}
$message = Installer::getMessage();
if ($message) {
$this->output->writeln(" |- " . $message);
}
if (!$is_dependency && $this->dependencies) {
$this->output->writeln("Finishing up uninstalling " . $package->name . "");
}
$this->output->writeln(" |- Uninstalling " . $package->name . " package... ok ");
return true;
}
/**
* @param $slug
* @param $package
*
* @return bool
*/
private function checkDestination($slug, $package)
{
$questionHelper = $this->getHelper('question');
$exists = $this->packageExists($slug, $package);
if ($exists == Installer::IS_LINK) {
$this->output->write("\x0D");
$this->output->writeln(" |- Checking destination... symbolic link");
if ($this->all_yes) {
$this->output->writeln(" | '- Skipped automatically.");
return false;
}
$question = new ConfirmationQuestion(" | '- Destination has been detected as symlink, delete symbolic link first? [y|N] ",
false);
$answer = $this->all_yes ? true : $questionHelper->ask($this->input, $this->output, $question);
if (!$answer) {
$this->output->writeln(" | '- You decided not to delete the symlink automatically.");
return false;
}
}
$this->output->write("\x0D");
$this->output->writeln(" |- Checking destination... ok");
return true;
}
/**
* Check if package exists
*
* @param $slug
* @param $package
* @return int
*/
private function packageExists($slug, $package)
{
$path = Grav::instance()['locator']->findResource($package->package_type . '://' . $slug);
Installer::isValidDestination($path);
return Installer::lastErrorCode();
}
}