From f772b7b4dd408061c8b1151331b9efc6e2e7b96c Mon Sep 17 00:00:00 2001
From: Joas Schilling <coding@schilljs.com>
Date: Thu, 3 May 2018 16:52:56 +0200
Subject: [PATCH] Add autocomplete to migration commands

Signed-off-by: Joas Schilling <coding@schilljs.com>
---
 core/Command/Db/Migrations/ExecuteCommand.php | 45 ++++++++++++++++++-
 .../Command/Db/Migrations/GenerateCommand.php | 42 ++++++++++++++++-
 .../GenerateFromSchemaFileCommand.php         |  6 +--
 core/Command/Db/Migrations/MigrateCommand.php | 37 ++++++++++++++-
 core/Command/Db/Migrations/StatusCommand.php  | 26 ++++++++++-
 core/register_command.php                     |  4 +-
 6 files changed, 147 insertions(+), 13 deletions(-)

diff --git a/core/Command/Db/Migrations/ExecuteCommand.php b/core/Command/Db/Migrations/ExecuteCommand.php
index 88dfe648090..c3fdc128047 100644
--- a/core/Command/Db/Migrations/ExecuteCommand.php
+++ b/core/Command/Db/Migrations/ExecuteCommand.php
@@ -26,27 +26,35 @@ namespace OC\Core\Command\Db\Migrations;
 
 use OC\DB\MigrationService;
 use OC\Migration\ConsoleOutput;
+use OCP\App\IAppManager;
 use OCP\IConfig;
 use OCP\IDBConnection;
+use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
+use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class ExecuteCommand extends Command {
+class ExecuteCommand extends Command implements CompletionAwareInterface {
 
 	/** @var IDBConnection */
 	private $connection;
+
 	/** @var IConfig */
 	private $config;
 
+	/** @var IAppManager */
+	protected $appManager;
+
 	/**
 	 * ExecuteCommand constructor.
 	 *
 	 * @param IDBConnection $connection
 	 * @param IConfig $config
+	 * @param IAppManager $appManager
 	 */
-	public function __construct(IDBConnection $connection, IConfig $config) {
+	public function __construct(IDBConnection $connection, IAppManager $appManager, IConfig $config) {
 		$this->connection = $connection;
 		$this->config = $config;
 
@@ -88,4 +96,37 @@ class ExecuteCommand extends Command {
 		return 0;
 	}
 
+	/**
+	 * @param string $optionName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeOptionValues($optionName, CompletionContext $context) {
+		return [];
+	}
+
+	/**
+	 * @param string $argumentName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeArgumentValues($argumentName, CompletionContext $context) {
+		if ($argumentName === 'app') {
+			$allApps = \OC_App::getAllApps();
+			return array_diff($allApps, \OC_App::getEnabledApps(true, true));
+		}
+
+		if ($argumentName === 'version') {
+			$appName = $context->getWordAtIndex($context->getWordIndex() - 1);
+
+			$ms = new MigrationService($appName, $this->connection);
+			$migrations = $ms->getAvailableVersions();
+
+			array_unshift($migrations, 'next', 'latest');
+			return $migrations;
+		}
+
+		return [];
+	}
+
 }
diff --git a/core/Command/Db/Migrations/GenerateCommand.php b/core/Command/Db/Migrations/GenerateCommand.php
index e37c51e85fb..50d58a9ea16 100644
--- a/core/Command/Db/Migrations/GenerateCommand.php
+++ b/core/Command/Db/Migrations/GenerateCommand.php
@@ -26,14 +26,17 @@ namespace OC\Core\Command\Db\Migrations;
 
 use OC\DB\MigrationService;
 use OC\Migration\ConsoleOutput;
+use OCP\App\IAppManager;
 use OCP\IDBConnection;
+use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
+use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Exception\RuntimeException;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class GenerateCommand extends Command {
+class GenerateCommand extends Command implements CompletionAwareInterface {
 
 	protected static $_templateSimple =
 		'<?php
@@ -82,11 +85,16 @@ class {{classname}} extends SimpleMigrationStep {
 	/** @var IDBConnection */
 	protected $connection;
 
+	/** @var IAppManager */
+	protected $appManager;
+
 	/**
 	 * @param IDBConnection $connection
+	 * @param IAppManager $appManager
 	 */
-	public function __construct(IDBConnection $connection) {
+	public function __construct(IDBConnection $connection, IAppManager $appManager) {
 		$this->connection = $connection;
+		$this->appManager = $appManager;
 
 		parent::__construct();
 	}
@@ -119,6 +127,36 @@ class {{classname}} extends SimpleMigrationStep {
 		return 0;
 	}
 
+	/**
+	 * @param string $optionName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeOptionValues($optionName, CompletionContext $context) {
+		return [];
+	}
+
+	/**
+	 * @param string $argumentName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeArgumentValues($argumentName, CompletionContext $context) {
+		if ($argumentName === 'app') {
+			$allApps = \OC_App::getAllApps();
+			return array_diff($allApps, \OC_App::getEnabledApps(true, true));
+		}
+
+		if ($argumentName === 'version') {
+			$appName = $context->getWordAtIndex($context->getWordIndex() - 1);
+
+			$version = explode('.', $this->appManager->getAppVersion($appName));
+			return [$version[0] . sprintf('%1$03d', $version[1])];
+		}
+
+		return [];
+	}
+
 	/**
 	 * @param MigrationService $ms
 	 * @param string $className
diff --git a/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
index 3ccaa563e89..e4fb940bb2c 100644
--- a/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
+++ b/core/Command/Db/Migrations/GenerateFromSchemaFileCommand.php
@@ -39,13 +39,9 @@ class GenerateFromSchemaFileCommand extends GenerateCommand {
 	/** @var IConfig */
 	protected $config;
 
-	/** @var IAppManager */
-	protected $appManager;
-
 	public function __construct(IConfig $config, IAppManager $appManager, IDBConnection $connection) {
-		parent::__construct($connection);
+		parent::__construct($connection, $appManager);
 		$this->config = $config;
-		$this->appManager = $appManager;
 	}
 
 
diff --git a/core/Command/Db/Migrations/MigrateCommand.php b/core/Command/Db/Migrations/MigrateCommand.php
index e5dddaebf2d..5a4ca1a6927 100644
--- a/core/Command/Db/Migrations/MigrateCommand.php
+++ b/core/Command/Db/Migrations/MigrateCommand.php
@@ -26,12 +26,14 @@ namespace OC\Core\Command\Db\Migrations;
 use OC\DB\MigrationService;
 use OC\Migration\ConsoleOutput;
 use OCP\IDBConnection;
+use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
+use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class MigrateCommand extends Command {
+class MigrateCommand extends Command implements CompletionAwareInterface {
 
 	/** @var IDBConnection */
 	private $connection;
@@ -62,4 +64,37 @@ class MigrateCommand extends Command {
 		$ms->migrate($version);
 	}
 
+	/**
+	 * @param string $optionName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeOptionValues($optionName, CompletionContext $context) {
+		return [];
+	}
+
+	/**
+	 * @param string $argumentName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeArgumentValues($argumentName, CompletionContext $context) {
+		if ($argumentName === 'app') {
+			$allApps = \OC_App::getAllApps();
+			return array_diff($allApps, \OC_App::getEnabledApps(true, true));
+		}
+
+		if ($argumentName === 'version') {
+			$appName = $context->getWordAtIndex($context->getWordIndex() - 1);
+
+			$ms = new MigrationService($appName, $this->connection);
+			$migrations = $ms->getAvailableVersions();
+
+			array_unshift($migrations, 'next', 'latest');
+			return $migrations;
+		}
+
+		return [];
+	}
+
 }
diff --git a/core/Command/Db/Migrations/StatusCommand.php b/core/Command/Db/Migrations/StatusCommand.php
index 9fa497a126f..1e5f102cea7 100644
--- a/core/Command/Db/Migrations/StatusCommand.php
+++ b/core/Command/Db/Migrations/StatusCommand.php
@@ -25,12 +25,14 @@ namespace OC\Core\Command\Db\Migrations;
 use OC\DB\MigrationService;
 use OC\Migration\ConsoleOutput;
 use OCP\IDBConnection;
+use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
+use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputArgument;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class StatusCommand extends Command {
+class StatusCommand extends Command implements CompletionAwareInterface {
 
 	/** @var IDBConnection */
 	private $connection;
@@ -60,6 +62,28 @@ class StatusCommand extends Command {
 		}
 	}
 
+	/**
+	 * @param string $optionName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeOptionValues($optionName, CompletionContext $context) {
+		return [];
+	}
+
+	/**
+	 * @param string $argumentName
+	 * @param CompletionContext $context
+	 * @return string[]
+	 */
+	public function completeArgumentValues($argumentName, CompletionContext $context) {
+		if ($argumentName === 'app') {
+			$allApps = \OC_App::getAllApps();
+			return array_diff($allApps, \OC_App::getEnabledApps(true, true));
+		}
+		return [];
+	}
+
 	/**
 	 * @param MigrationService $ms
 	 * @return array associative array of human readable info name as key and the actual information as value
diff --git a/core/register_command.php b/core/register_command.php
index 578b4f799b6..93a36c415ee 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -92,9 +92,9 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
 	$application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->getDatabaseConnection()));
 	$application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->getDatabaseConnection()));
 	$application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->getDatabaseConnection()));
-	$application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->getDatabaseConnection()));
+	$application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->getDatabaseConnection(), \OC::$server->getAppManager()));
 	$application->add(new OC\Core\Command\Db\Migrations\GenerateFromSchemaFileCommand(\OC::$server->getConfig(), \OC::$server->getAppManager(), \OC::$server->getDatabaseConnection()));
-	$application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()));
+	$application->add(new OC\Core\Command\Db\Migrations\ExecuteCommand(\OC::$server->getDatabaseConnection(), \OC::$server->getAppManager(), \OC::$server->getConfig()));
 
 	$application->add(new OC\Core\Command\Encryption\Disable(\OC::$server->getConfig()));
 	$application->add(new OC\Core\Command\Encryption\Enable(\OC::$server->getConfig(), \OC::$server->getEncryptionManager()));
-- 
GitLab