Passed
Push — master ( ebedbf...47a21f )
by Joas
12:46 queued 18s
created
core/Command/Integrity/SignApp.php 2 patches
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -40,76 +40,76 @@
 block discarded – undo
40 40
  * @package OC\Core\Command\Integrity
41 41
  */
42 42
 class SignApp extends Command {
43
-	/** @var Checker */
44
-	private $checker;
45
-	/** @var FileAccessHelper */
46
-	private $fileAccessHelper;
47
-	/** @var IURLGenerator */
48
-	private $urlGenerator;
43
+    /** @var Checker */
44
+    private $checker;
45
+    /** @var FileAccessHelper */
46
+    private $fileAccessHelper;
47
+    /** @var IURLGenerator */
48
+    private $urlGenerator;
49 49
 
50
-	/**
51
-	 * @param Checker $checker
52
-	 * @param FileAccessHelper $fileAccessHelper
53
-	 * @param IURLGenerator $urlGenerator
54
-	 */
55
-	public function __construct(Checker $checker,
56
-								FileAccessHelper $fileAccessHelper,
57
-								IURLGenerator $urlGenerator) {
58
-		parent::__construct(null);
59
-		$this->checker = $checker;
60
-		$this->fileAccessHelper = $fileAccessHelper;
61
-		$this->urlGenerator = $urlGenerator;
62
-	}
50
+    /**
51
+     * @param Checker $checker
52
+     * @param FileAccessHelper $fileAccessHelper
53
+     * @param IURLGenerator $urlGenerator
54
+     */
55
+    public function __construct(Checker $checker,
56
+                                FileAccessHelper $fileAccessHelper,
57
+                                IURLGenerator $urlGenerator) {
58
+        parent::__construct(null);
59
+        $this->checker = $checker;
60
+        $this->fileAccessHelper = $fileAccessHelper;
61
+        $this->urlGenerator = $urlGenerator;
62
+    }
63 63
 
64
-	protected function configure() {
65
-		$this
66
-			->setName('integrity:sign-app')
67
-			->setDescription('Signs an app using a private key.')
68
-			->addOption('path', null, InputOption::VALUE_REQUIRED, 'Application to sign')
69
-			->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
70
-			->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
71
-	}
64
+    protected function configure() {
65
+        $this
66
+            ->setName('integrity:sign-app')
67
+            ->setDescription('Signs an app using a private key.')
68
+            ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Application to sign')
69
+            ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
70
+            ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing');
71
+    }
72 72
 
73
-	/**
74
-	 * {@inheritdoc }
75
-	 */
76
-	protected function execute(InputInterface $input, OutputInterface $output): int {
77
-		$path = $input->getOption('path');
78
-		$privateKeyPath = $input->getOption('privateKey');
79
-		$keyBundlePath = $input->getOption('certificate');
80
-		if (is_null($path) || is_null($privateKeyPath) || is_null($keyBundlePath)) {
81
-			$documentationUrl = $this->urlGenerator->linkToDocs('developer-code-integrity');
82
-			$output->writeln('This command requires the --path, --privateKey and --certificate.');
83
-			$output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"');
84
-			$output->writeln('For more information please consult the documentation: '. $documentationUrl);
85
-			return 1;
86
-		}
73
+    /**
74
+     * {@inheritdoc }
75
+     */
76
+    protected function execute(InputInterface $input, OutputInterface $output): int {
77
+        $path = $input->getOption('path');
78
+        $privateKeyPath = $input->getOption('privateKey');
79
+        $keyBundlePath = $input->getOption('certificate');
80
+        if (is_null($path) || is_null($privateKeyPath) || is_null($keyBundlePath)) {
81
+            $documentationUrl = $this->urlGenerator->linkToDocs('developer-code-integrity');
82
+            $output->writeln('This command requires the --path, --privateKey and --certificate.');
83
+            $output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"');
84
+            $output->writeln('For more information please consult the documentation: '. $documentationUrl);
85
+            return 1;
86
+        }
87 87
 
88
-		$privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
89
-		$keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
88
+        $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
89
+        $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
90 90
 
91
-		if ($privateKey === false) {
92
-			$output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
93
-			return 1;
94
-		}
91
+        if ($privateKey === false) {
92
+            $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
93
+            return 1;
94
+        }
95 95
 
96
-		if ($keyBundle === false) {
97
-			$output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
98
-			return 1;
99
-		}
96
+        if ($keyBundle === false) {
97
+            $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
98
+            return 1;
99
+        }
100 100
 
101
-		$rsa = new RSA();
102
-		$rsa->loadKey($privateKey);
103
-		$x509 = new X509();
104
-		$x509->loadX509($keyBundle);
105
-		$x509->setPrivateKey($rsa);
106
-		try {
107
-			$this->checker->writeAppSignature($path, $x509, $rsa);
108
-			$output->writeln('Successfully signed "'.$path.'"');
109
-		} catch (\Exception $e) {
110
-			$output->writeln('Error: ' . $e->getMessage());
111
-			return 1;
112
-		}
113
-		return 0;
114
-	}
101
+        $rsa = new RSA();
102
+        $rsa->loadKey($privateKey);
103
+        $x509 = new X509();
104
+        $x509->loadX509($keyBundle);
105
+        $x509->setPrivateKey($rsa);
106
+        try {
107
+            $this->checker->writeAppSignature($path, $x509, $rsa);
108
+            $output->writeln('Successfully signed "'.$path.'"');
109
+        } catch (\Exception $e) {
110
+            $output->writeln('Error: ' . $e->getMessage());
111
+            return 1;
112
+        }
113
+        return 0;
114
+    }
115 115
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
 			$documentationUrl = $this->urlGenerator->linkToDocs('developer-code-integrity');
82 82
 			$output->writeln('This command requires the --path, --privateKey and --certificate.');
83 83
 			$output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"');
84
-			$output->writeln('For more information please consult the documentation: '. $documentationUrl);
84
+			$output->writeln('For more information please consult the documentation: '.$documentationUrl);
85 85
 			return 1;
86 86
 		}
87 87
 
@@ -107,7 +107,7 @@  discard block
 block discarded – undo
107 107
 			$this->checker->writeAppSignature($path, $x509, $rsa);
108 108
 			$output->writeln('Successfully signed "'.$path.'"');
109 109
 		} catch (\Exception $e) {
110
-			$output->writeln('Error: ' . $e->getMessage());
110
+			$output->writeln('Error: '.$e->getMessage());
111 111
 			return 1;
112 112
 		}
113 113
 		return 0;
Please login to merge, or discard this patch.
core/Command/Integrity/CheckCore.php 2 patches
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -36,35 +36,35 @@
 block discarded – undo
36 36
  * @package OC\Core\Command\Integrity
37 37
  */
38 38
 class CheckCore extends Base {
39
-	/**
40
-	 * @var Checker
41
-	 */
42
-	private $checker;
39
+    /**
40
+     * @var Checker
41
+     */
42
+    private $checker;
43 43
 
44
-	public function __construct(Checker $checker) {
45
-		parent::__construct();
46
-		$this->checker = $checker;
47
-	}
44
+    public function __construct(Checker $checker) {
45
+        parent::__construct();
46
+        $this->checker = $checker;
47
+    }
48 48
 
49
-	/**
50
-	 * {@inheritdoc }
51
-	 */
52
-	protected function configure() {
53
-		parent::configure();
54
-		$this
55
-			->setName('integrity:check-core')
56
-			->setDescription('Check integrity of core code using a signature.');
57
-	}
49
+    /**
50
+     * {@inheritdoc }
51
+     */
52
+    protected function configure() {
53
+        parent::configure();
54
+        $this
55
+            ->setName('integrity:check-core')
56
+            ->setDescription('Check integrity of core code using a signature.');
57
+    }
58 58
 
59
-	/**
60
-	 * {@inheritdoc }
61
-	 */
62
-	protected function execute(InputInterface $input, OutputInterface $output): int {
63
-		$result = $this->checker->verifyCoreSignature();
64
-		$this->writeArrayInOutputFormat($input, $output, $result);
65
-		if (count($result)>0) {
66
-			return 1;
67
-		}
68
-		return 0;
69
-	}
59
+    /**
60
+     * {@inheritdoc }
61
+     */
62
+    protected function execute(InputInterface $input, OutputInterface $output): int {
63
+        $result = $this->checker->verifyCoreSignature();
64
+        $this->writeArrayInOutputFormat($input, $output, $result);
65
+        if (count($result)>0) {
66
+            return 1;
67
+        }
68
+        return 0;
69
+    }
70 70
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@
 block discarded – undo
62 62
 	protected function execute(InputInterface $input, OutputInterface $output): int {
63 63
 		$result = $this->checker->verifyCoreSignature();
64 64
 		$this->writeArrayInOutputFormat($input, $output, $result);
65
-		if (count($result)>0) {
65
+		if (count($result) > 0) {
66 66
 			return 1;
67 67
 		}
68 68
 		return 0;
Please login to merge, or discard this patch.
core/Command/Integrity/CheckApp.php 2 patches
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -41,39 +41,39 @@
 block discarded – undo
41 41
  */
42 42
 class CheckApp extends Base {
43 43
 
44
-	/**
45
-	 * @var Checker
46
-	 */
47
-	private $checker;
44
+    /**
45
+     * @var Checker
46
+     */
47
+    private $checker;
48 48
 
49
-	public function __construct(Checker $checker) {
50
-		parent::__construct();
51
-		$this->checker = $checker;
52
-	}
49
+    public function __construct(Checker $checker) {
50
+        parent::__construct();
51
+        $this->checker = $checker;
52
+    }
53 53
 
54
-	/**
55
-	 * {@inheritdoc }
56
-	 */
57
-	protected function configure() {
58
-		parent::configure();
59
-		$this
60
-			->setName('integrity:check-app')
61
-			->setDescription('Check integrity of an app using a signature.')
62
-			->addArgument('appid', InputArgument::REQUIRED, 'Application to check')
63
-			->addOption('path', null, InputOption::VALUE_OPTIONAL, 'Path to application. If none is given it will be guessed.');
64
-	}
54
+    /**
55
+     * {@inheritdoc }
56
+     */
57
+    protected function configure() {
58
+        parent::configure();
59
+        $this
60
+            ->setName('integrity:check-app')
61
+            ->setDescription('Check integrity of an app using a signature.')
62
+            ->addArgument('appid', InputArgument::REQUIRED, 'Application to check')
63
+            ->addOption('path', null, InputOption::VALUE_OPTIONAL, 'Path to application. If none is given it will be guessed.');
64
+    }
65 65
 
66
-	/**
67
-	 * {@inheritdoc }
68
-	 */
69
-	protected function execute(InputInterface $input, OutputInterface $output): int {
70
-		$appid = $input->getArgument('appid');
71
-		$path = (string)$input->getOption('path');
72
-		$result = $this->checker->verifyAppSignature($appid, $path);
73
-		$this->writeArrayInOutputFormat($input, $output, $result);
74
-		if (count($result)>0) {
75
-			return 1;
76
-		}
77
-		return 0;
78
-	}
66
+    /**
67
+     * {@inheritdoc }
68
+     */
69
+    protected function execute(InputInterface $input, OutputInterface $output): int {
70
+        $appid = $input->getArgument('appid');
71
+        $path = (string)$input->getOption('path');
72
+        $result = $this->checker->verifyAppSignature($appid, $path);
73
+        $this->writeArrayInOutputFormat($input, $output, $result);
74
+        if (count($result)>0) {
75
+            return 1;
76
+        }
77
+        return 0;
78
+    }
79 79
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -68,10 +68,10 @@
 block discarded – undo
68 68
 	 */
69 69
 	protected function execute(InputInterface $input, OutputInterface $output): int {
70 70
 		$appid = $input->getArgument('appid');
71
-		$path = (string)$input->getOption('path');
71
+		$path = (string) $input->getOption('path');
72 72
 		$result = $this->checker->verifyAppSignature($appid, $path);
73 73
 		$this->writeArrayInOutputFormat($input, $output, $result);
74
-		if (count($result)>0) {
74
+		if (count($result) > 0) {
75 75
 			return 1;
76 76
 		}
77 77
 		return 0;
Please login to merge, or discard this patch.
core/Command/Integrity/SignCore.php 1 patch
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -39,69 +39,69 @@
 block discarded – undo
39 39
  * @package OC\Core\Command\Integrity
40 40
  */
41 41
 class SignCore extends Command {
42
-	/** @var Checker */
43
-	private $checker;
44
-	/** @var FileAccessHelper */
45
-	private $fileAccessHelper;
42
+    /** @var Checker */
43
+    private $checker;
44
+    /** @var FileAccessHelper */
45
+    private $fileAccessHelper;
46 46
 
47
-	/**
48
-	 * @param Checker $checker
49
-	 * @param FileAccessHelper $fileAccessHelper
50
-	 */
51
-	public function __construct(Checker $checker,
52
-								FileAccessHelper $fileAccessHelper) {
53
-		parent::__construct(null);
54
-		$this->checker = $checker;
55
-		$this->fileAccessHelper = $fileAccessHelper;
56
-	}
47
+    /**
48
+     * @param Checker $checker
49
+     * @param FileAccessHelper $fileAccessHelper
50
+     */
51
+    public function __construct(Checker $checker,
52
+                                FileAccessHelper $fileAccessHelper) {
53
+        parent::__construct(null);
54
+        $this->checker = $checker;
55
+        $this->fileAccessHelper = $fileAccessHelper;
56
+    }
57 57
 
58
-	protected function configure() {
59
-		$this
60
-			->setName('integrity:sign-core')
61
-			->setDescription('Sign core using a private key.')
62
-			->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
63
-			->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing')
64
-			->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign');
65
-	}
58
+    protected function configure() {
59
+        $this
60
+            ->setName('integrity:sign-core')
61
+            ->setDescription('Sign core using a private key.')
62
+            ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing')
63
+            ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing')
64
+            ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign');
65
+    }
66 66
 
67
-	/**
68
-	 * {@inheritdoc }
69
-	 */
70
-	protected function execute(InputInterface $input, OutputInterface $output): int {
71
-		$privateKeyPath = $input->getOption('privateKey');
72
-		$keyBundlePath = $input->getOption('certificate');
73
-		$path = $input->getOption('path');
74
-		if (is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) {
75
-			$output->writeln('--privateKey, --certificate and --path are required.');
76
-			return 1;
77
-		}
67
+    /**
68
+     * {@inheritdoc }
69
+     */
70
+    protected function execute(InputInterface $input, OutputInterface $output): int {
71
+        $privateKeyPath = $input->getOption('privateKey');
72
+        $keyBundlePath = $input->getOption('certificate');
73
+        $path = $input->getOption('path');
74
+        if (is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) {
75
+            $output->writeln('--privateKey, --certificate and --path are required.');
76
+            return 1;
77
+        }
78 78
 
79
-		$privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
80
-		$keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
79
+        $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath);
80
+        $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath);
81 81
 
82
-		if ($privateKey === false) {
83
-			$output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
84
-			return 1;
85
-		}
82
+        if ($privateKey === false) {
83
+            $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath));
84
+            return 1;
85
+        }
86 86
 
87
-		if ($keyBundle === false) {
88
-			$output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
89
-			return 1;
90
-		}
87
+        if ($keyBundle === false) {
88
+            $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath));
89
+            return 1;
90
+        }
91 91
 
92
-		$rsa = new RSA();
93
-		$rsa->loadKey($privateKey);
94
-		$x509 = new X509();
95
-		$x509->loadX509($keyBundle);
96
-		$x509->setPrivateKey($rsa);
92
+        $rsa = new RSA();
93
+        $rsa->loadKey($privateKey);
94
+        $x509 = new X509();
95
+        $x509->loadX509($keyBundle);
96
+        $x509->setPrivateKey($rsa);
97 97
 
98
-		try {
99
-			$this->checker->writeCoreSignature($x509, $rsa, $path);
100
-			$output->writeln('Successfully signed "core"');
101
-		} catch (\Exception $e) {
102
-			$output->writeln('Error: ' . $e->getMessage());
103
-			return 1;
104
-		}
105
-		return 0;
106
-	}
98
+        try {
99
+            $this->checker->writeCoreSignature($x509, $rsa, $path);
100
+            $output->writeln('Successfully signed "core"');
101
+        } catch (\Exception $e) {
102
+            $output->writeln('Error: ' . $e->getMessage());
103
+            return 1;
104
+        }
105
+        return 0;
106
+    }
107 107
 }
Please login to merge, or discard this patch.
core/Command/Background/Base.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -37,40 +37,40 @@
 block discarded – undo
37 37
  * Subclasses will override the getMode() function to specify the mode to configure.
38 38
  */
39 39
 abstract class Base extends Command {
40
-	abstract protected function getMode();
40
+    abstract protected function getMode();
41 41
 
42
-	/**
43
-	 * @var \OCP\IConfig
44
-	 */
45
-	protected $config;
42
+    /**
43
+     * @var \OCP\IConfig
44
+     */
45
+    protected $config;
46 46
 
47
-	/**
48
-	 * @param \OCP\IConfig $config
49
-	 */
50
-	public function __construct(IConfig $config) {
51
-		parent::__construct();
52
-		$this->config = $config;
53
-	}
47
+    /**
48
+     * @param \OCP\IConfig $config
49
+     */
50
+    public function __construct(IConfig $config) {
51
+        parent::__construct();
52
+        $this->config = $config;
53
+    }
54 54
 
55
-	protected function configure() {
56
-		$mode = $this->getMode();
57
-		$this
58
-			->setName("background:$mode")
59
-			->setDescription("Use $mode to run background jobs");
60
-	}
55
+    protected function configure() {
56
+        $mode = $this->getMode();
57
+        $this
58
+            ->setName("background:$mode")
59
+            ->setDescription("Use $mode to run background jobs");
60
+    }
61 61
 
62
-	/**
63
-	 * Executing this command will set the background job mode for owncloud.
64
-	 * The mode to set is specified by the concrete sub class by implementing the
65
-	 * getMode() function.
66
-	 *
67
-	 * @param InputInterface $input
68
-	 * @param OutputInterface $output
69
-	 */
70
-	protected function execute(InputInterface $input, OutputInterface $output): int {
71
-		$mode = $this->getMode();
72
-		$this->config->setAppValue('core', 'backgroundjobs_mode', $mode);
73
-		$output->writeln("Set mode for background jobs to '$mode'");
74
-		return 0;
75
-	}
62
+    /**
63
+     * Executing this command will set the background job mode for owncloud.
64
+     * The mode to set is specified by the concrete sub class by implementing the
65
+     * getMode() function.
66
+     *
67
+     * @param InputInterface $input
68
+     * @param OutputInterface $output
69
+     */
70
+    protected function execute(InputInterface $input, OutputInterface $output): int {
71
+        $mode = $this->getMode();
72
+        $this->config->setAppValue('core', 'backgroundjobs_mode', $mode);
73
+        $output->writeln("Set mode for background jobs to '$mode'");
74
+        return 0;
75
+    }
76 76
 }
Please login to merge, or discard this patch.
core/Command/L10n/CreateJs.php 1 patch
Indentation   +131 added lines, -131 removed lines patch added patch discarded remove patch
@@ -36,135 +36,135 @@
 block discarded – undo
36 36
 use UnexpectedValueException;
37 37
 
38 38
 class CreateJs extends Command implements CompletionAwareInterface {
39
-	protected function configure() {
40
-		$this
41
-			->setName('l10n:createjs')
42
-			->setDescription('Create javascript translation files for a given app')
43
-			->addArgument(
44
-				'app',
45
-				InputOption::VALUE_REQUIRED,
46
-				'name of the app'
47
-			)
48
-			->addArgument(
49
-				'lang',
50
-				InputOption::VALUE_OPTIONAL,
51
-				'name of the language'
52
-			);
53
-	}
54
-
55
-	protected function execute(InputInterface $input, OutputInterface $output): int {
56
-		$app = $input->getArgument('app');
57
-		$lang = $input->getArgument('lang');
58
-
59
-		$path = \OC_App::getAppPath($app);
60
-		if ($path === false) {
61
-			$output->writeln("The app <$app> is unknown.");
62
-			return 1;
63
-		}
64
-		$languages = $lang;
65
-		if (empty($lang)) {
66
-			$languages= $this->getAllLanguages($path);
67
-		}
68
-
69
-		foreach ($languages as $lang) {
70
-			$this->writeFiles($app, $path, $lang, $output);
71
-		}
72
-		return 0;
73
-	}
74
-
75
-	private function getAllLanguages($path) {
76
-		$result = [];
77
-		foreach (new DirectoryIterator("$path/l10n") as $fileInfo) {
78
-			if ($fileInfo->isDot()) {
79
-				continue;
80
-			}
81
-			if ($fileInfo->isDir()) {
82
-				continue;
83
-			}
84
-			if ($fileInfo->getExtension() !== 'php') {
85
-				continue;
86
-			}
87
-			$result[]= substr($fileInfo->getBasename(), 0, -4);
88
-		}
89
-
90
-		return $result;
91
-	}
92
-
93
-	private function writeFiles($app, $path, $lang, OutputInterface $output) {
94
-		list($translations, $plurals) = $this->loadTranslations($path, $lang);
95
-		$this->writeJsFile($app, $path, $lang, $output, $translations, $plurals);
96
-		$this->writeJsonFile($path, $lang, $output, $translations, $plurals);
97
-	}
98
-
99
-	private function writeJsFile($app, $path, $lang, OutputInterface $output, $translations, $plurals) {
100
-		$jsFile = "$path/l10n/$lang.js";
101
-		if (file_exists($jsFile)) {
102
-			$output->writeln("File already exists: $jsFile");
103
-			return;
104
-		}
105
-		$content = "OC.L10N.register(\n    \"$app\",\n    {\n    ";
106
-		$jsTrans = [];
107
-		foreach ($translations as $id => $val) {
108
-			if (is_array($val)) {
109
-				$val = '[ ' . implode(',', $val) . ']';
110
-			}
111
-			$jsTrans[] = "\"$id\" : \"$val\"";
112
-		}
113
-		$content .= implode(",\n    ", $jsTrans);
114
-		$content .= "\n},\n\"$plurals\");\n";
115
-
116
-		file_put_contents($jsFile, $content);
117
-		$output->writeln("Javascript translation file generated: $jsFile");
118
-	}
119
-
120
-	private function writeJsonFile($path, $lang, OutputInterface $output, $translations, $plurals) {
121
-		$jsFile = "$path/l10n/$lang.json";
122
-		if (file_exists($jsFile)) {
123
-			$output->writeln("File already exists: $jsFile");
124
-			return;
125
-		}
126
-		$content = ['translations' => $translations, 'pluralForm' => $plurals];
127
-		file_put_contents($jsFile, json_encode($content));
128
-		$output->writeln("Json translation file generated: $jsFile");
129
-	}
130
-
131
-	private function loadTranslations($path, $lang) {
132
-		$phpFile = "$path/l10n/$lang.php";
133
-		$TRANSLATIONS = [];
134
-		$PLURAL_FORMS = '';
135
-		if (!file_exists($phpFile)) {
136
-			throw new UnexpectedValueException("PHP translation file <$phpFile> does not exist.");
137
-		}
138
-		require $phpFile;
139
-
140
-		return [$TRANSLATIONS, $PLURAL_FORMS];
141
-	}
142
-
143
-	/**
144
-	 * Return possible values for the named option
145
-	 *
146
-	 * @param string $optionName
147
-	 * @param CompletionContext $context
148
-	 * @return string[]
149
-	 */
150
-	public function completeOptionValues($optionName, CompletionContext $context) {
151
-		return [];
152
-	}
153
-
154
-	/**
155
-	 * Return possible values for the named argument
156
-	 *
157
-	 * @param string $argumentName
158
-	 * @param CompletionContext $context
159
-	 * @return string[]
160
-	 */
161
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
162
-		if ($argumentName === 'app') {
163
-			return \OC_App::getAllApps();
164
-		} elseif ($argumentName === 'lang') {
165
-			$appName = $context->getWordAtIndex($context->getWordIndex() - 1);
166
-			return $this->getAllLanguages(\OC_App::getAppPath($appName));
167
-		}
168
-		return [];
169
-	}
39
+    protected function configure() {
40
+        $this
41
+            ->setName('l10n:createjs')
42
+            ->setDescription('Create javascript translation files for a given app')
43
+            ->addArgument(
44
+                'app',
45
+                InputOption::VALUE_REQUIRED,
46
+                'name of the app'
47
+            )
48
+            ->addArgument(
49
+                'lang',
50
+                InputOption::VALUE_OPTIONAL,
51
+                'name of the language'
52
+            );
53
+    }
54
+
55
+    protected function execute(InputInterface $input, OutputInterface $output): int {
56
+        $app = $input->getArgument('app');
57
+        $lang = $input->getArgument('lang');
58
+
59
+        $path = \OC_App::getAppPath($app);
60
+        if ($path === false) {
61
+            $output->writeln("The app <$app> is unknown.");
62
+            return 1;
63
+        }
64
+        $languages = $lang;
65
+        if (empty($lang)) {
66
+            $languages= $this->getAllLanguages($path);
67
+        }
68
+
69
+        foreach ($languages as $lang) {
70
+            $this->writeFiles($app, $path, $lang, $output);
71
+        }
72
+        return 0;
73
+    }
74
+
75
+    private function getAllLanguages($path) {
76
+        $result = [];
77
+        foreach (new DirectoryIterator("$path/l10n") as $fileInfo) {
78
+            if ($fileInfo->isDot()) {
79
+                continue;
80
+            }
81
+            if ($fileInfo->isDir()) {
82
+                continue;
83
+            }
84
+            if ($fileInfo->getExtension() !== 'php') {
85
+                continue;
86
+            }
87
+            $result[]= substr($fileInfo->getBasename(), 0, -4);
88
+        }
89
+
90
+        return $result;
91
+    }
92
+
93
+    private function writeFiles($app, $path, $lang, OutputInterface $output) {
94
+        list($translations, $plurals) = $this->loadTranslations($path, $lang);
95
+        $this->writeJsFile($app, $path, $lang, $output, $translations, $plurals);
96
+        $this->writeJsonFile($path, $lang, $output, $translations, $plurals);
97
+    }
98
+
99
+    private function writeJsFile($app, $path, $lang, OutputInterface $output, $translations, $plurals) {
100
+        $jsFile = "$path/l10n/$lang.js";
101
+        if (file_exists($jsFile)) {
102
+            $output->writeln("File already exists: $jsFile");
103
+            return;
104
+        }
105
+        $content = "OC.L10N.register(\n    \"$app\",\n    {\n    ";
106
+        $jsTrans = [];
107
+        foreach ($translations as $id => $val) {
108
+            if (is_array($val)) {
109
+                $val = '[ ' . implode(',', $val) . ']';
110
+            }
111
+            $jsTrans[] = "\"$id\" : \"$val\"";
112
+        }
113
+        $content .= implode(",\n    ", $jsTrans);
114
+        $content .= "\n},\n\"$plurals\");\n";
115
+
116
+        file_put_contents($jsFile, $content);
117
+        $output->writeln("Javascript translation file generated: $jsFile");
118
+    }
119
+
120
+    private function writeJsonFile($path, $lang, OutputInterface $output, $translations, $plurals) {
121
+        $jsFile = "$path/l10n/$lang.json";
122
+        if (file_exists($jsFile)) {
123
+            $output->writeln("File already exists: $jsFile");
124
+            return;
125
+        }
126
+        $content = ['translations' => $translations, 'pluralForm' => $plurals];
127
+        file_put_contents($jsFile, json_encode($content));
128
+        $output->writeln("Json translation file generated: $jsFile");
129
+    }
130
+
131
+    private function loadTranslations($path, $lang) {
132
+        $phpFile = "$path/l10n/$lang.php";
133
+        $TRANSLATIONS = [];
134
+        $PLURAL_FORMS = '';
135
+        if (!file_exists($phpFile)) {
136
+            throw new UnexpectedValueException("PHP translation file <$phpFile> does not exist.");
137
+        }
138
+        require $phpFile;
139
+
140
+        return [$TRANSLATIONS, $PLURAL_FORMS];
141
+    }
142
+
143
+    /**
144
+     * Return possible values for the named option
145
+     *
146
+     * @param string $optionName
147
+     * @param CompletionContext $context
148
+     * @return string[]
149
+     */
150
+    public function completeOptionValues($optionName, CompletionContext $context) {
151
+        return [];
152
+    }
153
+
154
+    /**
155
+     * Return possible values for the named argument
156
+     *
157
+     * @param string $argumentName
158
+     * @param CompletionContext $context
159
+     * @return string[]
160
+     */
161
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
162
+        if ($argumentName === 'app') {
163
+            return \OC_App::getAllApps();
164
+        } elseif ($argumentName === 'lang') {
165
+            $appName = $context->getWordAtIndex($context->getWordIndex() - 1);
166
+            return $this->getAllLanguages(\OC_App::getAppPath($appName));
167
+        }
168
+        return [];
169
+    }
170 170
 }
Please login to merge, or discard this patch.
core/Command/Db/ConvertFilecacheBigInt.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -38,87 +38,87 @@
 block discarded – undo
38 38
 
39 39
 class ConvertFilecacheBigInt extends Command {
40 40
 
41
-	/** @var IDBConnection */
42
-	private $connection;
43
-
44
-	/**
45
-	 * @param IDBConnection $connection
46
-	 */
47
-	public function __construct(IDBConnection $connection) {
48
-		$this->connection = $connection;
49
-		parent::__construct();
50
-	}
51
-
52
-	protected function configure() {
53
-		$this
54
-			->setName('db:convert-filecache-bigint')
55
-			->setDescription('Convert the ID columns of the filecache to BigInt');
56
-	}
57
-
58
-	protected function getColumnsByTable() {
59
-		// also update in CheckSetupController::hasBigIntConversionPendingColumns()
60
-		return [
61
-			'activity' => ['activity_id', 'object_id'],
62
-			'activity_mq' => ['mail_id'],
63
-			'authtoken' => ['id'],
64
-			'bruteforce_attempts' => ['id'],
65
-			'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
66
-			'file_locks' => ['id'],
67
-			'jobs' => ['id'],
68
-			'mimetypes' => ['id'],
69
-			'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
70
-			'storages' => ['numeric_id'],
71
-		];
72
-	}
73
-
74
-	protected function execute(InputInterface $input, OutputInterface $output): int {
75
-		$schema = new SchemaWrapper($this->connection);
76
-		$isSqlite = $this->connection->getDatabasePlatform() instanceof SqlitePlatform;
77
-		$updates = [];
78
-
79
-		$tables = $this->getColumnsByTable();
80
-		foreach ($tables as $tableName => $columns) {
81
-			if (!$schema->hasTable($tableName)) {
82
-				continue;
83
-			}
84
-
85
-			$table = $schema->getTable($tableName);
86
-
87
-			foreach ($columns as $columnName) {
88
-				$column = $table->getColumn($columnName);
89
-				$isAutoIncrement = $column->getAutoincrement();
90
-				$isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
91
-				if ($column->getType()->getName() !== Type::BIGINT && !$isAutoIncrementOnSqlite) {
92
-					$column->setType(Type::getType(Type::BIGINT));
93
-					$column->setOptions(['length' => 20]);
94
-
95
-					$updates[] = '* ' . $tableName . '.' . $columnName;
96
-				}
97
-			}
98
-		}
99
-
100
-		if (empty($updates)) {
101
-			$output->writeln('<info>All tables already up to date!</info>');
102
-			return 0;
103
-		}
104
-
105
-		$output->writeln('<comment>Following columns will be updated:</comment>');
106
-		$output->writeln('');
107
-		$output->writeln($updates);
108
-		$output->writeln('');
109
-		$output->writeln('<comment>This can take up to hours, depending on the number of files in your instance!</comment>');
110
-
111
-		if ($input->isInteractive()) {
112
-			$helper = $this->getHelper('question');
113
-			$question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', false);
114
-
115
-			if (!$helper->ask($input, $output, $question)) {
116
-				return 1;
117
-			}
118
-		}
119
-
120
-		$this->connection->migrateToSchema($schema->getWrappedSchema());
121
-
122
-		return 0;
123
-	}
41
+    /** @var IDBConnection */
42
+    private $connection;
43
+
44
+    /**
45
+     * @param IDBConnection $connection
46
+     */
47
+    public function __construct(IDBConnection $connection) {
48
+        $this->connection = $connection;
49
+        parent::__construct();
50
+    }
51
+
52
+    protected function configure() {
53
+        $this
54
+            ->setName('db:convert-filecache-bigint')
55
+            ->setDescription('Convert the ID columns of the filecache to BigInt');
56
+    }
57
+
58
+    protected function getColumnsByTable() {
59
+        // also update in CheckSetupController::hasBigIntConversionPendingColumns()
60
+        return [
61
+            'activity' => ['activity_id', 'object_id'],
62
+            'activity_mq' => ['mail_id'],
63
+            'authtoken' => ['id'],
64
+            'bruteforce_attempts' => ['id'],
65
+            'filecache' => ['fileid', 'storage', 'parent', 'mimetype', 'mimepart', 'mtime', 'storage_mtime'],
66
+            'file_locks' => ['id'],
67
+            'jobs' => ['id'],
68
+            'mimetypes' => ['id'],
69
+            'mounts' => ['id', 'storage_id', 'root_id', 'mount_id'],
70
+            'storages' => ['numeric_id'],
71
+        ];
72
+    }
73
+
74
+    protected function execute(InputInterface $input, OutputInterface $output): int {
75
+        $schema = new SchemaWrapper($this->connection);
76
+        $isSqlite = $this->connection->getDatabasePlatform() instanceof SqlitePlatform;
77
+        $updates = [];
78
+
79
+        $tables = $this->getColumnsByTable();
80
+        foreach ($tables as $tableName => $columns) {
81
+            if (!$schema->hasTable($tableName)) {
82
+                continue;
83
+            }
84
+
85
+            $table = $schema->getTable($tableName);
86
+
87
+            foreach ($columns as $columnName) {
88
+                $column = $table->getColumn($columnName);
89
+                $isAutoIncrement = $column->getAutoincrement();
90
+                $isAutoIncrementOnSqlite = $isSqlite && $isAutoIncrement;
91
+                if ($column->getType()->getName() !== Type::BIGINT && !$isAutoIncrementOnSqlite) {
92
+                    $column->setType(Type::getType(Type::BIGINT));
93
+                    $column->setOptions(['length' => 20]);
94
+
95
+                    $updates[] = '* ' . $tableName . '.' . $columnName;
96
+                }
97
+            }
98
+        }
99
+
100
+        if (empty($updates)) {
101
+            $output->writeln('<info>All tables already up to date!</info>');
102
+            return 0;
103
+        }
104
+
105
+        $output->writeln('<comment>Following columns will be updated:</comment>');
106
+        $output->writeln('');
107
+        $output->writeln($updates);
108
+        $output->writeln('');
109
+        $output->writeln('<comment>This can take up to hours, depending on the number of files in your instance!</comment>');
110
+
111
+        if ($input->isInteractive()) {
112
+            $helper = $this->getHelper('question');
113
+            $question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', false);
114
+
115
+            if (!$helper->ask($input, $output, $question)) {
116
+                return 1;
117
+            }
118
+        }
119
+
120
+        $this->connection->migrateToSchema($schema->getWrappedSchema());
121
+
122
+        return 0;
123
+    }
124 124
 }
Please login to merge, or discard this patch.
core/Command/Db/ConvertType.php 1 patch
Indentation   +411 added lines, -411 removed lines patch added patch discarded remove patch
@@ -54,415 +54,415 @@
 block discarded – undo
54 54
 use Symfony\Component\Console\Question\Question;
55 55
 
56 56
 class ConvertType extends Command implements CompletionAwareInterface {
57
-	/**
58
-	 * @var \OCP\IConfig
59
-	 */
60
-	protected $config;
61
-
62
-	/**
63
-	 * @var \OC\DB\ConnectionFactory
64
-	 */
65
-	protected $connectionFactory;
66
-
67
-	/** @var array */
68
-	protected $columnTypes;
69
-
70
-	/**
71
-	 * @param \OCP\IConfig $config
72
-	 * @param \OC\DB\ConnectionFactory $connectionFactory
73
-	 */
74
-	public function __construct(IConfig $config, ConnectionFactory $connectionFactory) {
75
-		$this->config = $config;
76
-		$this->connectionFactory = $connectionFactory;
77
-		parent::__construct();
78
-	}
79
-
80
-	protected function configure() {
81
-		$this
82
-			->setName('db:convert-type')
83
-			->setDescription('Convert the Nextcloud database to the newly configured one')
84
-			->addArgument(
85
-				'type',
86
-				InputArgument::REQUIRED,
87
-				'the type of the database to convert to'
88
-			)
89
-			->addArgument(
90
-				'username',
91
-				InputArgument::REQUIRED,
92
-				'the username of the database to convert to'
93
-			)
94
-			->addArgument(
95
-				'hostname',
96
-				InputArgument::REQUIRED,
97
-				'the hostname of the database to convert to'
98
-			)
99
-			->addArgument(
100
-				'database',
101
-				InputArgument::REQUIRED,
102
-				'the name of the database to convert to'
103
-			)
104
-			->addOption(
105
-				'port',
106
-				null,
107
-				InputOption::VALUE_REQUIRED,
108
-				'the port of the database to convert to'
109
-			)
110
-			->addOption(
111
-				'password',
112
-				null,
113
-				InputOption::VALUE_REQUIRED,
114
-				'the password of the database to convert to. Will be asked when not specified. Can also be passed via stdin.'
115
-			)
116
-			->addOption(
117
-				'clear-schema',
118
-				null,
119
-				InputOption::VALUE_NONE,
120
-				'remove all tables from the destination database'
121
-			)
122
-			->addOption(
123
-				'all-apps',
124
-				null,
125
-				InputOption::VALUE_NONE,
126
-				'whether to create schema for all apps instead of only installed apps'
127
-			)
128
-			->addOption(
129
-				'chunk-size',
130
-				null,
131
-				InputOption::VALUE_REQUIRED,
132
-				'the maximum number of database rows to handle in a single query, bigger tables will be handled in chunks of this size. Lower this if the process runs out of memory during conversion.',
133
-				1000
134
-			)
135
-		;
136
-	}
137
-
138
-	protected function validateInput(InputInterface $input, OutputInterface $output) {
139
-		$type = $this->connectionFactory->normalizeType($input->getArgument('type'));
140
-		if ($type === 'sqlite3') {
141
-			throw new \InvalidArgumentException(
142
-				'Converting to SQLite (sqlite3) is currently not supported.'
143
-			);
144
-		}
145
-		if ($type === $this->config->getSystemValue('dbtype', '')) {
146
-			throw new \InvalidArgumentException(sprintf(
147
-				'Can not convert from %1$s to %1$s.',
148
-				$type
149
-			));
150
-		}
151
-		if ($type === 'oci' && $input->getOption('clear-schema')) {
152
-			// Doctrine unconditionally tries (at least in version 2.3)
153
-			// to drop sequence triggers when dropping a table, even though
154
-			// such triggers may not exist. This results in errors like
155
-			// "ORA-04080: trigger 'OC_STORAGES_AI_PK' does not exist".
156
-			throw new \InvalidArgumentException(
157
-				'The --clear-schema option is not supported when converting to Oracle (oci).'
158
-			);
159
-		}
160
-	}
161
-
162
-	protected function readPassword(InputInterface $input, OutputInterface $output) {
163
-		// Explicitly specified password
164
-		if ($input->getOption('password')) {
165
-			return;
166
-		}
167
-
168
-		// Read from stdin. stream_set_blocking is used to prevent blocking
169
-		// when nothing is passed via stdin.
170
-		stream_set_blocking(STDIN, 0);
171
-		$password = file_get_contents('php://stdin');
172
-		stream_set_blocking(STDIN, 1);
173
-		if (trim($password) !== '') {
174
-			$input->setOption('password', $password);
175
-			return;
176
-		}
177
-
178
-		// Read password by interacting
179
-		if ($input->isInteractive()) {
180
-			/** @var QuestionHelper $helper */
181
-			$helper = $this->getHelper('question');
182
-			$question = new Question('What is the database password?');
183
-			$question->setHidden(true);
184
-			$question->setHiddenFallback(false);
185
-			$password = $helper->ask($input, $output, $question);
186
-			$input->setOption('password', $password);
187
-			return;
188
-		}
189
-	}
190
-
191
-	protected function execute(InputInterface $input, OutputInterface $output): int {
192
-		$this->validateInput($input, $output);
193
-		$this->readPassword($input, $output);
194
-
195
-		$fromDB = \OC::$server->getDatabaseConnection();
196
-		$toDB = $this->getToDBConnection($input, $output);
197
-
198
-		if ($input->getOption('clear-schema')) {
199
-			$this->clearSchema($toDB, $input, $output);
200
-		}
201
-
202
-		$this->createSchema($fromDB, $toDB, $input, $output);
203
-
204
-		$toTables = $this->getTables($toDB);
205
-		$fromTables = $this->getTables($fromDB);
206
-
207
-		// warn/fail if there are more tables in 'from' database
208
-		$extraFromTables = array_diff($fromTables, $toTables);
209
-		if (!empty($extraFromTables)) {
210
-			$output->writeln('<comment>The following tables will not be converted:</comment>');
211
-			$output->writeln($extraFromTables);
212
-			if (!$input->getOption('all-apps')) {
213
-				$output->writeln('<comment>Please note that tables belonging to available but currently not installed apps</comment>');
214
-				$output->writeln('<comment>can be included by specifying the --all-apps option.</comment>');
215
-			}
216
-
217
-			$continueConversion = !$input->isInteractive(); // assume yes for --no-interaction and no otherwise.
218
-			$question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', $continueConversion);
219
-
220
-			/** @var QuestionHelper $helper */
221
-			$helper = $this->getHelper('question');
222
-
223
-			if (!$helper->ask($input, $output, $question)) {
224
-				return 1;
225
-			}
226
-		}
227
-		$intersectingTables = array_intersect($toTables, $fromTables);
228
-		$this->convertDB($fromDB, $toDB, $intersectingTables, $input, $output);
229
-		return 0;
230
-	}
231
-
232
-	protected function createSchema(Connection $fromDB, Connection $toDB, InputInterface $input, OutputInterface $output) {
233
-		$output->writeln('<info>Creating schema in new database</info>');
234
-
235
-		$fromMS = new MigrationService('core', $fromDB);
236
-		$currentMigration = $fromMS->getMigration('current');
237
-		if ($currentMigration !== '0') {
238
-			$toMS = new MigrationService('core', $toDB);
239
-			$toMS->migrate($currentMigration);
240
-		}
241
-
242
-		$schemaManager = new \OC\DB\MDB2SchemaManager($toDB);
243
-		$apps = $input->getOption('all-apps') ? \OC_App::getAllApps() : \OC_App::getEnabledApps();
244
-		foreach ($apps as $app) {
245
-			if (file_exists(\OC_App::getAppPath($app).'/appinfo/database.xml')) {
246
-				$schemaManager->createDbFromStructure(\OC_App::getAppPath($app).'/appinfo/database.xml');
247
-			} else {
248
-				// Make sure autoloading works...
249
-				\OC_App::loadApp($app);
250
-				$fromMS = new MigrationService($app, $fromDB);
251
-				$currentMigration = $fromMS->getMigration('current');
252
-				if ($currentMigration !== '0') {
253
-					$toMS = new MigrationService($app, $toDB);
254
-					$toMS->migrate($currentMigration, true);
255
-				}
256
-			}
257
-		}
258
-	}
259
-
260
-	protected function getToDBConnection(InputInterface $input, OutputInterface $output) {
261
-		$type = $input->getArgument('type');
262
-		$connectionParams = $this->connectionFactory->createConnectionParams();
263
-		$connectionParams = array_merge($connectionParams, [
264
-			'host' => $input->getArgument('hostname'),
265
-			'user' => $input->getArgument('username'),
266
-			'password' => $input->getOption('password'),
267
-			'dbname' => $input->getArgument('database'),
268
-		]);
269
-		if ($input->getOption('port')) {
270
-			$connectionParams['port'] = $input->getOption('port');
271
-		}
272
-		return $this->connectionFactory->getConnection($type, $connectionParams);
273
-	}
274
-
275
-	protected function clearSchema(Connection $db, InputInterface $input, OutputInterface $output) {
276
-		$toTables = $this->getTables($db);
277
-		if (!empty($toTables)) {
278
-			$output->writeln('<info>Clearing schema in new database</info>');
279
-		}
280
-		foreach ($toTables as $table) {
281
-			$db->getSchemaManager()->dropTable($table);
282
-		}
283
-	}
284
-
285
-	protected function getTables(Connection $db) {
286
-		$filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
287
-		$db->getConfiguration()->
288
-			setFilterSchemaAssetsExpression($filterExpression);
289
-		return $db->getSchemaManager()->listTableNames();
290
-	}
291
-
292
-	/**
293
-	 * @param Connection $fromDB
294
-	 * @param Connection $toDB
295
-	 * @param Table $table
296
-	 * @param InputInterface $input
297
-	 * @param OutputInterface $output
298
-	 * @suppress SqlInjectionChecker
299
-	 */
300
-	protected function copyTable(Connection $fromDB, Connection $toDB, Table $table, InputInterface $input, OutputInterface $output) {
301
-		if ($table->getName() === $toDB->getPrefix() . 'migrations') {
302
-			$output->writeln('<comment>Skipping migrations table because it was already filled by running the migrations</comment>');
303
-			return;
304
-		}
305
-
306
-		$chunkSize = $input->getOption('chunk-size');
307
-
308
-		$query = $fromDB->getQueryBuilder();
309
-		$query->automaticTablePrefix(false);
310
-		$query->select($query->func()->count('*', 'num_entries'))
311
-			->from($table->getName());
312
-		$result = $query->execute();
313
-		$count = $result->fetchColumn();
314
-		$result->closeCursor();
315
-
316
-		$numChunks = ceil($count/$chunkSize);
317
-		if ($numChunks > 1) {
318
-			$output->writeln('chunked query, ' . $numChunks . ' chunks');
319
-		}
320
-
321
-		$progress = new ProgressBar($output, $count);
322
-		$progress->start();
323
-		$redraw = $count > $chunkSize ? 100 : ($count > 100 ? 5 : 1);
324
-		$progress->setRedrawFrequency($redraw);
325
-
326
-		$query = $fromDB->getQueryBuilder();
327
-		$query->automaticTablePrefix(false);
328
-		$query->select('*')
329
-			->from($table->getName())
330
-			->setMaxResults($chunkSize);
331
-
332
-		try {
333
-			$orderColumns = $table->getPrimaryKeyColumns();
334
-		} catch (DBALException $e) {
335
-			$orderColumns = [];
336
-			foreach ($table->getColumns() as $column) {
337
-				$orderColumns[] = $column->getName();
338
-			}
339
-		}
340
-
341
-		foreach ($orderColumns as $column) {
342
-			$query->addOrderBy($column);
343
-		}
344
-
345
-		$insertQuery = $toDB->getQueryBuilder();
346
-		$insertQuery->automaticTablePrefix(false);
347
-		$insertQuery->insert($table->getName());
348
-		$parametersCreated = false;
349
-
350
-		for ($chunk = 0; $chunk < $numChunks; $chunk++) {
351
-			$query->setFirstResult($chunk * $chunkSize);
352
-
353
-			$result = $query->execute();
354
-
355
-			while ($row = $result->fetch()) {
356
-				$progress->advance();
357
-				if (!$parametersCreated) {
358
-					foreach ($row as $key => $value) {
359
-						$insertQuery->setValue($key, $insertQuery->createParameter($key));
360
-					}
361
-					$parametersCreated = true;
362
-				}
363
-
364
-				foreach ($row as $key => $value) {
365
-					$type = $this->getColumnType($table, $key);
366
-					if ($type !== false) {
367
-						$insertQuery->setParameter($key, $value, $type);
368
-					} else {
369
-						$insertQuery->setParameter($key, $value);
370
-					}
371
-				}
372
-				$insertQuery->execute();
373
-			}
374
-			$result->closeCursor();
375
-		}
376
-		$progress->finish();
377
-	}
378
-
379
-	protected function getColumnType(Table $table, $columnName) {
380
-		$tableName = $table->getName();
381
-		if (isset($this->columnTypes[$tableName][$columnName])) {
382
-			return $this->columnTypes[$tableName][$columnName];
383
-		}
384
-
385
-		$type = $table->getColumn($columnName)->getType()->getName();
386
-
387
-		switch ($type) {
388
-			case Type::BLOB:
389
-			case Type::TEXT:
390
-				$this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_LOB;
391
-				break;
392
-			case Type::BOOLEAN:
393
-				$this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_BOOL;
394
-				break;
395
-			default:
396
-				$this->columnTypes[$tableName][$columnName] = false;
397
-		}
398
-
399
-		return $this->columnTypes[$tableName][$columnName];
400
-	}
401
-
402
-	protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) {
403
-		$this->config->setSystemValue('maintenance', true);
404
-		$schema = $fromDB->createSchema();
405
-
406
-		try {
407
-			// copy table rows
408
-			foreach ($tables as $table) {
409
-				$output->writeln($table);
410
-				$this->copyTable($fromDB, $toDB, $schema->getTable($table), $input, $output);
411
-			}
412
-			if ($input->getArgument('type') === 'pgsql') {
413
-				$tools = new \OC\DB\PgSqlTools($this->config);
414
-				$tools->resynchronizeDatabaseSequences($toDB);
415
-			}
416
-			// save new database config
417
-			$this->saveDBInfo($input);
418
-		} catch (\Exception $e) {
419
-			$this->config->setSystemValue('maintenance', false);
420
-			throw $e;
421
-		}
422
-		$this->config->setSystemValue('maintenance', false);
423
-	}
424
-
425
-	protected function saveDBInfo(InputInterface $input) {
426
-		$type = $input->getArgument('type');
427
-		$username = $input->getArgument('username');
428
-		$dbHost = $input->getArgument('hostname');
429
-		$dbName = $input->getArgument('database');
430
-		$password = $input->getOption('password');
431
-		if ($input->getOption('port')) {
432
-			$dbHost .= ':'.$input->getOption('port');
433
-		}
434
-
435
-		$this->config->setSystemValues([
436
-			'dbtype'		=> $type,
437
-			'dbname'		=> $dbName,
438
-			'dbhost'		=> $dbHost,
439
-			'dbuser'		=> $username,
440
-			'dbpassword'	=> $password,
441
-		]);
442
-	}
443
-
444
-	/**
445
-	 * Return possible values for the named option
446
-	 *
447
-	 * @param string $optionName
448
-	 * @param CompletionContext $context
449
-	 * @return string[]
450
-	 */
451
-	public function completeOptionValues($optionName, CompletionContext $context) {
452
-		return [];
453
-	}
454
-
455
-	/**
456
-	 * Return possible values for the named argument
457
-	 *
458
-	 * @param string $argumentName
459
-	 * @param CompletionContext $context
460
-	 * @return string[]
461
-	 */
462
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
463
-		if ($argumentName === 'type') {
464
-			return ['mysql', 'oci', 'pgsql'];
465
-		}
466
-		return [];
467
-	}
57
+    /**
58
+     * @var \OCP\IConfig
59
+     */
60
+    protected $config;
61
+
62
+    /**
63
+     * @var \OC\DB\ConnectionFactory
64
+     */
65
+    protected $connectionFactory;
66
+
67
+    /** @var array */
68
+    protected $columnTypes;
69
+
70
+    /**
71
+     * @param \OCP\IConfig $config
72
+     * @param \OC\DB\ConnectionFactory $connectionFactory
73
+     */
74
+    public function __construct(IConfig $config, ConnectionFactory $connectionFactory) {
75
+        $this->config = $config;
76
+        $this->connectionFactory = $connectionFactory;
77
+        parent::__construct();
78
+    }
79
+
80
+    protected function configure() {
81
+        $this
82
+            ->setName('db:convert-type')
83
+            ->setDescription('Convert the Nextcloud database to the newly configured one')
84
+            ->addArgument(
85
+                'type',
86
+                InputArgument::REQUIRED,
87
+                'the type of the database to convert to'
88
+            )
89
+            ->addArgument(
90
+                'username',
91
+                InputArgument::REQUIRED,
92
+                'the username of the database to convert to'
93
+            )
94
+            ->addArgument(
95
+                'hostname',
96
+                InputArgument::REQUIRED,
97
+                'the hostname of the database to convert to'
98
+            )
99
+            ->addArgument(
100
+                'database',
101
+                InputArgument::REQUIRED,
102
+                'the name of the database to convert to'
103
+            )
104
+            ->addOption(
105
+                'port',
106
+                null,
107
+                InputOption::VALUE_REQUIRED,
108
+                'the port of the database to convert to'
109
+            )
110
+            ->addOption(
111
+                'password',
112
+                null,
113
+                InputOption::VALUE_REQUIRED,
114
+                'the password of the database to convert to. Will be asked when not specified. Can also be passed via stdin.'
115
+            )
116
+            ->addOption(
117
+                'clear-schema',
118
+                null,
119
+                InputOption::VALUE_NONE,
120
+                'remove all tables from the destination database'
121
+            )
122
+            ->addOption(
123
+                'all-apps',
124
+                null,
125
+                InputOption::VALUE_NONE,
126
+                'whether to create schema for all apps instead of only installed apps'
127
+            )
128
+            ->addOption(
129
+                'chunk-size',
130
+                null,
131
+                InputOption::VALUE_REQUIRED,
132
+                'the maximum number of database rows to handle in a single query, bigger tables will be handled in chunks of this size. Lower this if the process runs out of memory during conversion.',
133
+                1000
134
+            )
135
+        ;
136
+    }
137
+
138
+    protected function validateInput(InputInterface $input, OutputInterface $output) {
139
+        $type = $this->connectionFactory->normalizeType($input->getArgument('type'));
140
+        if ($type === 'sqlite3') {
141
+            throw new \InvalidArgumentException(
142
+                'Converting to SQLite (sqlite3) is currently not supported.'
143
+            );
144
+        }
145
+        if ($type === $this->config->getSystemValue('dbtype', '')) {
146
+            throw new \InvalidArgumentException(sprintf(
147
+                'Can not convert from %1$s to %1$s.',
148
+                $type
149
+            ));
150
+        }
151
+        if ($type === 'oci' && $input->getOption('clear-schema')) {
152
+            // Doctrine unconditionally tries (at least in version 2.3)
153
+            // to drop sequence triggers when dropping a table, even though
154
+            // such triggers may not exist. This results in errors like
155
+            // "ORA-04080: trigger 'OC_STORAGES_AI_PK' does not exist".
156
+            throw new \InvalidArgumentException(
157
+                'The --clear-schema option is not supported when converting to Oracle (oci).'
158
+            );
159
+        }
160
+    }
161
+
162
+    protected function readPassword(InputInterface $input, OutputInterface $output) {
163
+        // Explicitly specified password
164
+        if ($input->getOption('password')) {
165
+            return;
166
+        }
167
+
168
+        // Read from stdin. stream_set_blocking is used to prevent blocking
169
+        // when nothing is passed via stdin.
170
+        stream_set_blocking(STDIN, 0);
171
+        $password = file_get_contents('php://stdin');
172
+        stream_set_blocking(STDIN, 1);
173
+        if (trim($password) !== '') {
174
+            $input->setOption('password', $password);
175
+            return;
176
+        }
177
+
178
+        // Read password by interacting
179
+        if ($input->isInteractive()) {
180
+            /** @var QuestionHelper $helper */
181
+            $helper = $this->getHelper('question');
182
+            $question = new Question('What is the database password?');
183
+            $question->setHidden(true);
184
+            $question->setHiddenFallback(false);
185
+            $password = $helper->ask($input, $output, $question);
186
+            $input->setOption('password', $password);
187
+            return;
188
+        }
189
+    }
190
+
191
+    protected function execute(InputInterface $input, OutputInterface $output): int {
192
+        $this->validateInput($input, $output);
193
+        $this->readPassword($input, $output);
194
+
195
+        $fromDB = \OC::$server->getDatabaseConnection();
196
+        $toDB = $this->getToDBConnection($input, $output);
197
+
198
+        if ($input->getOption('clear-schema')) {
199
+            $this->clearSchema($toDB, $input, $output);
200
+        }
201
+
202
+        $this->createSchema($fromDB, $toDB, $input, $output);
203
+
204
+        $toTables = $this->getTables($toDB);
205
+        $fromTables = $this->getTables($fromDB);
206
+
207
+        // warn/fail if there are more tables in 'from' database
208
+        $extraFromTables = array_diff($fromTables, $toTables);
209
+        if (!empty($extraFromTables)) {
210
+            $output->writeln('<comment>The following tables will not be converted:</comment>');
211
+            $output->writeln($extraFromTables);
212
+            if (!$input->getOption('all-apps')) {
213
+                $output->writeln('<comment>Please note that tables belonging to available but currently not installed apps</comment>');
214
+                $output->writeln('<comment>can be included by specifying the --all-apps option.</comment>');
215
+            }
216
+
217
+            $continueConversion = !$input->isInteractive(); // assume yes for --no-interaction and no otherwise.
218
+            $question = new ConfirmationQuestion('Continue with the conversion (y/n)? [n] ', $continueConversion);
219
+
220
+            /** @var QuestionHelper $helper */
221
+            $helper = $this->getHelper('question');
222
+
223
+            if (!$helper->ask($input, $output, $question)) {
224
+                return 1;
225
+            }
226
+        }
227
+        $intersectingTables = array_intersect($toTables, $fromTables);
228
+        $this->convertDB($fromDB, $toDB, $intersectingTables, $input, $output);
229
+        return 0;
230
+    }
231
+
232
+    protected function createSchema(Connection $fromDB, Connection $toDB, InputInterface $input, OutputInterface $output) {
233
+        $output->writeln('<info>Creating schema in new database</info>');
234
+
235
+        $fromMS = new MigrationService('core', $fromDB);
236
+        $currentMigration = $fromMS->getMigration('current');
237
+        if ($currentMigration !== '0') {
238
+            $toMS = new MigrationService('core', $toDB);
239
+            $toMS->migrate($currentMigration);
240
+        }
241
+
242
+        $schemaManager = new \OC\DB\MDB2SchemaManager($toDB);
243
+        $apps = $input->getOption('all-apps') ? \OC_App::getAllApps() : \OC_App::getEnabledApps();
244
+        foreach ($apps as $app) {
245
+            if (file_exists(\OC_App::getAppPath($app).'/appinfo/database.xml')) {
246
+                $schemaManager->createDbFromStructure(\OC_App::getAppPath($app).'/appinfo/database.xml');
247
+            } else {
248
+                // Make sure autoloading works...
249
+                \OC_App::loadApp($app);
250
+                $fromMS = new MigrationService($app, $fromDB);
251
+                $currentMigration = $fromMS->getMigration('current');
252
+                if ($currentMigration !== '0') {
253
+                    $toMS = new MigrationService($app, $toDB);
254
+                    $toMS->migrate($currentMigration, true);
255
+                }
256
+            }
257
+        }
258
+    }
259
+
260
+    protected function getToDBConnection(InputInterface $input, OutputInterface $output) {
261
+        $type = $input->getArgument('type');
262
+        $connectionParams = $this->connectionFactory->createConnectionParams();
263
+        $connectionParams = array_merge($connectionParams, [
264
+            'host' => $input->getArgument('hostname'),
265
+            'user' => $input->getArgument('username'),
266
+            'password' => $input->getOption('password'),
267
+            'dbname' => $input->getArgument('database'),
268
+        ]);
269
+        if ($input->getOption('port')) {
270
+            $connectionParams['port'] = $input->getOption('port');
271
+        }
272
+        return $this->connectionFactory->getConnection($type, $connectionParams);
273
+    }
274
+
275
+    protected function clearSchema(Connection $db, InputInterface $input, OutputInterface $output) {
276
+        $toTables = $this->getTables($db);
277
+        if (!empty($toTables)) {
278
+            $output->writeln('<info>Clearing schema in new database</info>');
279
+        }
280
+        foreach ($toTables as $table) {
281
+            $db->getSchemaManager()->dropTable($table);
282
+        }
283
+    }
284
+
285
+    protected function getTables(Connection $db) {
286
+        $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/';
287
+        $db->getConfiguration()->
288
+            setFilterSchemaAssetsExpression($filterExpression);
289
+        return $db->getSchemaManager()->listTableNames();
290
+    }
291
+
292
+    /**
293
+     * @param Connection $fromDB
294
+     * @param Connection $toDB
295
+     * @param Table $table
296
+     * @param InputInterface $input
297
+     * @param OutputInterface $output
298
+     * @suppress SqlInjectionChecker
299
+     */
300
+    protected function copyTable(Connection $fromDB, Connection $toDB, Table $table, InputInterface $input, OutputInterface $output) {
301
+        if ($table->getName() === $toDB->getPrefix() . 'migrations') {
302
+            $output->writeln('<comment>Skipping migrations table because it was already filled by running the migrations</comment>');
303
+            return;
304
+        }
305
+
306
+        $chunkSize = $input->getOption('chunk-size');
307
+
308
+        $query = $fromDB->getQueryBuilder();
309
+        $query->automaticTablePrefix(false);
310
+        $query->select($query->func()->count('*', 'num_entries'))
311
+            ->from($table->getName());
312
+        $result = $query->execute();
313
+        $count = $result->fetchColumn();
314
+        $result->closeCursor();
315
+
316
+        $numChunks = ceil($count/$chunkSize);
317
+        if ($numChunks > 1) {
318
+            $output->writeln('chunked query, ' . $numChunks . ' chunks');
319
+        }
320
+
321
+        $progress = new ProgressBar($output, $count);
322
+        $progress->start();
323
+        $redraw = $count > $chunkSize ? 100 : ($count > 100 ? 5 : 1);
324
+        $progress->setRedrawFrequency($redraw);
325
+
326
+        $query = $fromDB->getQueryBuilder();
327
+        $query->automaticTablePrefix(false);
328
+        $query->select('*')
329
+            ->from($table->getName())
330
+            ->setMaxResults($chunkSize);
331
+
332
+        try {
333
+            $orderColumns = $table->getPrimaryKeyColumns();
334
+        } catch (DBALException $e) {
335
+            $orderColumns = [];
336
+            foreach ($table->getColumns() as $column) {
337
+                $orderColumns[] = $column->getName();
338
+            }
339
+        }
340
+
341
+        foreach ($orderColumns as $column) {
342
+            $query->addOrderBy($column);
343
+        }
344
+
345
+        $insertQuery = $toDB->getQueryBuilder();
346
+        $insertQuery->automaticTablePrefix(false);
347
+        $insertQuery->insert($table->getName());
348
+        $parametersCreated = false;
349
+
350
+        for ($chunk = 0; $chunk < $numChunks; $chunk++) {
351
+            $query->setFirstResult($chunk * $chunkSize);
352
+
353
+            $result = $query->execute();
354
+
355
+            while ($row = $result->fetch()) {
356
+                $progress->advance();
357
+                if (!$parametersCreated) {
358
+                    foreach ($row as $key => $value) {
359
+                        $insertQuery->setValue($key, $insertQuery->createParameter($key));
360
+                    }
361
+                    $parametersCreated = true;
362
+                }
363
+
364
+                foreach ($row as $key => $value) {
365
+                    $type = $this->getColumnType($table, $key);
366
+                    if ($type !== false) {
367
+                        $insertQuery->setParameter($key, $value, $type);
368
+                    } else {
369
+                        $insertQuery->setParameter($key, $value);
370
+                    }
371
+                }
372
+                $insertQuery->execute();
373
+            }
374
+            $result->closeCursor();
375
+        }
376
+        $progress->finish();
377
+    }
378
+
379
+    protected function getColumnType(Table $table, $columnName) {
380
+        $tableName = $table->getName();
381
+        if (isset($this->columnTypes[$tableName][$columnName])) {
382
+            return $this->columnTypes[$tableName][$columnName];
383
+        }
384
+
385
+        $type = $table->getColumn($columnName)->getType()->getName();
386
+
387
+        switch ($type) {
388
+            case Type::BLOB:
389
+            case Type::TEXT:
390
+                $this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_LOB;
391
+                break;
392
+            case Type::BOOLEAN:
393
+                $this->columnTypes[$tableName][$columnName] = IQueryBuilder::PARAM_BOOL;
394
+                break;
395
+            default:
396
+                $this->columnTypes[$tableName][$columnName] = false;
397
+        }
398
+
399
+        return $this->columnTypes[$tableName][$columnName];
400
+    }
401
+
402
+    protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) {
403
+        $this->config->setSystemValue('maintenance', true);
404
+        $schema = $fromDB->createSchema();
405
+
406
+        try {
407
+            // copy table rows
408
+            foreach ($tables as $table) {
409
+                $output->writeln($table);
410
+                $this->copyTable($fromDB, $toDB, $schema->getTable($table), $input, $output);
411
+            }
412
+            if ($input->getArgument('type') === 'pgsql') {
413
+                $tools = new \OC\DB\PgSqlTools($this->config);
414
+                $tools->resynchronizeDatabaseSequences($toDB);
415
+            }
416
+            // save new database config
417
+            $this->saveDBInfo($input);
418
+        } catch (\Exception $e) {
419
+            $this->config->setSystemValue('maintenance', false);
420
+            throw $e;
421
+        }
422
+        $this->config->setSystemValue('maintenance', false);
423
+    }
424
+
425
+    protected function saveDBInfo(InputInterface $input) {
426
+        $type = $input->getArgument('type');
427
+        $username = $input->getArgument('username');
428
+        $dbHost = $input->getArgument('hostname');
429
+        $dbName = $input->getArgument('database');
430
+        $password = $input->getOption('password');
431
+        if ($input->getOption('port')) {
432
+            $dbHost .= ':'.$input->getOption('port');
433
+        }
434
+
435
+        $this->config->setSystemValues([
436
+            'dbtype'		=> $type,
437
+            'dbname'		=> $dbName,
438
+            'dbhost'		=> $dbHost,
439
+            'dbuser'		=> $username,
440
+            'dbpassword'	=> $password,
441
+        ]);
442
+    }
443
+
444
+    /**
445
+     * Return possible values for the named option
446
+     *
447
+     * @param string $optionName
448
+     * @param CompletionContext $context
449
+     * @return string[]
450
+     */
451
+    public function completeOptionValues($optionName, CompletionContext $context) {
452
+        return [];
453
+    }
454
+
455
+    /**
456
+     * Return possible values for the named argument
457
+     *
458
+     * @param string $argumentName
459
+     * @param CompletionContext $context
460
+     * @return string[]
461
+     */
462
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
463
+        if ($argumentName === 'type') {
464
+            return ['mysql', 'oci', 'pgsql'];
465
+        }
466
+        return [];
467
+    }
468 468
 }
Please login to merge, or discard this patch.
core/Command/Db/ConvertMysqlToMB4.php 1 patch
Indentation   +45 added lines, -45 removed lines patch added patch discarded remove patch
@@ -36,59 +36,59 @@
 block discarded – undo
36 36
 use Symfony\Component\Console\Output\OutputInterface;
37 37
 
38 38
 class ConvertMysqlToMB4 extends Command {
39
-	/** @var IConfig */
40
-	private $config;
39
+    /** @var IConfig */
40
+    private $config;
41 41
 
42
-	/** @var IDBConnection */
43
-	private $connection;
42
+    /** @var IDBConnection */
43
+    private $connection;
44 44
 
45
-	/** @var IURLGenerator */
46
-	private $urlGenerator;
45
+    /** @var IURLGenerator */
46
+    private $urlGenerator;
47 47
 
48
-	/** @var ILogger */
49
-	private $logger;
48
+    /** @var ILogger */
49
+    private $logger;
50 50
 
51
-	/**
52
-	 * @param IConfig $config
53
-	 * @param IDBConnection $connection
54
-	 * @param IURLGenerator $urlGenerator
55
-	 * @param ILogger $logger
56
-	 */
57
-	public function __construct(IConfig $config, IDBConnection $connection, IURLGenerator $urlGenerator, ILogger $logger) {
58
-		$this->config = $config;
59
-		$this->connection = $connection;
60
-		$this->urlGenerator = $urlGenerator;
61
-		$this->logger = $logger;
62
-		parent::__construct();
63
-	}
51
+    /**
52
+     * @param IConfig $config
53
+     * @param IDBConnection $connection
54
+     * @param IURLGenerator $urlGenerator
55
+     * @param ILogger $logger
56
+     */
57
+    public function __construct(IConfig $config, IDBConnection $connection, IURLGenerator $urlGenerator, ILogger $logger) {
58
+        $this->config = $config;
59
+        $this->connection = $connection;
60
+        $this->urlGenerator = $urlGenerator;
61
+        $this->logger = $logger;
62
+        parent::__construct();
63
+    }
64 64
 
65
-	protected function configure() {
66
-		$this
67
-			->setName('db:convert-mysql-charset')
68
-			->setDescription('Convert charset of MySQL/MariaDB to use utf8mb4');
69
-	}
65
+    protected function configure() {
66
+        $this
67
+            ->setName('db:convert-mysql-charset')
68
+            ->setDescription('Convert charset of MySQL/MariaDB to use utf8mb4');
69
+    }
70 70
 
71
-	protected function execute(InputInterface $input, OutputInterface $output): int {
72
-		if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
73
-			$output->writeln("This command is only valid for MySQL/MariaDB databases.");
74
-			return 1;
75
-		}
71
+    protected function execute(InputInterface $input, OutputInterface $output): int {
72
+        if (!$this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
73
+            $output->writeln("This command is only valid for MySQL/MariaDB databases.");
74
+            return 1;
75
+        }
76 76
 
77
-		$tools = new MySqlTools();
78
-		if (!$tools->supports4ByteCharset($this->connection)) {
79
-			$url = $this->urlGenerator->linkToDocs('admin-mysql-utf8mb4');
80
-			$output->writeln("The database is not properly setup to use the charset utf8mb4.");
81
-			$output->writeln("For more information please read the documentation at $url");
82
-			return 1;
83
-		}
77
+        $tools = new MySqlTools();
78
+        if (!$tools->supports4ByteCharset($this->connection)) {
79
+            $url = $this->urlGenerator->linkToDocs('admin-mysql-utf8mb4');
80
+            $output->writeln("The database is not properly setup to use the charset utf8mb4.");
81
+            $output->writeln("For more information please read the documentation at $url");
82
+            return 1;
83
+        }
84 84
 
85
-		// enable charset
86
-		$this->config->setSystemValue('mysql.utf8mb4', true);
85
+        // enable charset
86
+        $this->config->setSystemValue('mysql.utf8mb4', true);
87 87
 
88
-		// run conversion
89
-		$coll = new Collation($this->config, $this->logger, $this->connection, false);
90
-		$coll->run(new ConsoleOutput($output));
88
+        // run conversion
89
+        $coll = new Collation($this->config, $this->logger, $this->connection, false);
90
+        $coll->run(new ConsoleOutput($output));
91 91
 
92
-		return 0;
93
-	}
92
+        return 0;
93
+    }
94 94
 }
Please login to merge, or discard this patch.