Completed
Push — master ( 491c64...af172b )
by
unknown
34:20
created
lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php 1 patch
Indentation   +215 added lines, -215 removed lines patch added patch discarded remove patch
@@ -17,222 +17,222 @@
 block discarded – undo
17 17
  * @psalm-type ObjectStoreConfig array{class: class-string<IObjectStore>, arguments: array{multibucket: bool, ...}}
18 18
  */
19 19
 class PrimaryObjectStoreConfig {
20
-	public function __construct(
21
-		private readonly IConfig $config,
22
-		private readonly IAppManager $appManager,
23
-	) {
24
-	}
25
-
26
-	/**
27
-	 * @param ObjectStoreConfig $config
28
-	 */
29
-	public function buildObjectStore(array $config): IObjectStore {
30
-		return new $config['class']($config['arguments']);
31
-	}
32
-
33
-	/**
34
-	 * @return ?ObjectStoreConfig
35
-	 */
36
-	public function getObjectStoreConfigForRoot(): ?array {
37
-		if (!$this->hasObjectStore()) {
38
-			return null;
39
-		}
40
-
41
-		$config = $this->getObjectStoreConfiguration('root');
42
-
43
-		if ($config['arguments']['multibucket']) {
44
-			if (!isset($config['arguments']['bucket'])) {
45
-				$config['arguments']['bucket'] = '';
46
-			}
47
-
48
-			// put the root FS always in first bucket for multibucket configuration
49
-			$config['arguments']['bucket'] .= '0';
50
-		}
51
-		return $config;
52
-	}
53
-
54
-	/**
55
-	 * @return ?ObjectStoreConfig
56
-	 */
57
-	public function getObjectStoreConfigForUser(IUser $user): ?array {
58
-		if (!$this->hasObjectStore()) {
59
-			return null;
60
-		}
61
-
62
-		$store = $this->getObjectStoreForUser($user);
63
-		$config = $this->getObjectStoreConfiguration($store);
64
-
65
-		if ($config['arguments']['multibucket']) {
66
-			$config['arguments']['bucket'] = $this->getBucketForUser($user, $config);
67
-		}
68
-		return $config;
69
-	}
70
-
71
-	/**
72
-	 * @param string $name
73
-	 * @return ObjectStoreConfig
74
-	 */
75
-	public function getObjectStoreConfiguration(string $name): array {
76
-		$configs = $this->getObjectStoreConfigs();
77
-		$name = $this->resolveAlias($name);
78
-		if (!isset($configs[$name])) {
79
-			throw new \Exception("Object store configuration for '$name' not found");
80
-		}
81
-		if (is_string($configs[$name])) {
82
-			throw new \Exception("Object store configuration for '{$configs[$name]}' not found");
83
-		}
84
-		return $configs[$name];
85
-	}
86
-
87
-	public function resolveAlias(string $name): string {
88
-		$configs = $this->getObjectStoreConfigs();
89
-
90
-		while (isset($configs[$name]) && is_string($configs[$name])) {
91
-			$name = $configs[$name];
92
-		}
93
-		return $name;
94
-	}
95
-
96
-	public function hasObjectStore(): bool {
97
-		$objectStore = $this->config->getSystemValue('objectstore', null);
98
-		$objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
99
-		return $objectStore || $objectStoreMultiBucket;
100
-	}
101
-
102
-	public function hasMultipleObjectStorages(): bool {
103
-		$objectStore = $this->config->getSystemValue('objectstore', []);
104
-		return isset($objectStore['default']);
105
-	}
106
-
107
-	/**
108
-	 * @return ?array<string, ObjectStoreConfig|string>
109
-	 * @throws InvalidObjectStoreConfigurationException
110
-	 */
111
-	public function getObjectStoreConfigs(): ?array {
112
-		$objectStore = $this->config->getSystemValue('objectstore', null);
113
-		$objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
114
-
115
-		// new-style multibucket config uses the same 'objectstore' key but sets `'multibucket' => true`, transparently upgrade older style config
116
-		if ($objectStoreMultiBucket) {
117
-			$objectStoreMultiBucket['arguments']['multibucket'] = true;
118
-			$configs = [
119
-				'default' => 'server1',
120
-				'server1' => $this->validateObjectStoreConfig($objectStoreMultiBucket),
121
-				'root' => 'server1',
122
-			];
123
-		} elseif ($objectStore) {
124
-			if (!isset($objectStore['default'])) {
125
-				$objectStore = [
126
-					'default' => 'server1',
127
-					'root' => 'server1',
128
-					'server1' => $objectStore,
129
-				];
130
-			}
131
-			if (!isset($objectStore['root'])) {
132
-				$objectStore['root'] = 'default';
133
-			}
134
-
135
-			if (!is_string($objectStore['default'])) {
136
-				throw new InvalidObjectStoreConfigurationException('The \'default\' object storage configuration is required to be a reference to another configuration.');
137
-			}
138
-			$configs = array_map($this->validateObjectStoreConfig(...), $objectStore);
139
-		} else {
140
-			return null;
141
-		}
142
-
143
-		$usedBuckets = [];
144
-		foreach ($configs as $config) {
145
-			if (is_array($config)) {
146
-				$bucket = $config['arguments']['bucket'] ?? '';
147
-				if (in_array($bucket, $usedBuckets)) {
148
-					throw new InvalidObjectStoreConfigurationException('Each object store configuration must use distinct bucket names');
149
-				}
150
-				$usedBuckets[] = $bucket;
151
-			}
152
-		}
153
-
154
-		return $configs;
155
-	}
156
-
157
-	/**
158
-	 * @param array|string $config
159
-	 * @return string|ObjectStoreConfig
160
-	 */
161
-	private function validateObjectStoreConfig(array|string $config): array|string {
162
-		if (is_string($config)) {
163
-			return $config;
164
-		}
165
-		if (!isset($config['class'])) {
166
-			throw new InvalidObjectStoreConfigurationException('No class configured for object store');
167
-		}
168
-		if (!isset($config['arguments'])) {
169
-			$config['arguments'] = [];
170
-		}
171
-		$class = $config['class'];
172
-		$arguments = $config['arguments'];
173
-		if (!is_array($arguments)) {
174
-			throw new InvalidObjectStoreConfigurationException('Configured object store arguments are not an array');
175
-		}
176
-		if (!isset($arguments['multibucket'])) {
177
-			$arguments['multibucket'] = false;
178
-		}
179
-		if (!is_bool($arguments['multibucket'])) {
180
-			throw new InvalidObjectStoreConfigurationException('arguments.multibucket must be a boolean in object store configuration');
181
-		}
182
-
183
-		if (!is_string($class)) {
184
-			throw new InvalidObjectStoreConfigurationException('Configured class for object store is not a string');
185
-		}
186
-
187
-		if (str_starts_with($class, 'OCA\\') && substr_count($class, '\\') >= 2) {
188
-			[$appId] = explode('\\', $class);
189
-			$this->appManager->loadApp(strtolower($appId));
190
-		}
191
-
192
-		if (!is_a($class, IObjectStore::class, true)) {
193
-			throw new InvalidObjectStoreConfigurationException('Configured class for object store is not an object store');
194
-		}
195
-		return [
196
-			'class' => $class,
197
-			'arguments' => $arguments,
198
-		];
199
-	}
200
-
201
-	public function getBucketForUser(IUser $user, array $config): string {
202
-		$bucket = $this->getSetBucketForUser($user);
203
-
204
-		if ($bucket === null) {
205
-			/*
20
+    public function __construct(
21
+        private readonly IConfig $config,
22
+        private readonly IAppManager $appManager,
23
+    ) {
24
+    }
25
+
26
+    /**
27
+     * @param ObjectStoreConfig $config
28
+     */
29
+    public function buildObjectStore(array $config): IObjectStore {
30
+        return new $config['class']($config['arguments']);
31
+    }
32
+
33
+    /**
34
+     * @return ?ObjectStoreConfig
35
+     */
36
+    public function getObjectStoreConfigForRoot(): ?array {
37
+        if (!$this->hasObjectStore()) {
38
+            return null;
39
+        }
40
+
41
+        $config = $this->getObjectStoreConfiguration('root');
42
+
43
+        if ($config['arguments']['multibucket']) {
44
+            if (!isset($config['arguments']['bucket'])) {
45
+                $config['arguments']['bucket'] = '';
46
+            }
47
+
48
+            // put the root FS always in first bucket for multibucket configuration
49
+            $config['arguments']['bucket'] .= '0';
50
+        }
51
+        return $config;
52
+    }
53
+
54
+    /**
55
+     * @return ?ObjectStoreConfig
56
+     */
57
+    public function getObjectStoreConfigForUser(IUser $user): ?array {
58
+        if (!$this->hasObjectStore()) {
59
+            return null;
60
+        }
61
+
62
+        $store = $this->getObjectStoreForUser($user);
63
+        $config = $this->getObjectStoreConfiguration($store);
64
+
65
+        if ($config['arguments']['multibucket']) {
66
+            $config['arguments']['bucket'] = $this->getBucketForUser($user, $config);
67
+        }
68
+        return $config;
69
+    }
70
+
71
+    /**
72
+     * @param string $name
73
+     * @return ObjectStoreConfig
74
+     */
75
+    public function getObjectStoreConfiguration(string $name): array {
76
+        $configs = $this->getObjectStoreConfigs();
77
+        $name = $this->resolveAlias($name);
78
+        if (!isset($configs[$name])) {
79
+            throw new \Exception("Object store configuration for '$name' not found");
80
+        }
81
+        if (is_string($configs[$name])) {
82
+            throw new \Exception("Object store configuration for '{$configs[$name]}' not found");
83
+        }
84
+        return $configs[$name];
85
+    }
86
+
87
+    public function resolveAlias(string $name): string {
88
+        $configs = $this->getObjectStoreConfigs();
89
+
90
+        while (isset($configs[$name]) && is_string($configs[$name])) {
91
+            $name = $configs[$name];
92
+        }
93
+        return $name;
94
+    }
95
+
96
+    public function hasObjectStore(): bool {
97
+        $objectStore = $this->config->getSystemValue('objectstore', null);
98
+        $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
99
+        return $objectStore || $objectStoreMultiBucket;
100
+    }
101
+
102
+    public function hasMultipleObjectStorages(): bool {
103
+        $objectStore = $this->config->getSystemValue('objectstore', []);
104
+        return isset($objectStore['default']);
105
+    }
106
+
107
+    /**
108
+     * @return ?array<string, ObjectStoreConfig|string>
109
+     * @throws InvalidObjectStoreConfigurationException
110
+     */
111
+    public function getObjectStoreConfigs(): ?array {
112
+        $objectStore = $this->config->getSystemValue('objectstore', null);
113
+        $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
114
+
115
+        // new-style multibucket config uses the same 'objectstore' key but sets `'multibucket' => true`, transparently upgrade older style config
116
+        if ($objectStoreMultiBucket) {
117
+            $objectStoreMultiBucket['arguments']['multibucket'] = true;
118
+            $configs = [
119
+                'default' => 'server1',
120
+                'server1' => $this->validateObjectStoreConfig($objectStoreMultiBucket),
121
+                'root' => 'server1',
122
+            ];
123
+        } elseif ($objectStore) {
124
+            if (!isset($objectStore['default'])) {
125
+                $objectStore = [
126
+                    'default' => 'server1',
127
+                    'root' => 'server1',
128
+                    'server1' => $objectStore,
129
+                ];
130
+            }
131
+            if (!isset($objectStore['root'])) {
132
+                $objectStore['root'] = 'default';
133
+            }
134
+
135
+            if (!is_string($objectStore['default'])) {
136
+                throw new InvalidObjectStoreConfigurationException('The \'default\' object storage configuration is required to be a reference to another configuration.');
137
+            }
138
+            $configs = array_map($this->validateObjectStoreConfig(...), $objectStore);
139
+        } else {
140
+            return null;
141
+        }
142
+
143
+        $usedBuckets = [];
144
+        foreach ($configs as $config) {
145
+            if (is_array($config)) {
146
+                $bucket = $config['arguments']['bucket'] ?? '';
147
+                if (in_array($bucket, $usedBuckets)) {
148
+                    throw new InvalidObjectStoreConfigurationException('Each object store configuration must use distinct bucket names');
149
+                }
150
+                $usedBuckets[] = $bucket;
151
+            }
152
+        }
153
+
154
+        return $configs;
155
+    }
156
+
157
+    /**
158
+     * @param array|string $config
159
+     * @return string|ObjectStoreConfig
160
+     */
161
+    private function validateObjectStoreConfig(array|string $config): array|string {
162
+        if (is_string($config)) {
163
+            return $config;
164
+        }
165
+        if (!isset($config['class'])) {
166
+            throw new InvalidObjectStoreConfigurationException('No class configured for object store');
167
+        }
168
+        if (!isset($config['arguments'])) {
169
+            $config['arguments'] = [];
170
+        }
171
+        $class = $config['class'];
172
+        $arguments = $config['arguments'];
173
+        if (!is_array($arguments)) {
174
+            throw new InvalidObjectStoreConfigurationException('Configured object store arguments are not an array');
175
+        }
176
+        if (!isset($arguments['multibucket'])) {
177
+            $arguments['multibucket'] = false;
178
+        }
179
+        if (!is_bool($arguments['multibucket'])) {
180
+            throw new InvalidObjectStoreConfigurationException('arguments.multibucket must be a boolean in object store configuration');
181
+        }
182
+
183
+        if (!is_string($class)) {
184
+            throw new InvalidObjectStoreConfigurationException('Configured class for object store is not a string');
185
+        }
186
+
187
+        if (str_starts_with($class, 'OCA\\') && substr_count($class, '\\') >= 2) {
188
+            [$appId] = explode('\\', $class);
189
+            $this->appManager->loadApp(strtolower($appId));
190
+        }
191
+
192
+        if (!is_a($class, IObjectStore::class, true)) {
193
+            throw new InvalidObjectStoreConfigurationException('Configured class for object store is not an object store');
194
+        }
195
+        return [
196
+            'class' => $class,
197
+            'arguments' => $arguments,
198
+        ];
199
+    }
200
+
201
+    public function getBucketForUser(IUser $user, array $config): string {
202
+        $bucket = $this->getSetBucketForUser($user);
203
+
204
+        if ($bucket === null) {
205
+            /*
206 206
 			 * Use any provided bucket argument as prefix
207 207
 			 * and add the mapping from username => bucket
208 208
 			 */
209
-			if (!isset($config['arguments']['bucket'])) {
210
-				$config['arguments']['bucket'] = '';
211
-			}
212
-			$mapper = new Mapper($user, $config);
213
-			$numBuckets = $config['arguments']['num_buckets'] ?? 64;
214
-			$bucket = $config['arguments']['bucket'] . $mapper->getBucket($numBuckets);
215
-
216
-			$this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $bucket);
217
-		}
218
-
219
-		return $bucket;
220
-	}
221
-
222
-	public function getSetBucketForUser(IUser $user): ?string {
223
-		return $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null);
224
-	}
225
-
226
-	public function getObjectStoreForUser(IUser $user): string {
227
-		if ($this->hasMultipleObjectStorages()) {
228
-			$value = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'objectstore', null);
229
-			if ($value === null) {
230
-				$value = $this->resolveAlias('default');
231
-				$this->config->setUserValue($user->getUID(), 'homeobjectstore', 'objectstore', $value);
232
-			}
233
-			return $value;
234
-		} else {
235
-			return 'default';
236
-		}
237
-	}
209
+            if (!isset($config['arguments']['bucket'])) {
210
+                $config['arguments']['bucket'] = '';
211
+            }
212
+            $mapper = new Mapper($user, $config);
213
+            $numBuckets = $config['arguments']['num_buckets'] ?? 64;
214
+            $bucket = $config['arguments']['bucket'] . $mapper->getBucket($numBuckets);
215
+
216
+            $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $bucket);
217
+        }
218
+
219
+        return $bucket;
220
+    }
221
+
222
+    public function getSetBucketForUser(IUser $user): ?string {
223
+        return $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null);
224
+    }
225
+
226
+    public function getObjectStoreForUser(IUser $user): string {
227
+        if ($this->hasMultipleObjectStorages()) {
228
+            $value = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'objectstore', null);
229
+            if ($value === null) {
230
+                $value = $this->resolveAlias('default');
231
+                $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'objectstore', $value);
232
+            }
233
+            return $value;
234
+        } else {
235
+            return 'default';
236
+        }
237
+    }
238 238
 }
Please login to merge, or discard this patch.
tests/lib/Files/ObjectStore/PrimaryObjectStoreConfigTest.php 1 patch
Indentation   +272 added lines, -272 removed lines patch added patch discarded remove patch
@@ -17,276 +17,276 @@
 block discarded – undo
17 17
 use Test\TestCase;
18 18
 
19 19
 class PrimaryObjectStoreConfigTest extends TestCase {
20
-	private array $systemConfig = [];
21
-	private array $userConfig = [];
22
-	private IConfig&MockObject $config;
23
-	private IAppManager&MockObject $appManager;
24
-	private PrimaryObjectStoreConfig $objectStoreConfig;
25
-
26
-	protected function setUp(): void {
27
-		parent::setUp();
28
-
29
-		$this->systemConfig = [];
30
-		$this->config = $this->createMock(IConfig::class);
31
-		$this->appManager = $this->createMock(IAppManager::class);
32
-		$this->config->method('getSystemValue')
33
-			->willReturnCallback(function ($key, $default = '') {
34
-				if (isset($this->systemConfig[$key])) {
35
-					return $this->systemConfig[$key];
36
-				} else {
37
-					return $default;
38
-				}
39
-			});
40
-		$this->config->method('getUserValue')
41
-			->willReturnCallback(function ($userId, $appName, $key, $default = '') {
42
-				if (isset($this->userConfig[$userId][$appName][$key])) {
43
-					return $this->userConfig[$userId][$appName][$key];
44
-				} else {
45
-					return $default;
46
-				}
47
-			});
48
-		$this->config->method('setUserValue')
49
-			->willReturnCallback(function ($userId, $appName, $key, $value): void {
50
-				$this->userConfig[$userId][$appName][$key] = $value;
51
-			});
52
-
53
-		$this->objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->appManager);
54
-	}
55
-
56
-	private function getUser(string $uid): IUser {
57
-		$user = $this->createMock(IUser::class);
58
-		$user->method('getUID')
59
-			->willReturn($uid);
60
-		return $user;
61
-	}
62
-
63
-	private function setConfig(string $key, $value) {
64
-		$this->systemConfig[$key] = $value;
65
-	}
66
-
67
-	public function testNewUserGetsDefault() {
68
-		$this->setConfig('objectstore', [
69
-			'default' => 'server1',
70
-			'server1' => [
71
-				'class' => StorageObjectStore::class,
72
-				'arguments' => [
73
-					'host' => 'server1',
74
-				],
75
-			],
76
-		]);
77
-
78
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
79
-		$this->assertEquals('server1', $result['arguments']['host']);
80
-
81
-		$this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null));
82
-	}
83
-
84
-	public function testExistingUserKeepsStorage() {
85
-		// setup user with `server1` as storage
86
-		$this->testNewUserGetsDefault();
87
-
88
-		$this->setConfig('objectstore', [
89
-			'default' => 'server2',
90
-			'server1' => [
91
-				'class' => StorageObjectStore::class,
92
-				'arguments' => [
93
-					'host' => 'server1',
94
-					'bucket' => '1',
95
-				],
96
-			],
97
-			'server2' => [
98
-				'class' => StorageObjectStore::class,
99
-				'arguments' => [
100
-					'host' => 'server2',
101
-					'bucket' => '2',
102
-				],
103
-			],
104
-		]);
105
-
106
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
107
-		$this->assertEquals('server1', $result['arguments']['host']);
108
-
109
-		$this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null));
110
-
111
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('other-user'));
112
-		$this->assertEquals('server2', $result['arguments']['host']);
113
-	}
114
-
115
-	public function testNestedAliases() {
116
-		$this->setConfig('objectstore', [
117
-			'default' => 'a1',
118
-			'a1' => 'a2',
119
-			'a2' => 'server1',
120
-			'server1' => [
121
-				'class' => StorageObjectStore::class,
122
-				'arguments' => [
123
-					'host' => 'server1',
124
-					'bucket' => '1',
125
-				],
126
-			],
127
-		]);
128
-		$this->assertEquals('server1', $this->objectStoreConfig->resolveAlias('default'));
129
-	}
130
-
131
-	public function testMultibucketChangedConfig() {
132
-		$this->setConfig('objectstore', [
133
-			'default' => 'server1',
134
-			'server1' => [
135
-				'class' => StorageObjectStore::class,
136
-				'arguments' => [
137
-					'host' => 'server1',
138
-					'multibucket' => true,
139
-					'num_buckets' => 8,
140
-					'bucket' => 'bucket1-'
141
-				],
142
-			],
143
-		]);
144
-
145
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
146
-		$this->assertEquals('server1', $result['arguments']['host']);
147
-		$this->assertEquals('bucket1-7', $result['arguments']['bucket']);
148
-
149
-		$this->setConfig('objectstore', [
150
-			'default' => 'server1',
151
-			'server1' => [
152
-				'class' => StorageObjectStore::class,
153
-				'arguments' => [
154
-					'host' => 'server1',
155
-					'multibucket' => true,
156
-					'num_buckets' => 64,
157
-					'bucket' => 'bucket1-'
158
-				],
159
-			],
160
-		]);
161
-
162
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
163
-		$this->assertEquals('server1', $result['arguments']['host']);
164
-		$this->assertEquals('bucket1-7', $result['arguments']['bucket']);
165
-
166
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-foo'));
167
-		$this->assertEquals('server1', $result['arguments']['host']);
168
-		$this->assertEquals('bucket1-40', $result['arguments']['bucket']);
169
-
170
-		$this->setConfig('objectstore', [
171
-			'default' => 'server2',
172
-			'server1' => [
173
-				'class' => StorageObjectStore::class,
174
-				'arguments' => [
175
-					'host' => 'server1',
176
-					'multibucket' => true,
177
-					'num_buckets' => 64,
178
-					'bucket' => 'bucket1-'
179
-				],
180
-			],
181
-			'server2' => [
182
-				'class' => StorageObjectStore::class,
183
-				'arguments' => [
184
-					'host' => 'server2',
185
-					'multibucket' => true,
186
-					'num_buckets' => 16,
187
-					'bucket' => 'bucket2-'
188
-				],
189
-			],
190
-		]);
191
-
192
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
193
-		$this->assertEquals('server1', $result['arguments']['host']);
194
-		$this->assertEquals('bucket1-7', $result['arguments']['bucket']);
195
-
196
-		$result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-bar'));
197
-		$this->assertEquals('server2', $result['arguments']['host']);
198
-		$this->assertEquals('bucket2-4', $result['arguments']['bucket']);
199
-	}
200
-
201
-	public function testMultibucketOldConfig() {
202
-		$this->setConfig('objectstore_multibucket', [
203
-			'class' => StorageObjectStore::class,
204
-			'arguments' => [
205
-				'host' => 'server1',
206
-				'multibucket' => true,
207
-				'num_buckets' => 8,
208
-				'bucket' => 'bucket-'
209
-			],
210
-		]);
211
-		$configs = $this->objectStoreConfig->getObjectStoreConfigs();
212
-		$this->assertEquals([
213
-			'default' => 'server1',
214
-			'root' => 'server1',
215
-			'server1' => [
216
-				'class' => StorageObjectStore::class,
217
-				'arguments' => [
218
-					'host' => 'server1',
219
-					'multibucket' => true,
220
-					'num_buckets' => 8,
221
-					'bucket' => 'bucket-'
222
-				],
223
-			],
224
-		], $configs);
225
-	}
226
-
227
-	public function testSingleObjectStore() {
228
-		$this->setConfig('objectstore', [
229
-			'class' => StorageObjectStore::class,
230
-			'arguments' => [
231
-				'host' => 'server1',
232
-			],
233
-		]);
234
-		$configs = $this->objectStoreConfig->getObjectStoreConfigs();
235
-		$this->assertEquals([
236
-			'default' => 'server1',
237
-			'root' => 'server1',
238
-			'server1' => [
239
-				'class' => StorageObjectStore::class,
240
-				'arguments' => [
241
-					'host' => 'server1',
242
-					'multibucket' => false,
243
-				],
244
-			],
245
-		], $configs);
246
-	}
247
-
248
-	public function testRoot() {
249
-		$this->setConfig('objectstore', [
250
-			'default' => 'server1',
251
-			'server1' => [
252
-				'class' => StorageObjectStore::class,
253
-				'arguments' => [
254
-					'host' => 'server1',
255
-					'bucket' => '1',
256
-				],
257
-			],
258
-			'server2' => [
259
-				'class' => StorageObjectStore::class,
260
-				'arguments' => [
261
-					'host' => 'server2',
262
-					'bucket' => '2',
263
-				],
264
-			],
265
-		]);
266
-
267
-		$result = $this->objectStoreConfig->getObjectStoreConfigForRoot();
268
-		$this->assertEquals('server1', $result['arguments']['host']);
269
-
270
-		$this->setConfig('objectstore', [
271
-			'default' => 'server1',
272
-			'root' => 'server2',
273
-			'server1' => [
274
-				'class' => StorageObjectStore::class,
275
-				'arguments' => [
276
-					'host' => 'server1',
277
-					'bucket' => '1',
278
-				],
279
-			],
280
-			'server2' => [
281
-				'class' => StorageObjectStore::class,
282
-				'arguments' => [
283
-					'host' => 'server2',
284
-					'bucket' => '2',
285
-				],
286
-			],
287
-		]);
288
-
289
-		$result = $this->objectStoreConfig->getObjectStoreConfigForRoot();
290
-		$this->assertEquals('server2', $result['arguments']['host']);
291
-	}
20
+    private array $systemConfig = [];
21
+    private array $userConfig = [];
22
+    private IConfig&MockObject $config;
23
+    private IAppManager&MockObject $appManager;
24
+    private PrimaryObjectStoreConfig $objectStoreConfig;
25
+
26
+    protected function setUp(): void {
27
+        parent::setUp();
28
+
29
+        $this->systemConfig = [];
30
+        $this->config = $this->createMock(IConfig::class);
31
+        $this->appManager = $this->createMock(IAppManager::class);
32
+        $this->config->method('getSystemValue')
33
+            ->willReturnCallback(function ($key, $default = '') {
34
+                if (isset($this->systemConfig[$key])) {
35
+                    return $this->systemConfig[$key];
36
+                } else {
37
+                    return $default;
38
+                }
39
+            });
40
+        $this->config->method('getUserValue')
41
+            ->willReturnCallback(function ($userId, $appName, $key, $default = '') {
42
+                if (isset($this->userConfig[$userId][$appName][$key])) {
43
+                    return $this->userConfig[$userId][$appName][$key];
44
+                } else {
45
+                    return $default;
46
+                }
47
+            });
48
+        $this->config->method('setUserValue')
49
+            ->willReturnCallback(function ($userId, $appName, $key, $value): void {
50
+                $this->userConfig[$userId][$appName][$key] = $value;
51
+            });
52
+
53
+        $this->objectStoreConfig = new PrimaryObjectStoreConfig($this->config, $this->appManager);
54
+    }
55
+
56
+    private function getUser(string $uid): IUser {
57
+        $user = $this->createMock(IUser::class);
58
+        $user->method('getUID')
59
+            ->willReturn($uid);
60
+        return $user;
61
+    }
62
+
63
+    private function setConfig(string $key, $value) {
64
+        $this->systemConfig[$key] = $value;
65
+    }
66
+
67
+    public function testNewUserGetsDefault() {
68
+        $this->setConfig('objectstore', [
69
+            'default' => 'server1',
70
+            'server1' => [
71
+                'class' => StorageObjectStore::class,
72
+                'arguments' => [
73
+                    'host' => 'server1',
74
+                ],
75
+            ],
76
+        ]);
77
+
78
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
79
+        $this->assertEquals('server1', $result['arguments']['host']);
80
+
81
+        $this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null));
82
+    }
83
+
84
+    public function testExistingUserKeepsStorage() {
85
+        // setup user with `server1` as storage
86
+        $this->testNewUserGetsDefault();
87
+
88
+        $this->setConfig('objectstore', [
89
+            'default' => 'server2',
90
+            'server1' => [
91
+                'class' => StorageObjectStore::class,
92
+                'arguments' => [
93
+                    'host' => 'server1',
94
+                    'bucket' => '1',
95
+                ],
96
+            ],
97
+            'server2' => [
98
+                'class' => StorageObjectStore::class,
99
+                'arguments' => [
100
+                    'host' => 'server2',
101
+                    'bucket' => '2',
102
+                ],
103
+            ],
104
+        ]);
105
+
106
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
107
+        $this->assertEquals('server1', $result['arguments']['host']);
108
+
109
+        $this->assertEquals('server1', $this->config->getUserValue('test', 'homeobjectstore', 'objectstore', null));
110
+
111
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('other-user'));
112
+        $this->assertEquals('server2', $result['arguments']['host']);
113
+    }
114
+
115
+    public function testNestedAliases() {
116
+        $this->setConfig('objectstore', [
117
+            'default' => 'a1',
118
+            'a1' => 'a2',
119
+            'a2' => 'server1',
120
+            'server1' => [
121
+                'class' => StorageObjectStore::class,
122
+                'arguments' => [
123
+                    'host' => 'server1',
124
+                    'bucket' => '1',
125
+                ],
126
+            ],
127
+        ]);
128
+        $this->assertEquals('server1', $this->objectStoreConfig->resolveAlias('default'));
129
+    }
130
+
131
+    public function testMultibucketChangedConfig() {
132
+        $this->setConfig('objectstore', [
133
+            'default' => 'server1',
134
+            'server1' => [
135
+                'class' => StorageObjectStore::class,
136
+                'arguments' => [
137
+                    'host' => 'server1',
138
+                    'multibucket' => true,
139
+                    'num_buckets' => 8,
140
+                    'bucket' => 'bucket1-'
141
+                ],
142
+            ],
143
+        ]);
144
+
145
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
146
+        $this->assertEquals('server1', $result['arguments']['host']);
147
+        $this->assertEquals('bucket1-7', $result['arguments']['bucket']);
148
+
149
+        $this->setConfig('objectstore', [
150
+            'default' => 'server1',
151
+            'server1' => [
152
+                'class' => StorageObjectStore::class,
153
+                'arguments' => [
154
+                    'host' => 'server1',
155
+                    'multibucket' => true,
156
+                    'num_buckets' => 64,
157
+                    'bucket' => 'bucket1-'
158
+                ],
159
+            ],
160
+        ]);
161
+
162
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
163
+        $this->assertEquals('server1', $result['arguments']['host']);
164
+        $this->assertEquals('bucket1-7', $result['arguments']['bucket']);
165
+
166
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-foo'));
167
+        $this->assertEquals('server1', $result['arguments']['host']);
168
+        $this->assertEquals('bucket1-40', $result['arguments']['bucket']);
169
+
170
+        $this->setConfig('objectstore', [
171
+            'default' => 'server2',
172
+            'server1' => [
173
+                'class' => StorageObjectStore::class,
174
+                'arguments' => [
175
+                    'host' => 'server1',
176
+                    'multibucket' => true,
177
+                    'num_buckets' => 64,
178
+                    'bucket' => 'bucket1-'
179
+                ],
180
+            ],
181
+            'server2' => [
182
+                'class' => StorageObjectStore::class,
183
+                'arguments' => [
184
+                    'host' => 'server2',
185
+                    'multibucket' => true,
186
+                    'num_buckets' => 16,
187
+                    'bucket' => 'bucket2-'
188
+                ],
189
+            ],
190
+        ]);
191
+
192
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test'));
193
+        $this->assertEquals('server1', $result['arguments']['host']);
194
+        $this->assertEquals('bucket1-7', $result['arguments']['bucket']);
195
+
196
+        $result = $this->objectStoreConfig->getObjectStoreConfigForUser($this->getUser('test-bar'));
197
+        $this->assertEquals('server2', $result['arguments']['host']);
198
+        $this->assertEquals('bucket2-4', $result['arguments']['bucket']);
199
+    }
200
+
201
+    public function testMultibucketOldConfig() {
202
+        $this->setConfig('objectstore_multibucket', [
203
+            'class' => StorageObjectStore::class,
204
+            'arguments' => [
205
+                'host' => 'server1',
206
+                'multibucket' => true,
207
+                'num_buckets' => 8,
208
+                'bucket' => 'bucket-'
209
+            ],
210
+        ]);
211
+        $configs = $this->objectStoreConfig->getObjectStoreConfigs();
212
+        $this->assertEquals([
213
+            'default' => 'server1',
214
+            'root' => 'server1',
215
+            'server1' => [
216
+                'class' => StorageObjectStore::class,
217
+                'arguments' => [
218
+                    'host' => 'server1',
219
+                    'multibucket' => true,
220
+                    'num_buckets' => 8,
221
+                    'bucket' => 'bucket-'
222
+                ],
223
+            ],
224
+        ], $configs);
225
+    }
226
+
227
+    public function testSingleObjectStore() {
228
+        $this->setConfig('objectstore', [
229
+            'class' => StorageObjectStore::class,
230
+            'arguments' => [
231
+                'host' => 'server1',
232
+            ],
233
+        ]);
234
+        $configs = $this->objectStoreConfig->getObjectStoreConfigs();
235
+        $this->assertEquals([
236
+            'default' => 'server1',
237
+            'root' => 'server1',
238
+            'server1' => [
239
+                'class' => StorageObjectStore::class,
240
+                'arguments' => [
241
+                    'host' => 'server1',
242
+                    'multibucket' => false,
243
+                ],
244
+            ],
245
+        ], $configs);
246
+    }
247
+
248
+    public function testRoot() {
249
+        $this->setConfig('objectstore', [
250
+            'default' => 'server1',
251
+            'server1' => [
252
+                'class' => StorageObjectStore::class,
253
+                'arguments' => [
254
+                    'host' => 'server1',
255
+                    'bucket' => '1',
256
+                ],
257
+            ],
258
+            'server2' => [
259
+                'class' => StorageObjectStore::class,
260
+                'arguments' => [
261
+                    'host' => 'server2',
262
+                    'bucket' => '2',
263
+                ],
264
+            ],
265
+        ]);
266
+
267
+        $result = $this->objectStoreConfig->getObjectStoreConfigForRoot();
268
+        $this->assertEquals('server1', $result['arguments']['host']);
269
+
270
+        $this->setConfig('objectstore', [
271
+            'default' => 'server1',
272
+            'root' => 'server2',
273
+            'server1' => [
274
+                'class' => StorageObjectStore::class,
275
+                'arguments' => [
276
+                    'host' => 'server1',
277
+                    'bucket' => '1',
278
+                ],
279
+            ],
280
+            'server2' => [
281
+                'class' => StorageObjectStore::class,
282
+                'arguments' => [
283
+                    'host' => 'server2',
284
+                    'bucket' => '2',
285
+                ],
286
+            ],
287
+        ]);
288
+
289
+        $result = $this->objectStoreConfig->getObjectStoreConfigForRoot();
290
+        $this->assertEquals('server2', $result['arguments']['host']);
291
+    }
292 292
 }
Please login to merge, or discard this patch.