setName("update") ->addOption( 'force', 'f', InputOption::VALUE_NONE, 'Force re-fetching the data from remote' ) ->addOption( 'destination', 'd', InputOption::VALUE_OPTIONAL, 'The grav instance location where the updates should be applied to. By default this would be where the grav cli has been launched from', GRAV_ROOT ) ->addOption( 'all-yes', 'y', InputOption::VALUE_NONE, 'Assumes yes (or best approach) instead of prompting' ) ->addOption( 'overwrite', 'o', InputOption::VALUE_NONE, 'Option to overwrite packages if they already exist' ) ->addOption( 'plugins', 'p', InputOption::VALUE_NONE, 'Update only plugins' ) ->addOption( 'themes', 't', InputOption::VALUE_NONE, 'Update only themes' ) ->addArgument( 'package', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'The package or packages that is desired to update. By default all available updates will be applied.' ) ->setDescription("Detects and performs an update of plugins and themes when available") ->setHelp('The update command updates plugins and themes when a new version is available'); } /** * @return int|null|void */ protected function serve() { $this->upgrader = new Upgrader($this->input->getOption('force')); $local = $this->upgrader->getLocalVersion(); $remote = $this->upgrader->getRemoteVersion(); if ($local !== $remote) { $this->output->writeln("WARNING: A new version of Grav is available. You should update Grav before updating plugins and themes. If you continue without updating Grav, some plugins or themes may stop working."); $this->output->writeln(""); $questionHelper = $this->getHelper('question'); $question = new ConfirmationQuestion("Continue with the update process? [Y|n] ", true); $answer = $questionHelper->ask($this->input, $this->output, $question); if (!$answer) { $this->output->writeln("Update aborted. Exiting..."); exit; } } $this->gpm = new GPM($this->input->getOption('force')); $this->all_yes = $this->input->getOption('all-yes'); $this->overwrite = $this->input->getOption('overwrite'); $this->displayGPMRelease(); $this->destination = realpath($this->input->getOption('destination')); if (!Installer::isGravInstance($this->destination)) { $this->output->writeln("ERROR: " . Installer::lastErrorMsg()); exit; } if ($this->input->getOption('plugins') === false && $this->input->getOption('themes') === false) { $list_type = ['plugins' => true, 'themes' => true]; } else { $list_type['plugins'] = $this->input->getOption('plugins'); $list_type['themes'] = $this->input->getOption('themes'); } if ($this->overwrite) { $this->data = $this->gpm->getInstallable($list_type); $description = " can be overwritten"; } else { $this->data = $this->gpm->getUpdatable($list_type); $description = " need updating"; } $only_packages = array_map('strtolower', $this->input->getArgument('package')); if (!$this->overwrite && !$this->data['total']) { $this->output->writeln("Nothing to update."); exit; } $this->output->write("Found " . $this->gpm->countInstalled() . " packages installed of which " . $this->data['total'] . "" . $description); $limit_to = $this->userInputPackages($only_packages); $this->output->writeln(''); unset($this->data['total']); unset($limit_to['total']); // updates review $slugs = []; $index = 0; foreach ($this->data as $packages) { foreach ($packages as $slug => $package) { if (count($limit_to) && !array_key_exists($slug, $limit_to)) { continue; } if (!$package->available) { $package->available = $package->version; } $this->output->writeln( // index str_pad($index++ + 1, 2, '0', STR_PAD_LEFT) . ". " . // name "" . str_pad($package->name, 15) . " " . // version "[v" . $package->version . " -> v" . $package->available . "]" ); $slugs[] = $slug; } } if (!$this->all_yes) { // prompt to continue $this->output->writeln(""); $questionHelper = $this->getHelper('question'); $question = new ConfirmationQuestion("Continue with the update process? [Y|n] ", true); $answer = $questionHelper->ask($this->input, $this->output, $question); if (!$answer) { $this->output->writeln("Update aborted. Exiting..."); exit; } } // finally update $install_command = $this->getApplication()->find('install'); $args = new ArrayInput([ 'command' => 'install', 'package' => $slugs, '-f' => $this->input->getOption('force'), '-d' => $this->destination, '-y' => true ]); $command_exec = $install_command->run($args, $this->output); if ($command_exec != 0) { $this->output->writeln("Error: An error occurred while trying to install the packages"); exit; } } /** * @param $only_packages * * @return array */ private function userInputPackages($only_packages) { $found = ['total' => 0]; $ignore = []; if (!count($only_packages)) { $this->output->writeln(''); } else { foreach ($only_packages as $only_package) { $find = $this->gpm->findPackage($only_package); if (!$find || (!$this->overwrite && !$this->gpm->isUpdatable($find->slug))) { $name = isset($find->slug) ? $find->slug : $only_package; $ignore[$name] = $name; } else { $found[$find->slug] = $find; $found['total']++; } } if ($found['total']) { $list = $found; unset($list['total']); $list = array_keys($list); if ($found['total'] !== $this->data['total']) { $this->output->write(", only " . $found['total'] . " will be updated"); } $this->output->writeln(''); $this->output->writeln("Limiting updates for only " . implode(', ', $list) . ""); } if (count($ignore)) { $this->output->writeln(''); $this->output->writeln("Packages not found or not requiring updates: " . implode(', ', $ignore) . ""); } } return $found; } }