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(); } }