@@ -23,448 +23,448 @@ |
||
23 | 23 | |
24 | 24 | class ProfileTest extends TestCase { |
25 | 25 | |
26 | - protected IAccountManager&MockObject $accountManager; |
|
27 | - protected IUserManager&MockObject $userManager; |
|
28 | - protected IDBConnection&MockObject $connection; |
|
29 | - protected InputInterface&MockObject $consoleInput; |
|
30 | - protected OutputInterface&MockObject $consoleOutput; |
|
31 | - |
|
32 | - protected function setUp(): void { |
|
33 | - parent::setUp(); |
|
34 | - |
|
35 | - $this->accountManager = $this->createMock(IAccountManager::class); |
|
36 | - $this->userManager = $this->createMock(IUserManager::class); |
|
37 | - $this->connection = $this->createMock(IDBConnection::class); |
|
38 | - $this->consoleInput = $this->createMock(InputInterface::class); |
|
39 | - $this->consoleOutput = $this->createMock(OutputInterface::class); |
|
40 | - } |
|
41 | - |
|
42 | - public function getCommand(array $methods = []): Profile|MockObject { |
|
43 | - if (empty($methods)) { |
|
44 | - return new Profile($this->userManager, $this->accountManager); |
|
45 | - } else { |
|
46 | - return $this->getMockBuilder(Profile::class) |
|
47 | - ->setConstructorArgs([ |
|
48 | - $this->userManager, |
|
49 | - $this->accountManager, |
|
50 | - ]) |
|
51 | - ->onlyMethods($methods) |
|
52 | - ->getMock(); |
|
53 | - } |
|
54 | - } |
|
55 | - |
|
56 | - public static function dataCheckInput(): array { |
|
57 | - return [ |
|
58 | - 'Call with existing user should pass check' => [ |
|
59 | - [['uid', 'username']], |
|
60 | - [], |
|
61 | - [], |
|
62 | - true, |
|
63 | - null, |
|
64 | - ], |
|
65 | - 'Call with non-existing user should fail check' => [ |
|
66 | - [['uid', 'username']], |
|
67 | - [], |
|
68 | - [], |
|
69 | - false, |
|
70 | - 'The user "username" does not exist.', |
|
71 | - ], |
|
72 | - |
|
73 | - 'Call with uid, key and --default value should pass check' => [ |
|
74 | - [['uid', 'username'], ['key', 'configkey']], |
|
75 | - [], |
|
76 | - [['--default-value', false, true]], |
|
77 | - true, |
|
78 | - null, |
|
79 | - ], |
|
80 | - 'Call with uid and empty key with default-value option should fail check' => [ |
|
81 | - [['uid', 'username'], ['key', '']], |
|
82 | - [], |
|
83 | - [['--default-value', false, true]], |
|
84 | - true, |
|
85 | - 'The "default-value" option can only be used when specifying a key.', |
|
86 | - ], |
|
87 | - |
|
88 | - 'Call with uid, key, value should pass check' => [ |
|
89 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
90 | - [], |
|
91 | - [], |
|
92 | - true, |
|
93 | - null, |
|
94 | - ], |
|
95 | - 'Call with uid, empty key and empty value should fail check' => [ |
|
96 | - [['uid', 'username'], ['key', ''], ['value', '']], |
|
97 | - [], |
|
98 | - [], |
|
99 | - true, |
|
100 | - 'The value argument can only be used when specifying a key.', |
|
101 | - ], |
|
102 | - 'Call with uid, key, empty value and default-value option should fail check' => [ |
|
103 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
104 | - [], |
|
105 | - [['--default-value', false, true]], |
|
106 | - true, |
|
107 | - 'The value argument can not be used together with "default-value".', |
|
108 | - ], |
|
109 | - 'Call with uid, key, empty value and update-only option should pass check' => [ |
|
110 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
111 | - [['update-only', true]], |
|
112 | - [], |
|
113 | - true, |
|
114 | - null, |
|
115 | - ], |
|
116 | - 'Call with uid, key, null value and update-only option should fail check' => [ |
|
117 | - [['uid', 'username'], ['key', 'configkey'], ['value', null]], |
|
118 | - [['update-only', true]], |
|
119 | - [], |
|
120 | - true, |
|
121 | - 'The "update-only" option can only be used together with "value".', |
|
122 | - ], |
|
123 | - |
|
124 | - 'Call with uid, key and delete option should pass check' => [ |
|
125 | - [['uid', 'username'], ['key', 'configkey']], |
|
126 | - [['delete', true]], |
|
127 | - [], |
|
128 | - true, |
|
129 | - null, |
|
130 | - ], |
|
131 | - 'Call with uid, empty key and delete option should fail check' => [ |
|
132 | - [['uid', 'username'], ['key', '']], |
|
133 | - [['delete', true]], |
|
134 | - [], |
|
135 | - true, |
|
136 | - 'The "delete" option can only be used when specifying a key.', |
|
137 | - ], |
|
138 | - 'Call with uid, key, delete option and default-value should fail check' => [ |
|
139 | - [['uid', 'username'], ['key', 'configkey']], |
|
140 | - [['delete', true]], |
|
141 | - [['--default-value', false, true]], |
|
142 | - true, |
|
143 | - 'The "delete" option can not be used together with "default-value".', |
|
144 | - ], |
|
145 | - 'Call with uid, key, empty value and delete option should fail check' => [ |
|
146 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
147 | - [['delete', true]], |
|
148 | - [], |
|
149 | - true, |
|
150 | - 'The "delete" option can not be used together with "value".', |
|
151 | - ], |
|
152 | - 'Call with uid, key, delete and error-if-not-exists should pass check' => [ |
|
153 | - [['uid', 'username'], ['key', 'configkey']], |
|
154 | - [['delete', true], ['error-if-not-exists', true]], |
|
155 | - [], |
|
156 | - true, |
|
157 | - null, |
|
158 | - ], |
|
159 | - 'Call with uid, key and error-if-not-exists should fail check' => [ |
|
160 | - [['uid', 'username'], ['key', 'configkey']], |
|
161 | - [['delete', false], ['error-if-not-exists', true]], |
|
162 | - [], |
|
163 | - true, |
|
164 | - 'The "error-if-not-exists" option can only be used together with "delete".', |
|
165 | - ], |
|
166 | - ]; |
|
167 | - } |
|
168 | - |
|
169 | - /** |
|
170 | - * @dataProvider dataCheckInput |
|
171 | - */ |
|
172 | - public function testCheckInput(array $arguments, array $options, array $parameterOptions, bool $existingUser, ?string $expectedException): void { |
|
173 | - $this->consoleInput->expects($this->any()) |
|
174 | - ->method('getArgument') |
|
175 | - ->willReturnMap($arguments); |
|
176 | - $this->consoleInput->expects($this->any()) |
|
177 | - ->method('getOption') |
|
178 | - ->willReturnMap($options); |
|
179 | - $this->consoleInput->expects($this->any()) |
|
180 | - ->method('hasParameterOption') |
|
181 | - ->willReturnCallback(function (string|array $values, bool $onlyParams = false) use ($parameterOptions): bool { |
|
182 | - $arguments = func_get_args(); |
|
183 | - foreach ($parameterOptions as $parameterOption) { |
|
184 | - // check the arguments of the function, if they are the same, return the mocked value |
|
185 | - if (array_diff($arguments, $parameterOption) === []) { |
|
186 | - return end($parameterOption); |
|
187 | - } |
|
188 | - } |
|
189 | - |
|
190 | - return false; |
|
191 | - }); |
|
192 | - |
|
193 | - $returnedUser = null; |
|
194 | - if ($existingUser) { |
|
195 | - $mockUser = $this->createMock(IUser::class); |
|
196 | - $mockUser->expects($this->once())->method('getUID')->willReturn('user'); |
|
197 | - $returnedUser = $mockUser; |
|
198 | - } |
|
199 | - $this->userManager->expects($this->once()) |
|
200 | - ->method('get') |
|
201 | - ->willReturn($returnedUser); |
|
202 | - |
|
203 | - $command = $this->getCommand(); |
|
204 | - try { |
|
205 | - $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); |
|
206 | - $this->assertNull($expectedException); |
|
207 | - } catch (\InvalidArgumentException $e) { |
|
208 | - $this->assertEquals($expectedException, $e->getMessage()); |
|
209 | - } |
|
210 | - } |
|
211 | - |
|
212 | - public function testCheckInputExceptionCatch(): void { |
|
213 | - $command = $this->getCommand(['checkInput']); |
|
214 | - $command->expects($this->once()) |
|
215 | - ->method('checkInput') |
|
216 | - ->willThrowException(new \InvalidArgumentException('test')); |
|
217 | - |
|
218 | - $this->consoleOutput->expects($this->once()) |
|
219 | - ->method('writeln') |
|
220 | - ->with('<error>test</error>'); |
|
221 | - |
|
222 | - $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
223 | - } |
|
224 | - |
|
225 | - public static function dataExecuteDeleteProfileProperty(): array { |
|
226 | - return [ |
|
227 | - 'Deleting existing property should succeed' => ['address', 'Berlin', false, null, Command::SUCCESS], |
|
228 | - 'Deleting existing property with error-if-not-exists should succeed' => ['address', 'Berlin', true, null, Command::SUCCESS], |
|
229 | - 'Deleting non-existing property should succeed' => ['address', '', false, null, Command::SUCCESS], |
|
230 | - 'Deleting non-existing property with error-if-not-exists should fail' => ['address', '', true, '<error>The property does not exist for user "username".</error>', Command::FAILURE], |
|
231 | - ]; |
|
232 | - } |
|
233 | - |
|
234 | - /** |
|
235 | - * Tests the deletion mechanism on profile settings. |
|
236 | - * |
|
237 | - * @dataProvider dataExecuteDeleteProfileProperty |
|
238 | - */ |
|
239 | - public function testExecuteDeleteProfileProperty(string $configKey, string $value, bool $errorIfNotExists, ?string $expectedLine, int $expectedReturn): void { |
|
240 | - $uid = 'username'; |
|
241 | - $appName = 'profile'; |
|
242 | - $command = $this->getCommand([ |
|
243 | - 'writeArrayInOutputFormat', |
|
244 | - 'checkInput', |
|
245 | - ]); |
|
246 | - |
|
247 | - $this->consoleInput->expects($this->any()) |
|
248 | - ->method('getArgument') |
|
249 | - ->willReturnMap([ |
|
250 | - ['uid', $uid], |
|
251 | - ['app', $appName], |
|
252 | - ['key', $configKey], |
|
253 | - ]); |
|
254 | - |
|
255 | - $mocks = $this->setupProfilePropertiesMock([$configKey => $value]); |
|
256 | - |
|
257 | - $command->expects($this->once()) |
|
258 | - ->method('checkInput') |
|
259 | - ->willReturn($mocks['userMock']); |
|
260 | - |
|
261 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
262 | - ->method('hasParameterOption') |
|
263 | - ->willReturnMap([ |
|
264 | - ['--delete', false, true], |
|
265 | - ['--error-if-not-exists', false, $errorIfNotExists], |
|
266 | - ]); |
|
267 | - |
|
268 | - if ($expectedLine === null) { |
|
269 | - $this->consoleOutput->expects($this->never()) |
|
270 | - ->method('writeln'); |
|
271 | - $mocks['profilePropertiesMocks'][0]->expects($this->once()) |
|
272 | - ->method('setValue') |
|
273 | - ->with(''); |
|
274 | - $this->accountManager->expects($this->once()) |
|
275 | - ->method('updateAccount') |
|
276 | - ->with($mocks['accountMock']); |
|
277 | - } else { |
|
278 | - $this->consoleOutput->expects($this->once()) |
|
279 | - ->method('writeln') |
|
280 | - ->with($expectedLine); |
|
281 | - $this->accountManager->expects($this->never()) |
|
282 | - ->method('updateAccount'); |
|
283 | - } |
|
284 | - |
|
285 | - $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
286 | - } |
|
287 | - |
|
288 | - public function testExecuteSetProfileProperty(): void { |
|
289 | - $command = $this->getCommand([ |
|
290 | - 'writeArrayInOutputFormat', |
|
291 | - 'checkInput', |
|
292 | - ]); |
|
293 | - |
|
294 | - $uid = 'username'; |
|
295 | - $propertyKey = 'address'; |
|
296 | - $propertyValue = 'Barcelona'; |
|
297 | - |
|
298 | - $this->consoleInput->expects($this->atLeast(3)) |
|
299 | - ->method('getArgument') |
|
300 | - ->willReturnMap([ |
|
301 | - ['uid', $uid], |
|
302 | - ['key', $propertyKey], |
|
303 | - ['value', $propertyValue], |
|
304 | - ]); |
|
305 | - |
|
306 | - $mocks = $this->setupProfilePropertiesMock([$propertyKey => $propertyValue]); |
|
307 | - |
|
308 | - $command->expects($this->once()) |
|
309 | - ->method('checkInput') |
|
310 | - ->willReturn($mocks['userMock']); |
|
311 | - |
|
312 | - $mocks['profilePropertiesMocks'][0]->expects($this->once()) |
|
313 | - ->method('setValue') |
|
314 | - ->with($propertyValue); |
|
315 | - $this->accountManager->expects($this->once()) |
|
316 | - ->method('updateAccount') |
|
317 | - ->with($mocks['accountMock']); |
|
318 | - |
|
319 | - $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
320 | - } |
|
321 | - |
|
322 | - public static function dataExecuteGet(): array { |
|
323 | - return [ |
|
324 | - 'Get property with set value should pass' => ['configkey', 'value', null, 'value', Command::SUCCESS], |
|
325 | - 'Get property with empty value and default-value option should pass' => ['configkey', '', 'default-value', 'default-value', Command::SUCCESS], |
|
326 | - 'Get property with empty value should fail' => ['configkey', '', null, '<error>The property does not exist for user "username".</error>', Command::FAILURE], |
|
327 | - ]; |
|
328 | - } |
|
329 | - |
|
330 | - /** |
|
331 | - * @dataProvider dataExecuteGet |
|
332 | - */ |
|
333 | - public function testExecuteGet(string $key, string $value, ?string $defaultValue, string $expectedLine, int $expectedReturn): void { |
|
334 | - $command = $this->getCommand([ |
|
335 | - 'writeArrayInOutputFormat', |
|
336 | - 'checkInput', |
|
337 | - ]); |
|
338 | - |
|
339 | - $uid = 'username'; |
|
340 | - |
|
341 | - $this->consoleInput->expects($this->any()) |
|
342 | - ->method('getArgument') |
|
343 | - ->willReturnMap([ |
|
344 | - ['uid', $uid], |
|
345 | - ['key', $key], |
|
346 | - ]); |
|
347 | - |
|
348 | - $mocks = $this->setupProfilePropertiesMock([$key => $value]); |
|
349 | - |
|
350 | - $command->expects($this->once()) |
|
351 | - ->method('checkInput') |
|
352 | - ->willReturn($mocks['userMock']); |
|
353 | - |
|
354 | - if ($value === '') { |
|
355 | - if ($defaultValue === null) { |
|
356 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
357 | - ->method('hasParameterOption') |
|
358 | - ->willReturn(false); |
|
359 | - } else { |
|
360 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
361 | - ->method('hasParameterOption') |
|
362 | - ->willReturnCallback(fn (string|array $values): bool => $values === '--default-value'); |
|
363 | - $this->consoleInput->expects($this->once()) |
|
364 | - ->method('getOption') |
|
365 | - ->with('default-value') |
|
366 | - ->willReturn($defaultValue); |
|
367 | - } |
|
368 | - } |
|
369 | - |
|
370 | - $this->consoleOutput->expects($this->once()) |
|
371 | - ->method('writeln') |
|
372 | - ->with($expectedLine); |
|
373 | - |
|
374 | - $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
375 | - } |
|
376 | - |
|
377 | - public function testExecuteList(): void { |
|
378 | - $uid = 'username'; |
|
379 | - $profileData = [ |
|
380 | - 'pronouns' => 'they/them', |
|
381 | - 'address' => 'Berlin', |
|
382 | - ]; |
|
383 | - |
|
384 | - $command = $this->getCommand([ |
|
385 | - 'writeArrayInOutputFormat', |
|
386 | - 'checkInput', |
|
387 | - ]); |
|
388 | - |
|
389 | - $this->consoleInput->expects($this->any()) |
|
390 | - ->method('getArgument') |
|
391 | - ->willReturnMap([ |
|
392 | - ['uid', $uid], |
|
393 | - ['key', ''], |
|
394 | - ]); |
|
395 | - |
|
396 | - $mocks = $this->setupProfilePropertiesMock(['address' => $profileData['address'], 'pronouns' => $profileData['pronouns']]); |
|
397 | - |
|
398 | - $command->expects($this->once()) |
|
399 | - ->method('checkInput') |
|
400 | - ->willReturn($mocks['userMock']); |
|
401 | - |
|
402 | - $command->expects($this->once()) |
|
403 | - ->method('writeArrayInOutputFormat') |
|
404 | - ->with($this->consoleInput, $this->consoleOutput, $profileData); |
|
405 | - |
|
406 | - |
|
407 | - $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
408 | - } |
|
409 | - |
|
410 | - /** |
|
411 | - * Helper to avoid boilerplate in tests in this file when mocking objects |
|
412 | - * of IAccountProperty type. |
|
413 | - * |
|
414 | - * @param array<string, string> $properties the properties to be set up as key => value |
|
415 | - * @return array{ |
|
416 | - * userMock: IUser&MockObject, |
|
417 | - * accountMock: IAccount&MockObject, |
|
418 | - * profilePropertiesMocks: IAccountProperty&MockObject[] |
|
419 | - * } |
|
420 | - */ |
|
421 | - private function setupProfilePropertiesMock(array $properties): array { |
|
422 | - $userMock = $this->createMock(IUser::class); |
|
423 | - $accountMock = $this->createMock(IAccount::class); |
|
424 | - $this->accountManager->expects($this->atLeastOnce()) |
|
425 | - ->method('getAccount') |
|
426 | - ->with($userMock) |
|
427 | - ->willReturn($accountMock); |
|
428 | - |
|
429 | - /** @var IAccountProperty&MockObject[] $propertiesMocks */ |
|
430 | - $propertiesMocks = []; |
|
431 | - foreach ($properties as $key => $value) { |
|
432 | - $propertiesMocks[] = $this->getAccountPropertyMock($key, $value); |
|
433 | - } |
|
434 | - |
|
435 | - if (count($properties) === 1) { |
|
436 | - $accountMock->expects($this->atLeastOnce()) |
|
437 | - ->method('getProperty') |
|
438 | - ->with(array_keys($properties)[0]) |
|
439 | - ->willReturn($propertiesMocks[array_key_first($propertiesMocks)]); |
|
440 | - } else { |
|
441 | - $accountMock->expects($this->atLeastOnce()) |
|
442 | - ->method('getAllProperties') |
|
443 | - ->willReturnCallback(function () use ($propertiesMocks) { |
|
444 | - foreach ($propertiesMocks as $property) { |
|
445 | - yield $property; |
|
446 | - } |
|
447 | - }); |
|
448 | - } |
|
449 | - |
|
450 | - return [ |
|
451 | - 'userMock' => $userMock, |
|
452 | - 'accountMock' => $accountMock, |
|
453 | - 'profilePropertiesMocks' => $propertiesMocks, |
|
454 | - ]; |
|
455 | - } |
|
456 | - |
|
457 | - private function getAccountPropertyMock(string $name, string $value): IAccountProperty&MockObject { |
|
458 | - $propertyMock = $this->getMockBuilder(IAccountProperty::class) |
|
459 | - ->disableOriginalConstructor() |
|
460 | - ->getMock(); |
|
461 | - $propertyMock->expects($this->any()) |
|
462 | - ->method('getName') |
|
463 | - ->willReturn($name); |
|
464 | - $propertyMock->expects($this->any()) |
|
465 | - ->method('getValue') |
|
466 | - ->willReturn($value); |
|
467 | - |
|
468 | - return $propertyMock; |
|
469 | - } |
|
26 | + protected IAccountManager&MockObject $accountManager; |
|
27 | + protected IUserManager&MockObject $userManager; |
|
28 | + protected IDBConnection&MockObject $connection; |
|
29 | + protected InputInterface&MockObject $consoleInput; |
|
30 | + protected OutputInterface&MockObject $consoleOutput; |
|
31 | + |
|
32 | + protected function setUp(): void { |
|
33 | + parent::setUp(); |
|
34 | + |
|
35 | + $this->accountManager = $this->createMock(IAccountManager::class); |
|
36 | + $this->userManager = $this->createMock(IUserManager::class); |
|
37 | + $this->connection = $this->createMock(IDBConnection::class); |
|
38 | + $this->consoleInput = $this->createMock(InputInterface::class); |
|
39 | + $this->consoleOutput = $this->createMock(OutputInterface::class); |
|
40 | + } |
|
41 | + |
|
42 | + public function getCommand(array $methods = []): Profile|MockObject { |
|
43 | + if (empty($methods)) { |
|
44 | + return new Profile($this->userManager, $this->accountManager); |
|
45 | + } else { |
|
46 | + return $this->getMockBuilder(Profile::class) |
|
47 | + ->setConstructorArgs([ |
|
48 | + $this->userManager, |
|
49 | + $this->accountManager, |
|
50 | + ]) |
|
51 | + ->onlyMethods($methods) |
|
52 | + ->getMock(); |
|
53 | + } |
|
54 | + } |
|
55 | + |
|
56 | + public static function dataCheckInput(): array { |
|
57 | + return [ |
|
58 | + 'Call with existing user should pass check' => [ |
|
59 | + [['uid', 'username']], |
|
60 | + [], |
|
61 | + [], |
|
62 | + true, |
|
63 | + null, |
|
64 | + ], |
|
65 | + 'Call with non-existing user should fail check' => [ |
|
66 | + [['uid', 'username']], |
|
67 | + [], |
|
68 | + [], |
|
69 | + false, |
|
70 | + 'The user "username" does not exist.', |
|
71 | + ], |
|
72 | + |
|
73 | + 'Call with uid, key and --default value should pass check' => [ |
|
74 | + [['uid', 'username'], ['key', 'configkey']], |
|
75 | + [], |
|
76 | + [['--default-value', false, true]], |
|
77 | + true, |
|
78 | + null, |
|
79 | + ], |
|
80 | + 'Call with uid and empty key with default-value option should fail check' => [ |
|
81 | + [['uid', 'username'], ['key', '']], |
|
82 | + [], |
|
83 | + [['--default-value', false, true]], |
|
84 | + true, |
|
85 | + 'The "default-value" option can only be used when specifying a key.', |
|
86 | + ], |
|
87 | + |
|
88 | + 'Call with uid, key, value should pass check' => [ |
|
89 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
90 | + [], |
|
91 | + [], |
|
92 | + true, |
|
93 | + null, |
|
94 | + ], |
|
95 | + 'Call with uid, empty key and empty value should fail check' => [ |
|
96 | + [['uid', 'username'], ['key', ''], ['value', '']], |
|
97 | + [], |
|
98 | + [], |
|
99 | + true, |
|
100 | + 'The value argument can only be used when specifying a key.', |
|
101 | + ], |
|
102 | + 'Call with uid, key, empty value and default-value option should fail check' => [ |
|
103 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
104 | + [], |
|
105 | + [['--default-value', false, true]], |
|
106 | + true, |
|
107 | + 'The value argument can not be used together with "default-value".', |
|
108 | + ], |
|
109 | + 'Call with uid, key, empty value and update-only option should pass check' => [ |
|
110 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
111 | + [['update-only', true]], |
|
112 | + [], |
|
113 | + true, |
|
114 | + null, |
|
115 | + ], |
|
116 | + 'Call with uid, key, null value and update-only option should fail check' => [ |
|
117 | + [['uid', 'username'], ['key', 'configkey'], ['value', null]], |
|
118 | + [['update-only', true]], |
|
119 | + [], |
|
120 | + true, |
|
121 | + 'The "update-only" option can only be used together with "value".', |
|
122 | + ], |
|
123 | + |
|
124 | + 'Call with uid, key and delete option should pass check' => [ |
|
125 | + [['uid', 'username'], ['key', 'configkey']], |
|
126 | + [['delete', true]], |
|
127 | + [], |
|
128 | + true, |
|
129 | + null, |
|
130 | + ], |
|
131 | + 'Call with uid, empty key and delete option should fail check' => [ |
|
132 | + [['uid', 'username'], ['key', '']], |
|
133 | + [['delete', true]], |
|
134 | + [], |
|
135 | + true, |
|
136 | + 'The "delete" option can only be used when specifying a key.', |
|
137 | + ], |
|
138 | + 'Call with uid, key, delete option and default-value should fail check' => [ |
|
139 | + [['uid', 'username'], ['key', 'configkey']], |
|
140 | + [['delete', true]], |
|
141 | + [['--default-value', false, true]], |
|
142 | + true, |
|
143 | + 'The "delete" option can not be used together with "default-value".', |
|
144 | + ], |
|
145 | + 'Call with uid, key, empty value and delete option should fail check' => [ |
|
146 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
147 | + [['delete', true]], |
|
148 | + [], |
|
149 | + true, |
|
150 | + 'The "delete" option can not be used together with "value".', |
|
151 | + ], |
|
152 | + 'Call with uid, key, delete and error-if-not-exists should pass check' => [ |
|
153 | + [['uid', 'username'], ['key', 'configkey']], |
|
154 | + [['delete', true], ['error-if-not-exists', true]], |
|
155 | + [], |
|
156 | + true, |
|
157 | + null, |
|
158 | + ], |
|
159 | + 'Call with uid, key and error-if-not-exists should fail check' => [ |
|
160 | + [['uid', 'username'], ['key', 'configkey']], |
|
161 | + [['delete', false], ['error-if-not-exists', true]], |
|
162 | + [], |
|
163 | + true, |
|
164 | + 'The "error-if-not-exists" option can only be used together with "delete".', |
|
165 | + ], |
|
166 | + ]; |
|
167 | + } |
|
168 | + |
|
169 | + /** |
|
170 | + * @dataProvider dataCheckInput |
|
171 | + */ |
|
172 | + public function testCheckInput(array $arguments, array $options, array $parameterOptions, bool $existingUser, ?string $expectedException): void { |
|
173 | + $this->consoleInput->expects($this->any()) |
|
174 | + ->method('getArgument') |
|
175 | + ->willReturnMap($arguments); |
|
176 | + $this->consoleInput->expects($this->any()) |
|
177 | + ->method('getOption') |
|
178 | + ->willReturnMap($options); |
|
179 | + $this->consoleInput->expects($this->any()) |
|
180 | + ->method('hasParameterOption') |
|
181 | + ->willReturnCallback(function (string|array $values, bool $onlyParams = false) use ($parameterOptions): bool { |
|
182 | + $arguments = func_get_args(); |
|
183 | + foreach ($parameterOptions as $parameterOption) { |
|
184 | + // check the arguments of the function, if they are the same, return the mocked value |
|
185 | + if (array_diff($arguments, $parameterOption) === []) { |
|
186 | + return end($parameterOption); |
|
187 | + } |
|
188 | + } |
|
189 | + |
|
190 | + return false; |
|
191 | + }); |
|
192 | + |
|
193 | + $returnedUser = null; |
|
194 | + if ($existingUser) { |
|
195 | + $mockUser = $this->createMock(IUser::class); |
|
196 | + $mockUser->expects($this->once())->method('getUID')->willReturn('user'); |
|
197 | + $returnedUser = $mockUser; |
|
198 | + } |
|
199 | + $this->userManager->expects($this->once()) |
|
200 | + ->method('get') |
|
201 | + ->willReturn($returnedUser); |
|
202 | + |
|
203 | + $command = $this->getCommand(); |
|
204 | + try { |
|
205 | + $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); |
|
206 | + $this->assertNull($expectedException); |
|
207 | + } catch (\InvalidArgumentException $e) { |
|
208 | + $this->assertEquals($expectedException, $e->getMessage()); |
|
209 | + } |
|
210 | + } |
|
211 | + |
|
212 | + public function testCheckInputExceptionCatch(): void { |
|
213 | + $command = $this->getCommand(['checkInput']); |
|
214 | + $command->expects($this->once()) |
|
215 | + ->method('checkInput') |
|
216 | + ->willThrowException(new \InvalidArgumentException('test')); |
|
217 | + |
|
218 | + $this->consoleOutput->expects($this->once()) |
|
219 | + ->method('writeln') |
|
220 | + ->with('<error>test</error>'); |
|
221 | + |
|
222 | + $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
223 | + } |
|
224 | + |
|
225 | + public static function dataExecuteDeleteProfileProperty(): array { |
|
226 | + return [ |
|
227 | + 'Deleting existing property should succeed' => ['address', 'Berlin', false, null, Command::SUCCESS], |
|
228 | + 'Deleting existing property with error-if-not-exists should succeed' => ['address', 'Berlin', true, null, Command::SUCCESS], |
|
229 | + 'Deleting non-existing property should succeed' => ['address', '', false, null, Command::SUCCESS], |
|
230 | + 'Deleting non-existing property with error-if-not-exists should fail' => ['address', '', true, '<error>The property does not exist for user "username".</error>', Command::FAILURE], |
|
231 | + ]; |
|
232 | + } |
|
233 | + |
|
234 | + /** |
|
235 | + * Tests the deletion mechanism on profile settings. |
|
236 | + * |
|
237 | + * @dataProvider dataExecuteDeleteProfileProperty |
|
238 | + */ |
|
239 | + public function testExecuteDeleteProfileProperty(string $configKey, string $value, bool $errorIfNotExists, ?string $expectedLine, int $expectedReturn): void { |
|
240 | + $uid = 'username'; |
|
241 | + $appName = 'profile'; |
|
242 | + $command = $this->getCommand([ |
|
243 | + 'writeArrayInOutputFormat', |
|
244 | + 'checkInput', |
|
245 | + ]); |
|
246 | + |
|
247 | + $this->consoleInput->expects($this->any()) |
|
248 | + ->method('getArgument') |
|
249 | + ->willReturnMap([ |
|
250 | + ['uid', $uid], |
|
251 | + ['app', $appName], |
|
252 | + ['key', $configKey], |
|
253 | + ]); |
|
254 | + |
|
255 | + $mocks = $this->setupProfilePropertiesMock([$configKey => $value]); |
|
256 | + |
|
257 | + $command->expects($this->once()) |
|
258 | + ->method('checkInput') |
|
259 | + ->willReturn($mocks['userMock']); |
|
260 | + |
|
261 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
262 | + ->method('hasParameterOption') |
|
263 | + ->willReturnMap([ |
|
264 | + ['--delete', false, true], |
|
265 | + ['--error-if-not-exists', false, $errorIfNotExists], |
|
266 | + ]); |
|
267 | + |
|
268 | + if ($expectedLine === null) { |
|
269 | + $this->consoleOutput->expects($this->never()) |
|
270 | + ->method('writeln'); |
|
271 | + $mocks['profilePropertiesMocks'][0]->expects($this->once()) |
|
272 | + ->method('setValue') |
|
273 | + ->with(''); |
|
274 | + $this->accountManager->expects($this->once()) |
|
275 | + ->method('updateAccount') |
|
276 | + ->with($mocks['accountMock']); |
|
277 | + } else { |
|
278 | + $this->consoleOutput->expects($this->once()) |
|
279 | + ->method('writeln') |
|
280 | + ->with($expectedLine); |
|
281 | + $this->accountManager->expects($this->never()) |
|
282 | + ->method('updateAccount'); |
|
283 | + } |
|
284 | + |
|
285 | + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
286 | + } |
|
287 | + |
|
288 | + public function testExecuteSetProfileProperty(): void { |
|
289 | + $command = $this->getCommand([ |
|
290 | + 'writeArrayInOutputFormat', |
|
291 | + 'checkInput', |
|
292 | + ]); |
|
293 | + |
|
294 | + $uid = 'username'; |
|
295 | + $propertyKey = 'address'; |
|
296 | + $propertyValue = 'Barcelona'; |
|
297 | + |
|
298 | + $this->consoleInput->expects($this->atLeast(3)) |
|
299 | + ->method('getArgument') |
|
300 | + ->willReturnMap([ |
|
301 | + ['uid', $uid], |
|
302 | + ['key', $propertyKey], |
|
303 | + ['value', $propertyValue], |
|
304 | + ]); |
|
305 | + |
|
306 | + $mocks = $this->setupProfilePropertiesMock([$propertyKey => $propertyValue]); |
|
307 | + |
|
308 | + $command->expects($this->once()) |
|
309 | + ->method('checkInput') |
|
310 | + ->willReturn($mocks['userMock']); |
|
311 | + |
|
312 | + $mocks['profilePropertiesMocks'][0]->expects($this->once()) |
|
313 | + ->method('setValue') |
|
314 | + ->with($propertyValue); |
|
315 | + $this->accountManager->expects($this->once()) |
|
316 | + ->method('updateAccount') |
|
317 | + ->with($mocks['accountMock']); |
|
318 | + |
|
319 | + $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
320 | + } |
|
321 | + |
|
322 | + public static function dataExecuteGet(): array { |
|
323 | + return [ |
|
324 | + 'Get property with set value should pass' => ['configkey', 'value', null, 'value', Command::SUCCESS], |
|
325 | + 'Get property with empty value and default-value option should pass' => ['configkey', '', 'default-value', 'default-value', Command::SUCCESS], |
|
326 | + 'Get property with empty value should fail' => ['configkey', '', null, '<error>The property does not exist for user "username".</error>', Command::FAILURE], |
|
327 | + ]; |
|
328 | + } |
|
329 | + |
|
330 | + /** |
|
331 | + * @dataProvider dataExecuteGet |
|
332 | + */ |
|
333 | + public function testExecuteGet(string $key, string $value, ?string $defaultValue, string $expectedLine, int $expectedReturn): void { |
|
334 | + $command = $this->getCommand([ |
|
335 | + 'writeArrayInOutputFormat', |
|
336 | + 'checkInput', |
|
337 | + ]); |
|
338 | + |
|
339 | + $uid = 'username'; |
|
340 | + |
|
341 | + $this->consoleInput->expects($this->any()) |
|
342 | + ->method('getArgument') |
|
343 | + ->willReturnMap([ |
|
344 | + ['uid', $uid], |
|
345 | + ['key', $key], |
|
346 | + ]); |
|
347 | + |
|
348 | + $mocks = $this->setupProfilePropertiesMock([$key => $value]); |
|
349 | + |
|
350 | + $command->expects($this->once()) |
|
351 | + ->method('checkInput') |
|
352 | + ->willReturn($mocks['userMock']); |
|
353 | + |
|
354 | + if ($value === '') { |
|
355 | + if ($defaultValue === null) { |
|
356 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
357 | + ->method('hasParameterOption') |
|
358 | + ->willReturn(false); |
|
359 | + } else { |
|
360 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
361 | + ->method('hasParameterOption') |
|
362 | + ->willReturnCallback(fn (string|array $values): bool => $values === '--default-value'); |
|
363 | + $this->consoleInput->expects($this->once()) |
|
364 | + ->method('getOption') |
|
365 | + ->with('default-value') |
|
366 | + ->willReturn($defaultValue); |
|
367 | + } |
|
368 | + } |
|
369 | + |
|
370 | + $this->consoleOutput->expects($this->once()) |
|
371 | + ->method('writeln') |
|
372 | + ->with($expectedLine); |
|
373 | + |
|
374 | + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
375 | + } |
|
376 | + |
|
377 | + public function testExecuteList(): void { |
|
378 | + $uid = 'username'; |
|
379 | + $profileData = [ |
|
380 | + 'pronouns' => 'they/them', |
|
381 | + 'address' => 'Berlin', |
|
382 | + ]; |
|
383 | + |
|
384 | + $command = $this->getCommand([ |
|
385 | + 'writeArrayInOutputFormat', |
|
386 | + 'checkInput', |
|
387 | + ]); |
|
388 | + |
|
389 | + $this->consoleInput->expects($this->any()) |
|
390 | + ->method('getArgument') |
|
391 | + ->willReturnMap([ |
|
392 | + ['uid', $uid], |
|
393 | + ['key', ''], |
|
394 | + ]); |
|
395 | + |
|
396 | + $mocks = $this->setupProfilePropertiesMock(['address' => $profileData['address'], 'pronouns' => $profileData['pronouns']]); |
|
397 | + |
|
398 | + $command->expects($this->once()) |
|
399 | + ->method('checkInput') |
|
400 | + ->willReturn($mocks['userMock']); |
|
401 | + |
|
402 | + $command->expects($this->once()) |
|
403 | + ->method('writeArrayInOutputFormat') |
|
404 | + ->with($this->consoleInput, $this->consoleOutput, $profileData); |
|
405 | + |
|
406 | + |
|
407 | + $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
408 | + } |
|
409 | + |
|
410 | + /** |
|
411 | + * Helper to avoid boilerplate in tests in this file when mocking objects |
|
412 | + * of IAccountProperty type. |
|
413 | + * |
|
414 | + * @param array<string, string> $properties the properties to be set up as key => value |
|
415 | + * @return array{ |
|
416 | + * userMock: IUser&MockObject, |
|
417 | + * accountMock: IAccount&MockObject, |
|
418 | + * profilePropertiesMocks: IAccountProperty&MockObject[] |
|
419 | + * } |
|
420 | + */ |
|
421 | + private function setupProfilePropertiesMock(array $properties): array { |
|
422 | + $userMock = $this->createMock(IUser::class); |
|
423 | + $accountMock = $this->createMock(IAccount::class); |
|
424 | + $this->accountManager->expects($this->atLeastOnce()) |
|
425 | + ->method('getAccount') |
|
426 | + ->with($userMock) |
|
427 | + ->willReturn($accountMock); |
|
428 | + |
|
429 | + /** @var IAccountProperty&MockObject[] $propertiesMocks */ |
|
430 | + $propertiesMocks = []; |
|
431 | + foreach ($properties as $key => $value) { |
|
432 | + $propertiesMocks[] = $this->getAccountPropertyMock($key, $value); |
|
433 | + } |
|
434 | + |
|
435 | + if (count($properties) === 1) { |
|
436 | + $accountMock->expects($this->atLeastOnce()) |
|
437 | + ->method('getProperty') |
|
438 | + ->with(array_keys($properties)[0]) |
|
439 | + ->willReturn($propertiesMocks[array_key_first($propertiesMocks)]); |
|
440 | + } else { |
|
441 | + $accountMock->expects($this->atLeastOnce()) |
|
442 | + ->method('getAllProperties') |
|
443 | + ->willReturnCallback(function () use ($propertiesMocks) { |
|
444 | + foreach ($propertiesMocks as $property) { |
|
445 | + yield $property; |
|
446 | + } |
|
447 | + }); |
|
448 | + } |
|
449 | + |
|
450 | + return [ |
|
451 | + 'userMock' => $userMock, |
|
452 | + 'accountMock' => $accountMock, |
|
453 | + 'profilePropertiesMocks' => $propertiesMocks, |
|
454 | + ]; |
|
455 | + } |
|
456 | + |
|
457 | + private function getAccountPropertyMock(string $name, string $value): IAccountProperty&MockObject { |
|
458 | + $propertyMock = $this->getMockBuilder(IAccountProperty::class) |
|
459 | + ->disableOriginalConstructor() |
|
460 | + ->getMock(); |
|
461 | + $propertyMock->expects($this->any()) |
|
462 | + ->method('getName') |
|
463 | + ->willReturn($name); |
|
464 | + $propertyMock->expects($this->any()) |
|
465 | + ->method('getValue') |
|
466 | + ->willReturn($value); |
|
467 | + |
|
468 | + return $propertyMock; |
|
469 | + } |
|
470 | 470 | } |
@@ -18,434 +18,434 @@ |
||
18 | 18 | use Test\TestCase; |
19 | 19 | |
20 | 20 | class SettingTest extends TestCase { |
21 | - protected IUserManager&MockObject $userManager; |
|
22 | - protected IConfig&MockObject $config; |
|
23 | - protected IDBConnection&MockObject $connection; |
|
24 | - protected InputInterface&MockObject $consoleInput; |
|
25 | - protected MockObject&OutputInterface $consoleOutput; |
|
26 | - |
|
27 | - protected function setUp(): void { |
|
28 | - parent::setUp(); |
|
29 | - |
|
30 | - $this->userManager = $this->createMock(IUserManager::class); |
|
31 | - $this->config = $this->createMock(IConfig::class); |
|
32 | - $this->connection = $this->createMock(IDBConnection::class); |
|
33 | - $this->consoleInput = $this->createMock(InputInterface::class); |
|
34 | - $this->consoleOutput = $this->createMock(OutputInterface::class); |
|
35 | - } |
|
36 | - |
|
37 | - public function getCommand(array $methods = []) { |
|
38 | - if (empty($methods)) { |
|
39 | - return new Setting($this->userManager, $this->config); |
|
40 | - } else { |
|
41 | - $mock = $this->getMockBuilder(Setting::class) |
|
42 | - ->setConstructorArgs([ |
|
43 | - $this->userManager, |
|
44 | - $this->config, |
|
45 | - ]) |
|
46 | - ->onlyMethods($methods) |
|
47 | - ->getMock(); |
|
48 | - return $mock; |
|
49 | - } |
|
50 | - } |
|
51 | - |
|
52 | - public static function dataCheckInput(): array { |
|
53 | - return [ |
|
54 | - [ |
|
55 | - [['uid', 'username']], |
|
56 | - [['ignore-missing-user', true]], |
|
57 | - [], |
|
58 | - false, |
|
59 | - false, |
|
60 | - ], |
|
61 | - [ |
|
62 | - [['uid', 'username']], |
|
63 | - [['ignore-missing-user', false]], |
|
64 | - [], |
|
65 | - null, |
|
66 | - 'The user "username" does not exist.', |
|
67 | - ], |
|
68 | - |
|
69 | - [ |
|
70 | - [['uid', 'username'], ['key', 'configkey']], |
|
71 | - [['ignore-missing-user', true]], |
|
72 | - [['--default-value', false, true]], |
|
73 | - false, |
|
74 | - false, |
|
75 | - ], |
|
76 | - [ |
|
77 | - [['uid', 'username'], ['key', '']], |
|
78 | - [['ignore-missing-user', true]], |
|
79 | - [['--default-value', false, true]], |
|
80 | - false, |
|
81 | - 'The "default-value" option can only be used when specifying a key.', |
|
82 | - ], |
|
83 | - |
|
84 | - [ |
|
85 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
86 | - [['ignore-missing-user', true]], |
|
87 | - [], |
|
88 | - false, |
|
89 | - false, |
|
90 | - ], |
|
91 | - [ |
|
92 | - [['uid', 'username'], ['key', ''], ['value', '']], |
|
93 | - [['ignore-missing-user', true]], |
|
94 | - [], |
|
95 | - false, |
|
96 | - 'The value argument can only be used when specifying a key.', |
|
97 | - ], |
|
98 | - [ |
|
99 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
100 | - [['ignore-missing-user', true]], |
|
101 | - [['--default-value', false, true]], |
|
102 | - false, |
|
103 | - 'The value argument can not be used together with "default-value".', |
|
104 | - ], |
|
105 | - [ |
|
106 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
107 | - [['ignore-missing-user', true], ['update-only', true]], |
|
108 | - [], |
|
109 | - false, |
|
110 | - false, |
|
111 | - ], |
|
112 | - [ |
|
113 | - [['uid', 'username'], ['key', 'configkey'], ['value', null]], |
|
114 | - [['ignore-missing-user', true], ['update-only', true]], |
|
115 | - [], |
|
116 | - false, |
|
117 | - 'The "update-only" option can only be used together with "value".', |
|
118 | - ], |
|
119 | - |
|
120 | - [ |
|
121 | - [['uid', 'username'], ['key', 'configkey']], |
|
122 | - [['ignore-missing-user', true], ['delete', true]], |
|
123 | - [], |
|
124 | - false, |
|
125 | - false, |
|
126 | - ], |
|
127 | - [ |
|
128 | - [['uid', 'username'], ['key', '']], |
|
129 | - [['ignore-missing-user', true], ['delete', true]], |
|
130 | - [], |
|
131 | - false, |
|
132 | - 'The "delete" option can only be used when specifying a key.', |
|
133 | - ], |
|
134 | - [ |
|
135 | - [['uid', 'username'], ['key', 'configkey']], |
|
136 | - [['ignore-missing-user', true], ['delete', true]], |
|
137 | - [['--default-value', false, true]], |
|
138 | - false, |
|
139 | - 'The "delete" option can not be used together with "default-value".', |
|
140 | - ], |
|
141 | - [ |
|
142 | - [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
143 | - [['ignore-missing-user', true], ['delete', true]], |
|
144 | - [], |
|
145 | - false, |
|
146 | - 'The "delete" option can not be used together with "value".', |
|
147 | - ], |
|
148 | - [ |
|
149 | - [['uid', 'username'], ['key', 'configkey']], |
|
150 | - [['ignore-missing-user', true], ['delete', true], ['error-if-not-exists', true]], |
|
151 | - [], |
|
152 | - false, |
|
153 | - false, |
|
154 | - ], |
|
155 | - [ |
|
156 | - [['uid', 'username'], ['key', 'configkey']], |
|
157 | - [['ignore-missing-user', true], ['delete', false], ['error-if-not-exists', true]], |
|
158 | - [], |
|
159 | - false, |
|
160 | - 'The "error-if-not-exists" option can only be used together with "delete".', |
|
161 | - ], |
|
162 | - ]; |
|
163 | - } |
|
164 | - |
|
165 | - /** |
|
166 | - * @dataProvider dataCheckInput |
|
167 | - * |
|
168 | - * @param array $arguments |
|
169 | - * @param array $options |
|
170 | - * @param array $parameterOptions |
|
171 | - * @param mixed $user |
|
172 | - * @param string $expectedException |
|
173 | - */ |
|
174 | - public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException): void { |
|
175 | - $this->consoleInput->expects($this->any()) |
|
176 | - ->method('getArgument') |
|
177 | - ->willReturnMap($arguments); |
|
178 | - $this->consoleInput->expects($this->any()) |
|
179 | - ->method('getOption') |
|
180 | - ->willReturnMap($options); |
|
181 | - $this->consoleInput->expects($this->any()) |
|
182 | - ->method('hasParameterOption') |
|
183 | - ->willReturnCallback(function (string|array $config, bool $default = false) use ($parameterOptions): bool { |
|
184 | - foreach ($parameterOptions as $parameterOption) { |
|
185 | - if ($config === $parameterOption[0] |
|
186 | - // Check the default value if the maps has 3 entries |
|
187 | - && (!isset($parameterOption[2]) || $default === $parameterOption[1])) { |
|
188 | - return end($parameterOption); |
|
189 | - } |
|
190 | - } |
|
191 | - return false; |
|
192 | - }); |
|
193 | - |
|
194 | - if ($user !== false) { |
|
195 | - $this->userManager->expects($this->once()) |
|
196 | - ->method('get') |
|
197 | - ->willReturn($user); |
|
198 | - } else { |
|
199 | - $this->userManager->expects($this->never()) |
|
200 | - ->method('get'); |
|
201 | - } |
|
202 | - |
|
203 | - $command = $this->getCommand(); |
|
204 | - try { |
|
205 | - $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); |
|
206 | - $this->assertFalse($expectedException); |
|
207 | - } catch (InvalidArgumentException $e) { |
|
208 | - $this->assertEquals($expectedException, $e->getMessage()); |
|
209 | - } |
|
210 | - } |
|
211 | - |
|
212 | - public function testCheckInputExceptionCatch(): void { |
|
213 | - $command = $this->getCommand(['checkInput']); |
|
214 | - $command->expects($this->once()) |
|
215 | - ->method('checkInput') |
|
216 | - ->willThrowException(new InvalidArgumentException('test')); |
|
217 | - |
|
218 | - $this->consoleOutput->expects($this->once()) |
|
219 | - ->method('writeln') |
|
220 | - ->with('<error>test</error>'); |
|
221 | - |
|
222 | - $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
223 | - } |
|
224 | - |
|
225 | - public static function dataExecuteDelete(): array { |
|
226 | - return [ |
|
227 | - ['config', false, null, 0], |
|
228 | - ['config', true, null, 0], |
|
229 | - [null, false, null, 0], |
|
230 | - [null, true, '<error>The setting does not exist for user "username".</error>', 1], |
|
231 | - ]; |
|
232 | - } |
|
233 | - |
|
234 | - /** |
|
235 | - * @dataProvider dataExecuteDelete |
|
236 | - * |
|
237 | - * @param string|null $value |
|
238 | - * @param bool $errorIfNotExists |
|
239 | - * @param string $expectedLine |
|
240 | - * @param int $expectedReturn |
|
241 | - */ |
|
242 | - public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn): void { |
|
243 | - $command = $this->getCommand([ |
|
244 | - 'writeArrayInOutputFormat', |
|
245 | - 'checkInput', |
|
246 | - 'getUserSettings', |
|
247 | - ]); |
|
248 | - |
|
249 | - $this->consoleInput->expects($this->any()) |
|
250 | - ->method('getArgument') |
|
251 | - ->willReturnMap([ |
|
252 | - ['uid', 'username'], |
|
253 | - ['app', 'appname'], |
|
254 | - ['key', 'configkey'], |
|
255 | - ]); |
|
256 | - |
|
257 | - $command->expects($this->once()) |
|
258 | - ->method('checkInput'); |
|
259 | - |
|
260 | - $this->config->expects($this->once()) |
|
261 | - ->method('getUserValue') |
|
262 | - ->with('username', 'appname', 'configkey', null) |
|
263 | - ->willReturn($value); |
|
264 | - |
|
265 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
266 | - ->method('hasParameterOption') |
|
267 | - ->willReturnMap([ |
|
268 | - ['--delete', false, true], |
|
269 | - ['--error-if-not-exists', false, $errorIfNotExists], |
|
270 | - ]); |
|
271 | - |
|
272 | - if ($expectedLine === null) { |
|
273 | - $this->consoleOutput->expects($this->never()) |
|
274 | - ->method('writeln'); |
|
275 | - $this->config->expects($this->once()) |
|
276 | - ->method('deleteUserValue') |
|
277 | - ->with('username', 'appname', 'configkey'); |
|
278 | - } else { |
|
279 | - $this->consoleOutput->expects($this->once()) |
|
280 | - ->method('writeln') |
|
281 | - ->with($expectedLine); |
|
282 | - $this->config->expects($this->never()) |
|
283 | - ->method('deleteUserValue'); |
|
284 | - } |
|
285 | - |
|
286 | - $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
287 | - } |
|
288 | - |
|
289 | - public static function dataExecuteSet(): array { |
|
290 | - return [ |
|
291 | - ['config', false, null, 0], |
|
292 | - ['config', true, null, 0], |
|
293 | - [null, false, null, 0], |
|
294 | - [null, true, '<error>The setting does not exist for user "username".</error>', 1], |
|
295 | - ]; |
|
296 | - } |
|
297 | - |
|
298 | - /** |
|
299 | - * @dataProvider dataExecuteSet |
|
300 | - * |
|
301 | - * @param string|null $value |
|
302 | - * @param bool $updateOnly |
|
303 | - * @param string $expectedLine |
|
304 | - * @param int $expectedReturn |
|
305 | - */ |
|
306 | - public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn): void { |
|
307 | - $command = $this->getCommand([ |
|
308 | - 'writeArrayInOutputFormat', |
|
309 | - 'checkInput', |
|
310 | - 'getUserSettings', |
|
311 | - ]); |
|
312 | - |
|
313 | - $this->consoleInput->expects($this->atLeast(4)) |
|
314 | - ->method('getArgument') |
|
315 | - ->willReturnMap([ |
|
316 | - ['uid', 'username'], |
|
317 | - ['app', 'appname'], |
|
318 | - ['key', 'configkey'], |
|
319 | - ['value', 'setValue'], |
|
320 | - ]); |
|
321 | - |
|
322 | - $command->expects($this->once()) |
|
323 | - ->method('checkInput'); |
|
324 | - |
|
325 | - $this->config->expects($this->once()) |
|
326 | - ->method('getUserValue') |
|
327 | - ->with('username', 'appname', 'configkey', null) |
|
328 | - ->willReturn($value); |
|
329 | - |
|
330 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
331 | - ->method('hasParameterOption') |
|
332 | - ->willReturnMap([ |
|
333 | - ['--update-only', false, $updateOnly], |
|
334 | - ]); |
|
335 | - |
|
336 | - if ($expectedLine === null) { |
|
337 | - $this->consoleOutput->expects($this->never()) |
|
338 | - ->method('writeln'); |
|
339 | - |
|
340 | - $this->consoleInput->expects($this->never()) |
|
341 | - ->method('getOption'); |
|
342 | - |
|
343 | - $this->config->expects($this->once()) |
|
344 | - ->method('setUserValue') |
|
345 | - ->with('username', 'appname', 'configkey', 'setValue'); |
|
346 | - } else { |
|
347 | - $this->consoleOutput->expects($this->once()) |
|
348 | - ->method('writeln') |
|
349 | - ->with($expectedLine); |
|
350 | - $this->config->expects($this->never()) |
|
351 | - ->method('setUserValue'); |
|
352 | - } |
|
353 | - |
|
354 | - $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
355 | - } |
|
356 | - |
|
357 | - public static function dataExecuteGet(): array { |
|
358 | - return [ |
|
359 | - ['config', null, 'config', 0], |
|
360 | - [null, 'config', 'config', 0], |
|
361 | - [null, null, '<error>The setting does not exist for user "username".</error>', 1], |
|
362 | - ]; |
|
363 | - } |
|
364 | - |
|
365 | - /** |
|
366 | - * @dataProvider dataExecuteGet |
|
367 | - * |
|
368 | - * @param string|null $value |
|
369 | - * @param string|null $defaultValue |
|
370 | - * @param string $expectedLine |
|
371 | - * @param int $expectedReturn |
|
372 | - */ |
|
373 | - public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn): void { |
|
374 | - $command = $this->getCommand([ |
|
375 | - 'writeArrayInOutputFormat', |
|
376 | - 'checkInput', |
|
377 | - 'getUserSettings', |
|
378 | - ]); |
|
379 | - |
|
380 | - $this->consoleInput->expects($this->any()) |
|
381 | - ->method('getArgument') |
|
382 | - ->willReturnMap([ |
|
383 | - ['uid', 'username'], |
|
384 | - ['app', 'appname'], |
|
385 | - ['key', 'configkey'], |
|
386 | - ]); |
|
387 | - |
|
388 | - $command->expects($this->once()) |
|
389 | - ->method('checkInput'); |
|
390 | - |
|
391 | - $this->config->expects($this->once()) |
|
392 | - ->method('getUserValue') |
|
393 | - ->with('username', 'appname', 'configkey', null) |
|
394 | - ->willReturn($value); |
|
395 | - |
|
396 | - if ($value === null) { |
|
397 | - if ($defaultValue === null) { |
|
398 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
399 | - ->method('hasParameterOption') |
|
400 | - ->willReturn(false); |
|
401 | - } else { |
|
402 | - $this->consoleInput->expects($this->atLeastOnce()) |
|
403 | - ->method('hasParameterOption') |
|
404 | - ->willReturnCallback(function (string|array $config, bool $default = false): bool { |
|
405 | - if ($config === '--default-value' && $default === false) { |
|
406 | - return true; |
|
407 | - } |
|
408 | - return false; |
|
409 | - }); |
|
410 | - $this->consoleInput->expects($this->once()) |
|
411 | - ->method('getOption') |
|
412 | - ->with('default-value') |
|
413 | - ->willReturn($defaultValue); |
|
414 | - } |
|
415 | - } |
|
416 | - |
|
417 | - $this->consoleOutput->expects($this->once()) |
|
418 | - ->method('writeln') |
|
419 | - ->with($expectedLine); |
|
420 | - |
|
421 | - $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
422 | - } |
|
423 | - |
|
424 | - public function testExecuteList(): void { |
|
425 | - $command = $this->getCommand([ |
|
426 | - 'writeArrayInOutputFormat', |
|
427 | - 'checkInput', |
|
428 | - 'getUserSettings', |
|
429 | - ]); |
|
430 | - |
|
431 | - $this->consoleInput->expects($this->any()) |
|
432 | - ->method('getArgument') |
|
433 | - ->willReturnMap([ |
|
434 | - ['uid', 'username'], |
|
435 | - ['app', 'appname'], |
|
436 | - ['key', ''], |
|
437 | - ]); |
|
438 | - |
|
439 | - $command->expects($this->once()) |
|
440 | - ->method('checkInput'); |
|
441 | - $command->expects($this->once()) |
|
442 | - ->method('getUserSettings') |
|
443 | - ->willReturn(['settings']); |
|
444 | - $command->expects($this->once()) |
|
445 | - ->method('writeArrayInOutputFormat') |
|
446 | - ->with($this->consoleInput, $this->consoleOutput, ['settings']); |
|
447 | - |
|
448 | - |
|
449 | - $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
450 | - } |
|
21 | + protected IUserManager&MockObject $userManager; |
|
22 | + protected IConfig&MockObject $config; |
|
23 | + protected IDBConnection&MockObject $connection; |
|
24 | + protected InputInterface&MockObject $consoleInput; |
|
25 | + protected MockObject&OutputInterface $consoleOutput; |
|
26 | + |
|
27 | + protected function setUp(): void { |
|
28 | + parent::setUp(); |
|
29 | + |
|
30 | + $this->userManager = $this->createMock(IUserManager::class); |
|
31 | + $this->config = $this->createMock(IConfig::class); |
|
32 | + $this->connection = $this->createMock(IDBConnection::class); |
|
33 | + $this->consoleInput = $this->createMock(InputInterface::class); |
|
34 | + $this->consoleOutput = $this->createMock(OutputInterface::class); |
|
35 | + } |
|
36 | + |
|
37 | + public function getCommand(array $methods = []) { |
|
38 | + if (empty($methods)) { |
|
39 | + return new Setting($this->userManager, $this->config); |
|
40 | + } else { |
|
41 | + $mock = $this->getMockBuilder(Setting::class) |
|
42 | + ->setConstructorArgs([ |
|
43 | + $this->userManager, |
|
44 | + $this->config, |
|
45 | + ]) |
|
46 | + ->onlyMethods($methods) |
|
47 | + ->getMock(); |
|
48 | + return $mock; |
|
49 | + } |
|
50 | + } |
|
51 | + |
|
52 | + public static function dataCheckInput(): array { |
|
53 | + return [ |
|
54 | + [ |
|
55 | + [['uid', 'username']], |
|
56 | + [['ignore-missing-user', true]], |
|
57 | + [], |
|
58 | + false, |
|
59 | + false, |
|
60 | + ], |
|
61 | + [ |
|
62 | + [['uid', 'username']], |
|
63 | + [['ignore-missing-user', false]], |
|
64 | + [], |
|
65 | + null, |
|
66 | + 'The user "username" does not exist.', |
|
67 | + ], |
|
68 | + |
|
69 | + [ |
|
70 | + [['uid', 'username'], ['key', 'configkey']], |
|
71 | + [['ignore-missing-user', true]], |
|
72 | + [['--default-value', false, true]], |
|
73 | + false, |
|
74 | + false, |
|
75 | + ], |
|
76 | + [ |
|
77 | + [['uid', 'username'], ['key', '']], |
|
78 | + [['ignore-missing-user', true]], |
|
79 | + [['--default-value', false, true]], |
|
80 | + false, |
|
81 | + 'The "default-value" option can only be used when specifying a key.', |
|
82 | + ], |
|
83 | + |
|
84 | + [ |
|
85 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
86 | + [['ignore-missing-user', true]], |
|
87 | + [], |
|
88 | + false, |
|
89 | + false, |
|
90 | + ], |
|
91 | + [ |
|
92 | + [['uid', 'username'], ['key', ''], ['value', '']], |
|
93 | + [['ignore-missing-user', true]], |
|
94 | + [], |
|
95 | + false, |
|
96 | + 'The value argument can only be used when specifying a key.', |
|
97 | + ], |
|
98 | + [ |
|
99 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
100 | + [['ignore-missing-user', true]], |
|
101 | + [['--default-value', false, true]], |
|
102 | + false, |
|
103 | + 'The value argument can not be used together with "default-value".', |
|
104 | + ], |
|
105 | + [ |
|
106 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
107 | + [['ignore-missing-user', true], ['update-only', true]], |
|
108 | + [], |
|
109 | + false, |
|
110 | + false, |
|
111 | + ], |
|
112 | + [ |
|
113 | + [['uid', 'username'], ['key', 'configkey'], ['value', null]], |
|
114 | + [['ignore-missing-user', true], ['update-only', true]], |
|
115 | + [], |
|
116 | + false, |
|
117 | + 'The "update-only" option can only be used together with "value".', |
|
118 | + ], |
|
119 | + |
|
120 | + [ |
|
121 | + [['uid', 'username'], ['key', 'configkey']], |
|
122 | + [['ignore-missing-user', true], ['delete', true]], |
|
123 | + [], |
|
124 | + false, |
|
125 | + false, |
|
126 | + ], |
|
127 | + [ |
|
128 | + [['uid', 'username'], ['key', '']], |
|
129 | + [['ignore-missing-user', true], ['delete', true]], |
|
130 | + [], |
|
131 | + false, |
|
132 | + 'The "delete" option can only be used when specifying a key.', |
|
133 | + ], |
|
134 | + [ |
|
135 | + [['uid', 'username'], ['key', 'configkey']], |
|
136 | + [['ignore-missing-user', true], ['delete', true]], |
|
137 | + [['--default-value', false, true]], |
|
138 | + false, |
|
139 | + 'The "delete" option can not be used together with "default-value".', |
|
140 | + ], |
|
141 | + [ |
|
142 | + [['uid', 'username'], ['key', 'configkey'], ['value', '']], |
|
143 | + [['ignore-missing-user', true], ['delete', true]], |
|
144 | + [], |
|
145 | + false, |
|
146 | + 'The "delete" option can not be used together with "value".', |
|
147 | + ], |
|
148 | + [ |
|
149 | + [['uid', 'username'], ['key', 'configkey']], |
|
150 | + [['ignore-missing-user', true], ['delete', true], ['error-if-not-exists', true]], |
|
151 | + [], |
|
152 | + false, |
|
153 | + false, |
|
154 | + ], |
|
155 | + [ |
|
156 | + [['uid', 'username'], ['key', 'configkey']], |
|
157 | + [['ignore-missing-user', true], ['delete', false], ['error-if-not-exists', true]], |
|
158 | + [], |
|
159 | + false, |
|
160 | + 'The "error-if-not-exists" option can only be used together with "delete".', |
|
161 | + ], |
|
162 | + ]; |
|
163 | + } |
|
164 | + |
|
165 | + /** |
|
166 | + * @dataProvider dataCheckInput |
|
167 | + * |
|
168 | + * @param array $arguments |
|
169 | + * @param array $options |
|
170 | + * @param array $parameterOptions |
|
171 | + * @param mixed $user |
|
172 | + * @param string $expectedException |
|
173 | + */ |
|
174 | + public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException): void { |
|
175 | + $this->consoleInput->expects($this->any()) |
|
176 | + ->method('getArgument') |
|
177 | + ->willReturnMap($arguments); |
|
178 | + $this->consoleInput->expects($this->any()) |
|
179 | + ->method('getOption') |
|
180 | + ->willReturnMap($options); |
|
181 | + $this->consoleInput->expects($this->any()) |
|
182 | + ->method('hasParameterOption') |
|
183 | + ->willReturnCallback(function (string|array $config, bool $default = false) use ($parameterOptions): bool { |
|
184 | + foreach ($parameterOptions as $parameterOption) { |
|
185 | + if ($config === $parameterOption[0] |
|
186 | + // Check the default value if the maps has 3 entries |
|
187 | + && (!isset($parameterOption[2]) || $default === $parameterOption[1])) { |
|
188 | + return end($parameterOption); |
|
189 | + } |
|
190 | + } |
|
191 | + return false; |
|
192 | + }); |
|
193 | + |
|
194 | + if ($user !== false) { |
|
195 | + $this->userManager->expects($this->once()) |
|
196 | + ->method('get') |
|
197 | + ->willReturn($user); |
|
198 | + } else { |
|
199 | + $this->userManager->expects($this->never()) |
|
200 | + ->method('get'); |
|
201 | + } |
|
202 | + |
|
203 | + $command = $this->getCommand(); |
|
204 | + try { |
|
205 | + $this->invokePrivate($command, 'checkInput', [$this->consoleInput]); |
|
206 | + $this->assertFalse($expectedException); |
|
207 | + } catch (InvalidArgumentException $e) { |
|
208 | + $this->assertEquals($expectedException, $e->getMessage()); |
|
209 | + } |
|
210 | + } |
|
211 | + |
|
212 | + public function testCheckInputExceptionCatch(): void { |
|
213 | + $command = $this->getCommand(['checkInput']); |
|
214 | + $command->expects($this->once()) |
|
215 | + ->method('checkInput') |
|
216 | + ->willThrowException(new InvalidArgumentException('test')); |
|
217 | + |
|
218 | + $this->consoleOutput->expects($this->once()) |
|
219 | + ->method('writeln') |
|
220 | + ->with('<error>test</error>'); |
|
221 | + |
|
222 | + $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
223 | + } |
|
224 | + |
|
225 | + public static function dataExecuteDelete(): array { |
|
226 | + return [ |
|
227 | + ['config', false, null, 0], |
|
228 | + ['config', true, null, 0], |
|
229 | + [null, false, null, 0], |
|
230 | + [null, true, '<error>The setting does not exist for user "username".</error>', 1], |
|
231 | + ]; |
|
232 | + } |
|
233 | + |
|
234 | + /** |
|
235 | + * @dataProvider dataExecuteDelete |
|
236 | + * |
|
237 | + * @param string|null $value |
|
238 | + * @param bool $errorIfNotExists |
|
239 | + * @param string $expectedLine |
|
240 | + * @param int $expectedReturn |
|
241 | + */ |
|
242 | + public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn): void { |
|
243 | + $command = $this->getCommand([ |
|
244 | + 'writeArrayInOutputFormat', |
|
245 | + 'checkInput', |
|
246 | + 'getUserSettings', |
|
247 | + ]); |
|
248 | + |
|
249 | + $this->consoleInput->expects($this->any()) |
|
250 | + ->method('getArgument') |
|
251 | + ->willReturnMap([ |
|
252 | + ['uid', 'username'], |
|
253 | + ['app', 'appname'], |
|
254 | + ['key', 'configkey'], |
|
255 | + ]); |
|
256 | + |
|
257 | + $command->expects($this->once()) |
|
258 | + ->method('checkInput'); |
|
259 | + |
|
260 | + $this->config->expects($this->once()) |
|
261 | + ->method('getUserValue') |
|
262 | + ->with('username', 'appname', 'configkey', null) |
|
263 | + ->willReturn($value); |
|
264 | + |
|
265 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
266 | + ->method('hasParameterOption') |
|
267 | + ->willReturnMap([ |
|
268 | + ['--delete', false, true], |
|
269 | + ['--error-if-not-exists', false, $errorIfNotExists], |
|
270 | + ]); |
|
271 | + |
|
272 | + if ($expectedLine === null) { |
|
273 | + $this->consoleOutput->expects($this->never()) |
|
274 | + ->method('writeln'); |
|
275 | + $this->config->expects($this->once()) |
|
276 | + ->method('deleteUserValue') |
|
277 | + ->with('username', 'appname', 'configkey'); |
|
278 | + } else { |
|
279 | + $this->consoleOutput->expects($this->once()) |
|
280 | + ->method('writeln') |
|
281 | + ->with($expectedLine); |
|
282 | + $this->config->expects($this->never()) |
|
283 | + ->method('deleteUserValue'); |
|
284 | + } |
|
285 | + |
|
286 | + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
287 | + } |
|
288 | + |
|
289 | + public static function dataExecuteSet(): array { |
|
290 | + return [ |
|
291 | + ['config', false, null, 0], |
|
292 | + ['config', true, null, 0], |
|
293 | + [null, false, null, 0], |
|
294 | + [null, true, '<error>The setting does not exist for user "username".</error>', 1], |
|
295 | + ]; |
|
296 | + } |
|
297 | + |
|
298 | + /** |
|
299 | + * @dataProvider dataExecuteSet |
|
300 | + * |
|
301 | + * @param string|null $value |
|
302 | + * @param bool $updateOnly |
|
303 | + * @param string $expectedLine |
|
304 | + * @param int $expectedReturn |
|
305 | + */ |
|
306 | + public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn): void { |
|
307 | + $command = $this->getCommand([ |
|
308 | + 'writeArrayInOutputFormat', |
|
309 | + 'checkInput', |
|
310 | + 'getUserSettings', |
|
311 | + ]); |
|
312 | + |
|
313 | + $this->consoleInput->expects($this->atLeast(4)) |
|
314 | + ->method('getArgument') |
|
315 | + ->willReturnMap([ |
|
316 | + ['uid', 'username'], |
|
317 | + ['app', 'appname'], |
|
318 | + ['key', 'configkey'], |
|
319 | + ['value', 'setValue'], |
|
320 | + ]); |
|
321 | + |
|
322 | + $command->expects($this->once()) |
|
323 | + ->method('checkInput'); |
|
324 | + |
|
325 | + $this->config->expects($this->once()) |
|
326 | + ->method('getUserValue') |
|
327 | + ->with('username', 'appname', 'configkey', null) |
|
328 | + ->willReturn($value); |
|
329 | + |
|
330 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
331 | + ->method('hasParameterOption') |
|
332 | + ->willReturnMap([ |
|
333 | + ['--update-only', false, $updateOnly], |
|
334 | + ]); |
|
335 | + |
|
336 | + if ($expectedLine === null) { |
|
337 | + $this->consoleOutput->expects($this->never()) |
|
338 | + ->method('writeln'); |
|
339 | + |
|
340 | + $this->consoleInput->expects($this->never()) |
|
341 | + ->method('getOption'); |
|
342 | + |
|
343 | + $this->config->expects($this->once()) |
|
344 | + ->method('setUserValue') |
|
345 | + ->with('username', 'appname', 'configkey', 'setValue'); |
|
346 | + } else { |
|
347 | + $this->consoleOutput->expects($this->once()) |
|
348 | + ->method('writeln') |
|
349 | + ->with($expectedLine); |
|
350 | + $this->config->expects($this->never()) |
|
351 | + ->method('setUserValue'); |
|
352 | + } |
|
353 | + |
|
354 | + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
355 | + } |
|
356 | + |
|
357 | + public static function dataExecuteGet(): array { |
|
358 | + return [ |
|
359 | + ['config', null, 'config', 0], |
|
360 | + [null, 'config', 'config', 0], |
|
361 | + [null, null, '<error>The setting does not exist for user "username".</error>', 1], |
|
362 | + ]; |
|
363 | + } |
|
364 | + |
|
365 | + /** |
|
366 | + * @dataProvider dataExecuteGet |
|
367 | + * |
|
368 | + * @param string|null $value |
|
369 | + * @param string|null $defaultValue |
|
370 | + * @param string $expectedLine |
|
371 | + * @param int $expectedReturn |
|
372 | + */ |
|
373 | + public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn): void { |
|
374 | + $command = $this->getCommand([ |
|
375 | + 'writeArrayInOutputFormat', |
|
376 | + 'checkInput', |
|
377 | + 'getUserSettings', |
|
378 | + ]); |
|
379 | + |
|
380 | + $this->consoleInput->expects($this->any()) |
|
381 | + ->method('getArgument') |
|
382 | + ->willReturnMap([ |
|
383 | + ['uid', 'username'], |
|
384 | + ['app', 'appname'], |
|
385 | + ['key', 'configkey'], |
|
386 | + ]); |
|
387 | + |
|
388 | + $command->expects($this->once()) |
|
389 | + ->method('checkInput'); |
|
390 | + |
|
391 | + $this->config->expects($this->once()) |
|
392 | + ->method('getUserValue') |
|
393 | + ->with('username', 'appname', 'configkey', null) |
|
394 | + ->willReturn($value); |
|
395 | + |
|
396 | + if ($value === null) { |
|
397 | + if ($defaultValue === null) { |
|
398 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
399 | + ->method('hasParameterOption') |
|
400 | + ->willReturn(false); |
|
401 | + } else { |
|
402 | + $this->consoleInput->expects($this->atLeastOnce()) |
|
403 | + ->method('hasParameterOption') |
|
404 | + ->willReturnCallback(function (string|array $config, bool $default = false): bool { |
|
405 | + if ($config === '--default-value' && $default === false) { |
|
406 | + return true; |
|
407 | + } |
|
408 | + return false; |
|
409 | + }); |
|
410 | + $this->consoleInput->expects($this->once()) |
|
411 | + ->method('getOption') |
|
412 | + ->with('default-value') |
|
413 | + ->willReturn($defaultValue); |
|
414 | + } |
|
415 | + } |
|
416 | + |
|
417 | + $this->consoleOutput->expects($this->once()) |
|
418 | + ->method('writeln') |
|
419 | + ->with($expectedLine); |
|
420 | + |
|
421 | + $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
422 | + } |
|
423 | + |
|
424 | + public function testExecuteList(): void { |
|
425 | + $command = $this->getCommand([ |
|
426 | + 'writeArrayInOutputFormat', |
|
427 | + 'checkInput', |
|
428 | + 'getUserSettings', |
|
429 | + ]); |
|
430 | + |
|
431 | + $this->consoleInput->expects($this->any()) |
|
432 | + ->method('getArgument') |
|
433 | + ->willReturnMap([ |
|
434 | + ['uid', 'username'], |
|
435 | + ['app', 'appname'], |
|
436 | + ['key', ''], |
|
437 | + ]); |
|
438 | + |
|
439 | + $command->expects($this->once()) |
|
440 | + ->method('checkInput'); |
|
441 | + $command->expects($this->once()) |
|
442 | + ->method('getUserSettings') |
|
443 | + ->willReturn(['settings']); |
|
444 | + $command->expects($this->once()) |
|
445 | + ->method('writeArrayInOutputFormat') |
|
446 | + ->with($this->consoleInput, $this->consoleOutput, ['settings']); |
|
447 | + |
|
448 | + |
|
449 | + $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput])); |
|
450 | + } |
|
451 | 451 | } |
@@ -114,137 +114,137 @@ |
||
114 | 114 | $config = Server::get(IConfig::class); |
115 | 115 | |
116 | 116 | if ($config->getSystemValueBool('installed', false)) { |
117 | - $application->add(Server::get(Disable::class)); |
|
118 | - $application->add(Server::get(Enable::class)); |
|
119 | - $application->add(Server::get(Install::class)); |
|
120 | - $application->add(Server::get(GetPath::class)); |
|
121 | - $application->add(Server::get(ListApps::class)); |
|
122 | - $application->add(Server::get(Remove::class)); |
|
123 | - $application->add(Server::get(Update::class)); |
|
124 | - |
|
125 | - $application->add(Server::get(Cleanup::class)); |
|
126 | - $application->add(Server::get(Enforce::class)); |
|
127 | - $application->add(Server::get(Command\TwoFactorAuth\Enable::class)); |
|
128 | - $application->add(Server::get(Command\TwoFactorAuth\Disable::class)); |
|
129 | - $application->add(Server::get(State::class)); |
|
130 | - |
|
131 | - $application->add(Server::get(Mode::class)); |
|
132 | - $application->add(Server::get(Job::class)); |
|
133 | - $application->add(Server::get(ListCommand::class)); |
|
134 | - $application->add(Server::get(Delete::class)); |
|
135 | - $application->add(Server::get(JobWorker::class)); |
|
136 | - |
|
137 | - $application->add(Server::get(Test::class)); |
|
138 | - |
|
139 | - $application->add(Server::get(DeleteConfig::class)); |
|
140 | - $application->add(Server::get(GetConfig::class)); |
|
141 | - $application->add(Server::get(SetConfig::class)); |
|
142 | - $application->add(Server::get(Import::class)); |
|
143 | - $application->add(Server::get(ListConfigs::class)); |
|
144 | - $application->add(Server::get(Command\Config\System\DeleteConfig::class)); |
|
145 | - $application->add(Server::get(Command\Config\System\GetConfig::class)); |
|
146 | - $application->add(Server::get(Command\Config\System\SetConfig::class)); |
|
147 | - |
|
148 | - $application->add(Server::get(File::class)); |
|
149 | - $application->add(Server::get(Space::class)); |
|
150 | - $application->add(Server::get(Storage::class)); |
|
151 | - $application->add(Server::get(Storages::class)); |
|
152 | - |
|
153 | - $application->add(Server::get(ConvertType::class)); |
|
154 | - $application->add(Server::get(ConvertMysqlToMB4::class)); |
|
155 | - $application->add(Server::get(ConvertFilecacheBigInt::class)); |
|
156 | - $application->add(Server::get(AddMissingColumns::class)); |
|
157 | - $application->add(Server::get(AddMissingIndices::class)); |
|
158 | - $application->add(Server::get(AddMissingPrimaryKeys::class)); |
|
159 | - $application->add(Server::get(ExpectedSchema::class)); |
|
160 | - $application->add(Server::get(ExportSchema::class)); |
|
161 | - |
|
162 | - $application->add(Server::get(GenerateMetadataCommand::class)); |
|
163 | - $application->add(Server::get(PreviewCommand::class)); |
|
164 | - if ($config->getSystemValueBool('debug', false)) { |
|
165 | - $application->add(Server::get(StatusCommand::class)); |
|
166 | - $application->add(Server::get(MigrateCommand::class)); |
|
167 | - $application->add(Server::get(GenerateCommand::class)); |
|
168 | - $application->add(Server::get(ExecuteCommand::class)); |
|
169 | - } |
|
170 | - |
|
171 | - $application->add(Server::get(Command\Encryption\Disable::class)); |
|
172 | - $application->add(Server::get(Command\Encryption\Enable::class)); |
|
173 | - $application->add(Server::get(ListModules::class)); |
|
174 | - $application->add(Server::get(SetDefaultModule::class)); |
|
175 | - $application->add(Server::get(Command\Encryption\Status::class)); |
|
176 | - $application->add(Server::get(EncryptAll::class)); |
|
177 | - $application->add(Server::get(DecryptAll::class)); |
|
178 | - |
|
179 | - $application->add(Server::get(Manage::class)); |
|
180 | - $application->add(Server::get(Command\Log\File::class)); |
|
181 | - |
|
182 | - $application->add(Server::get(ChangeKeyStorageRoot::class)); |
|
183 | - $application->add(Server::get(ShowKeyStorageRoot::class)); |
|
184 | - $application->add(Server::get(MigrateKeyStorage::class)); |
|
185 | - |
|
186 | - $application->add(Server::get(DataFingerprint::class)); |
|
187 | - $application->add(Server::get(UpdateDB::class)); |
|
188 | - $application->add(Server::get(UpdateJS::class)); |
|
189 | - $application->add(Server::get(Command\Maintenance\Mode::class)); |
|
190 | - $application->add(Server::get(UpdateHtaccess::class)); |
|
191 | - $application->add(Server::get(UpdateTheme::class)); |
|
192 | - |
|
193 | - $application->add(Server::get(Upgrade::class)); |
|
194 | - $application->add(Server::get(Repair::class)); |
|
195 | - $application->add(Server::get(RepairShareOwnership::class)); |
|
196 | - |
|
197 | - $application->add(Server::get(Command\Preview\Cleanup::class)); |
|
198 | - $application->add(Server::get(Generate::class)); |
|
199 | - $application->add(Server::get(Command\Preview\Repair::class)); |
|
200 | - $application->add(Server::get(ResetRenderedTexts::class)); |
|
201 | - |
|
202 | - $application->add(Server::get(Add::class)); |
|
203 | - $application->add(Server::get(Command\User\Delete::class)); |
|
204 | - $application->add(Server::get(Command\User\Disable::class)); |
|
205 | - $application->add(Server::get(Command\User\Enable::class)); |
|
206 | - $application->add(Server::get(LastSeen::class)); |
|
207 | - $application->add(Server::get(Report::class)); |
|
208 | - $application->add(Server::get(ResetPassword::class)); |
|
209 | - $application->add(Server::get(Setting::class)); |
|
210 | - $application->add(Server::get(Profile::class)); |
|
211 | - $application->add(Server::get(Command\User\ListCommand::class)); |
|
212 | - $application->add(Server::get(ClearGeneratedAvatarCacheCommand::class)); |
|
213 | - $application->add(Server::get(Info::class)); |
|
214 | - $application->add(Server::get(SyncAccountDataCommand::class)); |
|
215 | - $application->add(Server::get(Command\User\AuthTokens\Add::class)); |
|
216 | - $application->add(Server::get(Command\User\AuthTokens\ListCommand::class)); |
|
217 | - $application->add(Server::get(Command\User\AuthTokens\Delete::class)); |
|
218 | - $application->add(Server::get(Verify::class)); |
|
219 | - $application->add(Server::get(Welcome::class)); |
|
220 | - |
|
221 | - $application->add(Server::get(Command\Group\Add::class)); |
|
222 | - $application->add(Server::get(Command\Group\Delete::class)); |
|
223 | - $application->add(Server::get(Command\Group\ListCommand::class)); |
|
224 | - $application->add(Server::get(AddUser::class)); |
|
225 | - $application->add(Server::get(RemoveUser::class)); |
|
226 | - $application->add(Server::get(Command\Group\Info::class)); |
|
227 | - |
|
228 | - $application->add(Server::get(Command\SystemTag\ListCommand::class)); |
|
229 | - $application->add(Server::get(Command\SystemTag\Delete::class)); |
|
230 | - $application->add(Server::get(Command\SystemTag\Add::class)); |
|
231 | - $application->add(Server::get(Edit::class)); |
|
232 | - |
|
233 | - $application->add(Server::get(ListCertificates::class)); |
|
234 | - $application->add(Server::get(ExportCertificates::class)); |
|
235 | - $application->add(Server::get(ImportCertificate::class)); |
|
236 | - $application->add(Server::get(RemoveCertificate::class)); |
|
237 | - $application->add(Server::get(BruteforceAttempts::class)); |
|
238 | - $application->add(Server::get(BruteforceResetAttempts::class)); |
|
239 | - $application->add(Server::get(SetupChecks::class)); |
|
240 | - $application->add(Server::get(Get::class)); |
|
241 | - |
|
242 | - $application->add(Server::get(GetCommand::class)); |
|
243 | - $application->add(Server::get(EnabledCommand::class)); |
|
244 | - $application->add(Server::get(Command\TaskProcessing\ListCommand::class)); |
|
245 | - $application->add(Server::get(Statistics::class)); |
|
246 | - |
|
247 | - $application->add(Server::get(RedisCommand::class)); |
|
117 | + $application->add(Server::get(Disable::class)); |
|
118 | + $application->add(Server::get(Enable::class)); |
|
119 | + $application->add(Server::get(Install::class)); |
|
120 | + $application->add(Server::get(GetPath::class)); |
|
121 | + $application->add(Server::get(ListApps::class)); |
|
122 | + $application->add(Server::get(Remove::class)); |
|
123 | + $application->add(Server::get(Update::class)); |
|
124 | + |
|
125 | + $application->add(Server::get(Cleanup::class)); |
|
126 | + $application->add(Server::get(Enforce::class)); |
|
127 | + $application->add(Server::get(Command\TwoFactorAuth\Enable::class)); |
|
128 | + $application->add(Server::get(Command\TwoFactorAuth\Disable::class)); |
|
129 | + $application->add(Server::get(State::class)); |
|
130 | + |
|
131 | + $application->add(Server::get(Mode::class)); |
|
132 | + $application->add(Server::get(Job::class)); |
|
133 | + $application->add(Server::get(ListCommand::class)); |
|
134 | + $application->add(Server::get(Delete::class)); |
|
135 | + $application->add(Server::get(JobWorker::class)); |
|
136 | + |
|
137 | + $application->add(Server::get(Test::class)); |
|
138 | + |
|
139 | + $application->add(Server::get(DeleteConfig::class)); |
|
140 | + $application->add(Server::get(GetConfig::class)); |
|
141 | + $application->add(Server::get(SetConfig::class)); |
|
142 | + $application->add(Server::get(Import::class)); |
|
143 | + $application->add(Server::get(ListConfigs::class)); |
|
144 | + $application->add(Server::get(Command\Config\System\DeleteConfig::class)); |
|
145 | + $application->add(Server::get(Command\Config\System\GetConfig::class)); |
|
146 | + $application->add(Server::get(Command\Config\System\SetConfig::class)); |
|
147 | + |
|
148 | + $application->add(Server::get(File::class)); |
|
149 | + $application->add(Server::get(Space::class)); |
|
150 | + $application->add(Server::get(Storage::class)); |
|
151 | + $application->add(Server::get(Storages::class)); |
|
152 | + |
|
153 | + $application->add(Server::get(ConvertType::class)); |
|
154 | + $application->add(Server::get(ConvertMysqlToMB4::class)); |
|
155 | + $application->add(Server::get(ConvertFilecacheBigInt::class)); |
|
156 | + $application->add(Server::get(AddMissingColumns::class)); |
|
157 | + $application->add(Server::get(AddMissingIndices::class)); |
|
158 | + $application->add(Server::get(AddMissingPrimaryKeys::class)); |
|
159 | + $application->add(Server::get(ExpectedSchema::class)); |
|
160 | + $application->add(Server::get(ExportSchema::class)); |
|
161 | + |
|
162 | + $application->add(Server::get(GenerateMetadataCommand::class)); |
|
163 | + $application->add(Server::get(PreviewCommand::class)); |
|
164 | + if ($config->getSystemValueBool('debug', false)) { |
|
165 | + $application->add(Server::get(StatusCommand::class)); |
|
166 | + $application->add(Server::get(MigrateCommand::class)); |
|
167 | + $application->add(Server::get(GenerateCommand::class)); |
|
168 | + $application->add(Server::get(ExecuteCommand::class)); |
|
169 | + } |
|
170 | + |
|
171 | + $application->add(Server::get(Command\Encryption\Disable::class)); |
|
172 | + $application->add(Server::get(Command\Encryption\Enable::class)); |
|
173 | + $application->add(Server::get(ListModules::class)); |
|
174 | + $application->add(Server::get(SetDefaultModule::class)); |
|
175 | + $application->add(Server::get(Command\Encryption\Status::class)); |
|
176 | + $application->add(Server::get(EncryptAll::class)); |
|
177 | + $application->add(Server::get(DecryptAll::class)); |
|
178 | + |
|
179 | + $application->add(Server::get(Manage::class)); |
|
180 | + $application->add(Server::get(Command\Log\File::class)); |
|
181 | + |
|
182 | + $application->add(Server::get(ChangeKeyStorageRoot::class)); |
|
183 | + $application->add(Server::get(ShowKeyStorageRoot::class)); |
|
184 | + $application->add(Server::get(MigrateKeyStorage::class)); |
|
185 | + |
|
186 | + $application->add(Server::get(DataFingerprint::class)); |
|
187 | + $application->add(Server::get(UpdateDB::class)); |
|
188 | + $application->add(Server::get(UpdateJS::class)); |
|
189 | + $application->add(Server::get(Command\Maintenance\Mode::class)); |
|
190 | + $application->add(Server::get(UpdateHtaccess::class)); |
|
191 | + $application->add(Server::get(UpdateTheme::class)); |
|
192 | + |
|
193 | + $application->add(Server::get(Upgrade::class)); |
|
194 | + $application->add(Server::get(Repair::class)); |
|
195 | + $application->add(Server::get(RepairShareOwnership::class)); |
|
196 | + |
|
197 | + $application->add(Server::get(Command\Preview\Cleanup::class)); |
|
198 | + $application->add(Server::get(Generate::class)); |
|
199 | + $application->add(Server::get(Command\Preview\Repair::class)); |
|
200 | + $application->add(Server::get(ResetRenderedTexts::class)); |
|
201 | + |
|
202 | + $application->add(Server::get(Add::class)); |
|
203 | + $application->add(Server::get(Command\User\Delete::class)); |
|
204 | + $application->add(Server::get(Command\User\Disable::class)); |
|
205 | + $application->add(Server::get(Command\User\Enable::class)); |
|
206 | + $application->add(Server::get(LastSeen::class)); |
|
207 | + $application->add(Server::get(Report::class)); |
|
208 | + $application->add(Server::get(ResetPassword::class)); |
|
209 | + $application->add(Server::get(Setting::class)); |
|
210 | + $application->add(Server::get(Profile::class)); |
|
211 | + $application->add(Server::get(Command\User\ListCommand::class)); |
|
212 | + $application->add(Server::get(ClearGeneratedAvatarCacheCommand::class)); |
|
213 | + $application->add(Server::get(Info::class)); |
|
214 | + $application->add(Server::get(SyncAccountDataCommand::class)); |
|
215 | + $application->add(Server::get(Command\User\AuthTokens\Add::class)); |
|
216 | + $application->add(Server::get(Command\User\AuthTokens\ListCommand::class)); |
|
217 | + $application->add(Server::get(Command\User\AuthTokens\Delete::class)); |
|
218 | + $application->add(Server::get(Verify::class)); |
|
219 | + $application->add(Server::get(Welcome::class)); |
|
220 | + |
|
221 | + $application->add(Server::get(Command\Group\Add::class)); |
|
222 | + $application->add(Server::get(Command\Group\Delete::class)); |
|
223 | + $application->add(Server::get(Command\Group\ListCommand::class)); |
|
224 | + $application->add(Server::get(AddUser::class)); |
|
225 | + $application->add(Server::get(RemoveUser::class)); |
|
226 | + $application->add(Server::get(Command\Group\Info::class)); |
|
227 | + |
|
228 | + $application->add(Server::get(Command\SystemTag\ListCommand::class)); |
|
229 | + $application->add(Server::get(Command\SystemTag\Delete::class)); |
|
230 | + $application->add(Server::get(Command\SystemTag\Add::class)); |
|
231 | + $application->add(Server::get(Edit::class)); |
|
232 | + |
|
233 | + $application->add(Server::get(ListCertificates::class)); |
|
234 | + $application->add(Server::get(ExportCertificates::class)); |
|
235 | + $application->add(Server::get(ImportCertificate::class)); |
|
236 | + $application->add(Server::get(RemoveCertificate::class)); |
|
237 | + $application->add(Server::get(BruteforceAttempts::class)); |
|
238 | + $application->add(Server::get(BruteforceResetAttempts::class)); |
|
239 | + $application->add(Server::get(SetupChecks::class)); |
|
240 | + $application->add(Server::get(Get::class)); |
|
241 | + |
|
242 | + $application->add(Server::get(GetCommand::class)); |
|
243 | + $application->add(Server::get(EnabledCommand::class)); |
|
244 | + $application->add(Server::get(Command\TaskProcessing\ListCommand::class)); |
|
245 | + $application->add(Server::get(Statistics::class)); |
|
246 | + |
|
247 | + $application->add(Server::get(RedisCommand::class)); |
|
248 | 248 | } else { |
249 | - $application->add(Server::get(Command\Maintenance\Install::class)); |
|
249 | + $application->add(Server::get(Command\Maintenance\Install::class)); |
|
250 | 250 | } |
@@ -21,214 +21,214 @@ |
||
21 | 21 | use Symfony\Component\Console\Output\OutputInterface; |
22 | 22 | |
23 | 23 | class Profile extends Base { |
24 | - public function __construct( |
|
25 | - protected IUserManager $userManager, |
|
26 | - protected IAccountManager $accountManager, |
|
27 | - ) { |
|
28 | - parent::__construct(); |
|
29 | - } |
|
30 | - |
|
31 | - protected function configure() { |
|
32 | - parent::configure(); |
|
33 | - $this |
|
34 | - ->setName('user:profile') |
|
35 | - ->setDescription('Read and modify user profile properties') |
|
36 | - ->addArgument( |
|
37 | - 'uid', |
|
38 | - InputArgument::REQUIRED, |
|
39 | - 'Account ID used to login' |
|
40 | - ) |
|
41 | - ->addArgument( |
|
42 | - 'key', |
|
43 | - InputArgument::OPTIONAL, |
|
44 | - 'Profile property to set, get or delete', |
|
45 | - '' |
|
46 | - ) |
|
47 | - |
|
48 | - // Get |
|
49 | - ->addOption( |
|
50 | - 'default-value', |
|
51 | - null, |
|
52 | - InputOption::VALUE_REQUIRED, |
|
53 | - '(Only applicable on get) If no default value is set and the property does not exist, the command will exit with 1' |
|
54 | - ) |
|
55 | - |
|
56 | - // Set |
|
57 | - ->addArgument( |
|
58 | - 'value', |
|
59 | - InputArgument::OPTIONAL, |
|
60 | - 'The new value of the property', |
|
61 | - null |
|
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 | - // Delete |
|
71 | - ->addOption( |
|
72 | - 'delete', |
|
73 | - null, |
|
74 | - InputOption::VALUE_NONE, |
|
75 | - 'Specify this option to delete the property value' |
|
76 | - ) |
|
77 | - ->addOption( |
|
78 | - 'error-if-not-exists', |
|
79 | - null, |
|
80 | - InputOption::VALUE_NONE, |
|
81 | - 'Checks whether the property exists before deleting it' |
|
82 | - ) |
|
83 | - ; |
|
84 | - } |
|
85 | - |
|
86 | - protected function checkInput(InputInterface $input): IUser { |
|
87 | - $uid = $input->getArgument('uid'); |
|
88 | - $user = $this->userManager->get($uid); |
|
89 | - if (!$user) { |
|
90 | - throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.'); |
|
91 | - } |
|
92 | - // normalize uid |
|
93 | - $input->setArgument('uid', $user->getUID()); |
|
94 | - |
|
95 | - $key = $input->getArgument('key'); |
|
96 | - if ($key === '') { |
|
97 | - if ($input->hasParameterOption('--default-value')) { |
|
98 | - throw new \InvalidArgumentException('The "default-value" option can only be used when specifying a key.'); |
|
99 | - } |
|
100 | - if ($input->getArgument('value') !== null) { |
|
101 | - throw new \InvalidArgumentException('The value argument can only be used when specifying a key.'); |
|
102 | - } |
|
103 | - if ($input->getOption('delete')) { |
|
104 | - throw new \InvalidArgumentException('The "delete" option can only be used when specifying a key.'); |
|
105 | - } |
|
106 | - } |
|
107 | - |
|
108 | - if ($input->getArgument('value') !== null && $input->hasParameterOption('--default-value')) { |
|
109 | - throw new \InvalidArgumentException('The value argument can not be used together with "default-value".'); |
|
110 | - } |
|
111 | - if ($input->getOption('update-only') && $input->getArgument('value') === null) { |
|
112 | - throw new \InvalidArgumentException('The "update-only" option can only be used together with "value".'); |
|
113 | - } |
|
114 | - |
|
115 | - if ($input->getOption('delete') && $input->hasParameterOption('--default-value')) { |
|
116 | - throw new \InvalidArgumentException('The "delete" option can not be used together with "default-value".'); |
|
117 | - } |
|
118 | - if ($input->getOption('delete') && $input->getArgument('value') !== null) { |
|
119 | - throw new \InvalidArgumentException('The "delete" option can not be used together with "value".'); |
|
120 | - } |
|
121 | - if ($input->getOption('error-if-not-exists') && !$input->getOption('delete')) { |
|
122 | - throw new \InvalidArgumentException('The "error-if-not-exists" option can only be used together with "delete".'); |
|
123 | - } |
|
124 | - |
|
125 | - return $user; |
|
126 | - } |
|
127 | - |
|
128 | - protected function execute(InputInterface $input, OutputInterface $output): int { |
|
129 | - try { |
|
130 | - $user = $this->checkInput($input); |
|
131 | - } catch (\InvalidArgumentException $e) { |
|
132 | - $output->writeln('<error>' . $e->getMessage() . '</error>'); |
|
133 | - return self::FAILURE; |
|
134 | - } |
|
135 | - |
|
136 | - $uid = $input->getArgument('uid'); |
|
137 | - $key = $input->getArgument('key'); |
|
138 | - $userAccount = $this->accountManager->getAccount($user); |
|
139 | - |
|
140 | - if ($key === '') { |
|
141 | - $settings = $this->getAllProfileProperties($userAccount); |
|
142 | - $this->writeArrayInOutputFormat($input, $output, $settings); |
|
143 | - return self::SUCCESS; |
|
144 | - } |
|
145 | - |
|
146 | - $value = $this->getStoredValue($userAccount, $key); |
|
147 | - $inputValue = $input->getArgument('value'); |
|
148 | - if ($inputValue !== null) { |
|
149 | - if ($input->hasParameterOption('--update-only') && $value === null) { |
|
150 | - $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
151 | - return self::FAILURE; |
|
152 | - } |
|
153 | - |
|
154 | - return $this->editProfileProperty($output, $userAccount, $key, $inputValue); |
|
155 | - } elseif ($input->hasParameterOption('--delete')) { |
|
156 | - if ($input->hasParameterOption('--error-if-not-exists') && $value === null) { |
|
157 | - $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
158 | - return self::FAILURE; |
|
159 | - } |
|
160 | - |
|
161 | - return $this->deleteProfileProperty($output, $userAccount, $key); |
|
162 | - } elseif ($value !== null) { |
|
163 | - $output->writeln($value); |
|
164 | - } elseif ($input->hasParameterOption('--default-value')) { |
|
165 | - $output->writeln($input->getOption('default-value')); |
|
166 | - } else { |
|
167 | - $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
168 | - return self::FAILURE; |
|
169 | - } |
|
170 | - |
|
171 | - return self::SUCCESS; |
|
172 | - } |
|
173 | - |
|
174 | - private function deleteProfileProperty(OutputInterface $output, IAccount $userAccount, string $key): int { |
|
175 | - return $this->editProfileProperty($output, $userAccount, $key, ''); |
|
176 | - } |
|
177 | - |
|
178 | - private function editProfileProperty(OutputInterface $output, IAccount $userAccount, string $key, string $value): int { |
|
179 | - try { |
|
180 | - $userAccount->getProperty($key)->setValue($value); |
|
181 | - } catch (PropertyDoesNotExistException $exception) { |
|
182 | - $output->writeln('<error>' . $exception->getMessage() . '</error>'); |
|
183 | - return self::FAILURE; |
|
184 | - } |
|
185 | - |
|
186 | - $this->accountManager->updateAccount($userAccount); |
|
187 | - return self::SUCCESS; |
|
188 | - } |
|
189 | - |
|
190 | - private function getStoredValue(IAccount $userAccount, string $key): ?string { |
|
191 | - try { |
|
192 | - $property = $userAccount->getProperty($key); |
|
193 | - } catch (PropertyDoesNotExistException) { |
|
194 | - return null; |
|
195 | - } |
|
196 | - return $property->getValue() === '' ? null : $property->getValue(); |
|
197 | - } |
|
198 | - |
|
199 | - private function getAllProfileProperties(IAccount $userAccount): array { |
|
200 | - $properties = []; |
|
201 | - |
|
202 | - foreach ($userAccount->getAllProperties() as $property) { |
|
203 | - if ($property->getValue() !== '') { |
|
204 | - $properties[$property->getName()] = $property->getValue(); |
|
205 | - } |
|
206 | - } |
|
207 | - |
|
208 | - return $properties; |
|
209 | - } |
|
210 | - |
|
211 | - /** |
|
212 | - * @param string $argumentName |
|
213 | - * @param CompletionContext $context |
|
214 | - * @return string[] |
|
215 | - */ |
|
216 | - public function completeArgumentValues($argumentName, CompletionContext $context): array { |
|
217 | - if ($argumentName === 'uid') { |
|
218 | - return array_map(static fn (IUser $user) => $user->getUID(), $this->userManager->search($context->getCurrentWord())); |
|
219 | - } |
|
220 | - if ($argumentName === 'key') { |
|
221 | - $userId = $context->getWordAtIndex($context->getWordIndex() - 1); |
|
222 | - $user = $this->userManager->get($userId); |
|
223 | - if (!($user instanceof IUser)) { |
|
224 | - return []; |
|
225 | - } |
|
226 | - |
|
227 | - $account = $this->accountManager->getAccount($user); |
|
228 | - |
|
229 | - $properties = $this->getAllProfileProperties($account); |
|
230 | - return array_keys($properties); |
|
231 | - } |
|
232 | - return []; |
|
233 | - } |
|
24 | + public function __construct( |
|
25 | + protected IUserManager $userManager, |
|
26 | + protected IAccountManager $accountManager, |
|
27 | + ) { |
|
28 | + parent::__construct(); |
|
29 | + } |
|
30 | + |
|
31 | + protected function configure() { |
|
32 | + parent::configure(); |
|
33 | + $this |
|
34 | + ->setName('user:profile') |
|
35 | + ->setDescription('Read and modify user profile properties') |
|
36 | + ->addArgument( |
|
37 | + 'uid', |
|
38 | + InputArgument::REQUIRED, |
|
39 | + 'Account ID used to login' |
|
40 | + ) |
|
41 | + ->addArgument( |
|
42 | + 'key', |
|
43 | + InputArgument::OPTIONAL, |
|
44 | + 'Profile property to set, get or delete', |
|
45 | + '' |
|
46 | + ) |
|
47 | + |
|
48 | + // Get |
|
49 | + ->addOption( |
|
50 | + 'default-value', |
|
51 | + null, |
|
52 | + InputOption::VALUE_REQUIRED, |
|
53 | + '(Only applicable on get) If no default value is set and the property does not exist, the command will exit with 1' |
|
54 | + ) |
|
55 | + |
|
56 | + // Set |
|
57 | + ->addArgument( |
|
58 | + 'value', |
|
59 | + InputArgument::OPTIONAL, |
|
60 | + 'The new value of the property', |
|
61 | + null |
|
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 | + // Delete |
|
71 | + ->addOption( |
|
72 | + 'delete', |
|
73 | + null, |
|
74 | + InputOption::VALUE_NONE, |
|
75 | + 'Specify this option to delete the property value' |
|
76 | + ) |
|
77 | + ->addOption( |
|
78 | + 'error-if-not-exists', |
|
79 | + null, |
|
80 | + InputOption::VALUE_NONE, |
|
81 | + 'Checks whether the property exists before deleting it' |
|
82 | + ) |
|
83 | + ; |
|
84 | + } |
|
85 | + |
|
86 | + protected function checkInput(InputInterface $input): IUser { |
|
87 | + $uid = $input->getArgument('uid'); |
|
88 | + $user = $this->userManager->get($uid); |
|
89 | + if (!$user) { |
|
90 | + throw new \InvalidArgumentException('The user "' . $uid . '" does not exist.'); |
|
91 | + } |
|
92 | + // normalize uid |
|
93 | + $input->setArgument('uid', $user->getUID()); |
|
94 | + |
|
95 | + $key = $input->getArgument('key'); |
|
96 | + if ($key === '') { |
|
97 | + if ($input->hasParameterOption('--default-value')) { |
|
98 | + throw new \InvalidArgumentException('The "default-value" option can only be used when specifying a key.'); |
|
99 | + } |
|
100 | + if ($input->getArgument('value') !== null) { |
|
101 | + throw new \InvalidArgumentException('The value argument can only be used when specifying a key.'); |
|
102 | + } |
|
103 | + if ($input->getOption('delete')) { |
|
104 | + throw new \InvalidArgumentException('The "delete" option can only be used when specifying a key.'); |
|
105 | + } |
|
106 | + } |
|
107 | + |
|
108 | + if ($input->getArgument('value') !== null && $input->hasParameterOption('--default-value')) { |
|
109 | + throw new \InvalidArgumentException('The value argument can not be used together with "default-value".'); |
|
110 | + } |
|
111 | + if ($input->getOption('update-only') && $input->getArgument('value') === null) { |
|
112 | + throw new \InvalidArgumentException('The "update-only" option can only be used together with "value".'); |
|
113 | + } |
|
114 | + |
|
115 | + if ($input->getOption('delete') && $input->hasParameterOption('--default-value')) { |
|
116 | + throw new \InvalidArgumentException('The "delete" option can not be used together with "default-value".'); |
|
117 | + } |
|
118 | + if ($input->getOption('delete') && $input->getArgument('value') !== null) { |
|
119 | + throw new \InvalidArgumentException('The "delete" option can not be used together with "value".'); |
|
120 | + } |
|
121 | + if ($input->getOption('error-if-not-exists') && !$input->getOption('delete')) { |
|
122 | + throw new \InvalidArgumentException('The "error-if-not-exists" option can only be used together with "delete".'); |
|
123 | + } |
|
124 | + |
|
125 | + return $user; |
|
126 | + } |
|
127 | + |
|
128 | + protected function execute(InputInterface $input, OutputInterface $output): int { |
|
129 | + try { |
|
130 | + $user = $this->checkInput($input); |
|
131 | + } catch (\InvalidArgumentException $e) { |
|
132 | + $output->writeln('<error>' . $e->getMessage() . '</error>'); |
|
133 | + return self::FAILURE; |
|
134 | + } |
|
135 | + |
|
136 | + $uid = $input->getArgument('uid'); |
|
137 | + $key = $input->getArgument('key'); |
|
138 | + $userAccount = $this->accountManager->getAccount($user); |
|
139 | + |
|
140 | + if ($key === '') { |
|
141 | + $settings = $this->getAllProfileProperties($userAccount); |
|
142 | + $this->writeArrayInOutputFormat($input, $output, $settings); |
|
143 | + return self::SUCCESS; |
|
144 | + } |
|
145 | + |
|
146 | + $value = $this->getStoredValue($userAccount, $key); |
|
147 | + $inputValue = $input->getArgument('value'); |
|
148 | + if ($inputValue !== null) { |
|
149 | + if ($input->hasParameterOption('--update-only') && $value === null) { |
|
150 | + $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
151 | + return self::FAILURE; |
|
152 | + } |
|
153 | + |
|
154 | + return $this->editProfileProperty($output, $userAccount, $key, $inputValue); |
|
155 | + } elseif ($input->hasParameterOption('--delete')) { |
|
156 | + if ($input->hasParameterOption('--error-if-not-exists') && $value === null) { |
|
157 | + $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
158 | + return self::FAILURE; |
|
159 | + } |
|
160 | + |
|
161 | + return $this->deleteProfileProperty($output, $userAccount, $key); |
|
162 | + } elseif ($value !== null) { |
|
163 | + $output->writeln($value); |
|
164 | + } elseif ($input->hasParameterOption('--default-value')) { |
|
165 | + $output->writeln($input->getOption('default-value')); |
|
166 | + } else { |
|
167 | + $output->writeln('<error>The property does not exist for user "' . $uid . '".</error>'); |
|
168 | + return self::FAILURE; |
|
169 | + } |
|
170 | + |
|
171 | + return self::SUCCESS; |
|
172 | + } |
|
173 | + |
|
174 | + private function deleteProfileProperty(OutputInterface $output, IAccount $userAccount, string $key): int { |
|
175 | + return $this->editProfileProperty($output, $userAccount, $key, ''); |
|
176 | + } |
|
177 | + |
|
178 | + private function editProfileProperty(OutputInterface $output, IAccount $userAccount, string $key, string $value): int { |
|
179 | + try { |
|
180 | + $userAccount->getProperty($key)->setValue($value); |
|
181 | + } catch (PropertyDoesNotExistException $exception) { |
|
182 | + $output->writeln('<error>' . $exception->getMessage() . '</error>'); |
|
183 | + return self::FAILURE; |
|
184 | + } |
|
185 | + |
|
186 | + $this->accountManager->updateAccount($userAccount); |
|
187 | + return self::SUCCESS; |
|
188 | + } |
|
189 | + |
|
190 | + private function getStoredValue(IAccount $userAccount, string $key): ?string { |
|
191 | + try { |
|
192 | + $property = $userAccount->getProperty($key); |
|
193 | + } catch (PropertyDoesNotExistException) { |
|
194 | + return null; |
|
195 | + } |
|
196 | + return $property->getValue() === '' ? null : $property->getValue(); |
|
197 | + } |
|
198 | + |
|
199 | + private function getAllProfileProperties(IAccount $userAccount): array { |
|
200 | + $properties = []; |
|
201 | + |
|
202 | + foreach ($userAccount->getAllProperties() as $property) { |
|
203 | + if ($property->getValue() !== '') { |
|
204 | + $properties[$property->getName()] = $property->getValue(); |
|
205 | + } |
|
206 | + } |
|
207 | + |
|
208 | + return $properties; |
|
209 | + } |
|
210 | + |
|
211 | + /** |
|
212 | + * @param string $argumentName |
|
213 | + * @param CompletionContext $context |
|
214 | + * @return string[] |
|
215 | + */ |
|
216 | + public function completeArgumentValues($argumentName, CompletionContext $context): array { |
|
217 | + if ($argumentName === 'uid') { |
|
218 | + return array_map(static fn (IUser $user) => $user->getUID(), $this->userManager->search($context->getCurrentWord())); |
|
219 | + } |
|
220 | + if ($argumentName === 'key') { |
|
221 | + $userId = $context->getWordAtIndex($context->getWordIndex() - 1); |
|
222 | + $user = $this->userManager->get($userId); |
|
223 | + if (!($user instanceof IUser)) { |
|
224 | + return []; |
|
225 | + } |
|
226 | + |
|
227 | + $account = $this->accountManager->getAccount($user); |
|
228 | + |
|
229 | + $properties = $this->getAllProfileProperties($account); |
|
230 | + return array_keys($properties); |
|
231 | + } |
|
232 | + return []; |
|
233 | + } |
|
234 | 234 | } |