Completed
Push — master ( abced2...d161e0 )
by Maxence
34:21 queued 29s
created
lib/private/Repair/ConfigKeyMigration.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -14,16 +14,16 @@
 block discarded – undo
14 14
 use OCP\Migration\IRepairStep;
15 15
 
16 16
 class ConfigKeyMigration implements IRepairStep {
17
-	public function __construct(
18
-		private ConfigManager $configManager,
19
-	) {
20
-	}
17
+    public function __construct(
18
+        private ConfigManager $configManager,
19
+    ) {
20
+    }
21 21
 
22
-	public function getName(): string {
23
-		return 'Migrate config keys';
24
-	}
22
+    public function getName(): string {
23
+        return 'Migrate config keys';
24
+    }
25 25
 
26
-	public function run(IOutput $output) {
27
-		$this->configManager->migrateConfigLexiconKeys();
28
-	}
26
+    public function run(IOutput $output) {
27
+        $this->configManager->migrateConfigLexiconKeys();
28
+    }
29 29
 }
Please login to merge, or discard this patch.
core/Command/Config/App/Base.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -12,27 +12,27 @@
 block discarded – undo
12 12
 use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
13 13
 
14 14
 abstract class Base extends \OC\Core\Command\Base {
15
-	public function __construct(
16
-		protected IAppConfig $appConfig,
17
-		protected readonly ConfigManager $configManager,
18
-	) {
19
-		parent::__construct();
20
-	}
15
+    public function __construct(
16
+        protected IAppConfig $appConfig,
17
+        protected readonly ConfigManager $configManager,
18
+    ) {
19
+        parent::__construct();
20
+    }
21 21
 
22
-	/**
23
-	 * @param string $argumentName
24
-	 * @param CompletionContext $context
25
-	 * @return string[]
26
-	 */
27
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
28
-		if ($argumentName === 'app') {
29
-			return $this->appConfig->getApps();
30
-		}
22
+    /**
23
+     * @param string $argumentName
24
+     * @param CompletionContext $context
25
+     * @return string[]
26
+     */
27
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
28
+        if ($argumentName === 'app') {
29
+            return $this->appConfig->getApps();
30
+        }
31 31
 
32
-		if ($argumentName === 'name') {
33
-			$appName = $context->getWordAtIndex($context->getWordIndex() - 1);
34
-			return $this->appConfig->getKeys($appName);
35
-		}
36
-		return [];
37
-	}
32
+        if ($argumentName === 'name') {
33
+            $appName = $context->getWordAtIndex($context->getWordIndex() - 1);
34
+            return $this->appConfig->getKeys($appName);
35
+        }
36
+        return [];
37
+    }
38 38
 }
Please login to merge, or discard this patch.
core/Command/Config/App/SetConfig.php 2 patches
Indentation   +211 added lines, -211 removed lines patch added patch discarded remove patch
@@ -19,215 +19,215 @@
 block discarded – undo
19 19
 use Symfony\Component\Console\Question\Question;
20 20
 
21 21
 class SetConfig extends Base {
22
-	protected function configure() {
23
-		parent::configure();
24
-
25
-		$this
26
-			->setName('config:app:set')
27
-			->setDescription('Set an app config value')
28
-			->addArgument(
29
-				'app',
30
-				InputArgument::REQUIRED,
31
-				'Name of the app'
32
-			)
33
-			->addArgument(
34
-				'name',
35
-				InputArgument::REQUIRED,
36
-				'Name of the config to set'
37
-			)
38
-			->addOption(
39
-				'value',
40
-				null,
41
-				InputOption::VALUE_REQUIRED,
42
-				'The new value of the config'
43
-			)
44
-			->addOption(
45
-				'type',
46
-				null,
47
-				InputOption::VALUE_REQUIRED,
48
-				'Value type [string, integer, float, boolean, array]',
49
-				'string'
50
-			)
51
-			->addOption(
52
-				'lazy',
53
-				null,
54
-				InputOption::VALUE_NEGATABLE,
55
-				'Set value as lazy loaded',
56
-			)
57
-			->addOption(
58
-				'sensitive',
59
-				null,
60
-				InputOption::VALUE_NEGATABLE,
61
-				'Set value as sensitive',
62
-			)
63
-			->addOption(
64
-				'update-only',
65
-				null,
66
-				InputOption::VALUE_NONE,
67
-				'Only updates the value, if it is not set before, it is not being added'
68
-			)
69
-		;
70
-	}
71
-
72
-	protected function execute(InputInterface $input, OutputInterface $output): int {
73
-		$appName = $input->getArgument('app');
74
-		$configName = $input->getArgument('name');
75
-
76
-		if (!($this->appConfig instanceof AppConfig)) {
77
-			throw new \Exception('Only compatible with OC\AppConfig as it uses internal methods');
78
-		}
79
-
80
-		if ($input->hasParameterOption('--update-only') && !$this->appConfig->hasKey($appName, $configName)) {
81
-			$output->writeln(
82
-				'<comment>Config value ' . $configName . ' for app ' . $appName
83
-				. ' not updated, as it has not been set before.</comment>'
84
-			);
85
-
86
-			return 1;
87
-		}
88
-
89
-		$type = $typeString = null;
90
-		if ($input->hasParameterOption('--type')) {
91
-			$typeString = $input->getOption('type');
92
-			$type = $this->appConfig->convertTypeToInt($typeString);
93
-		}
94
-
95
-		/**
96
-		 * If --Value is not specified, returns an exception if no value exists in database
97
-		 * compare with current status in database and displays a reminder that this can break things.
98
-		 * confirmation is required by admin, unless --no-interaction
99
-		 */
100
-		$updated = false;
101
-		if (!$input->hasParameterOption('--value')) {
102
-			if (!$input->getOption('lazy') && $this->appConfig->isLazy($appName, $configName) && $this->ask($input, $output, 'NOT LAZY')) {
103
-				$updated = $this->appConfig->updateLazy($appName, $configName, false);
104
-			}
105
-			if ($input->getOption('lazy') && !$this->appConfig->isLazy($appName, $configName) && $this->ask($input, $output, 'LAZY')) {
106
-				$updated = $this->appConfig->updateLazy($appName, $configName, true) || $updated;
107
-			}
108
-			if (!$input->getOption('sensitive') && $this->appConfig->isSensitive($appName, $configName) && $this->ask($input, $output, 'NOT SENSITIVE')) {
109
-				$updated = $this->appConfig->updateSensitive($appName, $configName, false) || $updated;
110
-			}
111
-			if ($input->getOption('sensitive') && !$this->appConfig->isSensitive($appName, $configName) && $this->ask($input, $output, 'SENSITIVE')) {
112
-				$updated = $this->appConfig->updateSensitive($appName, $configName, true) || $updated;
113
-			}
114
-			if ($type !== null && $type !== $this->appConfig->getValueType($appName, $configName) && $typeString !== null && $this->ask($input, $output, $typeString)) {
115
-				$updated = $this->appConfig->updateType($appName, $configName, $type) || $updated;
116
-			}
117
-		} else {
118
-			/**
119
-			 * If --type is specified in the command line, we upgrade the type in database
120
-			 * after a confirmation from admin.
121
-			 * If not we get the type from current stored value or VALUE_MIXED as default.
122
-			 */
123
-			try {
124
-				$currType = $this->appConfig->getValueType($appName, $configName);
125
-				if ($type === null || $typeString === null || $type === $currType || !$this->ask($input, $output, $typeString)) {
126
-					$type = $currType;
127
-				} else {
128
-					$updated = $this->appConfig->updateType($appName, $configName, $type);
129
-				}
130
-			} catch (AppConfigUnknownKeyException) {
131
-				$type = $type ?? IAppConfig::VALUE_MIXED;
132
-			}
133
-
134
-			/**
135
-			 * if --lazy/--no-lazy option are set, compare with data stored in database.
136
-			 * If no data in database, or identical, continue.
137
-			 * If different, ask admin for confirmation.
138
-			 */
139
-			$lazy = $input->getOption('lazy');
140
-			try {
141
-				$currLazy = $this->appConfig->isLazy($appName, $configName);
142
-				if ($lazy === null || $lazy === $currLazy || !$this->ask($input, $output, ($lazy) ? 'LAZY' : 'NOT LAZY')) {
143
-					$lazy = $currLazy;
144
-				}
145
-			} catch (AppConfigUnknownKeyException) {
146
-				$lazy = $lazy ?? false;
147
-			}
148
-
149
-			/**
150
-			 * same with sensitive status
151
-			 */
152
-			$sensitive = $input->getOption('sensitive');
153
-			try {
154
-				$currSensitive = $this->appConfig->isSensitive($appName, $configName, null);
155
-				if ($sensitive === null || $sensitive === $currSensitive || !$this->ask($input, $output, ($sensitive) ? 'SENSITIVE' : 'NOT SENSITIVE')) {
156
-					$sensitive = $currSensitive;
157
-				}
158
-			} catch (AppConfigUnknownKeyException) {
159
-				$sensitive = $sensitive ?? false;
160
-			}
161
-
162
-			$value = (string)$input->getOption('value');
163
-			switch ($type) {
164
-				case IAppConfig::VALUE_MIXED:
165
-					$updated = $this->appConfig->setValueMixed($appName, $configName, $value, $lazy, $sensitive);
166
-					break;
167
-
168
-				case IAppConfig::VALUE_STRING:
169
-					$updated = $this->appConfig->setValueString($appName, $configName, $value, $lazy, $sensitive);
170
-					break;
171
-
172
-				case IAppConfig::VALUE_INT:
173
-					$updated = $this->appConfig->setValueInt($appName, $configName, $this->configManager->convertToInt($value), $lazy, $sensitive);
174
-					break;
175
-
176
-				case IAppConfig::VALUE_FLOAT:
177
-					$updated = $this->appConfig->setValueFloat($appName, $configName, $this->configManager->convertToFloat($value), $lazy, $sensitive);
178
-					break;
179
-
180
-				case IAppConfig::VALUE_BOOL:
181
-					$updated = $this->appConfig->setValueBool($appName, $configName, $this->configManager->convertToBool($value), $lazy);
182
-					break;
183
-
184
-				case IAppConfig::VALUE_ARRAY:
185
-					$updated = $this->appConfig->setValueArray($appName, $configName, $this->configManager->convertToArray($value), $lazy, $sensitive);
186
-					break;
187
-			}
188
-		}
189
-
190
-		if ($updated) {
191
-			$current = $this->appConfig->getDetails($appName, $configName);
192
-			$output->writeln(
193
-				sprintf(
194
-					"<info>Config value '%s' for app '%s' is now set to '%s', stored as %s in %s</info>",
195
-					$configName,
196
-					$appName,
197
-					$current['sensitive'] ? '<sensitive>' : $current['value'],
198
-					$current['typeString'],
199
-					$current['lazy'] ? 'lazy cache' : 'fast cache'
200
-				)
201
-			);
202
-		} else {
203
-			$output->writeln('<info>Config value were not updated</info>');
204
-		}
205
-
206
-		return 0;
207
-	}
208
-
209
-	private function ask(InputInterface $input, OutputInterface $output, string $request): bool {
210
-		/** @var QuestionHelper $helper */
211
-		$helper = $this->getHelper('question');
212
-		if ($input->getOption('no-interaction')) {
213
-			return true;
214
-		}
215
-
216
-		$output->writeln(sprintf('You are about to set config value %s as <info>%s</info>',
217
-			'<info>' . $input->getArgument('app') . '</info>/<info>' . $input->getArgument('name') . '</info>',
218
-			strtoupper($request)
219
-		));
220
-		$output->writeln('');
221
-		$output->writeln('<comment>This might break thing, affect performance on your instance or its security!</comment>');
222
-
223
-		$result = (strtolower((string)$helper->ask(
224
-			$input,
225
-			$output,
226
-			new Question('<comment>Confirm this action by typing \'yes\'</comment>: '))) === 'yes');
227
-
228
-		$output->writeln(($result) ? 'done' : 'cancelled');
229
-		$output->writeln('');
230
-
231
-		return $result;
232
-	}
22
+    protected function configure() {
23
+        parent::configure();
24
+
25
+        $this
26
+            ->setName('config:app:set')
27
+            ->setDescription('Set an app config value')
28
+            ->addArgument(
29
+                'app',
30
+                InputArgument::REQUIRED,
31
+                'Name of the app'
32
+            )
33
+            ->addArgument(
34
+                'name',
35
+                InputArgument::REQUIRED,
36
+                'Name of the config to set'
37
+            )
38
+            ->addOption(
39
+                'value',
40
+                null,
41
+                InputOption::VALUE_REQUIRED,
42
+                'The new value of the config'
43
+            )
44
+            ->addOption(
45
+                'type',
46
+                null,
47
+                InputOption::VALUE_REQUIRED,
48
+                'Value type [string, integer, float, boolean, array]',
49
+                'string'
50
+            )
51
+            ->addOption(
52
+                'lazy',
53
+                null,
54
+                InputOption::VALUE_NEGATABLE,
55
+                'Set value as lazy loaded',
56
+            )
57
+            ->addOption(
58
+                'sensitive',
59
+                null,
60
+                InputOption::VALUE_NEGATABLE,
61
+                'Set value as sensitive',
62
+            )
63
+            ->addOption(
64
+                'update-only',
65
+                null,
66
+                InputOption::VALUE_NONE,
67
+                'Only updates the value, if it is not set before, it is not being added'
68
+            )
69
+        ;
70
+    }
71
+
72
+    protected function execute(InputInterface $input, OutputInterface $output): int {
73
+        $appName = $input->getArgument('app');
74
+        $configName = $input->getArgument('name');
75
+
76
+        if (!($this->appConfig instanceof AppConfig)) {
77
+            throw new \Exception('Only compatible with OC\AppConfig as it uses internal methods');
78
+        }
79
+
80
+        if ($input->hasParameterOption('--update-only') && !$this->appConfig->hasKey($appName, $configName)) {
81
+            $output->writeln(
82
+                '<comment>Config value ' . $configName . ' for app ' . $appName
83
+                . ' not updated, as it has not been set before.</comment>'
84
+            );
85
+
86
+            return 1;
87
+        }
88
+
89
+        $type = $typeString = null;
90
+        if ($input->hasParameterOption('--type')) {
91
+            $typeString = $input->getOption('type');
92
+            $type = $this->appConfig->convertTypeToInt($typeString);
93
+        }
94
+
95
+        /**
96
+         * If --Value is not specified, returns an exception if no value exists in database
97
+         * compare with current status in database and displays a reminder that this can break things.
98
+         * confirmation is required by admin, unless --no-interaction
99
+         */
100
+        $updated = false;
101
+        if (!$input->hasParameterOption('--value')) {
102
+            if (!$input->getOption('lazy') && $this->appConfig->isLazy($appName, $configName) && $this->ask($input, $output, 'NOT LAZY')) {
103
+                $updated = $this->appConfig->updateLazy($appName, $configName, false);
104
+            }
105
+            if ($input->getOption('lazy') && !$this->appConfig->isLazy($appName, $configName) && $this->ask($input, $output, 'LAZY')) {
106
+                $updated = $this->appConfig->updateLazy($appName, $configName, true) || $updated;
107
+            }
108
+            if (!$input->getOption('sensitive') && $this->appConfig->isSensitive($appName, $configName) && $this->ask($input, $output, 'NOT SENSITIVE')) {
109
+                $updated = $this->appConfig->updateSensitive($appName, $configName, false) || $updated;
110
+            }
111
+            if ($input->getOption('sensitive') && !$this->appConfig->isSensitive($appName, $configName) && $this->ask($input, $output, 'SENSITIVE')) {
112
+                $updated = $this->appConfig->updateSensitive($appName, $configName, true) || $updated;
113
+            }
114
+            if ($type !== null && $type !== $this->appConfig->getValueType($appName, $configName) && $typeString !== null && $this->ask($input, $output, $typeString)) {
115
+                $updated = $this->appConfig->updateType($appName, $configName, $type) || $updated;
116
+            }
117
+        } else {
118
+            /**
119
+             * If --type is specified in the command line, we upgrade the type in database
120
+             * after a confirmation from admin.
121
+             * If not we get the type from current stored value or VALUE_MIXED as default.
122
+             */
123
+            try {
124
+                $currType = $this->appConfig->getValueType($appName, $configName);
125
+                if ($type === null || $typeString === null || $type === $currType || !$this->ask($input, $output, $typeString)) {
126
+                    $type = $currType;
127
+                } else {
128
+                    $updated = $this->appConfig->updateType($appName, $configName, $type);
129
+                }
130
+            } catch (AppConfigUnknownKeyException) {
131
+                $type = $type ?? IAppConfig::VALUE_MIXED;
132
+            }
133
+
134
+            /**
135
+             * if --lazy/--no-lazy option are set, compare with data stored in database.
136
+             * If no data in database, or identical, continue.
137
+             * If different, ask admin for confirmation.
138
+             */
139
+            $lazy = $input->getOption('lazy');
140
+            try {
141
+                $currLazy = $this->appConfig->isLazy($appName, $configName);
142
+                if ($lazy === null || $lazy === $currLazy || !$this->ask($input, $output, ($lazy) ? 'LAZY' : 'NOT LAZY')) {
143
+                    $lazy = $currLazy;
144
+                }
145
+            } catch (AppConfigUnknownKeyException) {
146
+                $lazy = $lazy ?? false;
147
+            }
148
+
149
+            /**
150
+             * same with sensitive status
151
+             */
152
+            $sensitive = $input->getOption('sensitive');
153
+            try {
154
+                $currSensitive = $this->appConfig->isSensitive($appName, $configName, null);
155
+                if ($sensitive === null || $sensitive === $currSensitive || !$this->ask($input, $output, ($sensitive) ? 'SENSITIVE' : 'NOT SENSITIVE')) {
156
+                    $sensitive = $currSensitive;
157
+                }
158
+            } catch (AppConfigUnknownKeyException) {
159
+                $sensitive = $sensitive ?? false;
160
+            }
161
+
162
+            $value = (string)$input->getOption('value');
163
+            switch ($type) {
164
+                case IAppConfig::VALUE_MIXED:
165
+                    $updated = $this->appConfig->setValueMixed($appName, $configName, $value, $lazy, $sensitive);
166
+                    break;
167
+
168
+                case IAppConfig::VALUE_STRING:
169
+                    $updated = $this->appConfig->setValueString($appName, $configName, $value, $lazy, $sensitive);
170
+                    break;
171
+
172
+                case IAppConfig::VALUE_INT:
173
+                    $updated = $this->appConfig->setValueInt($appName, $configName, $this->configManager->convertToInt($value), $lazy, $sensitive);
174
+                    break;
175
+
176
+                case IAppConfig::VALUE_FLOAT:
177
+                    $updated = $this->appConfig->setValueFloat($appName, $configName, $this->configManager->convertToFloat($value), $lazy, $sensitive);
178
+                    break;
179
+
180
+                case IAppConfig::VALUE_BOOL:
181
+                    $updated = $this->appConfig->setValueBool($appName, $configName, $this->configManager->convertToBool($value), $lazy);
182
+                    break;
183
+
184
+                case IAppConfig::VALUE_ARRAY:
185
+                    $updated = $this->appConfig->setValueArray($appName, $configName, $this->configManager->convertToArray($value), $lazy, $sensitive);
186
+                    break;
187
+            }
188
+        }
189
+
190
+        if ($updated) {
191
+            $current = $this->appConfig->getDetails($appName, $configName);
192
+            $output->writeln(
193
+                sprintf(
194
+                    "<info>Config value '%s' for app '%s' is now set to '%s', stored as %s in %s</info>",
195
+                    $configName,
196
+                    $appName,
197
+                    $current['sensitive'] ? '<sensitive>' : $current['value'],
198
+                    $current['typeString'],
199
+                    $current['lazy'] ? 'lazy cache' : 'fast cache'
200
+                )
201
+            );
202
+        } else {
203
+            $output->writeln('<info>Config value were not updated</info>');
204
+        }
205
+
206
+        return 0;
207
+    }
208
+
209
+    private function ask(InputInterface $input, OutputInterface $output, string $request): bool {
210
+        /** @var QuestionHelper $helper */
211
+        $helper = $this->getHelper('question');
212
+        if ($input->getOption('no-interaction')) {
213
+            return true;
214
+        }
215
+
216
+        $output->writeln(sprintf('You are about to set config value %s as <info>%s</info>',
217
+            '<info>' . $input->getArgument('app') . '</info>/<info>' . $input->getArgument('name') . '</info>',
218
+            strtoupper($request)
219
+        ));
220
+        $output->writeln('');
221
+        $output->writeln('<comment>This might break thing, affect performance on your instance or its security!</comment>');
222
+
223
+        $result = (strtolower((string)$helper->ask(
224
+            $input,
225
+            $output,
226
+            new Question('<comment>Confirm this action by typing \'yes\'</comment>: '))) === 'yes');
227
+
228
+        $output->writeln(($result) ? 'done' : 'cancelled');
229
+        $output->writeln('');
230
+
231
+        return $result;
232
+    }
233 233
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
 
80 80
 		if ($input->hasParameterOption('--update-only') && !$this->appConfig->hasKey($appName, $configName)) {
81 81
 			$output->writeln(
82
-				'<comment>Config value ' . $configName . ' for app ' . $appName
82
+				'<comment>Config value '.$configName.' for app '.$appName
83 83
 				. ' not updated, as it has not been set before.</comment>'
84 84
 			);
85 85
 
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
 				$sensitive = $sensitive ?? false;
160 160
 			}
161 161
 
162
-			$value = (string)$input->getOption('value');
162
+			$value = (string) $input->getOption('value');
163 163
 			switch ($type) {
164 164
 				case IAppConfig::VALUE_MIXED:
165 165
 					$updated = $this->appConfig->setValueMixed($appName, $configName, $value, $lazy, $sensitive);
@@ -214,13 +214,13 @@  discard block
 block discarded – undo
214 214
 		}
215 215
 
216 216
 		$output->writeln(sprintf('You are about to set config value %s as <info>%s</info>',
217
-			'<info>' . $input->getArgument('app') . '</info>/<info>' . $input->getArgument('name') . '</info>',
217
+			'<info>'.$input->getArgument('app').'</info>/<info>'.$input->getArgument('name').'</info>',
218 218
 			strtoupper($request)
219 219
 		));
220 220
 		$output->writeln('');
221 221
 		$output->writeln('<comment>This might break thing, affect performance on your instance or its security!</comment>');
222 222
 
223
-		$result = (strtolower((string)$helper->ask(
223
+		$result = (strtolower((string) $helper->ask(
224 224
 			$input,
225 225
 			$output,
226 226
 			new Question('<comment>Confirm this action by typing \'yes\'</comment>: '))) === 'yes');
Please login to merge, or discard this patch.
core/Command/Config/ListConfigs.php 1 patch
Indentation   +124 added lines, -124 removed lines patch added patch discarded remove patch
@@ -18,128 +18,128 @@
 block discarded – undo
18 18
 use Symfony\Component\Console\Output\OutputInterface;
19 19
 
20 20
 class ListConfigs extends Base {
21
-	protected string $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY;
22
-
23
-	public function __construct(
24
-		protected SystemConfig $systemConfig,
25
-		protected IAppConfig $appConfig,
26
-		protected ConfigManager $configManager,
27
-	) {
28
-		parent::__construct();
29
-	}
30
-
31
-	protected function configure() {
32
-		parent::configure();
33
-
34
-		$this
35
-			->setName('config:list')
36
-			->setDescription('List all configs')
37
-			->addArgument(
38
-				'app',
39
-				InputArgument::OPTIONAL,
40
-				'Name of the app ("system" to get the config.php values, "all" for all apps and system)',
41
-				'all'
42
-			)
43
-			->addOption(
44
-				'private',
45
-				null,
46
-				InputOption::VALUE_NONE,
47
-				'Use this option when you want to include sensitive configs like passwords, salts, ...'
48
-			)
49
-			->addOption('migrate', null, InputOption::VALUE_NONE, 'Rename config keys of all enabled apps, based on ConfigLexicon')
50
-		;
51
-	}
52
-
53
-	protected function execute(InputInterface $input, OutputInterface $output): int {
54
-		$app = $input->getArgument('app');
55
-		$noSensitiveValues = !$input->getOption('private');
56
-
57
-		if ($input->getOption('migrate')) {
58
-			$this->configManager->migrateConfigLexiconKeys(($app === 'all') ? null : $app);
59
-		}
60
-
61
-		if (!is_string($app)) {
62
-			$output->writeln('<error>Invalid app value given</error>');
63
-			return 1;
64
-		}
65
-
66
-		switch ($app) {
67
-			case 'system':
68
-				$configs = [
69
-					'system' => $this->getSystemConfigs($noSensitiveValues),
70
-				];
71
-				break;
72
-
73
-			case 'all':
74
-				$apps = $this->appConfig->getApps();
75
-				$configs = [
76
-					'system' => $this->getSystemConfigs($noSensitiveValues),
77
-					'apps' => [],
78
-				];
79
-				foreach ($apps as $appName) {
80
-					$configs['apps'][$appName] = $this->getAppConfigs($appName, $noSensitiveValues);
81
-				}
82
-				break;
83
-
84
-			default:
85
-				$configs = [
86
-					'apps' => [$app => $this->getAppConfigs($app, $noSensitiveValues)],
87
-				];
88
-		}
89
-
90
-		$this->writeArrayInOutputFormat($input, $output, $configs);
91
-		return 0;
92
-	}
93
-
94
-	/**
95
-	 * Get the system configs
96
-	 *
97
-	 * @param bool $noSensitiveValues
98
-	 * @return array
99
-	 */
100
-	protected function getSystemConfigs(bool $noSensitiveValues): array {
101
-		$keys = $this->systemConfig->getKeys();
102
-
103
-		$configs = [];
104
-		foreach ($keys as $key) {
105
-			if ($noSensitiveValues) {
106
-				$value = $this->systemConfig->getFilteredValue($key, serialize(null));
107
-			} else {
108
-				$value = $this->systemConfig->getValue($key, serialize(null));
109
-			}
110
-
111
-			if ($value !== 'N;') {
112
-				$configs[$key] = $value;
113
-			}
114
-		}
115
-
116
-		return $configs;
117
-	}
118
-
119
-	/**
120
-	 * Get the app configs
121
-	 *
122
-	 * @param string $app
123
-	 * @param bool $noSensitiveValues
124
-	 * @return array
125
-	 */
126
-	protected function getAppConfigs(string $app, bool $noSensitiveValues) {
127
-		if ($noSensitiveValues) {
128
-			return $this->appConfig->getFilteredValues($app, false);
129
-		} else {
130
-			return $this->appConfig->getValues($app, false);
131
-		}
132
-	}
133
-
134
-	/**
135
-	 * @param string $argumentName
136
-	 * @param CompletionContext $context
137
-	 * @return string[]
138
-	 */
139
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
140
-		if ($argumentName === 'app') {
141
-			return array_merge(['all', 'system'], \OC_App::getAllApps());
142
-		}
143
-		return [];
144
-	}
21
+    protected string $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY;
22
+
23
+    public function __construct(
24
+        protected SystemConfig $systemConfig,
25
+        protected IAppConfig $appConfig,
26
+        protected ConfigManager $configManager,
27
+    ) {
28
+        parent::__construct();
29
+    }
30
+
31
+    protected function configure() {
32
+        parent::configure();
33
+
34
+        $this
35
+            ->setName('config:list')
36
+            ->setDescription('List all configs')
37
+            ->addArgument(
38
+                'app',
39
+                InputArgument::OPTIONAL,
40
+                'Name of the app ("system" to get the config.php values, "all" for all apps and system)',
41
+                'all'
42
+            )
43
+            ->addOption(
44
+                'private',
45
+                null,
46
+                InputOption::VALUE_NONE,
47
+                'Use this option when you want to include sensitive configs like passwords, salts, ...'
48
+            )
49
+            ->addOption('migrate', null, InputOption::VALUE_NONE, 'Rename config keys of all enabled apps, based on ConfigLexicon')
50
+        ;
51
+    }
52
+
53
+    protected function execute(InputInterface $input, OutputInterface $output): int {
54
+        $app = $input->getArgument('app');
55
+        $noSensitiveValues = !$input->getOption('private');
56
+
57
+        if ($input->getOption('migrate')) {
58
+            $this->configManager->migrateConfigLexiconKeys(($app === 'all') ? null : $app);
59
+        }
60
+
61
+        if (!is_string($app)) {
62
+            $output->writeln('<error>Invalid app value given</error>');
63
+            return 1;
64
+        }
65
+
66
+        switch ($app) {
67
+            case 'system':
68
+                $configs = [
69
+                    'system' => $this->getSystemConfigs($noSensitiveValues),
70
+                ];
71
+                break;
72
+
73
+            case 'all':
74
+                $apps = $this->appConfig->getApps();
75
+                $configs = [
76
+                    'system' => $this->getSystemConfigs($noSensitiveValues),
77
+                    'apps' => [],
78
+                ];
79
+                foreach ($apps as $appName) {
80
+                    $configs['apps'][$appName] = $this->getAppConfigs($appName, $noSensitiveValues);
81
+                }
82
+                break;
83
+
84
+            default:
85
+                $configs = [
86
+                    'apps' => [$app => $this->getAppConfigs($app, $noSensitiveValues)],
87
+                ];
88
+        }
89
+
90
+        $this->writeArrayInOutputFormat($input, $output, $configs);
91
+        return 0;
92
+    }
93
+
94
+    /**
95
+     * Get the system configs
96
+     *
97
+     * @param bool $noSensitiveValues
98
+     * @return array
99
+     */
100
+    protected function getSystemConfigs(bool $noSensitiveValues): array {
101
+        $keys = $this->systemConfig->getKeys();
102
+
103
+        $configs = [];
104
+        foreach ($keys as $key) {
105
+            if ($noSensitiveValues) {
106
+                $value = $this->systemConfig->getFilteredValue($key, serialize(null));
107
+            } else {
108
+                $value = $this->systemConfig->getValue($key, serialize(null));
109
+            }
110
+
111
+            if ($value !== 'N;') {
112
+                $configs[$key] = $value;
113
+            }
114
+        }
115
+
116
+        return $configs;
117
+    }
118
+
119
+    /**
120
+     * Get the app configs
121
+     *
122
+     * @param string $app
123
+     * @param bool $noSensitiveValues
124
+     * @return array
125
+     */
126
+    protected function getAppConfigs(string $app, bool $noSensitiveValues) {
127
+        if ($noSensitiveValues) {
128
+            return $this->appConfig->getFilteredValues($app, false);
129
+        } else {
130
+            return $this->appConfig->getValues($app, false);
131
+        }
132
+    }
133
+
134
+    /**
135
+     * @param string $argumentName
136
+     * @param CompletionContext $context
137
+     * @return string[]
138
+     */
139
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
140
+        if ($argumentName === 'app') {
141
+            return array_merge(['all', 'system'], \OC_App::getAllApps());
142
+        }
143
+        return [];
144
+    }
145 145
 }
Please login to merge, or discard this patch.
tests/lib/Config/TestConfigLexicon_I.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -16,26 +16,26 @@
 block discarded – undo
16 16
 use OCP\IAppConfig;
17 17
 
18 18
 class TestConfigLexicon_I implements IConfigLexicon {
19
-	public const APPID = 'lexicon_test_i';
20
-
21
-	public function getStrictness(): ConfigLexiconStrictness {
22
-		return ConfigLexiconStrictness::IGNORE;
23
-	}
24
-
25
-	public function getAppConfigs(): array {
26
-		return [
27
-			new ConfigLexiconEntry('key1', ValueType::STRING, 'abcde', 'test key', true, IAppConfig::FLAG_SENSITIVE),
28
-			new ConfigLexiconEntry('key2', ValueType::INT, 12345, 'test key', false),
29
-			new ConfigLexiconEntry('key3', ValueType::INT, 12345, 'test key', true, rename: 'old_key3'),
30
-			new ConfigLexiconEntry('key4', ValueType::BOOL, 12345, 'test key', true, rename: 'old_key4', options: ConfigLexiconEntry::RENAME_INVERT_BOOLEAN),
31
-		];
32
-	}
33
-
34
-	public function getUserConfigs(): array {
35
-		return [
36
-			new ConfigLexiconEntry('key1', ValueType::STRING, 'abcde', 'test key', true, IUserConfig::FLAG_SENSITIVE),
37
-			new ConfigLexiconEntry('key2', ValueType::INT, 12345, 'test key', false)
38
-		];
39
-	}
19
+    public const APPID = 'lexicon_test_i';
20
+
21
+    public function getStrictness(): ConfigLexiconStrictness {
22
+        return ConfigLexiconStrictness::IGNORE;
23
+    }
24
+
25
+    public function getAppConfigs(): array {
26
+        return [
27
+            new ConfigLexiconEntry('key1', ValueType::STRING, 'abcde', 'test key', true, IAppConfig::FLAG_SENSITIVE),
28
+            new ConfigLexiconEntry('key2', ValueType::INT, 12345, 'test key', false),
29
+            new ConfigLexiconEntry('key3', ValueType::INT, 12345, 'test key', true, rename: 'old_key3'),
30
+            new ConfigLexiconEntry('key4', ValueType::BOOL, 12345, 'test key', true, rename: 'old_key4', options: ConfigLexiconEntry::RENAME_INVERT_BOOLEAN),
31
+        ];
32
+    }
33
+
34
+    public function getUserConfigs(): array {
35
+        return [
36
+            new ConfigLexiconEntry('key1', ValueType::STRING, 'abcde', 'test key', true, IUserConfig::FLAG_SENSITIVE),
37
+            new ConfigLexiconEntry('key2', ValueType::INT, 12345, 'test key', false)
38
+        ];
39
+    }
40 40
 
41 41
 }
Please login to merge, or discard this patch.
tests/lib/Config/LexiconTest.php 1 patch
Indentation   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -27,180 +27,180 @@
 block discarded – undo
27 27
  * @package Test
28 28
  */
29 29
 class LexiconTest extends TestCase {
30
-	/** @var AppConfig */
31
-	private IAppConfig $appConfig;
32
-	private IUserConfig $userConfig;
33
-	private ConfigManager $configManager;
34
-
35
-	protected function setUp(): void {
36
-		parent::setUp();
37
-
38
-		$bootstrapCoordinator = Server::get(Coordinator::class);
39
-		$bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_I::APPID, TestConfigLexicon_I::class);
40
-		$bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_N::APPID, TestConfigLexicon_N::class);
41
-		$bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_W::APPID, TestConfigLexicon_W::class);
42
-		$bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_E::APPID, TestConfigLexicon_E::class);
43
-
44
-		$this->appConfig = Server::get(IAppConfig::class);
45
-		$this->userConfig = Server::get(IUserConfig::class);
46
-		$this->configManager = Server::get(ConfigManager::class);
47
-	}
48
-
49
-	protected function tearDown(): void {
50
-		parent::tearDown();
51
-
52
-		$this->appConfig->deleteApp(TestConfigLexicon_I::APPID);
53
-		$this->appConfig->deleteApp(TestConfigLexicon_N::APPID);
54
-		$this->appConfig->deleteApp(TestConfigLexicon_W::APPID);
55
-		$this->appConfig->deleteApp(TestConfigLexicon_E::APPID);
56
-
57
-		$this->userConfig->deleteApp(TestConfigLexicon_I::APPID);
58
-		$this->userConfig->deleteApp(TestConfigLexicon_N::APPID);
59
-		$this->userConfig->deleteApp(TestConfigLexicon_W::APPID);
60
-		$this->userConfig->deleteApp(TestConfigLexicon_E::APPID);
61
-	}
62
-
63
-	public function testAppLexiconSetCorrect() {
64
-		$this->assertSame(true, $this->appConfig->setValueString(TestConfigLexicon_E::APPID, 'key1', 'new_value'));
65
-		$this->assertSame(true, $this->appConfig->isLazy(TestConfigLexicon_E::APPID, 'key1'));
66
-		$this->assertSame(true, $this->appConfig->isSensitive(TestConfigLexicon_E::APPID, 'key1'));
67
-		$this->appConfig->deleteKey(TestConfigLexicon_E::APPID, 'key1');
68
-	}
69
-
70
-	public function testAppLexiconGetCorrect() {
71
-		$this->assertSame('abcde', $this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key1', 'default'));
72
-	}
73
-
74
-	public function testAppLexiconSetIncorrectValueType() {
75
-		$this->expectException(AppConfigTypeConflictException::class);
76
-		$this->appConfig->setValueInt(TestConfigLexicon_E::APPID, 'key1', -1);
77
-	}
78
-
79
-	public function testAppLexiconGetIncorrectValueType() {
80
-		$this->expectException(AppConfigTypeConflictException::class);
81
-		$this->appConfig->getValueInt(TestConfigLexicon_E::APPID, 'key1');
82
-	}
83
-
84
-	public function testAppLexiconIgnore() {
85
-		$this->appConfig->setValueString(TestConfigLexicon_I::APPID, 'key_ignore', 'new_value');
86
-		$this->assertSame('new_value', $this->appConfig->getValueString(TestConfigLexicon_I::APPID, 'key_ignore', ''));
87
-	}
88
-
89
-	public function testAppLexiconNotice() {
90
-		$this->appConfig->setValueString(TestConfigLexicon_N::APPID, 'key_notice', 'new_value');
91
-		$this->assertSame('new_value', $this->appConfig->getValueString(TestConfigLexicon_N::APPID, 'key_notice', ''));
92
-	}
93
-
94
-	public function testAppLexiconWarning() {
95
-		$this->appConfig->setValueString(TestConfigLexicon_W::APPID, 'key_warning', 'new_value');
96
-		$this->assertSame('', $this->appConfig->getValueString(TestConfigLexicon_W::APPID, 'key_warning', ''));
97
-	}
98
-
99
-	public function testAppLexiconSetException() {
100
-		$this->expectException(AppConfigUnknownKeyException::class);
101
-		$this->appConfig->setValueString(TestConfigLexicon_E::APPID, 'key_exception', 'new_value');
102
-		$this->assertSame('', $this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key3', ''));
103
-	}
104
-
105
-	public function testAppLexiconGetException() {
106
-		$this->expectException(AppConfigUnknownKeyException::class);
107
-		$this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key_exception');
108
-	}
109
-
110
-	public function testUserLexiconSetCorrect() {
111
-		$this->assertSame(true, $this->userConfig->setValueString('user1', TestConfigLexicon_E::APPID, 'key1', 'new_value'));
112
-		$this->assertSame(true, $this->userConfig->isLazy('user1', TestConfigLexicon_E::APPID, 'key1'));
113
-		$this->assertSame(true, $this->userConfig->isSensitive('user1', TestConfigLexicon_E::APPID, 'key1'));
114
-		$this->userConfig->deleteKey(TestConfigLexicon_E::APPID, 'key1');
115
-	}
116
-
117
-	public function testUserLexiconGetCorrect() {
118
-		$this->assertSame('abcde', $this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key1', 'default'));
119
-	}
120
-
121
-	public function testUserLexiconSetIncorrectValueType() {
122
-		$this->expectException(TypeConflictException::class);
123
-		$this->userConfig->setValueInt('user1', TestConfigLexicon_E::APPID, 'key1', -1);
124
-	}
125
-
126
-	public function testUserLexiconGetIncorrectValueType() {
127
-		$this->expectException(TypeConflictException::class);
128
-		$this->userConfig->getValueInt('user1', TestConfigLexicon_E::APPID, 'key1');
129
-	}
130
-
131
-	public function testUserLexiconIgnore() {
132
-		$this->userConfig->setValueString('user1', TestConfigLexicon_I::APPID, 'key_ignore', 'new_value');
133
-		$this->assertSame('new_value', $this->userConfig->getValueString('user1', TestConfigLexicon_I::APPID, 'key_ignore', ''));
134
-	}
135
-
136
-	public function testUserLexiconNotice() {
137
-		$this->userConfig->setValueString('user1', TestConfigLexicon_N::APPID, 'key_notice', 'new_value');
138
-		$this->assertSame('new_value', $this->userConfig->getValueString('user1', TestConfigLexicon_N::APPID, 'key_notice', ''));
139
-	}
140
-
141
-	public function testUserLexiconWarning() {
142
-		$this->userConfig->setValueString('user1', TestConfigLexicon_W::APPID, 'key_warning', 'new_value');
143
-		$this->assertSame('', $this->userConfig->getValueString('user1', TestConfigLexicon_W::APPID, 'key_warning', ''));
144
-	}
145
-
146
-	public function testUserLexiconSetException() {
147
-		$this->expectException(UnknownKeyException::class);
148
-		$this->userConfig->setValueString('user1', TestConfigLexicon_E::APPID, 'key_exception', 'new_value');
149
-		$this->assertSame('', $this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key5', ''));
150
-	}
151
-
152
-	public function testUserLexiconGetException() {
153
-		$this->expectException(UnknownKeyException::class);
154
-		$this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key_exception');
155
-	}
156
-
157
-	public function testAppConfigLexiconRenameSetNewValue() {
158
-		$this->assertSame(12345, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
159
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 994);
160
-		$this->assertSame(994, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
161
-	}
162
-
163
-	public function testAppConfigLexiconRenameSetOldValuePreMigration() {
164
-		$this->appConfig->ignoreLexiconAliases(true);
165
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 993);
166
-		$this->appConfig->ignoreLexiconAliases(false);
167
-		$this->assertSame(12345, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
168
-	}
169
-
170
-	public function testAppConfigLexiconRenameSetOldValuePostMigration() {
171
-		$this->appConfig->ignoreLexiconAliases(true);
172
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 994);
173
-		$this->appConfig->ignoreLexiconAliases(false);
174
-		$this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
175
-		$this->assertSame(994, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
176
-	}
177
-
178
-	public function testAppConfigLexiconRenameGetNewValue() {
179
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 981);
180
-		$this->assertSame(981, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
181
-	}
182
-
183
-	public function testAppConfigLexiconRenameGetOldValuePreMigration() {
184
-		$this->appConfig->ignoreLexiconAliases(true);
185
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 984);
186
-		$this->assertSame(123, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
187
-		$this->appConfig->ignoreLexiconAliases(false);
188
-	}
189
-
190
-	public function testAppConfigLexiconRenameGetOldValuePostMigration() {
191
-		$this->appConfig->ignoreLexiconAliases(true);
192
-		$this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 987);
193
-		$this->appConfig->ignoreLexiconAliases(false);
194
-		$this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
195
-		$this->assertSame(987, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
196
-	}
197
-
198
-	public function testAppConfigLexiconRenameInvertBoolean() {
199
-		$this->appConfig->ignoreLexiconAliases(true);
200
-		$this->appConfig->setValueBool(TestConfigLexicon_I::APPID, 'old_key4', true);
201
-		$this->appConfig->ignoreLexiconAliases(false);
202
-		$this->assertSame(true, $this->appConfig->getValueBool(TestConfigLexicon_I::APPID, 'key4'));
203
-		$this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
204
-		$this->assertSame(false, $this->appConfig->getValueBool(TestConfigLexicon_I::APPID, 'key4'));
205
-	}
30
+    /** @var AppConfig */
31
+    private IAppConfig $appConfig;
32
+    private IUserConfig $userConfig;
33
+    private ConfigManager $configManager;
34
+
35
+    protected function setUp(): void {
36
+        parent::setUp();
37
+
38
+        $bootstrapCoordinator = Server::get(Coordinator::class);
39
+        $bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_I::APPID, TestConfigLexicon_I::class);
40
+        $bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_N::APPID, TestConfigLexicon_N::class);
41
+        $bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_W::APPID, TestConfigLexicon_W::class);
42
+        $bootstrapCoordinator->getRegistrationContext()?->registerConfigLexicon(TestConfigLexicon_E::APPID, TestConfigLexicon_E::class);
43
+
44
+        $this->appConfig = Server::get(IAppConfig::class);
45
+        $this->userConfig = Server::get(IUserConfig::class);
46
+        $this->configManager = Server::get(ConfigManager::class);
47
+    }
48
+
49
+    protected function tearDown(): void {
50
+        parent::tearDown();
51
+
52
+        $this->appConfig->deleteApp(TestConfigLexicon_I::APPID);
53
+        $this->appConfig->deleteApp(TestConfigLexicon_N::APPID);
54
+        $this->appConfig->deleteApp(TestConfigLexicon_W::APPID);
55
+        $this->appConfig->deleteApp(TestConfigLexicon_E::APPID);
56
+
57
+        $this->userConfig->deleteApp(TestConfigLexicon_I::APPID);
58
+        $this->userConfig->deleteApp(TestConfigLexicon_N::APPID);
59
+        $this->userConfig->deleteApp(TestConfigLexicon_W::APPID);
60
+        $this->userConfig->deleteApp(TestConfigLexicon_E::APPID);
61
+    }
62
+
63
+    public function testAppLexiconSetCorrect() {
64
+        $this->assertSame(true, $this->appConfig->setValueString(TestConfigLexicon_E::APPID, 'key1', 'new_value'));
65
+        $this->assertSame(true, $this->appConfig->isLazy(TestConfigLexicon_E::APPID, 'key1'));
66
+        $this->assertSame(true, $this->appConfig->isSensitive(TestConfigLexicon_E::APPID, 'key1'));
67
+        $this->appConfig->deleteKey(TestConfigLexicon_E::APPID, 'key1');
68
+    }
69
+
70
+    public function testAppLexiconGetCorrect() {
71
+        $this->assertSame('abcde', $this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key1', 'default'));
72
+    }
73
+
74
+    public function testAppLexiconSetIncorrectValueType() {
75
+        $this->expectException(AppConfigTypeConflictException::class);
76
+        $this->appConfig->setValueInt(TestConfigLexicon_E::APPID, 'key1', -1);
77
+    }
78
+
79
+    public function testAppLexiconGetIncorrectValueType() {
80
+        $this->expectException(AppConfigTypeConflictException::class);
81
+        $this->appConfig->getValueInt(TestConfigLexicon_E::APPID, 'key1');
82
+    }
83
+
84
+    public function testAppLexiconIgnore() {
85
+        $this->appConfig->setValueString(TestConfigLexicon_I::APPID, 'key_ignore', 'new_value');
86
+        $this->assertSame('new_value', $this->appConfig->getValueString(TestConfigLexicon_I::APPID, 'key_ignore', ''));
87
+    }
88
+
89
+    public function testAppLexiconNotice() {
90
+        $this->appConfig->setValueString(TestConfigLexicon_N::APPID, 'key_notice', 'new_value');
91
+        $this->assertSame('new_value', $this->appConfig->getValueString(TestConfigLexicon_N::APPID, 'key_notice', ''));
92
+    }
93
+
94
+    public function testAppLexiconWarning() {
95
+        $this->appConfig->setValueString(TestConfigLexicon_W::APPID, 'key_warning', 'new_value');
96
+        $this->assertSame('', $this->appConfig->getValueString(TestConfigLexicon_W::APPID, 'key_warning', ''));
97
+    }
98
+
99
+    public function testAppLexiconSetException() {
100
+        $this->expectException(AppConfigUnknownKeyException::class);
101
+        $this->appConfig->setValueString(TestConfigLexicon_E::APPID, 'key_exception', 'new_value');
102
+        $this->assertSame('', $this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key3', ''));
103
+    }
104
+
105
+    public function testAppLexiconGetException() {
106
+        $this->expectException(AppConfigUnknownKeyException::class);
107
+        $this->appConfig->getValueString(TestConfigLexicon_E::APPID, 'key_exception');
108
+    }
109
+
110
+    public function testUserLexiconSetCorrect() {
111
+        $this->assertSame(true, $this->userConfig->setValueString('user1', TestConfigLexicon_E::APPID, 'key1', 'new_value'));
112
+        $this->assertSame(true, $this->userConfig->isLazy('user1', TestConfigLexicon_E::APPID, 'key1'));
113
+        $this->assertSame(true, $this->userConfig->isSensitive('user1', TestConfigLexicon_E::APPID, 'key1'));
114
+        $this->userConfig->deleteKey(TestConfigLexicon_E::APPID, 'key1');
115
+    }
116
+
117
+    public function testUserLexiconGetCorrect() {
118
+        $this->assertSame('abcde', $this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key1', 'default'));
119
+    }
120
+
121
+    public function testUserLexiconSetIncorrectValueType() {
122
+        $this->expectException(TypeConflictException::class);
123
+        $this->userConfig->setValueInt('user1', TestConfigLexicon_E::APPID, 'key1', -1);
124
+    }
125
+
126
+    public function testUserLexiconGetIncorrectValueType() {
127
+        $this->expectException(TypeConflictException::class);
128
+        $this->userConfig->getValueInt('user1', TestConfigLexicon_E::APPID, 'key1');
129
+    }
130
+
131
+    public function testUserLexiconIgnore() {
132
+        $this->userConfig->setValueString('user1', TestConfigLexicon_I::APPID, 'key_ignore', 'new_value');
133
+        $this->assertSame('new_value', $this->userConfig->getValueString('user1', TestConfigLexicon_I::APPID, 'key_ignore', ''));
134
+    }
135
+
136
+    public function testUserLexiconNotice() {
137
+        $this->userConfig->setValueString('user1', TestConfigLexicon_N::APPID, 'key_notice', 'new_value');
138
+        $this->assertSame('new_value', $this->userConfig->getValueString('user1', TestConfigLexicon_N::APPID, 'key_notice', ''));
139
+    }
140
+
141
+    public function testUserLexiconWarning() {
142
+        $this->userConfig->setValueString('user1', TestConfigLexicon_W::APPID, 'key_warning', 'new_value');
143
+        $this->assertSame('', $this->userConfig->getValueString('user1', TestConfigLexicon_W::APPID, 'key_warning', ''));
144
+    }
145
+
146
+    public function testUserLexiconSetException() {
147
+        $this->expectException(UnknownKeyException::class);
148
+        $this->userConfig->setValueString('user1', TestConfigLexicon_E::APPID, 'key_exception', 'new_value');
149
+        $this->assertSame('', $this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key5', ''));
150
+    }
151
+
152
+    public function testUserLexiconGetException() {
153
+        $this->expectException(UnknownKeyException::class);
154
+        $this->userConfig->getValueString('user1', TestConfigLexicon_E::APPID, 'key_exception');
155
+    }
156
+
157
+    public function testAppConfigLexiconRenameSetNewValue() {
158
+        $this->assertSame(12345, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
159
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 994);
160
+        $this->assertSame(994, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
161
+    }
162
+
163
+    public function testAppConfigLexiconRenameSetOldValuePreMigration() {
164
+        $this->appConfig->ignoreLexiconAliases(true);
165
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 993);
166
+        $this->appConfig->ignoreLexiconAliases(false);
167
+        $this->assertSame(12345, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
168
+    }
169
+
170
+    public function testAppConfigLexiconRenameSetOldValuePostMigration() {
171
+        $this->appConfig->ignoreLexiconAliases(true);
172
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'old_key3', 994);
173
+        $this->appConfig->ignoreLexiconAliases(false);
174
+        $this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
175
+        $this->assertSame(994, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'key3', 123));
176
+    }
177
+
178
+    public function testAppConfigLexiconRenameGetNewValue() {
179
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 981);
180
+        $this->assertSame(981, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
181
+    }
182
+
183
+    public function testAppConfigLexiconRenameGetOldValuePreMigration() {
184
+        $this->appConfig->ignoreLexiconAliases(true);
185
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 984);
186
+        $this->assertSame(123, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
187
+        $this->appConfig->ignoreLexiconAliases(false);
188
+    }
189
+
190
+    public function testAppConfigLexiconRenameGetOldValuePostMigration() {
191
+        $this->appConfig->ignoreLexiconAliases(true);
192
+        $this->appConfig->setValueInt(TestConfigLexicon_I::APPID, 'key3', 987);
193
+        $this->appConfig->ignoreLexiconAliases(false);
194
+        $this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
195
+        $this->assertSame(987, $this->appConfig->getValueInt(TestConfigLexicon_I::APPID, 'old_key3', 123));
196
+    }
197
+
198
+    public function testAppConfigLexiconRenameInvertBoolean() {
199
+        $this->appConfig->ignoreLexiconAliases(true);
200
+        $this->appConfig->setValueBool(TestConfigLexicon_I::APPID, 'old_key4', true);
201
+        $this->appConfig->ignoreLexiconAliases(false);
202
+        $this->assertSame(true, $this->appConfig->getValueBool(TestConfigLexicon_I::APPID, 'key4'));
203
+        $this->configManager->migrateConfigLexiconKeys(TestConfigLexicon_I::APPID);
204
+        $this->assertSame(false, $this->appConfig->getValueBool(TestConfigLexicon_I::APPID, 'key4'));
205
+    }
206 206
 }
Please login to merge, or discard this patch.
tests/lib/AppTest.php 1 patch
Indentation   +613 added lines, -613 removed lines patch added patch discarded remove patch
@@ -30,617 +30,617 @@
 block discarded – undo
30 30
  * @group DB
31 31
  */
32 32
 class AppTest extends \Test\TestCase {
33
-	public const TEST_USER1 = 'user1';
34
-	public const TEST_USER2 = 'user2';
35
-	public const TEST_USER3 = 'user3';
36
-	public const TEST_GROUP1 = 'group1';
37
-	public const TEST_GROUP2 = 'group2';
38
-
39
-	public static function appVersionsProvider(): array {
40
-		return [
41
-			// exact match
42
-			[
43
-				'6.0.0.0',
44
-				[
45
-					'requiremin' => '6.0',
46
-					'requiremax' => '6.0',
47
-				],
48
-				true
49
-			],
50
-			// in-between match
51
-			[
52
-				'6.0.0.0',
53
-				[
54
-					'requiremin' => '5.0',
55
-					'requiremax' => '7.0',
56
-				],
57
-				true
58
-			],
59
-			// app too old
60
-			[
61
-				'6.0.0.0',
62
-				[
63
-					'requiremin' => '5.0',
64
-					'requiremax' => '5.0',
65
-				],
66
-				false
67
-			],
68
-			// app too new
69
-			[
70
-				'5.0.0.0',
71
-				[
72
-					'requiremin' => '6.0',
73
-					'requiremax' => '6.0',
74
-				],
75
-				false
76
-			],
77
-			// only min specified
78
-			[
79
-				'6.0.0.0',
80
-				[
81
-					'requiremin' => '6.0',
82
-				],
83
-				true
84
-			],
85
-			// only min specified fail
86
-			[
87
-				'5.0.0.0',
88
-				[
89
-					'requiremin' => '6.0',
90
-				],
91
-				false
92
-			],
93
-			// only min specified legacy
94
-			[
95
-				'6.0.0.0',
96
-				[
97
-					'require' => '6.0',
98
-				],
99
-				true
100
-			],
101
-			// only min specified legacy fail
102
-			[
103
-				'4.0.0.0',
104
-				[
105
-					'require' => '6.0',
106
-				],
107
-				false
108
-			],
109
-			// only max specified
110
-			[
111
-				'5.0.0.0',
112
-				[
113
-					'requiremax' => '6.0',
114
-				],
115
-				true
116
-			],
117
-			// only max specified fail
118
-			[
119
-				'7.0.0.0',
120
-				[
121
-					'requiremax' => '6.0',
122
-				],
123
-				false
124
-			],
125
-			// variations of versions
126
-			// single OC number
127
-			[
128
-				'4',
129
-				[
130
-					'require' => '4.0',
131
-				],
132
-				true
133
-			],
134
-			// multiple OC number
135
-			[
136
-				'4.3.1',
137
-				[
138
-					'require' => '4.3',
139
-				],
140
-				true
141
-			],
142
-			// single app number
143
-			[
144
-				'4',
145
-				[
146
-					'require' => '4',
147
-				],
148
-				true
149
-			],
150
-			// single app number fail
151
-			[
152
-				'4.3',
153
-				[
154
-					'require' => '5',
155
-				],
156
-				false
157
-			],
158
-			// complex
159
-			[
160
-				'5.0.0',
161
-				[
162
-					'require' => '4.5.1',
163
-				],
164
-				true
165
-			],
166
-			// complex fail
167
-			[
168
-				'4.3.1',
169
-				[
170
-					'require' => '4.3.2',
171
-				],
172
-				false
173
-			],
174
-			// two numbers
175
-			[
176
-				'4.3.1',
177
-				[
178
-					'require' => '4.4',
179
-				],
180
-				false
181
-			],
182
-			// one number fail
183
-			[
184
-				'4.3.1',
185
-				[
186
-					'require' => '5',
187
-				],
188
-				false
189
-			],
190
-			// pre-alpha app
191
-			[
192
-				'5.0.3',
193
-				[
194
-					'require' => '4.93',
195
-				],
196
-				true
197
-			],
198
-			// pre-alpha OC
199
-			[
200
-				'6.90.0.2',
201
-				[
202
-					'require' => '6.90',
203
-				],
204
-				true
205
-			],
206
-			// pre-alpha OC max
207
-			[
208
-				'6.90.0.2',
209
-				[
210
-					'requiremax' => '7',
211
-				],
212
-				true
213
-			],
214
-			// expect same major number match
215
-			[
216
-				'5.0.3',
217
-				[
218
-					'require' => '5',
219
-				],
220
-				true
221
-			],
222
-			// expect same major number match
223
-			[
224
-				'5.0.3',
225
-				[
226
-					'requiremax' => '5',
227
-				],
228
-				true
229
-			],
230
-			// dependencies versions before require*
231
-			[
232
-				'6.0.0.0',
233
-				[
234
-					'requiremin' => '5.0',
235
-					'requiremax' => '7.0',
236
-					'dependencies' => [
237
-						'owncloud' => [
238
-							'@attributes' => [
239
-								'min-version' => '7.0',
240
-								'max-version' => '7.0',
241
-							],
242
-						],
243
-					],
244
-				],
245
-				false
246
-			],
247
-			[
248
-				'6.0.0.0',
249
-				[
250
-					'requiremin' => '5.0',
251
-					'requiremax' => '7.0',
252
-					'dependencies' => [
253
-						'owncloud' => [
254
-							'@attributes' => [
255
-								'min-version' => '5.0',
256
-								'max-version' => '5.0',
257
-							],
258
-						],
259
-					],
260
-				],
261
-				false
262
-			],
263
-			[
264
-				'6.0.0.0',
265
-				[
266
-					'requiremin' => '5.0',
267
-					'requiremax' => '5.0',
268
-					'dependencies' => [
269
-						'owncloud' => [
270
-							'@attributes' => [
271
-								'min-version' => '5.0',
272
-								'max-version' => '7.0',
273
-							],
274
-						],
275
-					],
276
-				],
277
-				true
278
-			],
279
-			[
280
-				'9.2.0.0',
281
-				[
282
-					'dependencies' => [
283
-						'owncloud' => [
284
-							'@attributes' => [
285
-								'min-version' => '9.0',
286
-								'max-version' => '9.1',
287
-							],
288
-						],
289
-						'nextcloud' => [
290
-							'@attributes' => [
291
-								'min-version' => '9.1',
292
-								'max-version' => '9.2',
293
-							],
294
-						],
295
-					],
296
-				],
297
-				true
298
-			],
299
-			[
300
-				'9.2.0.0',
301
-				[
302
-					'dependencies' => [
303
-						'nextcloud' => [
304
-							'@attributes' => [
305
-								'min-version' => '9.1',
306
-								'max-version' => '9.2',
307
-							],
308
-						],
309
-					],
310
-				],
311
-				true
312
-			],
313
-		];
314
-	}
315
-
316
-	/**
317
-	 * @dataProvider appVersionsProvider
318
-	 */
319
-	public function testIsAppCompatible($ocVersion, $appInfo, $expectedResult): void {
320
-		$this->assertEquals($expectedResult, \OC_App::isAppCompatible($ocVersion, $appInfo));
321
-	}
322
-
323
-	/**
324
-	 * Tests that the app order is correct
325
-	 */
326
-	public function testGetEnabledAppsIsSorted(): void {
327
-		$apps = \OC_App::getEnabledApps();
328
-		// copy array
329
-		$sortedApps = $apps;
330
-		sort($sortedApps);
331
-		// 'files' is always on top
332
-		unset($sortedApps[array_search('files', $sortedApps)]);
333
-		array_unshift($sortedApps, 'files');
334
-		$this->assertEquals($sortedApps, $apps);
335
-	}
336
-
337
-	/**
338
-	 * Providers for the app config values
339
-	 */
340
-	public static function appConfigValuesProvider(): array {
341
-		return [
342
-			// logged in user1
343
-			[
344
-				self::TEST_USER1,
345
-				[
346
-					'files',
347
-					'app1',
348
-					'app3',
349
-					'appforgroup1',
350
-					'appforgroup12',
351
-					'cloud_federation_api',
352
-					'dav',
353
-					'federatedfilesharing',
354
-					'lookup_server_connector',
355
-					'oauth2',
356
-					'profile',
357
-					'provisioning_api',
358
-					'settings',
359
-					'theming',
360
-					'twofactor_backupcodes',
361
-					'viewer',
362
-					'workflowengine',
363
-				],
364
-				false
365
-			],
366
-			// logged in user2
367
-			[
368
-				self::TEST_USER2,
369
-				[
370
-					'files',
371
-					'app1',
372
-					'app3',
373
-					'appforgroup12',
374
-					'appforgroup2',
375
-					'cloud_federation_api',
376
-					'dav',
377
-					'federatedfilesharing',
378
-					'lookup_server_connector',
379
-					'oauth2',
380
-					'profile',
381
-					'provisioning_api',
382
-					'settings',
383
-					'theming',
384
-					'twofactor_backupcodes',
385
-					'viewer',
386
-					'workflowengine',
387
-				],
388
-				false
389
-			],
390
-			// logged in user3
391
-			[
392
-				self::TEST_USER3,
393
-				[
394
-					'files',
395
-					'app1',
396
-					'app3',
397
-					'appforgroup1',
398
-					'appforgroup12',
399
-					'appforgroup2',
400
-					'cloud_federation_api',
401
-					'dav',
402
-					'federatedfilesharing',
403
-					'lookup_server_connector',
404
-					'oauth2',
405
-					'profile',
406
-					'provisioning_api',
407
-					'settings',
408
-					'theming',
409
-					'twofactor_backupcodes',
410
-					'viewer',
411
-					'workflowengine',
412
-				],
413
-				false
414
-			],
415
-			//  no user, returns all apps
416
-			[
417
-				null,
418
-				[
419
-					'files',
420
-					'app1',
421
-					'app3',
422
-					'appforgroup1',
423
-					'appforgroup12',
424
-					'appforgroup2',
425
-					'cloud_federation_api',
426
-					'dav',
427
-					'federatedfilesharing',
428
-					'lookup_server_connector',
429
-					'oauth2',
430
-					'profile',
431
-					'provisioning_api',
432
-					'settings',
433
-					'theming',
434
-					'twofactor_backupcodes',
435
-					'viewer',
436
-					'workflowengine',
437
-				],
438
-				false,
439
-			],
440
-			//  user given, but ask for all
441
-			[
442
-				self::TEST_USER1,
443
-				[
444
-					'files',
445
-					'app1',
446
-					'app3',
447
-					'appforgroup1',
448
-					'appforgroup12',
449
-					'appforgroup2',
450
-					'cloud_federation_api',
451
-					'dav',
452
-					'federatedfilesharing',
453
-					'lookup_server_connector',
454
-					'oauth2',
455
-					'profile',
456
-					'provisioning_api',
457
-					'settings',
458
-					'theming',
459
-					'twofactor_backupcodes',
460
-					'viewer',
461
-					'workflowengine',
462
-				],
463
-				true,
464
-			],
465
-		];
466
-	}
467
-
468
-	/**
469
-	 * Test enabled apps
470
-	 *
471
-	 * @dataProvider appConfigValuesProvider
472
-	 */
473
-	public function testEnabledApps($user, $expectedApps, $forceAll): void {
474
-		$userManager = Server::get(IUserManager::class);
475
-		$groupManager = Server::get(IGroupManager::class);
476
-		$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
477
-		$user2 = $userManager->createUser(self::TEST_USER2, 'NotAnEasyPassword123456_');
478
-		$user3 = $userManager->createUser(self::TEST_USER3, 'NotAnEasyPassword123456?');
479
-
480
-		$group1 = $groupManager->createGroup(self::TEST_GROUP1);
481
-		$group1->addUser($user1);
482
-		$group1->addUser($user3);
483
-		$group2 = $groupManager->createGroup(self::TEST_GROUP2);
484
-		$group2->addUser($user2);
485
-		$group2->addUser($user3);
486
-
487
-		\OC_User::setUserId($user);
488
-
489
-		$this->setupAppConfigMock()->expects($this->once())
490
-			->method('searchValues')
491
-			->willReturn(
492
-				[
493
-					'app3' => 'yes',
494
-					'app2' => 'no',
495
-					'app1' => 'yes',
496
-					'appforgroup1' => '["group1"]',
497
-					'appforgroup2' => '["group2"]',
498
-					'appforgroup12' => '["group2","group1"]',
499
-				]
500
-			);
501
-
502
-		$apps = \OC_App::getEnabledApps(false, $forceAll);
503
-
504
-		$this->restoreAppConfig();
505
-		\OC_User::setUserId(null);
506
-
507
-		$user1->delete();
508
-		$user2->delete();
509
-		$user3->delete();
510
-
511
-		$group1->delete();
512
-		$group2->delete();
513
-
514
-		$this->assertEquals($expectedApps, $apps);
515
-	}
516
-
517
-	/**
518
-	 * Test isEnabledApps() with cache, not re-reading the list of
519
-	 * enabled apps more than once when a user is set.
520
-	 */
521
-	public function testEnabledAppsCache(): void {
522
-		$userManager = Server::get(IUserManager::class);
523
-		$user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
524
-
525
-		\OC_User::setUserId(self::TEST_USER1);
526
-
527
-		$this->setupAppConfigMock()->expects($this->once())
528
-			->method('searchValues')
529
-			->willReturn(
530
-				[
531
-					'app3' => 'yes',
532
-					'app2' => 'no',
533
-				]
534
-			);
535
-
536
-		$apps = \OC_App::getEnabledApps();
537
-		$this->assertEquals(['files', 'app3', 'cloud_federation_api', 'dav', 'federatedfilesharing', 'lookup_server_connector', 'oauth2', 'profile', 'provisioning_api', 'settings', 'theming', 'twofactor_backupcodes', 'viewer', 'workflowengine'], $apps);
538
-
539
-		// mock should not be called again here
540
-		$apps = \OC_App::getEnabledApps();
541
-		$this->assertEquals(['files', 'app3', 'cloud_federation_api', 'dav', 'federatedfilesharing', 'lookup_server_connector', 'oauth2', 'profile', 'provisioning_api', 'settings', 'theming', 'twofactor_backupcodes', 'viewer', 'workflowengine'], $apps);
542
-
543
-		$this->restoreAppConfig();
544
-		\OC_User::setUserId(null);
545
-
546
-		$user1->delete();
547
-	}
548
-
549
-
550
-	private function setupAppConfigMock() {
551
-		/** @var AppConfig|MockObject */
552
-		$appConfig = $this->getMockBuilder(AppConfig::class)
553
-			->onlyMethods(['searchValues'])
554
-			->setConstructorArgs([Server::get(IDBConnection::class)])
555
-			->disableOriginalConstructor()
556
-			->getMock();
557
-
558
-		$this->registerAppConfig($appConfig);
559
-		return $appConfig;
560
-	}
561
-
562
-	/**
563
-	 * Register an app config mock for testing purposes.
564
-	 *
565
-	 * @param IAppConfig $appConfig app config mock
566
-	 */
567
-	private function registerAppConfig(AppConfig $appConfig) {
568
-		$this->overwriteService(AppConfig::class, $appConfig);
569
-		$this->overwriteService(AppManager::class, new AppManager(
570
-			Server::get(IUserSession::class),
571
-			Server::get(IConfig::class),
572
-			Server::get(IGroupManager::class),
573
-			Server::get(ICacheFactory::class),
574
-			Server::get(IEventDispatcher::class),
575
-			Server::get(LoggerInterface::class),
576
-			Server::get(ServerVersion::class),
577
-			\OCP\Server::get(ConfigManager::class),
578
-		));
579
-	}
580
-
581
-	/**
582
-	 * Restore the original app config service.
583
-	 */
584
-	private function restoreAppConfig() {
585
-		$this->restoreService(AppConfig::class);
586
-		$this->restoreService(AppManager::class);
587
-
588
-		// Remove the cache of the mocked apps list with a forceRefresh
589
-		\OC_App::getEnabledApps();
590
-	}
591
-
592
-	/**
593
-	 * Providers for the app data values
594
-	 */
595
-	public static function appDataProvider(): array {
596
-		return [
597
-			[
598
-				['description' => " \t  This is a multiline \n test with \n \t \n \n some new lines   "],
599
-				['description' => "This is a multiline \n test with \n \t \n \n some new lines"],
600
-			],
601
-			[
602
-				['description' => " \t  This is a multiline \n test with \n \t   some new lines   "],
603
-				['description' => "This is a multiline \n test with \n \t   some new lines"],
604
-			],
605
-			[
606
-				['description' => hex2bin('5065726d657420646520732761757468656e7469666965722064616e732070697769676f20646972656374656d656e74206176656320736573206964656e74696669616e7473206f776e636c6f75642073616e73206c65732072657461706572206574206d657420c3a0206a6f757273206365757820636920656e20636173206465206368616e67656d656e74206465206d6f742064652070617373652e0d0a0d')],
607
-				['description' => "Permet de s'authentifier dans piwigo directement avec ses identifiants owncloud sans les retaper et met à jours ceux ci en cas de changement de mot de passe."],
608
-			],
609
-			[
610
-				['not-a-description' => " \t  This is a multiline \n test with \n \t   some new lines   "],
611
-				[
612
-					'not-a-description' => " \t  This is a multiline \n test with \n \t   some new lines   ",
613
-					'description' => '',
614
-				],
615
-			],
616
-			[
617
-				['description' => [100, 'bla']],
618
-				['description' => ''],
619
-			],
620
-		];
621
-	}
622
-
623
-	/**
624
-	 * Test app info parser
625
-	 *
626
-	 * @dataProvider appDataProvider
627
-	 * @param array $data
628
-	 * @param array $expected
629
-	 */
630
-	public function testParseAppInfo(array $data, array $expected): void {
631
-		$this->assertSame($expected, \OC_App::parseAppInfo($data));
632
-	}
633
-
634
-	public function testParseAppInfoL10N(): void {
635
-		$parser = new InfoParser();
636
-		$data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-multi-lang.xml');
637
-		$this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
638
-		$this->assertEquals('German', \OC_App::parseAppInfo($data, 'de')['description']);
639
-	}
640
-
641
-	public function testParseAppInfoL10NSingleLanguage(): void {
642
-		$parser = new InfoParser();
643
-		$data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-single-lang.xml');
644
-		$this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
645
-	}
33
+    public const TEST_USER1 = 'user1';
34
+    public const TEST_USER2 = 'user2';
35
+    public const TEST_USER3 = 'user3';
36
+    public const TEST_GROUP1 = 'group1';
37
+    public const TEST_GROUP2 = 'group2';
38
+
39
+    public static function appVersionsProvider(): array {
40
+        return [
41
+            // exact match
42
+            [
43
+                '6.0.0.0',
44
+                [
45
+                    'requiremin' => '6.0',
46
+                    'requiremax' => '6.0',
47
+                ],
48
+                true
49
+            ],
50
+            // in-between match
51
+            [
52
+                '6.0.0.0',
53
+                [
54
+                    'requiremin' => '5.0',
55
+                    'requiremax' => '7.0',
56
+                ],
57
+                true
58
+            ],
59
+            // app too old
60
+            [
61
+                '6.0.0.0',
62
+                [
63
+                    'requiremin' => '5.0',
64
+                    'requiremax' => '5.0',
65
+                ],
66
+                false
67
+            ],
68
+            // app too new
69
+            [
70
+                '5.0.0.0',
71
+                [
72
+                    'requiremin' => '6.0',
73
+                    'requiremax' => '6.0',
74
+                ],
75
+                false
76
+            ],
77
+            // only min specified
78
+            [
79
+                '6.0.0.0',
80
+                [
81
+                    'requiremin' => '6.0',
82
+                ],
83
+                true
84
+            ],
85
+            // only min specified fail
86
+            [
87
+                '5.0.0.0',
88
+                [
89
+                    'requiremin' => '6.0',
90
+                ],
91
+                false
92
+            ],
93
+            // only min specified legacy
94
+            [
95
+                '6.0.0.0',
96
+                [
97
+                    'require' => '6.0',
98
+                ],
99
+                true
100
+            ],
101
+            // only min specified legacy fail
102
+            [
103
+                '4.0.0.0',
104
+                [
105
+                    'require' => '6.0',
106
+                ],
107
+                false
108
+            ],
109
+            // only max specified
110
+            [
111
+                '5.0.0.0',
112
+                [
113
+                    'requiremax' => '6.0',
114
+                ],
115
+                true
116
+            ],
117
+            // only max specified fail
118
+            [
119
+                '7.0.0.0',
120
+                [
121
+                    'requiremax' => '6.0',
122
+                ],
123
+                false
124
+            ],
125
+            // variations of versions
126
+            // single OC number
127
+            [
128
+                '4',
129
+                [
130
+                    'require' => '4.0',
131
+                ],
132
+                true
133
+            ],
134
+            // multiple OC number
135
+            [
136
+                '4.3.1',
137
+                [
138
+                    'require' => '4.3',
139
+                ],
140
+                true
141
+            ],
142
+            // single app number
143
+            [
144
+                '4',
145
+                [
146
+                    'require' => '4',
147
+                ],
148
+                true
149
+            ],
150
+            // single app number fail
151
+            [
152
+                '4.3',
153
+                [
154
+                    'require' => '5',
155
+                ],
156
+                false
157
+            ],
158
+            // complex
159
+            [
160
+                '5.0.0',
161
+                [
162
+                    'require' => '4.5.1',
163
+                ],
164
+                true
165
+            ],
166
+            // complex fail
167
+            [
168
+                '4.3.1',
169
+                [
170
+                    'require' => '4.3.2',
171
+                ],
172
+                false
173
+            ],
174
+            // two numbers
175
+            [
176
+                '4.3.1',
177
+                [
178
+                    'require' => '4.4',
179
+                ],
180
+                false
181
+            ],
182
+            // one number fail
183
+            [
184
+                '4.3.1',
185
+                [
186
+                    'require' => '5',
187
+                ],
188
+                false
189
+            ],
190
+            // pre-alpha app
191
+            [
192
+                '5.0.3',
193
+                [
194
+                    'require' => '4.93',
195
+                ],
196
+                true
197
+            ],
198
+            // pre-alpha OC
199
+            [
200
+                '6.90.0.2',
201
+                [
202
+                    'require' => '6.90',
203
+                ],
204
+                true
205
+            ],
206
+            // pre-alpha OC max
207
+            [
208
+                '6.90.0.2',
209
+                [
210
+                    'requiremax' => '7',
211
+                ],
212
+                true
213
+            ],
214
+            // expect same major number match
215
+            [
216
+                '5.0.3',
217
+                [
218
+                    'require' => '5',
219
+                ],
220
+                true
221
+            ],
222
+            // expect same major number match
223
+            [
224
+                '5.0.3',
225
+                [
226
+                    'requiremax' => '5',
227
+                ],
228
+                true
229
+            ],
230
+            // dependencies versions before require*
231
+            [
232
+                '6.0.0.0',
233
+                [
234
+                    'requiremin' => '5.0',
235
+                    'requiremax' => '7.0',
236
+                    'dependencies' => [
237
+                        'owncloud' => [
238
+                            '@attributes' => [
239
+                                'min-version' => '7.0',
240
+                                'max-version' => '7.0',
241
+                            ],
242
+                        ],
243
+                    ],
244
+                ],
245
+                false
246
+            ],
247
+            [
248
+                '6.0.0.0',
249
+                [
250
+                    'requiremin' => '5.0',
251
+                    'requiremax' => '7.0',
252
+                    'dependencies' => [
253
+                        'owncloud' => [
254
+                            '@attributes' => [
255
+                                'min-version' => '5.0',
256
+                                'max-version' => '5.0',
257
+                            ],
258
+                        ],
259
+                    ],
260
+                ],
261
+                false
262
+            ],
263
+            [
264
+                '6.0.0.0',
265
+                [
266
+                    'requiremin' => '5.0',
267
+                    'requiremax' => '5.0',
268
+                    'dependencies' => [
269
+                        'owncloud' => [
270
+                            '@attributes' => [
271
+                                'min-version' => '5.0',
272
+                                'max-version' => '7.0',
273
+                            ],
274
+                        ],
275
+                    ],
276
+                ],
277
+                true
278
+            ],
279
+            [
280
+                '9.2.0.0',
281
+                [
282
+                    'dependencies' => [
283
+                        'owncloud' => [
284
+                            '@attributes' => [
285
+                                'min-version' => '9.0',
286
+                                'max-version' => '9.1',
287
+                            ],
288
+                        ],
289
+                        'nextcloud' => [
290
+                            '@attributes' => [
291
+                                'min-version' => '9.1',
292
+                                'max-version' => '9.2',
293
+                            ],
294
+                        ],
295
+                    ],
296
+                ],
297
+                true
298
+            ],
299
+            [
300
+                '9.2.0.0',
301
+                [
302
+                    'dependencies' => [
303
+                        'nextcloud' => [
304
+                            '@attributes' => [
305
+                                'min-version' => '9.1',
306
+                                'max-version' => '9.2',
307
+                            ],
308
+                        ],
309
+                    ],
310
+                ],
311
+                true
312
+            ],
313
+        ];
314
+    }
315
+
316
+    /**
317
+     * @dataProvider appVersionsProvider
318
+     */
319
+    public function testIsAppCompatible($ocVersion, $appInfo, $expectedResult): void {
320
+        $this->assertEquals($expectedResult, \OC_App::isAppCompatible($ocVersion, $appInfo));
321
+    }
322
+
323
+    /**
324
+     * Tests that the app order is correct
325
+     */
326
+    public function testGetEnabledAppsIsSorted(): void {
327
+        $apps = \OC_App::getEnabledApps();
328
+        // copy array
329
+        $sortedApps = $apps;
330
+        sort($sortedApps);
331
+        // 'files' is always on top
332
+        unset($sortedApps[array_search('files', $sortedApps)]);
333
+        array_unshift($sortedApps, 'files');
334
+        $this->assertEquals($sortedApps, $apps);
335
+    }
336
+
337
+    /**
338
+     * Providers for the app config values
339
+     */
340
+    public static function appConfigValuesProvider(): array {
341
+        return [
342
+            // logged in user1
343
+            [
344
+                self::TEST_USER1,
345
+                [
346
+                    'files',
347
+                    'app1',
348
+                    'app3',
349
+                    'appforgroup1',
350
+                    'appforgroup12',
351
+                    'cloud_federation_api',
352
+                    'dav',
353
+                    'federatedfilesharing',
354
+                    'lookup_server_connector',
355
+                    'oauth2',
356
+                    'profile',
357
+                    'provisioning_api',
358
+                    'settings',
359
+                    'theming',
360
+                    'twofactor_backupcodes',
361
+                    'viewer',
362
+                    'workflowengine',
363
+                ],
364
+                false
365
+            ],
366
+            // logged in user2
367
+            [
368
+                self::TEST_USER2,
369
+                [
370
+                    'files',
371
+                    'app1',
372
+                    'app3',
373
+                    'appforgroup12',
374
+                    'appforgroup2',
375
+                    'cloud_federation_api',
376
+                    'dav',
377
+                    'federatedfilesharing',
378
+                    'lookup_server_connector',
379
+                    'oauth2',
380
+                    'profile',
381
+                    'provisioning_api',
382
+                    'settings',
383
+                    'theming',
384
+                    'twofactor_backupcodes',
385
+                    'viewer',
386
+                    'workflowengine',
387
+                ],
388
+                false
389
+            ],
390
+            // logged in user3
391
+            [
392
+                self::TEST_USER3,
393
+                [
394
+                    'files',
395
+                    'app1',
396
+                    'app3',
397
+                    'appforgroup1',
398
+                    'appforgroup12',
399
+                    'appforgroup2',
400
+                    'cloud_federation_api',
401
+                    'dav',
402
+                    'federatedfilesharing',
403
+                    'lookup_server_connector',
404
+                    'oauth2',
405
+                    'profile',
406
+                    'provisioning_api',
407
+                    'settings',
408
+                    'theming',
409
+                    'twofactor_backupcodes',
410
+                    'viewer',
411
+                    'workflowengine',
412
+                ],
413
+                false
414
+            ],
415
+            //  no user, returns all apps
416
+            [
417
+                null,
418
+                [
419
+                    'files',
420
+                    'app1',
421
+                    'app3',
422
+                    'appforgroup1',
423
+                    'appforgroup12',
424
+                    'appforgroup2',
425
+                    'cloud_federation_api',
426
+                    'dav',
427
+                    'federatedfilesharing',
428
+                    'lookup_server_connector',
429
+                    'oauth2',
430
+                    'profile',
431
+                    'provisioning_api',
432
+                    'settings',
433
+                    'theming',
434
+                    'twofactor_backupcodes',
435
+                    'viewer',
436
+                    'workflowengine',
437
+                ],
438
+                false,
439
+            ],
440
+            //  user given, but ask for all
441
+            [
442
+                self::TEST_USER1,
443
+                [
444
+                    'files',
445
+                    'app1',
446
+                    'app3',
447
+                    'appforgroup1',
448
+                    'appforgroup12',
449
+                    'appforgroup2',
450
+                    'cloud_federation_api',
451
+                    'dav',
452
+                    'federatedfilesharing',
453
+                    'lookup_server_connector',
454
+                    'oauth2',
455
+                    'profile',
456
+                    'provisioning_api',
457
+                    'settings',
458
+                    'theming',
459
+                    'twofactor_backupcodes',
460
+                    'viewer',
461
+                    'workflowengine',
462
+                ],
463
+                true,
464
+            ],
465
+        ];
466
+    }
467
+
468
+    /**
469
+     * Test enabled apps
470
+     *
471
+     * @dataProvider appConfigValuesProvider
472
+     */
473
+    public function testEnabledApps($user, $expectedApps, $forceAll): void {
474
+        $userManager = Server::get(IUserManager::class);
475
+        $groupManager = Server::get(IGroupManager::class);
476
+        $user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
477
+        $user2 = $userManager->createUser(self::TEST_USER2, 'NotAnEasyPassword123456_');
478
+        $user3 = $userManager->createUser(self::TEST_USER3, 'NotAnEasyPassword123456?');
479
+
480
+        $group1 = $groupManager->createGroup(self::TEST_GROUP1);
481
+        $group1->addUser($user1);
482
+        $group1->addUser($user3);
483
+        $group2 = $groupManager->createGroup(self::TEST_GROUP2);
484
+        $group2->addUser($user2);
485
+        $group2->addUser($user3);
486
+
487
+        \OC_User::setUserId($user);
488
+
489
+        $this->setupAppConfigMock()->expects($this->once())
490
+            ->method('searchValues')
491
+            ->willReturn(
492
+                [
493
+                    'app3' => 'yes',
494
+                    'app2' => 'no',
495
+                    'app1' => 'yes',
496
+                    'appforgroup1' => '["group1"]',
497
+                    'appforgroup2' => '["group2"]',
498
+                    'appforgroup12' => '["group2","group1"]',
499
+                ]
500
+            );
501
+
502
+        $apps = \OC_App::getEnabledApps(false, $forceAll);
503
+
504
+        $this->restoreAppConfig();
505
+        \OC_User::setUserId(null);
506
+
507
+        $user1->delete();
508
+        $user2->delete();
509
+        $user3->delete();
510
+
511
+        $group1->delete();
512
+        $group2->delete();
513
+
514
+        $this->assertEquals($expectedApps, $apps);
515
+    }
516
+
517
+    /**
518
+     * Test isEnabledApps() with cache, not re-reading the list of
519
+     * enabled apps more than once when a user is set.
520
+     */
521
+    public function testEnabledAppsCache(): void {
522
+        $userManager = Server::get(IUserManager::class);
523
+        $user1 = $userManager->createUser(self::TEST_USER1, 'NotAnEasyPassword123456+');
524
+
525
+        \OC_User::setUserId(self::TEST_USER1);
526
+
527
+        $this->setupAppConfigMock()->expects($this->once())
528
+            ->method('searchValues')
529
+            ->willReturn(
530
+                [
531
+                    'app3' => 'yes',
532
+                    'app2' => 'no',
533
+                ]
534
+            );
535
+
536
+        $apps = \OC_App::getEnabledApps();
537
+        $this->assertEquals(['files', 'app3', 'cloud_federation_api', 'dav', 'federatedfilesharing', 'lookup_server_connector', 'oauth2', 'profile', 'provisioning_api', 'settings', 'theming', 'twofactor_backupcodes', 'viewer', 'workflowengine'], $apps);
538
+
539
+        // mock should not be called again here
540
+        $apps = \OC_App::getEnabledApps();
541
+        $this->assertEquals(['files', 'app3', 'cloud_federation_api', 'dav', 'federatedfilesharing', 'lookup_server_connector', 'oauth2', 'profile', 'provisioning_api', 'settings', 'theming', 'twofactor_backupcodes', 'viewer', 'workflowengine'], $apps);
542
+
543
+        $this->restoreAppConfig();
544
+        \OC_User::setUserId(null);
545
+
546
+        $user1->delete();
547
+    }
548
+
549
+
550
+    private function setupAppConfigMock() {
551
+        /** @var AppConfig|MockObject */
552
+        $appConfig = $this->getMockBuilder(AppConfig::class)
553
+            ->onlyMethods(['searchValues'])
554
+            ->setConstructorArgs([Server::get(IDBConnection::class)])
555
+            ->disableOriginalConstructor()
556
+            ->getMock();
557
+
558
+        $this->registerAppConfig($appConfig);
559
+        return $appConfig;
560
+    }
561
+
562
+    /**
563
+     * Register an app config mock for testing purposes.
564
+     *
565
+     * @param IAppConfig $appConfig app config mock
566
+     */
567
+    private function registerAppConfig(AppConfig $appConfig) {
568
+        $this->overwriteService(AppConfig::class, $appConfig);
569
+        $this->overwriteService(AppManager::class, new AppManager(
570
+            Server::get(IUserSession::class),
571
+            Server::get(IConfig::class),
572
+            Server::get(IGroupManager::class),
573
+            Server::get(ICacheFactory::class),
574
+            Server::get(IEventDispatcher::class),
575
+            Server::get(LoggerInterface::class),
576
+            Server::get(ServerVersion::class),
577
+            \OCP\Server::get(ConfigManager::class),
578
+        ));
579
+    }
580
+
581
+    /**
582
+     * Restore the original app config service.
583
+     */
584
+    private function restoreAppConfig() {
585
+        $this->restoreService(AppConfig::class);
586
+        $this->restoreService(AppManager::class);
587
+
588
+        // Remove the cache of the mocked apps list with a forceRefresh
589
+        \OC_App::getEnabledApps();
590
+    }
591
+
592
+    /**
593
+     * Providers for the app data values
594
+     */
595
+    public static function appDataProvider(): array {
596
+        return [
597
+            [
598
+                ['description' => " \t  This is a multiline \n test with \n \t \n \n some new lines   "],
599
+                ['description' => "This is a multiline \n test with \n \t \n \n some new lines"],
600
+            ],
601
+            [
602
+                ['description' => " \t  This is a multiline \n test with \n \t   some new lines   "],
603
+                ['description' => "This is a multiline \n test with \n \t   some new lines"],
604
+            ],
605
+            [
606
+                ['description' => hex2bin('5065726d657420646520732761757468656e7469666965722064616e732070697769676f20646972656374656d656e74206176656320736573206964656e74696669616e7473206f776e636c6f75642073616e73206c65732072657461706572206574206d657420c3a0206a6f757273206365757820636920656e20636173206465206368616e67656d656e74206465206d6f742064652070617373652e0d0a0d')],
607
+                ['description' => "Permet de s'authentifier dans piwigo directement avec ses identifiants owncloud sans les retaper et met à jours ceux ci en cas de changement de mot de passe."],
608
+            ],
609
+            [
610
+                ['not-a-description' => " \t  This is a multiline \n test with \n \t   some new lines   "],
611
+                [
612
+                    'not-a-description' => " \t  This is a multiline \n test with \n \t   some new lines   ",
613
+                    'description' => '',
614
+                ],
615
+            ],
616
+            [
617
+                ['description' => [100, 'bla']],
618
+                ['description' => ''],
619
+            ],
620
+        ];
621
+    }
622
+
623
+    /**
624
+     * Test app info parser
625
+     *
626
+     * @dataProvider appDataProvider
627
+     * @param array $data
628
+     * @param array $expected
629
+     */
630
+    public function testParseAppInfo(array $data, array $expected): void {
631
+        $this->assertSame($expected, \OC_App::parseAppInfo($data));
632
+    }
633
+
634
+    public function testParseAppInfoL10N(): void {
635
+        $parser = new InfoParser();
636
+        $data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-multi-lang.xml');
637
+        $this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
638
+        $this->assertEquals('German', \OC_App::parseAppInfo($data, 'de')['description']);
639
+    }
640
+
641
+    public function testParseAppInfoL10NSingleLanguage(): void {
642
+        $parser = new InfoParser();
643
+        $data = $parser->parse(\OC::$SERVERROOT . '/tests/data/app/description-single-lang.xml');
644
+        $this->assertEquals('English', \OC_App::parseAppInfo($data, 'en')['description']);
645
+    }
646 646
 }
Please login to merge, or discard this patch.
tests/lib/App/AppManagerTest.php 1 patch
Indentation   +853 added lines, -853 removed lines patch added patch discarded remove patch
@@ -37,858 +37,858 @@
 block discarded – undo
37 37
  * @package Test\App
38 38
  */
39 39
 class AppManagerTest extends TestCase {
40
-	protected function getAppConfig(): AppConfig&MockObject {
41
-		$appConfig = [];
42
-		$config = $this->createMock(AppConfig::class);
43
-
44
-		$config->expects($this->any())
45
-			->method('getValue')
46
-			->willReturnCallback(function ($app, $key, $default) use (&$appConfig) {
47
-				return (isset($appConfig[$app]) and isset($appConfig[$app][$key])) ? $appConfig[$app][$key] : $default;
48
-			});
49
-		$config->expects($this->any())
50
-			->method('setValue')
51
-			->willReturnCallback(function ($app, $key, $value) use (&$appConfig): void {
52
-				if (!isset($appConfig[$app])) {
53
-					$appConfig[$app] = [];
54
-				}
55
-				$appConfig[$app][$key] = $value;
56
-			});
57
-		$config->expects($this->any())
58
-			->method('getValues')
59
-			->willReturnCallback(function ($app, $key) use (&$appConfig) {
60
-				if ($app) {
61
-					return $appConfig[$app];
62
-				} else {
63
-					$values = [];
64
-					foreach ($appConfig as $appid => $appData) {
65
-						if (isset($appData[$key])) {
66
-							$values[$appid] = $appData[$key];
67
-						}
68
-					}
69
-					return $values;
70
-				}
71
-			});
72
-		$config->expects($this->any())
73
-			->method('searchValues')
74
-			->willReturnCallback(function ($key, $lazy, $type) use (&$appConfig) {
75
-				$values = [];
76
-				foreach ($appConfig as $appid => $appData) {
77
-					if (isset($appData[$key])) {
78
-						$values[$appid] = $appData[$key];
79
-					}
80
-				}
81
-				return $values;
82
-			});
83
-
84
-		return $config;
85
-	}
86
-
87
-	protected IUserSession&MockObject $userSession;
88
-	private IConfig&MockObject $config;
89
-	protected IGroupManager&MockObject $groupManager;
90
-	protected AppConfig&MockObject $appConfig;
91
-	protected ICache&MockObject $cache;
92
-	protected ICacheFactory&MockObject $cacheFactory;
93
-	protected IEventDispatcher&MockObject $eventDispatcher;
94
-	protected LoggerInterface&MockObject $logger;
95
-	protected IURLGenerator&MockObject $urlGenerator;
96
-	protected ServerVersion&MockObject $serverVersion;
97
-	protected ConfigManager&MockObject $configManager;
98
-
99
-	/** @var IAppManager */
100
-	protected $manager;
101
-
102
-	protected function setUp(): void {
103
-		parent::setUp();
104
-
105
-		$this->userSession = $this->createMock(IUserSession::class);
106
-		$this->groupManager = $this->createMock(IGroupManager::class);
107
-		$this->config = $this->createMock(IConfig::class);
108
-		$this->appConfig = $this->getAppConfig();
109
-		$this->cacheFactory = $this->createMock(ICacheFactory::class);
110
-		$this->cache = $this->createMock(ICache::class);
111
-		$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
112
-		$this->logger = $this->createMock(LoggerInterface::class);
113
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
114
-		$this->serverVersion = $this->createMock(ServerVersion::class);
115
-		$this->configManager = $this->createMock(ConfigManager::class);
116
-
117
-		$this->overwriteService(AppConfig::class, $this->appConfig);
118
-		$this->overwriteService(IURLGenerator::class, $this->urlGenerator);
119
-
120
-		$this->cacheFactory->expects($this->any())
121
-			->method('createDistributed')
122
-			->with('settings')
123
-			->willReturn($this->cache);
124
-
125
-		$this->config
126
-			->method('getSystemValueBool')
127
-			->with('installed', false)
128
-			->willReturn(true);
129
-
130
-		$this->manager = new AppManager(
131
-			$this->userSession,
132
-			$this->config,
133
-			$this->groupManager,
134
-			$this->cacheFactory,
135
-			$this->eventDispatcher,
136
-			$this->logger,
137
-			$this->serverVersion,
138
-			$this->configManager,
139
-		);
140
-	}
141
-
142
-	/**
143
-	 * @dataProvider dataGetAppIcon
144
-	 */
145
-	public function testGetAppIcon($callback, ?bool $dark, ?string $expected): void {
146
-		$this->urlGenerator->expects($this->atLeastOnce())
147
-			->method('imagePath')
148
-			->willReturnCallback($callback);
149
-
150
-		if ($dark !== null) {
151
-			$this->assertEquals($expected, $this->manager->getAppIcon('test', $dark));
152
-		} else {
153
-			$this->assertEquals($expected, $this->manager->getAppIcon('test'));
154
-		}
155
-	}
156
-
157
-	public static function dataGetAppIcon(): array {
158
-		$nothing = function ($appId): void {
159
-			self::assertEquals('test', $appId);
160
-			throw new \RuntimeException();
161
-		};
162
-
163
-		$createCallback = function ($workingIcons) {
164
-			return function ($appId, $icon) use ($workingIcons) {
165
-				self::assertEquals('test', $appId);
166
-				if (in_array($icon, $workingIcons)) {
167
-					return '/path/' . $icon;
168
-				}
169
-				throw new \RuntimeException();
170
-			};
171
-		};
172
-
173
-		return [
174
-			'does not find anything' => [
175
-				$nothing,
176
-				false,
177
-				null,
178
-			],
179
-			'nothing if request dark but only bright available' => [
180
-				$createCallback(['app.svg']),
181
-				true,
182
-				null,
183
-			],
184
-			'nothing if request bright but only dark available' => [
185
-				$createCallback(['app-dark.svg']),
186
-				false,
187
-				null,
188
-			],
189
-			'bright and only app.svg' => [
190
-				$createCallback(['app.svg']),
191
-				false,
192
-				'/path/app.svg',
193
-			],
194
-			'dark and only app-dark.svg' => [
195
-				$createCallback(['app-dark.svg']),
196
-				true,
197
-				'/path/app-dark.svg',
198
-			],
199
-			'dark only appname -dark.svg' => [
200
-				$createCallback(['test-dark.svg']),
201
-				true,
202
-				'/path/test-dark.svg',
203
-			],
204
-			'bright and only appname.svg' => [
205
-				$createCallback(['test.svg']),
206
-				false,
207
-				'/path/test.svg',
208
-			],
209
-			'priotize custom over default' => [
210
-				$createCallback(['app.svg', 'test.svg']),
211
-				false,
212
-				'/path/test.svg',
213
-			],
214
-			'defaults to bright' => [
215
-				$createCallback(['test-dark.svg', 'test.svg']),
216
-				null,
217
-				'/path/test.svg',
218
-			],
219
-			'no dark icon on default' => [
220
-				$createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']),
221
-				false,
222
-				'/path/test.svg',
223
-			],
224
-			'no bright icon on dark' => [
225
-				$createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']),
226
-				true,
227
-				'/path/test-dark.svg',
228
-			],
229
-		];
230
-	}
231
-
232
-	public function testEnableApp(): void {
233
-		// making sure "files_trashbin" is disabled
234
-		if ($this->manager->isEnabledForUser('files_trashbin')) {
235
-			$this->manager->disableApp('files_trashbin');
236
-		}
237
-		$this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('files_trashbin'));
238
-		$this->manager->enableApp('files_trashbin');
239
-		$this->assertEquals('yes', $this->appConfig->getValue('files_trashbin', 'enabled', 'no'));
240
-	}
241
-
242
-	public function testDisableApp(): void {
243
-		$this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppDisableEvent('files_trashbin'));
244
-		$this->manager->disableApp('files_trashbin');
245
-		$this->assertEquals('no', $this->appConfig->getValue('files_trashbin', 'enabled', 'no'));
246
-	}
247
-
248
-	public function testNotEnableIfNotInstalled(): void {
249
-		try {
250
-			$this->manager->enableApp('some_random_name_which_i_hope_is_not_an_app');
251
-			$this->assertFalse(true, 'If this line is reached the expected exception is not thrown.');
252
-		} catch (AppPathNotFoundException $e) {
253
-			// Exception is expected
254
-			$this->assertEquals('Could not find path for some_random_name_which_i_hope_is_not_an_app', $e->getMessage());
255
-		}
256
-
257
-		$this->assertEquals('no', $this->appConfig->getValue(
258
-			'some_random_name_which_i_hope_is_not_an_app', 'enabled', 'no'
259
-		));
260
-	}
261
-
262
-	public function testEnableAppForGroups(): void {
263
-		$group1 = $this->createMock(IGroup::class);
264
-		$group1->method('getGID')
265
-			->willReturn('group1');
266
-		$group2 = $this->createMock(IGroup::class);
267
-		$group2->method('getGID')
268
-			->willReturn('group2');
269
-
270
-		$groups = [$group1, $group2];
271
-
272
-		/** @var AppManager|MockObject $manager */
273
-		$manager = $this->getMockBuilder(AppManager::class)
274
-			->setConstructorArgs([
275
-				$this->userSession,
276
-				$this->config,
277
-				$this->groupManager,
278
-				$this->cacheFactory,
279
-				$this->eventDispatcher,
280
-				$this->logger,
281
-				$this->serverVersion,
282
-				$this->configManager,
283
-			])
284
-			->onlyMethods([
285
-				'getAppPath',
286
-			])
287
-			->getMock();
288
-
289
-		$manager->expects($this->exactly(2))
290
-			->method('getAppPath')
291
-			->with('test')
292
-			->willReturn('apps/test');
293
-
294
-		$this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
295
-
296
-		$manager->enableAppForGroups('test', $groups);
297
-		$this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no'));
298
-	}
299
-
300
-	public static function dataEnableAppForGroupsAllowedTypes(): array {
301
-		return [
302
-			[[]],
303
-			[[
304
-				'types' => [],
305
-			]],
306
-			[[
307
-				'types' => ['nickvergessen'],
308
-			]],
309
-		];
310
-	}
311
-
312
-	/**
313
-	 * @dataProvider dataEnableAppForGroupsAllowedTypes
314
-	 *
315
-	 * @param array $appInfo
316
-	 */
317
-	public function testEnableAppForGroupsAllowedTypes(array $appInfo): void {
318
-		$group1 = $this->createMock(IGroup::class);
319
-		$group1->method('getGID')
320
-			->willReturn('group1');
321
-		$group2 = $this->createMock(IGroup::class);
322
-		$group2->method('getGID')
323
-			->willReturn('group2');
324
-
325
-		$groups = [$group1, $group2];
326
-
327
-		/** @var AppManager|MockObject $manager */
328
-		$manager = $this->getMockBuilder(AppManager::class)
329
-			->setConstructorArgs([
330
-				$this->userSession,
331
-				$this->config,
332
-				$this->groupManager,
333
-				$this->cacheFactory,
334
-				$this->eventDispatcher,
335
-				$this->logger,
336
-				$this->serverVersion,
337
-				$this->configManager,
338
-			])
339
-			->onlyMethods([
340
-				'getAppPath',
341
-				'getAppInfo',
342
-			])
343
-			->getMock();
344
-
345
-		$manager->expects($this->once())
346
-			->method('getAppPath')
347
-			->with('test')
348
-			->willReturn('');
349
-
350
-		$manager->expects($this->once())
351
-			->method('getAppInfo')
352
-			->with('test')
353
-			->willReturn($appInfo);
354
-
355
-		$this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
356
-
357
-		$manager->enableAppForGroups('test', $groups);
358
-		$this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no'));
359
-	}
360
-
361
-	public static function dataEnableAppForGroupsForbiddenTypes(): array {
362
-		return [
363
-			['filesystem'],
364
-			['prelogin'],
365
-			['authentication'],
366
-			['logging'],
367
-			['prevent_group_restriction'],
368
-		];
369
-	}
370
-
371
-	/**
372
-	 * @dataProvider dataEnableAppForGroupsForbiddenTypes
373
-	 *
374
-	 * @param string $type
375
-	 *
376
-	 */
377
-	public function testEnableAppForGroupsForbiddenTypes($type): void {
378
-		$this->expectException(\Exception::class);
379
-		$this->expectExceptionMessage('test can\'t be enabled for groups.');
380
-
381
-		$group1 = $this->createMock(IGroup::class);
382
-		$group1->method('getGID')
383
-			->willReturn('group1');
384
-		$group2 = $this->createMock(IGroup::class);
385
-		$group2->method('getGID')
386
-			->willReturn('group2');
387
-
388
-		$groups = [$group1, $group2];
389
-
390
-		/** @var AppManager|MockObject $manager */
391
-		$manager = $this->getMockBuilder(AppManager::class)
392
-			->setConstructorArgs([
393
-				$this->userSession,
394
-				$this->config,
395
-				$this->groupManager,
396
-				$this->cacheFactory,
397
-				$this->eventDispatcher,
398
-				$this->logger,
399
-				$this->serverVersion,
400
-				$this->configManager,
401
-			])
402
-			->onlyMethods([
403
-				'getAppPath',
404
-				'getAppInfo',
405
-			])
406
-			->getMock();
407
-
408
-		$manager->expects($this->once())
409
-			->method('getAppPath')
410
-			->with('test')
411
-			->willReturn('');
412
-
413
-		$manager->expects($this->once())
414
-			->method('getAppInfo')
415
-			->with('test')
416
-			->willReturn([
417
-				'types' => [$type],
418
-			]);
419
-
420
-		$this->eventDispatcher->expects($this->never())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
421
-
422
-		$manager->enableAppForGroups('test', $groups);
423
-	}
424
-
425
-	public function testIsInstalledEnabled(): void {
426
-		$this->appConfig->setValue('test', 'enabled', 'yes');
427
-		$this->assertTrue($this->manager->isEnabledForAnyone('test'));
428
-	}
429
-
430
-	public function testIsInstalledDisabled(): void {
431
-		$this->appConfig->setValue('test', 'enabled', 'no');
432
-		$this->assertFalse($this->manager->isEnabledForAnyone('test'));
433
-	}
434
-
435
-	public function testIsInstalledEnabledForGroups(): void {
436
-		$this->appConfig->setValue('test', 'enabled', '["foo"]');
437
-		$this->assertTrue($this->manager->isEnabledForAnyone('test'));
438
-	}
439
-
440
-	private function newUser($uid) {
441
-		$user = $this->createMock(IUser::class);
442
-		$user->method('getUID')
443
-			->willReturn($uid);
444
-
445
-		return $user;
446
-	}
447
-
448
-	public function testIsEnabledForUserEnabled(): void {
449
-		$this->appConfig->setValue('test', 'enabled', 'yes');
450
-		$user = $this->newUser('user1');
451
-		$this->assertTrue($this->manager->isEnabledForUser('test', $user));
452
-	}
453
-
454
-	public function testIsEnabledForUserDisabled(): void {
455
-		$this->appConfig->setValue('test', 'enabled', 'no');
456
-		$user = $this->newUser('user1');
457
-		$this->assertFalse($this->manager->isEnabledForUser('test', $user));
458
-	}
459
-
460
-	public function testGetAppPath(): void {
461
-		$this->assertEquals(\OC::$SERVERROOT . '/apps/files', $this->manager->getAppPath('files'));
462
-	}
463
-
464
-	public function testGetAppPathSymlink(): void {
465
-		$fakeAppDirname = sha1(uniqid('test', true));
466
-		$fakeAppPath = sys_get_temp_dir() . '/' . $fakeAppDirname;
467
-		$fakeAppLink = \OC::$SERVERROOT . '/' . $fakeAppDirname;
468
-
469
-		mkdir($fakeAppPath);
470
-		if (symlink($fakeAppPath, $fakeAppLink) === false) {
471
-			$this->markTestSkipped('Failed to create symlink');
472
-		}
473
-
474
-		// Use the symlink as the app path
475
-		\OC::$APPSROOTS[] = [
476
-			'path' => $fakeAppLink,
477
-			'url' => \OC::$WEBROOT . '/' . $fakeAppDirname,
478
-			'writable' => false,
479
-		];
480
-
481
-		$fakeTestAppPath = $fakeAppPath . '/' . 'test-test-app';
482
-		mkdir($fakeTestAppPath);
483
-
484
-		$generatedAppPath = $this->manager->getAppPath('test-test-app');
485
-
486
-		rmdir($fakeTestAppPath);
487
-		unlink($fakeAppLink);
488
-		rmdir($fakeAppPath);
489
-
490
-		$this->assertEquals($fakeAppLink . '/test-test-app', $generatedAppPath);
491
-	}
492
-
493
-	public function testGetAppPathFail(): void {
494
-		$this->expectException(AppPathNotFoundException::class);
495
-		$this->manager->getAppPath('testnotexisting');
496
-	}
497
-
498
-	public function testIsEnabledForUserEnabledForGroup(): void {
499
-		$user = $this->newUser('user1');
500
-		$this->groupManager->expects($this->once())
501
-			->method('getUserGroupIds')
502
-			->with($user)
503
-			->willReturn(['foo', 'bar']);
504
-
505
-		$this->appConfig->setValue('test', 'enabled', '["foo"]');
506
-		$this->assertTrue($this->manager->isEnabledForUser('test', $user));
507
-	}
508
-
509
-	public function testIsEnabledForUserDisabledForGroup(): void {
510
-		$user = $this->newUser('user1');
511
-		$this->groupManager->expects($this->once())
512
-			->method('getUserGroupIds')
513
-			->with($user)
514
-			->willReturn(['bar']);
515
-
516
-		$this->appConfig->setValue('test', 'enabled', '["foo"]');
517
-		$this->assertFalse($this->manager->isEnabledForUser('test', $user));
518
-	}
519
-
520
-	public function testIsEnabledForUserLoggedOut(): void {
521
-		$this->appConfig->setValue('test', 'enabled', '["foo"]');
522
-		$this->assertFalse($this->manager->isEnabledForUser('test'));
523
-	}
524
-
525
-	public function testIsEnabledForUserLoggedIn(): void {
526
-		$user = $this->newUser('user1');
527
-
528
-		$this->userSession->expects($this->once())
529
-			->method('getUser')
530
-			->willReturn($user);
531
-		$this->groupManager->expects($this->once())
532
-			->method('getUserGroupIds')
533
-			->with($user)
534
-			->willReturn(['foo', 'bar']);
535
-
536
-		$this->appConfig->setValue('test', 'enabled', '["foo"]');
537
-		$this->assertTrue($this->manager->isEnabledForUser('test'));
538
-	}
539
-
540
-	public function testGetEnabledApps(): void {
541
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
542
-		$this->appConfig->setValue('test2', 'enabled', 'no');
543
-		$this->appConfig->setValue('test3', 'enabled', '["foo"]');
544
-		$apps = [
545
-			'cloud_federation_api',
546
-			'dav',
547
-			'federatedfilesharing',
548
-			'files',
549
-			'lookup_server_connector',
550
-			'oauth2',
551
-			'profile',
552
-			'provisioning_api',
553
-			'settings',
554
-			'test1',
555
-			'test3',
556
-			'theming',
557
-			'twofactor_backupcodes',
558
-			'viewer',
559
-			'workflowengine',
560
-		];
561
-		$this->assertEquals($apps, $this->manager->getEnabledApps());
562
-	}
563
-
564
-	public function testGetAppsForUser(): void {
565
-		$user = $this->newUser('user1');
566
-		$this->groupManager->expects($this->any())
567
-			->method('getUserGroupIds')
568
-			->with($user)
569
-			->willReturn(['foo', 'bar']);
570
-
571
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
572
-		$this->appConfig->setValue('test2', 'enabled', 'no');
573
-		$this->appConfig->setValue('test3', 'enabled', '["foo"]');
574
-		$this->appConfig->setValue('test4', 'enabled', '["asd"]');
575
-		$enabled = [
576
-			'cloud_federation_api',
577
-			'dav',
578
-			'federatedfilesharing',
579
-			'files',
580
-			'lookup_server_connector',
581
-			'oauth2',
582
-			'profile',
583
-			'provisioning_api',
584
-			'settings',
585
-			'test1',
586
-			'test3',
587
-			'theming',
588
-			'twofactor_backupcodes',
589
-			'viewer',
590
-			'workflowengine',
591
-		];
592
-		$this->assertEquals($enabled, $this->manager->getEnabledAppsForUser($user));
593
-	}
594
-
595
-	public function testGetAppsNeedingUpgrade(): void {
596
-		/** @var AppManager|MockObject $manager */
597
-		$manager = $this->getMockBuilder(AppManager::class)
598
-			->setConstructorArgs([
599
-				$this->userSession,
600
-				$this->config,
601
-				$this->groupManager,
602
-				$this->cacheFactory,
603
-				$this->eventDispatcher,
604
-				$this->logger,
605
-				$this->serverVersion,
606
-				$this->configManager,
607
-			])
608
-			->onlyMethods(['getAppInfo'])
609
-			->getMock();
610
-
611
-		$appInfos = [
612
-			'cloud_federation_api' => ['id' => 'cloud_federation_api'],
613
-			'dav' => ['id' => 'dav'],
614
-			'files' => ['id' => 'files'],
615
-			'federatedfilesharing' => ['id' => 'federatedfilesharing'],
616
-			'profile' => ['id' => 'profile'],
617
-			'provisioning_api' => ['id' => 'provisioning_api'],
618
-			'lookup_server_connector' => ['id' => 'lookup_server_connector'],
619
-			'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '9.0.0'],
620
-			'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
621
-			'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
622
-			'test4' => ['id' => 'test4', 'version' => '3.0.0', 'requiremin' => '8.1.0'],
623
-			'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
624
-			'settings' => ['id' => 'settings'],
625
-			'theming' => ['id' => 'theming'],
626
-			'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'],
627
-			'viewer' => ['id' => 'viewer'],
628
-			'workflowengine' => ['id' => 'workflowengine'],
629
-			'oauth2' => ['id' => 'oauth2'],
630
-		];
631
-
632
-		$manager->expects($this->any())
633
-			->method('getAppInfo')
634
-			->willReturnCallback(
635
-				function ($appId) use ($appInfos) {
636
-					return $appInfos[$appId];
637
-				}
638
-			);
639
-
640
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
641
-		$this->appConfig->setValue('test1', 'installed_version', '1.0.0');
642
-		$this->appConfig->setValue('test2', 'enabled', 'yes');
643
-		$this->appConfig->setValue('test2', 'installed_version', '1.0.0');
644
-		$this->appConfig->setValue('test3', 'enabled', 'yes');
645
-		$this->appConfig->setValue('test3', 'installed_version', '1.0.0');
646
-		$this->appConfig->setValue('test4', 'enabled', 'yes');
647
-		$this->appConfig->setValue('test4', 'installed_version', '2.4.0');
648
-
649
-		$apps = $manager->getAppsNeedingUpgrade('8.2.0');
650
-
651
-		$this->assertCount(2, $apps);
652
-		$this->assertEquals('test1', $apps[0]['id']);
653
-		$this->assertEquals('test4', $apps[1]['id']);
654
-	}
655
-
656
-	public function testGetIncompatibleApps(): void {
657
-		/** @var AppManager|MockObject $manager */
658
-		$manager = $this->getMockBuilder(AppManager::class)
659
-			->setConstructorArgs([
660
-				$this->userSession,
661
-				$this->config,
662
-				$this->groupManager,
663
-				$this->cacheFactory,
664
-				$this->eventDispatcher,
665
-				$this->logger,
666
-				$this->serverVersion,
667
-				$this->configManager,
668
-			])
669
-			->onlyMethods(['getAppInfo'])
670
-			->getMock();
671
-
672
-		$appInfos = [
673
-			'cloud_federation_api' => ['id' => 'cloud_federation_api'],
674
-			'dav' => ['id' => 'dav'],
675
-			'files' => ['id' => 'files'],
676
-			'federatedfilesharing' => ['id' => 'federatedfilesharing'],
677
-			'profile' => ['id' => 'profile'],
678
-			'provisioning_api' => ['id' => 'provisioning_api'],
679
-			'lookup_server_connector' => ['id' => 'lookup_server_connector'],
680
-			'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '8.0.0'],
681
-			'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
682
-			'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
683
-			'settings' => ['id' => 'settings'],
684
-			'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
685
-			'theming' => ['id' => 'theming'],
686
-			'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'],
687
-			'workflowengine' => ['id' => 'workflowengine'],
688
-			'oauth2' => ['id' => 'oauth2'],
689
-			'viewer' => ['id' => 'viewer'],
690
-		];
691
-
692
-		$manager->expects($this->any())
693
-			->method('getAppInfo')
694
-			->willReturnCallback(
695
-				function ($appId) use ($appInfos) {
696
-					return $appInfos[$appId];
697
-				}
698
-			);
699
-
700
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
701
-		$this->appConfig->setValue('test2', 'enabled', 'yes');
702
-		$this->appConfig->setValue('test3', 'enabled', 'yes');
703
-
704
-		$apps = $manager->getIncompatibleApps('8.2.0');
705
-
706
-		$this->assertCount(2, $apps);
707
-		$this->assertEquals('test1', $apps[0]['id']);
708
-		$this->assertEquals('test3', $apps[1]['id']);
709
-	}
710
-
711
-	public function testGetEnabledAppsForGroup(): void {
712
-		$group = $this->createMock(IGroup::class);
713
-		$group->expects($this->any())
714
-			->method('getGID')
715
-			->willReturn('foo');
716
-
717
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
718
-		$this->appConfig->setValue('test2', 'enabled', 'no');
719
-		$this->appConfig->setValue('test3', 'enabled', '["foo"]');
720
-		$this->appConfig->setValue('test4', 'enabled', '["asd"]');
721
-		$enabled = [
722
-			'cloud_federation_api',
723
-			'dav',
724
-			'federatedfilesharing',
725
-			'files',
726
-			'lookup_server_connector',
727
-			'oauth2',
728
-			'profile',
729
-			'provisioning_api',
730
-			'settings',
731
-			'test1',
732
-			'test3',
733
-			'theming',
734
-			'twofactor_backupcodes',
735
-			'viewer',
736
-			'workflowengine',
737
-		];
738
-		$this->assertEquals($enabled, $this->manager->getEnabledAppsForGroup($group));
739
-	}
740
-
741
-	public function testGetAppRestriction(): void {
742
-		$this->appConfig->setValue('test1', 'enabled', 'yes');
743
-		$this->appConfig->setValue('test2', 'enabled', 'no');
744
-		$this->appConfig->setValue('test3', 'enabled', '["foo"]');
745
-
746
-		$this->assertEquals([], $this->manager->getAppRestriction('test1'));
747
-		$this->assertEquals([], $this->manager->getAppRestriction('test2'));
748
-		$this->assertEquals(['foo'], $this->manager->getAppRestriction('test3'));
749
-	}
750
-
751
-	public static function isBackendRequiredDataProvider(): array {
752
-		return [
753
-			// backend available
754
-			[
755
-				'caldav',
756
-				['app1' => ['caldav']],
757
-				true,
758
-			],
759
-			[
760
-				'caldav',
761
-				['app1' => [], 'app2' => ['foo'], 'app3' => ['caldav']],
762
-				true,
763
-			],
764
-			// backend not available
765
-			[
766
-				'caldav',
767
-				['app3' => [], 'app1' => ['foo'], 'app2' => ['bar', 'baz']],
768
-				false,
769
-			],
770
-			// no app available
771
-			[
772
-				'caldav',
773
-				[],
774
-				false,
775
-			],
776
-		];
777
-	}
778
-
779
-	/**
780
-	 * @dataProvider isBackendRequiredDataProvider
781
-	 */
782
-	public function testIsBackendRequired(
783
-		string $backend,
784
-		array $appBackends,
785
-		bool $expected,
786
-	): void {
787
-		$appInfoData = array_map(
788
-			static fn (array $backends) => ['dependencies' => ['backend' => $backends]],
789
-			$appBackends,
790
-		);
791
-
792
-		$reflection = new \ReflectionClass($this->manager);
793
-		$property = $reflection->getProperty('appInfos');
794
-		$property->setValue($this->manager, $appInfoData);
795
-
796
-		$this->assertEquals($expected, $this->manager->isBackendRequired($backend));
797
-	}
798
-
799
-	public function testGetAppVersion() {
800
-		$manager = $this->getMockBuilder(AppManager::class)
801
-			->setConstructorArgs([
802
-				$this->userSession,
803
-				$this->config,
804
-				$this->groupManager,
805
-				$this->cacheFactory,
806
-				$this->eventDispatcher,
807
-				$this->logger,
808
-				$this->serverVersion,
809
-				$this->configManager,
810
-			])
811
-			->onlyMethods([
812
-				'getAppInfo',
813
-			])
814
-			->getMock();
815
-
816
-		$manager->expects(self::once())
817
-			->method('getAppInfo')
818
-			->with('myapp')
819
-			->willReturn(['version' => '99.99.99-rc.99']);
820
-
821
-		$this->serverVersion
822
-			->expects(self::never())
823
-			->method('getVersionString');
824
-
825
-		$this->assertEquals(
826
-			'99.99.99-rc.99',
827
-			$manager->getAppVersion('myapp'),
828
-		);
829
-	}
830
-
831
-	public function testGetAppVersionCore() {
832
-		$manager = $this->getMockBuilder(AppManager::class)
833
-			->setConstructorArgs([
834
-				$this->userSession,
835
-				$this->config,
836
-				$this->groupManager,
837
-				$this->cacheFactory,
838
-				$this->eventDispatcher,
839
-				$this->logger,
840
-				$this->serverVersion,
841
-				$this->configManager,
842
-			])
843
-			->onlyMethods([
844
-				'getAppInfo',
845
-			])
846
-			->getMock();
847
-
848
-		$manager->expects(self::never())
849
-			->method('getAppInfo');
850
-
851
-		$this->serverVersion
852
-			->expects(self::once())
853
-			->method('getVersionString')
854
-			->willReturn('1.2.3-beta.4');
855
-
856
-		$this->assertEquals(
857
-			'1.2.3-beta.4',
858
-			$manager->getAppVersion('core'),
859
-		);
860
-	}
861
-
862
-	public function testGetAppVersionUnknown() {
863
-		$manager = $this->getMockBuilder(AppManager::class)
864
-			->setConstructorArgs([
865
-				$this->userSession,
866
-				$this->config,
867
-				$this->groupManager,
868
-				$this->cacheFactory,
869
-				$this->eventDispatcher,
870
-				$this->logger,
871
-				$this->serverVersion,
872
-				$this->configManager,
873
-			])
874
-			->onlyMethods([
875
-				'getAppInfo',
876
-			])
877
-			->getMock();
878
-
879
-		$manager->expects(self::once())
880
-			->method('getAppInfo')
881
-			->with('unknown')
882
-			->willReturn(null);
883
-
884
-		$this->serverVersion
885
-			->expects(self::never())
886
-			->method('getVersionString');
887
-
888
-		$this->assertEquals(
889
-			'0',
890
-			$manager->getAppVersion('unknown'),
891
-		);
892
-	}
40
+    protected function getAppConfig(): AppConfig&MockObject {
41
+        $appConfig = [];
42
+        $config = $this->createMock(AppConfig::class);
43
+
44
+        $config->expects($this->any())
45
+            ->method('getValue')
46
+            ->willReturnCallback(function ($app, $key, $default) use (&$appConfig) {
47
+                return (isset($appConfig[$app]) and isset($appConfig[$app][$key])) ? $appConfig[$app][$key] : $default;
48
+            });
49
+        $config->expects($this->any())
50
+            ->method('setValue')
51
+            ->willReturnCallback(function ($app, $key, $value) use (&$appConfig): void {
52
+                if (!isset($appConfig[$app])) {
53
+                    $appConfig[$app] = [];
54
+                }
55
+                $appConfig[$app][$key] = $value;
56
+            });
57
+        $config->expects($this->any())
58
+            ->method('getValues')
59
+            ->willReturnCallback(function ($app, $key) use (&$appConfig) {
60
+                if ($app) {
61
+                    return $appConfig[$app];
62
+                } else {
63
+                    $values = [];
64
+                    foreach ($appConfig as $appid => $appData) {
65
+                        if (isset($appData[$key])) {
66
+                            $values[$appid] = $appData[$key];
67
+                        }
68
+                    }
69
+                    return $values;
70
+                }
71
+            });
72
+        $config->expects($this->any())
73
+            ->method('searchValues')
74
+            ->willReturnCallback(function ($key, $lazy, $type) use (&$appConfig) {
75
+                $values = [];
76
+                foreach ($appConfig as $appid => $appData) {
77
+                    if (isset($appData[$key])) {
78
+                        $values[$appid] = $appData[$key];
79
+                    }
80
+                }
81
+                return $values;
82
+            });
83
+
84
+        return $config;
85
+    }
86
+
87
+    protected IUserSession&MockObject $userSession;
88
+    private IConfig&MockObject $config;
89
+    protected IGroupManager&MockObject $groupManager;
90
+    protected AppConfig&MockObject $appConfig;
91
+    protected ICache&MockObject $cache;
92
+    protected ICacheFactory&MockObject $cacheFactory;
93
+    protected IEventDispatcher&MockObject $eventDispatcher;
94
+    protected LoggerInterface&MockObject $logger;
95
+    protected IURLGenerator&MockObject $urlGenerator;
96
+    protected ServerVersion&MockObject $serverVersion;
97
+    protected ConfigManager&MockObject $configManager;
98
+
99
+    /** @var IAppManager */
100
+    protected $manager;
101
+
102
+    protected function setUp(): void {
103
+        parent::setUp();
104
+
105
+        $this->userSession = $this->createMock(IUserSession::class);
106
+        $this->groupManager = $this->createMock(IGroupManager::class);
107
+        $this->config = $this->createMock(IConfig::class);
108
+        $this->appConfig = $this->getAppConfig();
109
+        $this->cacheFactory = $this->createMock(ICacheFactory::class);
110
+        $this->cache = $this->createMock(ICache::class);
111
+        $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
112
+        $this->logger = $this->createMock(LoggerInterface::class);
113
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
114
+        $this->serverVersion = $this->createMock(ServerVersion::class);
115
+        $this->configManager = $this->createMock(ConfigManager::class);
116
+
117
+        $this->overwriteService(AppConfig::class, $this->appConfig);
118
+        $this->overwriteService(IURLGenerator::class, $this->urlGenerator);
119
+
120
+        $this->cacheFactory->expects($this->any())
121
+            ->method('createDistributed')
122
+            ->with('settings')
123
+            ->willReturn($this->cache);
124
+
125
+        $this->config
126
+            ->method('getSystemValueBool')
127
+            ->with('installed', false)
128
+            ->willReturn(true);
129
+
130
+        $this->manager = new AppManager(
131
+            $this->userSession,
132
+            $this->config,
133
+            $this->groupManager,
134
+            $this->cacheFactory,
135
+            $this->eventDispatcher,
136
+            $this->logger,
137
+            $this->serverVersion,
138
+            $this->configManager,
139
+        );
140
+    }
141
+
142
+    /**
143
+     * @dataProvider dataGetAppIcon
144
+     */
145
+    public function testGetAppIcon($callback, ?bool $dark, ?string $expected): void {
146
+        $this->urlGenerator->expects($this->atLeastOnce())
147
+            ->method('imagePath')
148
+            ->willReturnCallback($callback);
149
+
150
+        if ($dark !== null) {
151
+            $this->assertEquals($expected, $this->manager->getAppIcon('test', $dark));
152
+        } else {
153
+            $this->assertEquals($expected, $this->manager->getAppIcon('test'));
154
+        }
155
+    }
156
+
157
+    public static function dataGetAppIcon(): array {
158
+        $nothing = function ($appId): void {
159
+            self::assertEquals('test', $appId);
160
+            throw new \RuntimeException();
161
+        };
162
+
163
+        $createCallback = function ($workingIcons) {
164
+            return function ($appId, $icon) use ($workingIcons) {
165
+                self::assertEquals('test', $appId);
166
+                if (in_array($icon, $workingIcons)) {
167
+                    return '/path/' . $icon;
168
+                }
169
+                throw new \RuntimeException();
170
+            };
171
+        };
172
+
173
+        return [
174
+            'does not find anything' => [
175
+                $nothing,
176
+                false,
177
+                null,
178
+            ],
179
+            'nothing if request dark but only bright available' => [
180
+                $createCallback(['app.svg']),
181
+                true,
182
+                null,
183
+            ],
184
+            'nothing if request bright but only dark available' => [
185
+                $createCallback(['app-dark.svg']),
186
+                false,
187
+                null,
188
+            ],
189
+            'bright and only app.svg' => [
190
+                $createCallback(['app.svg']),
191
+                false,
192
+                '/path/app.svg',
193
+            ],
194
+            'dark and only app-dark.svg' => [
195
+                $createCallback(['app-dark.svg']),
196
+                true,
197
+                '/path/app-dark.svg',
198
+            ],
199
+            'dark only appname -dark.svg' => [
200
+                $createCallback(['test-dark.svg']),
201
+                true,
202
+                '/path/test-dark.svg',
203
+            ],
204
+            'bright and only appname.svg' => [
205
+                $createCallback(['test.svg']),
206
+                false,
207
+                '/path/test.svg',
208
+            ],
209
+            'priotize custom over default' => [
210
+                $createCallback(['app.svg', 'test.svg']),
211
+                false,
212
+                '/path/test.svg',
213
+            ],
214
+            'defaults to bright' => [
215
+                $createCallback(['test-dark.svg', 'test.svg']),
216
+                null,
217
+                '/path/test.svg',
218
+            ],
219
+            'no dark icon on default' => [
220
+                $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']),
221
+                false,
222
+                '/path/test.svg',
223
+            ],
224
+            'no bright icon on dark' => [
225
+                $createCallback(['test-dark.svg', 'test.svg', 'app-dark.svg', 'app.svg']),
226
+                true,
227
+                '/path/test-dark.svg',
228
+            ],
229
+        ];
230
+    }
231
+
232
+    public function testEnableApp(): void {
233
+        // making sure "files_trashbin" is disabled
234
+        if ($this->manager->isEnabledForUser('files_trashbin')) {
235
+            $this->manager->disableApp('files_trashbin');
236
+        }
237
+        $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('files_trashbin'));
238
+        $this->manager->enableApp('files_trashbin');
239
+        $this->assertEquals('yes', $this->appConfig->getValue('files_trashbin', 'enabled', 'no'));
240
+    }
241
+
242
+    public function testDisableApp(): void {
243
+        $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppDisableEvent('files_trashbin'));
244
+        $this->manager->disableApp('files_trashbin');
245
+        $this->assertEquals('no', $this->appConfig->getValue('files_trashbin', 'enabled', 'no'));
246
+    }
247
+
248
+    public function testNotEnableIfNotInstalled(): void {
249
+        try {
250
+            $this->manager->enableApp('some_random_name_which_i_hope_is_not_an_app');
251
+            $this->assertFalse(true, 'If this line is reached the expected exception is not thrown.');
252
+        } catch (AppPathNotFoundException $e) {
253
+            // Exception is expected
254
+            $this->assertEquals('Could not find path for some_random_name_which_i_hope_is_not_an_app', $e->getMessage());
255
+        }
256
+
257
+        $this->assertEquals('no', $this->appConfig->getValue(
258
+            'some_random_name_which_i_hope_is_not_an_app', 'enabled', 'no'
259
+        ));
260
+    }
261
+
262
+    public function testEnableAppForGroups(): void {
263
+        $group1 = $this->createMock(IGroup::class);
264
+        $group1->method('getGID')
265
+            ->willReturn('group1');
266
+        $group2 = $this->createMock(IGroup::class);
267
+        $group2->method('getGID')
268
+            ->willReturn('group2');
269
+
270
+        $groups = [$group1, $group2];
271
+
272
+        /** @var AppManager|MockObject $manager */
273
+        $manager = $this->getMockBuilder(AppManager::class)
274
+            ->setConstructorArgs([
275
+                $this->userSession,
276
+                $this->config,
277
+                $this->groupManager,
278
+                $this->cacheFactory,
279
+                $this->eventDispatcher,
280
+                $this->logger,
281
+                $this->serverVersion,
282
+                $this->configManager,
283
+            ])
284
+            ->onlyMethods([
285
+                'getAppPath',
286
+            ])
287
+            ->getMock();
288
+
289
+        $manager->expects($this->exactly(2))
290
+            ->method('getAppPath')
291
+            ->with('test')
292
+            ->willReturn('apps/test');
293
+
294
+        $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
295
+
296
+        $manager->enableAppForGroups('test', $groups);
297
+        $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no'));
298
+    }
299
+
300
+    public static function dataEnableAppForGroupsAllowedTypes(): array {
301
+        return [
302
+            [[]],
303
+            [[
304
+                'types' => [],
305
+            ]],
306
+            [[
307
+                'types' => ['nickvergessen'],
308
+            ]],
309
+        ];
310
+    }
311
+
312
+    /**
313
+     * @dataProvider dataEnableAppForGroupsAllowedTypes
314
+     *
315
+     * @param array $appInfo
316
+     */
317
+    public function testEnableAppForGroupsAllowedTypes(array $appInfo): void {
318
+        $group1 = $this->createMock(IGroup::class);
319
+        $group1->method('getGID')
320
+            ->willReturn('group1');
321
+        $group2 = $this->createMock(IGroup::class);
322
+        $group2->method('getGID')
323
+            ->willReturn('group2');
324
+
325
+        $groups = [$group1, $group2];
326
+
327
+        /** @var AppManager|MockObject $manager */
328
+        $manager = $this->getMockBuilder(AppManager::class)
329
+            ->setConstructorArgs([
330
+                $this->userSession,
331
+                $this->config,
332
+                $this->groupManager,
333
+                $this->cacheFactory,
334
+                $this->eventDispatcher,
335
+                $this->logger,
336
+                $this->serverVersion,
337
+                $this->configManager,
338
+            ])
339
+            ->onlyMethods([
340
+                'getAppPath',
341
+                'getAppInfo',
342
+            ])
343
+            ->getMock();
344
+
345
+        $manager->expects($this->once())
346
+            ->method('getAppPath')
347
+            ->with('test')
348
+            ->willReturn('');
349
+
350
+        $manager->expects($this->once())
351
+            ->method('getAppInfo')
352
+            ->with('test')
353
+            ->willReturn($appInfo);
354
+
355
+        $this->eventDispatcher->expects($this->once())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
356
+
357
+        $manager->enableAppForGroups('test', $groups);
358
+        $this->assertEquals('["group1","group2"]', $this->appConfig->getValue('test', 'enabled', 'no'));
359
+    }
360
+
361
+    public static function dataEnableAppForGroupsForbiddenTypes(): array {
362
+        return [
363
+            ['filesystem'],
364
+            ['prelogin'],
365
+            ['authentication'],
366
+            ['logging'],
367
+            ['prevent_group_restriction'],
368
+        ];
369
+    }
370
+
371
+    /**
372
+     * @dataProvider dataEnableAppForGroupsForbiddenTypes
373
+     *
374
+     * @param string $type
375
+     *
376
+     */
377
+    public function testEnableAppForGroupsForbiddenTypes($type): void {
378
+        $this->expectException(\Exception::class);
379
+        $this->expectExceptionMessage('test can\'t be enabled for groups.');
380
+
381
+        $group1 = $this->createMock(IGroup::class);
382
+        $group1->method('getGID')
383
+            ->willReturn('group1');
384
+        $group2 = $this->createMock(IGroup::class);
385
+        $group2->method('getGID')
386
+            ->willReturn('group2');
387
+
388
+        $groups = [$group1, $group2];
389
+
390
+        /** @var AppManager|MockObject $manager */
391
+        $manager = $this->getMockBuilder(AppManager::class)
392
+            ->setConstructorArgs([
393
+                $this->userSession,
394
+                $this->config,
395
+                $this->groupManager,
396
+                $this->cacheFactory,
397
+                $this->eventDispatcher,
398
+                $this->logger,
399
+                $this->serverVersion,
400
+                $this->configManager,
401
+            ])
402
+            ->onlyMethods([
403
+                'getAppPath',
404
+                'getAppInfo',
405
+            ])
406
+            ->getMock();
407
+
408
+        $manager->expects($this->once())
409
+            ->method('getAppPath')
410
+            ->with('test')
411
+            ->willReturn('');
412
+
413
+        $manager->expects($this->once())
414
+            ->method('getAppInfo')
415
+            ->with('test')
416
+            ->willReturn([
417
+                'types' => [$type],
418
+            ]);
419
+
420
+        $this->eventDispatcher->expects($this->never())->method('dispatchTyped')->with(new AppEnableEvent('test', ['group1', 'group2']));
421
+
422
+        $manager->enableAppForGroups('test', $groups);
423
+    }
424
+
425
+    public function testIsInstalledEnabled(): void {
426
+        $this->appConfig->setValue('test', 'enabled', 'yes');
427
+        $this->assertTrue($this->manager->isEnabledForAnyone('test'));
428
+    }
429
+
430
+    public function testIsInstalledDisabled(): void {
431
+        $this->appConfig->setValue('test', 'enabled', 'no');
432
+        $this->assertFalse($this->manager->isEnabledForAnyone('test'));
433
+    }
434
+
435
+    public function testIsInstalledEnabledForGroups(): void {
436
+        $this->appConfig->setValue('test', 'enabled', '["foo"]');
437
+        $this->assertTrue($this->manager->isEnabledForAnyone('test'));
438
+    }
439
+
440
+    private function newUser($uid) {
441
+        $user = $this->createMock(IUser::class);
442
+        $user->method('getUID')
443
+            ->willReturn($uid);
444
+
445
+        return $user;
446
+    }
447
+
448
+    public function testIsEnabledForUserEnabled(): void {
449
+        $this->appConfig->setValue('test', 'enabled', 'yes');
450
+        $user = $this->newUser('user1');
451
+        $this->assertTrue($this->manager->isEnabledForUser('test', $user));
452
+    }
453
+
454
+    public function testIsEnabledForUserDisabled(): void {
455
+        $this->appConfig->setValue('test', 'enabled', 'no');
456
+        $user = $this->newUser('user1');
457
+        $this->assertFalse($this->manager->isEnabledForUser('test', $user));
458
+    }
459
+
460
+    public function testGetAppPath(): void {
461
+        $this->assertEquals(\OC::$SERVERROOT . '/apps/files', $this->manager->getAppPath('files'));
462
+    }
463
+
464
+    public function testGetAppPathSymlink(): void {
465
+        $fakeAppDirname = sha1(uniqid('test', true));
466
+        $fakeAppPath = sys_get_temp_dir() . '/' . $fakeAppDirname;
467
+        $fakeAppLink = \OC::$SERVERROOT . '/' . $fakeAppDirname;
468
+
469
+        mkdir($fakeAppPath);
470
+        if (symlink($fakeAppPath, $fakeAppLink) === false) {
471
+            $this->markTestSkipped('Failed to create symlink');
472
+        }
473
+
474
+        // Use the symlink as the app path
475
+        \OC::$APPSROOTS[] = [
476
+            'path' => $fakeAppLink,
477
+            'url' => \OC::$WEBROOT . '/' . $fakeAppDirname,
478
+            'writable' => false,
479
+        ];
480
+
481
+        $fakeTestAppPath = $fakeAppPath . '/' . 'test-test-app';
482
+        mkdir($fakeTestAppPath);
483
+
484
+        $generatedAppPath = $this->manager->getAppPath('test-test-app');
485
+
486
+        rmdir($fakeTestAppPath);
487
+        unlink($fakeAppLink);
488
+        rmdir($fakeAppPath);
489
+
490
+        $this->assertEquals($fakeAppLink . '/test-test-app', $generatedAppPath);
491
+    }
492
+
493
+    public function testGetAppPathFail(): void {
494
+        $this->expectException(AppPathNotFoundException::class);
495
+        $this->manager->getAppPath('testnotexisting');
496
+    }
497
+
498
+    public function testIsEnabledForUserEnabledForGroup(): void {
499
+        $user = $this->newUser('user1');
500
+        $this->groupManager->expects($this->once())
501
+            ->method('getUserGroupIds')
502
+            ->with($user)
503
+            ->willReturn(['foo', 'bar']);
504
+
505
+        $this->appConfig->setValue('test', 'enabled', '["foo"]');
506
+        $this->assertTrue($this->manager->isEnabledForUser('test', $user));
507
+    }
508
+
509
+    public function testIsEnabledForUserDisabledForGroup(): void {
510
+        $user = $this->newUser('user1');
511
+        $this->groupManager->expects($this->once())
512
+            ->method('getUserGroupIds')
513
+            ->with($user)
514
+            ->willReturn(['bar']);
515
+
516
+        $this->appConfig->setValue('test', 'enabled', '["foo"]');
517
+        $this->assertFalse($this->manager->isEnabledForUser('test', $user));
518
+    }
519
+
520
+    public function testIsEnabledForUserLoggedOut(): void {
521
+        $this->appConfig->setValue('test', 'enabled', '["foo"]');
522
+        $this->assertFalse($this->manager->isEnabledForUser('test'));
523
+    }
524
+
525
+    public function testIsEnabledForUserLoggedIn(): void {
526
+        $user = $this->newUser('user1');
527
+
528
+        $this->userSession->expects($this->once())
529
+            ->method('getUser')
530
+            ->willReturn($user);
531
+        $this->groupManager->expects($this->once())
532
+            ->method('getUserGroupIds')
533
+            ->with($user)
534
+            ->willReturn(['foo', 'bar']);
535
+
536
+        $this->appConfig->setValue('test', 'enabled', '["foo"]');
537
+        $this->assertTrue($this->manager->isEnabledForUser('test'));
538
+    }
539
+
540
+    public function testGetEnabledApps(): void {
541
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
542
+        $this->appConfig->setValue('test2', 'enabled', 'no');
543
+        $this->appConfig->setValue('test3', 'enabled', '["foo"]');
544
+        $apps = [
545
+            'cloud_federation_api',
546
+            'dav',
547
+            'federatedfilesharing',
548
+            'files',
549
+            'lookup_server_connector',
550
+            'oauth2',
551
+            'profile',
552
+            'provisioning_api',
553
+            'settings',
554
+            'test1',
555
+            'test3',
556
+            'theming',
557
+            'twofactor_backupcodes',
558
+            'viewer',
559
+            'workflowengine',
560
+        ];
561
+        $this->assertEquals($apps, $this->manager->getEnabledApps());
562
+    }
563
+
564
+    public function testGetAppsForUser(): void {
565
+        $user = $this->newUser('user1');
566
+        $this->groupManager->expects($this->any())
567
+            ->method('getUserGroupIds')
568
+            ->with($user)
569
+            ->willReturn(['foo', 'bar']);
570
+
571
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
572
+        $this->appConfig->setValue('test2', 'enabled', 'no');
573
+        $this->appConfig->setValue('test3', 'enabled', '["foo"]');
574
+        $this->appConfig->setValue('test4', 'enabled', '["asd"]');
575
+        $enabled = [
576
+            'cloud_federation_api',
577
+            'dav',
578
+            'federatedfilesharing',
579
+            'files',
580
+            'lookup_server_connector',
581
+            'oauth2',
582
+            'profile',
583
+            'provisioning_api',
584
+            'settings',
585
+            'test1',
586
+            'test3',
587
+            'theming',
588
+            'twofactor_backupcodes',
589
+            'viewer',
590
+            'workflowengine',
591
+        ];
592
+        $this->assertEquals($enabled, $this->manager->getEnabledAppsForUser($user));
593
+    }
594
+
595
+    public function testGetAppsNeedingUpgrade(): void {
596
+        /** @var AppManager|MockObject $manager */
597
+        $manager = $this->getMockBuilder(AppManager::class)
598
+            ->setConstructorArgs([
599
+                $this->userSession,
600
+                $this->config,
601
+                $this->groupManager,
602
+                $this->cacheFactory,
603
+                $this->eventDispatcher,
604
+                $this->logger,
605
+                $this->serverVersion,
606
+                $this->configManager,
607
+            ])
608
+            ->onlyMethods(['getAppInfo'])
609
+            ->getMock();
610
+
611
+        $appInfos = [
612
+            'cloud_federation_api' => ['id' => 'cloud_federation_api'],
613
+            'dav' => ['id' => 'dav'],
614
+            'files' => ['id' => 'files'],
615
+            'federatedfilesharing' => ['id' => 'federatedfilesharing'],
616
+            'profile' => ['id' => 'profile'],
617
+            'provisioning_api' => ['id' => 'provisioning_api'],
618
+            'lookup_server_connector' => ['id' => 'lookup_server_connector'],
619
+            'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '9.0.0'],
620
+            'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
621
+            'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
622
+            'test4' => ['id' => 'test4', 'version' => '3.0.0', 'requiremin' => '8.1.0'],
623
+            'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
624
+            'settings' => ['id' => 'settings'],
625
+            'theming' => ['id' => 'theming'],
626
+            'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'],
627
+            'viewer' => ['id' => 'viewer'],
628
+            'workflowengine' => ['id' => 'workflowengine'],
629
+            'oauth2' => ['id' => 'oauth2'],
630
+        ];
631
+
632
+        $manager->expects($this->any())
633
+            ->method('getAppInfo')
634
+            ->willReturnCallback(
635
+                function ($appId) use ($appInfos) {
636
+                    return $appInfos[$appId];
637
+                }
638
+            );
639
+
640
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
641
+        $this->appConfig->setValue('test1', 'installed_version', '1.0.0');
642
+        $this->appConfig->setValue('test2', 'enabled', 'yes');
643
+        $this->appConfig->setValue('test2', 'installed_version', '1.0.0');
644
+        $this->appConfig->setValue('test3', 'enabled', 'yes');
645
+        $this->appConfig->setValue('test3', 'installed_version', '1.0.0');
646
+        $this->appConfig->setValue('test4', 'enabled', 'yes');
647
+        $this->appConfig->setValue('test4', 'installed_version', '2.4.0');
648
+
649
+        $apps = $manager->getAppsNeedingUpgrade('8.2.0');
650
+
651
+        $this->assertCount(2, $apps);
652
+        $this->assertEquals('test1', $apps[0]['id']);
653
+        $this->assertEquals('test4', $apps[1]['id']);
654
+    }
655
+
656
+    public function testGetIncompatibleApps(): void {
657
+        /** @var AppManager|MockObject $manager */
658
+        $manager = $this->getMockBuilder(AppManager::class)
659
+            ->setConstructorArgs([
660
+                $this->userSession,
661
+                $this->config,
662
+                $this->groupManager,
663
+                $this->cacheFactory,
664
+                $this->eventDispatcher,
665
+                $this->logger,
666
+                $this->serverVersion,
667
+                $this->configManager,
668
+            ])
669
+            ->onlyMethods(['getAppInfo'])
670
+            ->getMock();
671
+
672
+        $appInfos = [
673
+            'cloud_federation_api' => ['id' => 'cloud_federation_api'],
674
+            'dav' => ['id' => 'dav'],
675
+            'files' => ['id' => 'files'],
676
+            'federatedfilesharing' => ['id' => 'federatedfilesharing'],
677
+            'profile' => ['id' => 'profile'],
678
+            'provisioning_api' => ['id' => 'provisioning_api'],
679
+            'lookup_server_connector' => ['id' => 'lookup_server_connector'],
680
+            'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '8.0.0'],
681
+            'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
682
+            'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
683
+            'settings' => ['id' => 'settings'],
684
+            'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
685
+            'theming' => ['id' => 'theming'],
686
+            'twofactor_backupcodes' => ['id' => 'twofactor_backupcodes'],
687
+            'workflowengine' => ['id' => 'workflowengine'],
688
+            'oauth2' => ['id' => 'oauth2'],
689
+            'viewer' => ['id' => 'viewer'],
690
+        ];
691
+
692
+        $manager->expects($this->any())
693
+            ->method('getAppInfo')
694
+            ->willReturnCallback(
695
+                function ($appId) use ($appInfos) {
696
+                    return $appInfos[$appId];
697
+                }
698
+            );
699
+
700
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
701
+        $this->appConfig->setValue('test2', 'enabled', 'yes');
702
+        $this->appConfig->setValue('test3', 'enabled', 'yes');
703
+
704
+        $apps = $manager->getIncompatibleApps('8.2.0');
705
+
706
+        $this->assertCount(2, $apps);
707
+        $this->assertEquals('test1', $apps[0]['id']);
708
+        $this->assertEquals('test3', $apps[1]['id']);
709
+    }
710
+
711
+    public function testGetEnabledAppsForGroup(): void {
712
+        $group = $this->createMock(IGroup::class);
713
+        $group->expects($this->any())
714
+            ->method('getGID')
715
+            ->willReturn('foo');
716
+
717
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
718
+        $this->appConfig->setValue('test2', 'enabled', 'no');
719
+        $this->appConfig->setValue('test3', 'enabled', '["foo"]');
720
+        $this->appConfig->setValue('test4', 'enabled', '["asd"]');
721
+        $enabled = [
722
+            'cloud_federation_api',
723
+            'dav',
724
+            'federatedfilesharing',
725
+            'files',
726
+            'lookup_server_connector',
727
+            'oauth2',
728
+            'profile',
729
+            'provisioning_api',
730
+            'settings',
731
+            'test1',
732
+            'test3',
733
+            'theming',
734
+            'twofactor_backupcodes',
735
+            'viewer',
736
+            'workflowengine',
737
+        ];
738
+        $this->assertEquals($enabled, $this->manager->getEnabledAppsForGroup($group));
739
+    }
740
+
741
+    public function testGetAppRestriction(): void {
742
+        $this->appConfig->setValue('test1', 'enabled', 'yes');
743
+        $this->appConfig->setValue('test2', 'enabled', 'no');
744
+        $this->appConfig->setValue('test3', 'enabled', '["foo"]');
745
+
746
+        $this->assertEquals([], $this->manager->getAppRestriction('test1'));
747
+        $this->assertEquals([], $this->manager->getAppRestriction('test2'));
748
+        $this->assertEquals(['foo'], $this->manager->getAppRestriction('test3'));
749
+    }
750
+
751
+    public static function isBackendRequiredDataProvider(): array {
752
+        return [
753
+            // backend available
754
+            [
755
+                'caldav',
756
+                ['app1' => ['caldav']],
757
+                true,
758
+            ],
759
+            [
760
+                'caldav',
761
+                ['app1' => [], 'app2' => ['foo'], 'app3' => ['caldav']],
762
+                true,
763
+            ],
764
+            // backend not available
765
+            [
766
+                'caldav',
767
+                ['app3' => [], 'app1' => ['foo'], 'app2' => ['bar', 'baz']],
768
+                false,
769
+            ],
770
+            // no app available
771
+            [
772
+                'caldav',
773
+                [],
774
+                false,
775
+            ],
776
+        ];
777
+    }
778
+
779
+    /**
780
+     * @dataProvider isBackendRequiredDataProvider
781
+     */
782
+    public function testIsBackendRequired(
783
+        string $backend,
784
+        array $appBackends,
785
+        bool $expected,
786
+    ): void {
787
+        $appInfoData = array_map(
788
+            static fn (array $backends) => ['dependencies' => ['backend' => $backends]],
789
+            $appBackends,
790
+        );
791
+
792
+        $reflection = new \ReflectionClass($this->manager);
793
+        $property = $reflection->getProperty('appInfos');
794
+        $property->setValue($this->manager, $appInfoData);
795
+
796
+        $this->assertEquals($expected, $this->manager->isBackendRequired($backend));
797
+    }
798
+
799
+    public function testGetAppVersion() {
800
+        $manager = $this->getMockBuilder(AppManager::class)
801
+            ->setConstructorArgs([
802
+                $this->userSession,
803
+                $this->config,
804
+                $this->groupManager,
805
+                $this->cacheFactory,
806
+                $this->eventDispatcher,
807
+                $this->logger,
808
+                $this->serverVersion,
809
+                $this->configManager,
810
+            ])
811
+            ->onlyMethods([
812
+                'getAppInfo',
813
+            ])
814
+            ->getMock();
815
+
816
+        $manager->expects(self::once())
817
+            ->method('getAppInfo')
818
+            ->with('myapp')
819
+            ->willReturn(['version' => '99.99.99-rc.99']);
820
+
821
+        $this->serverVersion
822
+            ->expects(self::never())
823
+            ->method('getVersionString');
824
+
825
+        $this->assertEquals(
826
+            '99.99.99-rc.99',
827
+            $manager->getAppVersion('myapp'),
828
+        );
829
+    }
830
+
831
+    public function testGetAppVersionCore() {
832
+        $manager = $this->getMockBuilder(AppManager::class)
833
+            ->setConstructorArgs([
834
+                $this->userSession,
835
+                $this->config,
836
+                $this->groupManager,
837
+                $this->cacheFactory,
838
+                $this->eventDispatcher,
839
+                $this->logger,
840
+                $this->serverVersion,
841
+                $this->configManager,
842
+            ])
843
+            ->onlyMethods([
844
+                'getAppInfo',
845
+            ])
846
+            ->getMock();
847
+
848
+        $manager->expects(self::never())
849
+            ->method('getAppInfo');
850
+
851
+        $this->serverVersion
852
+            ->expects(self::once())
853
+            ->method('getVersionString')
854
+            ->willReturn('1.2.3-beta.4');
855
+
856
+        $this->assertEquals(
857
+            '1.2.3-beta.4',
858
+            $manager->getAppVersion('core'),
859
+        );
860
+    }
861
+
862
+    public function testGetAppVersionUnknown() {
863
+        $manager = $this->getMockBuilder(AppManager::class)
864
+            ->setConstructorArgs([
865
+                $this->userSession,
866
+                $this->config,
867
+                $this->groupManager,
868
+                $this->cacheFactory,
869
+                $this->eventDispatcher,
870
+                $this->logger,
871
+                $this->serverVersion,
872
+                $this->configManager,
873
+            ])
874
+            ->onlyMethods([
875
+                'getAppInfo',
876
+            ])
877
+            ->getMock();
878
+
879
+        $manager->expects(self::once())
880
+            ->method('getAppInfo')
881
+            ->with('unknown')
882
+            ->willReturn(null);
883
+
884
+        $this->serverVersion
885
+            ->expects(self::never())
886
+            ->method('getVersionString');
887
+
888
+        $this->assertEquals(
889
+            '0',
890
+            $manager->getAppVersion('unknown'),
891
+        );
892
+    }
893 893
 
894 894
 }
Please login to merge, or discard this patch.
tests/lib/DB/AdapterTest.php 1 patch
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -11,58 +11,58 @@
 block discarded – undo
11 11
 use Test\TestCase;
12 12
 
13 13
 class AdapterTest extends TestCase {
14
-	private string $appId;
15
-	private $connection;
14
+    private string $appId;
15
+    private $connection;
16 16
 
17
-	public function setUp(): void {
18
-		$this->connection = Server::get(IDBConnection::class);
19
-		$this->appId = substr(uniqid('test_db_adapter', true), 0, 32);
20
-	}
17
+    public function setUp(): void {
18
+        $this->connection = Server::get(IDBConnection::class);
19
+        $this->appId = substr(uniqid('test_db_adapter', true), 0, 32);
20
+    }
21 21
 
22
-	public function tearDown(): void {
23
-		$qb = $this->connection->getQueryBuilder();
22
+    public function tearDown(): void {
23
+        $qb = $this->connection->getQueryBuilder();
24 24
 
25
-		$qb->delete('appconfig')
26
-			->from('appconfig')
27
-			->where($qb->expr()->eq('appid', $qb->createNamedParameter($this->appId)))
28
-			->execute();
29
-	}
25
+        $qb->delete('appconfig')
26
+            ->from('appconfig')
27
+            ->where($qb->expr()->eq('appid', $qb->createNamedParameter($this->appId)))
28
+            ->execute();
29
+    }
30 30
 
31
-	public function testInsertIgnoreOnConflictDuplicate(): void {
32
-		$configKey = uniqid('key', true);
33
-		$expected = [
34
-			[
35
-				'configkey' => $configKey,
36
-				'configvalue' => '1',
37
-			]
38
-		];
39
-		$result = $this->connection->insertIgnoreConflict('appconfig', [
40
-			'appid' => $this->appId,
41
-			'configkey' => $configKey,
42
-			'configvalue' => '1',
43
-		]);
44
-		$this->assertEquals(1, $result);
45
-		$rows = $this->getRows($configKey);
46
-		$this->assertSame($expected, $rows);
31
+    public function testInsertIgnoreOnConflictDuplicate(): void {
32
+        $configKey = uniqid('key', true);
33
+        $expected = [
34
+            [
35
+                'configkey' => $configKey,
36
+                'configvalue' => '1',
37
+            ]
38
+        ];
39
+        $result = $this->connection->insertIgnoreConflict('appconfig', [
40
+            'appid' => $this->appId,
41
+            'configkey' => $configKey,
42
+            'configvalue' => '1',
43
+        ]);
44
+        $this->assertEquals(1, $result);
45
+        $rows = $this->getRows($configKey);
46
+        $this->assertSame($expected, $rows);
47 47
 
48 48
 
49
-		$result = $this->connection->insertIgnoreConflict('appconfig', [
50
-			'appid' => $this->appId,
51
-			'configkey' => $configKey,
52
-			'configvalue' => '2',
53
-		]);
54
-		$this->assertEquals(0, $result);
55
-		$rows = $this->getRows($configKey);
56
-		$this->assertSame($expected, $rows);
57
-	}
49
+        $result = $this->connection->insertIgnoreConflict('appconfig', [
50
+            'appid' => $this->appId,
51
+            'configkey' => $configKey,
52
+            'configvalue' => '2',
53
+        ]);
54
+        $this->assertEquals(0, $result);
55
+        $rows = $this->getRows($configKey);
56
+        $this->assertSame($expected, $rows);
57
+    }
58 58
 
59
-	private function getRows(string $configKey): array {
60
-		$qb = $this->connection->getQueryBuilder();
61
-		return $qb->select(['configkey', 'configvalue'])
62
-			->from('appconfig')
63
-			->where($qb->expr()->eq('appid', $qb->createNamedParameter($this->appId)))
64
-			->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($configKey)))
65
-			->execute()
66
-			->fetchAll();
67
-	}
59
+    private function getRows(string $configKey): array {
60
+        $qb = $this->connection->getQueryBuilder();
61
+        return $qb->select(['configkey', 'configvalue'])
62
+            ->from('appconfig')
63
+            ->where($qb->expr()->eq('appid', $qb->createNamedParameter($this->appId)))
64
+            ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($configKey)))
65
+            ->execute()
66
+            ->fetchAll();
67
+    }
68 68
 }
Please login to merge, or discard this patch.