Completed
Push — master ( 58f3ff...11de3c )
by Maxence
20:22
created
lib/private/Repair.php 1 patch
Indentation   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -75,215 +75,215 @@
 block discarded – undo
75 75
 use Throwable;
76 76
 
77 77
 class Repair implements IOutput {
78
-	/** @var IRepairStep[] */
79
-	private array $repairSteps = [];
78
+    /** @var IRepairStep[] */
79
+    private array $repairSteps = [];
80 80
 
81
-	private string $currentStep;
81
+    private string $currentStep;
82 82
 
83
-	public function __construct(
84
-		private IEventDispatcher $dispatcher,
85
-		private LoggerInterface $logger,
86
-	) {
87
-	}
83
+    public function __construct(
84
+        private IEventDispatcher $dispatcher,
85
+        private LoggerInterface $logger,
86
+    ) {
87
+    }
88 88
 
89
-	/** @param IRepairStep[] $repairSteps */
90
-	public function setRepairSteps(array $repairSteps): void {
91
-		$this->repairSteps = $repairSteps;
92
-	}
89
+    /** @param IRepairStep[] $repairSteps */
90
+    public function setRepairSteps(array $repairSteps): void {
91
+        $this->repairSteps = $repairSteps;
92
+    }
93 93
 
94
-	/**
95
-	 * Run a series of repair steps for common problems
96
-	 */
97
-	public function run() {
98
-		if (count($this->repairSteps) === 0) {
99
-			$this->dispatcher->dispatchTyped(new RepairInfoEvent('No repair steps available'));
94
+    /**
95
+     * Run a series of repair steps for common problems
96
+     */
97
+    public function run() {
98
+        if (count($this->repairSteps) === 0) {
99
+            $this->dispatcher->dispatchTyped(new RepairInfoEvent('No repair steps available'));
100 100
 
101
-			return;
102
-		}
103
-		// run each repair step
104
-		foreach ($this->repairSteps as $step) {
105
-			$this->currentStep = $step->getName();
106
-			$this->dispatcher->dispatchTyped(new RepairStepEvent($this->currentStep));
107
-			try {
108
-				$step->run($this);
109
-			} catch (\Exception $e) {
110
-				$this->logger->error('Exception while executing repair step ' . $step->getName(), ['exception' => $e]);
111
-				$this->dispatcher->dispatchTyped(new RepairErrorEvent($e->getMessage()));
112
-			}
113
-		}
101
+            return;
102
+        }
103
+        // run each repair step
104
+        foreach ($this->repairSteps as $step) {
105
+            $this->currentStep = $step->getName();
106
+            $this->dispatcher->dispatchTyped(new RepairStepEvent($this->currentStep));
107
+            try {
108
+                $step->run($this);
109
+            } catch (\Exception $e) {
110
+                $this->logger->error('Exception while executing repair step ' . $step->getName(), ['exception' => $e]);
111
+                $this->dispatcher->dispatchTyped(new RepairErrorEvent($e->getMessage()));
112
+            }
113
+        }
114 114
 
115
-		$this->repairSteps = [];
116
-	}
115
+        $this->repairSteps = [];
116
+    }
117 117
 
118
-	/**
119
-	 * Add repair step
120
-	 *
121
-	 * @param IRepairStep|string $repairStep repair step
122
-	 * @throws \Exception
123
-	 */
124
-	public function addStep($repairStep) {
125
-		if (is_string($repairStep)) {
126
-			try {
127
-				$s = \OC::$server->get($repairStep);
128
-			} catch (QueryException $e) {
129
-				if (class_exists($repairStep)) {
130
-					try {
131
-						// Last resort: hope there are no constructor arguments
132
-						$s = new $repairStep();
133
-					} catch (Throwable $inner) {
134
-						// Well, it was worth a try
135
-						throw new \Exception("Repair step '$repairStep' can't be instantiated: " . $e->getMessage(), 0, $e);
136
-					}
137
-				} else {
138
-					throw new \Exception("Repair step '$repairStep' is unknown", 0, $e);
139
-				}
140
-			}
118
+    /**
119
+     * Add repair step
120
+     *
121
+     * @param IRepairStep|string $repairStep repair step
122
+     * @throws \Exception
123
+     */
124
+    public function addStep($repairStep) {
125
+        if (is_string($repairStep)) {
126
+            try {
127
+                $s = \OC::$server->get($repairStep);
128
+            } catch (QueryException $e) {
129
+                if (class_exists($repairStep)) {
130
+                    try {
131
+                        // Last resort: hope there are no constructor arguments
132
+                        $s = new $repairStep();
133
+                    } catch (Throwable $inner) {
134
+                        // Well, it was worth a try
135
+                        throw new \Exception("Repair step '$repairStep' can't be instantiated: " . $e->getMessage(), 0, $e);
136
+                    }
137
+                } else {
138
+                    throw new \Exception("Repair step '$repairStep' is unknown", 0, $e);
139
+                }
140
+            }
141 141
 
142
-			if ($s instanceof IRepairStep) {
143
-				$this->repairSteps[] = $s;
144
-			} else {
145
-				throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
146
-			}
147
-		} else {
148
-			$this->repairSteps[] = $repairStep;
149
-		}
150
-	}
142
+            if ($s instanceof IRepairStep) {
143
+                $this->repairSteps[] = $s;
144
+            } else {
145
+                throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
146
+            }
147
+        } else {
148
+            $this->repairSteps[] = $repairStep;
149
+        }
150
+    }
151 151
 
152
-	/**
153
-	 * Returns the default repair steps to be run on the
154
-	 * command line or after an upgrade.
155
-	 *
156
-	 * @return IRepairStep[]
157
-	 */
158
-	public static function getRepairSteps(): array {
159
-		return [
160
-			new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->getDatabaseConnection(), false),
161
-			new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
162
-			new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
163
-			new MoveUpdaterStepFile(\OC::$server->getConfig()),
164
-			new MoveAvatars(
165
-				\OC::$server->getJobList(),
166
-				\OC::$server->getConfig()
167
-			),
168
-			new CleanPreviews(
169
-				\OC::$server->getJobList(),
170
-				\OC::$server->getUserManager(),
171
-				\OC::$server->getConfig()
172
-			),
173
-			\OCP\Server::get(MigratePropertiesTable::class),
174
-			\OC::$server->get(MigrateOauthTables::class),
175
-			new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
176
-			new AddLogRotateJob(\OC::$server->getJobList()),
177
-			new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OCP\Server::get(JSCombiner::class)),
178
-			\OCP\Server::get(ClearGeneratedAvatarCache::class),
179
-			new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()),
180
-			new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()),
181
-			new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OCP\Server::get(IAppDataFactory::class), \OC::$server->get(LoggerInterface::class)),
182
-			new AddClenupLoginFlowV2BackgroundJob(\OC::$server->getJobList()),
183
-			new RemoveLinkShares(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), \OC::$server->get(INotificationManager::class), \OCP\Server::get(ITimeFactory::class)),
184
-			new ClearCollectionsAccessCache(\OC::$server->getConfig(), \OCP\Server::get(IManager::class)),
185
-			\OCP\Server::get(ResetGeneratedAvatarFlag::class),
186
-			\OCP\Server::get(EncryptionLegacyCipher::class),
187
-			\OCP\Server::get(EncryptionMigration::class),
188
-			\OCP\Server::get(ShippedDashboardEnable::class),
189
-			\OCP\Server::get(AddBruteForceCleanupJob::class),
190
-			\OCP\Server::get(AddCheckForUserCertificatesJob::class),
191
-			\OCP\Server::get(RepairDavShares::class),
192
-			\OCP\Server::get(LookupServerSendCheck::class),
193
-			\OCP\Server::get(AddTokenCleanupJob::class),
194
-			\OCP\Server::get(CleanUpAbandonedApps::class),
195
-			\OCP\Server::get(AddMissingSecretJob::class),
196
-			\OCP\Server::get(AddRemoveOldTasksBackgroundJob::class),
197
-			\OCP\Server::get(AddMetadataGenerationJob::class),
198
-			\OCP\Server::get(RepairLogoDimension::class),
199
-			\OCP\Server::get(RemoveLegacyDatadirFile::class),
200
-			\OCP\Server::get(AddCleanupDeletedUsersBackgroundJob::class),
201
-			\OCP\Server::get(SanitizeAccountProperties::class),
202
-			\OCP\Server::get(AddMovePreviewJob::class),
203
-			\OCP\Server::get(ConfigKeyMigration::class),
204
-		];
205
-	}
152
+    /**
153
+     * Returns the default repair steps to be run on the
154
+     * command line or after an upgrade.
155
+     *
156
+     * @return IRepairStep[]
157
+     */
158
+    public static function getRepairSteps(): array {
159
+        return [
160
+            new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), \OC::$server->getDatabaseConnection(), false),
161
+            new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
162
+            new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
163
+            new MoveUpdaterStepFile(\OC::$server->getConfig()),
164
+            new MoveAvatars(
165
+                \OC::$server->getJobList(),
166
+                \OC::$server->getConfig()
167
+            ),
168
+            new CleanPreviews(
169
+                \OC::$server->getJobList(),
170
+                \OC::$server->getUserManager(),
171
+                \OC::$server->getConfig()
172
+            ),
173
+            \OCP\Server::get(MigratePropertiesTable::class),
174
+            \OC::$server->get(MigrateOauthTables::class),
175
+            new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
176
+            new AddLogRotateJob(\OC::$server->getJobList()),
177
+            new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OCP\Server::get(JSCombiner::class)),
178
+            \OCP\Server::get(ClearGeneratedAvatarCache::class),
179
+            new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()),
180
+            new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()),
181
+            new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OCP\Server::get(IAppDataFactory::class), \OC::$server->get(LoggerInterface::class)),
182
+            new AddClenupLoginFlowV2BackgroundJob(\OC::$server->getJobList()),
183
+            new RemoveLinkShares(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), \OC::$server->get(INotificationManager::class), \OCP\Server::get(ITimeFactory::class)),
184
+            new ClearCollectionsAccessCache(\OC::$server->getConfig(), \OCP\Server::get(IManager::class)),
185
+            \OCP\Server::get(ResetGeneratedAvatarFlag::class),
186
+            \OCP\Server::get(EncryptionLegacyCipher::class),
187
+            \OCP\Server::get(EncryptionMigration::class),
188
+            \OCP\Server::get(ShippedDashboardEnable::class),
189
+            \OCP\Server::get(AddBruteForceCleanupJob::class),
190
+            \OCP\Server::get(AddCheckForUserCertificatesJob::class),
191
+            \OCP\Server::get(RepairDavShares::class),
192
+            \OCP\Server::get(LookupServerSendCheck::class),
193
+            \OCP\Server::get(AddTokenCleanupJob::class),
194
+            \OCP\Server::get(CleanUpAbandonedApps::class),
195
+            \OCP\Server::get(AddMissingSecretJob::class),
196
+            \OCP\Server::get(AddRemoveOldTasksBackgroundJob::class),
197
+            \OCP\Server::get(AddMetadataGenerationJob::class),
198
+            \OCP\Server::get(RepairLogoDimension::class),
199
+            \OCP\Server::get(RemoveLegacyDatadirFile::class),
200
+            \OCP\Server::get(AddCleanupDeletedUsersBackgroundJob::class),
201
+            \OCP\Server::get(SanitizeAccountProperties::class),
202
+            \OCP\Server::get(AddMovePreviewJob::class),
203
+            \OCP\Server::get(ConfigKeyMigration::class),
204
+        ];
205
+    }
206 206
 
207
-	/**
208
-	 * Returns expensive repair steps to be run on the
209
-	 * command line with a special option.
210
-	 *
211
-	 * @return IRepairStep[]
212
-	 */
213
-	public static function getExpensiveRepairSteps() {
214
-		return [
215
-			new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
216
-			new RemoveBrokenProperties(\OCP\Server::get(IDBConnection::class)),
217
-			new RepairMimeTypes(
218
-				\OCP\Server::get(IConfig::class),
219
-				\OCP\Server::get(IAppConfig::class),
220
-				\OCP\Server::get(IDBConnection::class)
221
-			),
222
-			\OCP\Server::get(DeleteSchedulingObjects::class),
223
-			\OC::$server->get(RemoveObjectProperties::class),
224
-		];
225
-	}
207
+    /**
208
+     * Returns expensive repair steps to be run on the
209
+     * command line with a special option.
210
+     *
211
+     * @return IRepairStep[]
212
+     */
213
+    public static function getExpensiveRepairSteps() {
214
+        return [
215
+            new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
216
+            new RemoveBrokenProperties(\OCP\Server::get(IDBConnection::class)),
217
+            new RepairMimeTypes(
218
+                \OCP\Server::get(IConfig::class),
219
+                \OCP\Server::get(IAppConfig::class),
220
+                \OCP\Server::get(IDBConnection::class)
221
+            ),
222
+            \OCP\Server::get(DeleteSchedulingObjects::class),
223
+            \OC::$server->get(RemoveObjectProperties::class),
224
+        ];
225
+    }
226 226
 
227
-	/**
228
-	 * Returns the repair steps to be run before an
229
-	 * upgrade.
230
-	 *
231
-	 * @return IRepairStep[]
232
-	 */
233
-	public static function getBeforeUpgradeRepairSteps() {
234
-		/** @var ConnectionAdapter $connectionAdapter */
235
-		$connectionAdapter = \OC::$server->get(ConnectionAdapter::class);
236
-		$config = \OC::$server->getConfig();
237
-		$steps = [
238
-			new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), $connectionAdapter, true),
239
-			new SaveAccountsTableData($connectionAdapter, $config),
240
-			new DropAccountTermsTable($connectionAdapter),
241
-		];
227
+    /**
228
+     * Returns the repair steps to be run before an
229
+     * upgrade.
230
+     *
231
+     * @return IRepairStep[]
232
+     */
233
+    public static function getBeforeUpgradeRepairSteps() {
234
+        /** @var ConnectionAdapter $connectionAdapter */
235
+        $connectionAdapter = \OC::$server->get(ConnectionAdapter::class);
236
+        $config = \OC::$server->getConfig();
237
+        $steps = [
238
+            new Collation(\OC::$server->getConfig(), \OC::$server->get(LoggerInterface::class), $connectionAdapter, true),
239
+            new SaveAccountsTableData($connectionAdapter, $config),
240
+            new DropAccountTermsTable($connectionAdapter),
241
+        ];
242 242
 
243
-		return $steps;
244
-	}
243
+        return $steps;
244
+    }
245 245
 
246
-	public function debug(string $message): void {
247
-	}
246
+    public function debug(string $message): void {
247
+    }
248 248
 
249
-	/**
250
-	 * @param string $message
251
-	 */
252
-	public function info($message) {
253
-		// for now just emit as we did in the past
254
-		$this->dispatcher->dispatchTyped(new RepairInfoEvent($message));
255
-	}
249
+    /**
250
+     * @param string $message
251
+     */
252
+    public function info($message) {
253
+        // for now just emit as we did in the past
254
+        $this->dispatcher->dispatchTyped(new RepairInfoEvent($message));
255
+    }
256 256
 
257
-	/**
258
-	 * @param string $message
259
-	 */
260
-	public function warning($message) {
261
-		// for now just emit as we did in the past
262
-		$this->dispatcher->dispatchTyped(new RepairWarningEvent($message));
263
-	}
257
+    /**
258
+     * @param string $message
259
+     */
260
+    public function warning($message) {
261
+        // for now just emit as we did in the past
262
+        $this->dispatcher->dispatchTyped(new RepairWarningEvent($message));
263
+    }
264 264
 
265
-	/**
266
-	 * @param int $max
267
-	 */
268
-	public function startProgress($max = 0) {
269
-		// for now just emit as we did in the past
270
-		$this->dispatcher->dispatchTyped(new RepairStartEvent($max, $this->currentStep));
271
-	}
265
+    /**
266
+     * @param int $max
267
+     */
268
+    public function startProgress($max = 0) {
269
+        // for now just emit as we did in the past
270
+        $this->dispatcher->dispatchTyped(new RepairStartEvent($max, $this->currentStep));
271
+    }
272 272
 
273
-	/**
274
-	 * @param int $step number of step to advance
275
-	 * @param string $description
276
-	 */
277
-	public function advance($step = 1, $description = '') {
278
-		// for now just emit as we did in the past
279
-		$this->dispatcher->dispatchTyped(new RepairAdvanceEvent($step, $description));
280
-	}
273
+    /**
274
+     * @param int $step number of step to advance
275
+     * @param string $description
276
+     */
277
+    public function advance($step = 1, $description = '') {
278
+        // for now just emit as we did in the past
279
+        $this->dispatcher->dispatchTyped(new RepairAdvanceEvent($step, $description));
280
+    }
281 281
 
282
-	/**
283
-	 * @param int $max
284
-	 */
285
-	public function finishProgress() {
286
-		// for now just emit as we did in the past
287
-		$this->dispatcher->dispatchTyped(new RepairFinishEvent());
288
-	}
282
+    /**
283
+     * @param int $max
284
+     */
285
+    public function finishProgress() {
286
+        // for now just emit as we did in the past
287
+        $this->dispatcher->dispatchTyped(new RepairFinishEvent());
288
+    }
289 289
 }
Please login to merge, or discard this patch.
lib/private/Config/ConfigManager.php 1 patch
Indentation   +269 added lines, -269 removed lines patch added patch discarded remove patch
@@ -25,273 +25,273 @@
 block discarded – undo
25 25
  * @since 32.0.0
26 26
  */
27 27
 class ConfigManager {
28
-	/** @var AppConfig|null $appConfig */
29
-	private ?IAppConfig $appConfig = null;
30
-	/** @var UserConfig|null $userConfig */
31
-	private ?IUserConfig $userConfig = null;
32
-
33
-	public function __construct(
34
-		private readonly LoggerInterface $logger,
35
-	) {
36
-	}
37
-
38
-	public function clearConfigCaches(): void {
39
-		$this->loadConfigServices();
40
-		$this->appConfig->clearCache();
41
-		$this->userConfig->clearCacheAll();
42
-	}
43
-
44
-
45
-	/**
46
-	 * Use the rename values from the list of ConfigLexiconEntry defined in each app ConfigLexicon
47
-	 * to migrate config value to a new config key.
48
-	 * Migration will only occur if new config key has no value in database.
49
-	 * The previous value from the key set in rename will be deleted from the database when migration
50
-	 * is over.
51
-	 *
52
-	 * This method should be mainly called during a new upgrade or when a new app is enabled.
53
-	 *
54
-	 * @param string|null $appId when set to NULL the method will be executed for all enabled apps of the instance
55
-	 *
56
-	 * @internal
57
-	 * @since 32.0.0
58
-	 * @see Entry
59
-	 */
60
-	public function migrateConfigLexiconKeys(?string $appId = null): void {
61
-		if ($appId === null) {
62
-			$this->migrateConfigLexiconKeys('core');
63
-			$appManager = Server::get(IAppManager::class);
64
-			foreach ($appManager->getEnabledApps() as $app) {
65
-				$this->migrateConfigLexiconKeys($app);
66
-			}
67
-
68
-			return;
69
-		}
70
-
71
-		$this->loadConfigServices();
72
-
73
-		// it is required to ignore aliases when moving config values
74
-		$this->appConfig->ignoreLexiconAliases(true);
75
-		$this->userConfig->ignoreLexiconAliases(true);
76
-
77
-		$this->migrateAppConfigKeys($appId);
78
-		$this->migrateUserConfigKeys($appId);
79
-
80
-		// switch back to normal behavior
81
-		$this->appConfig->ignoreLexiconAliases(false);
82
-		$this->userConfig->ignoreLexiconAliases(false);
83
-	}
84
-
85
-	/**
86
-	 * Upgrade stored data in case of changes in the lexicon.
87
-	 * Heavy process to be executed on core and app upgrade.
88
-	 */
89
-	public function updateLexiconEntries(string $appId): void {
90
-		$this->loadConfigServices();
91
-		$this->updateLexiconAppConfigEntries($appId);
92
-		$this->updateLexiconUserConfigEntries($appId);
93
-	}
94
-
95
-	/**
96
-	 * Apply modification on the lexicon to the stored app config values:
97
-	 *
98
-	 * - Upgrade AppConfig entries if set as lazy/not-lazy
99
-	 */
100
-	private function updateLexiconAppConfigEntries(string $appId): void {
101
-		$lexicon = $this->appConfig->getConfigDetailsFromLexicon($appId);
102
-		foreach ($lexicon['entries'] as $entry) {
103
-			// update laziness
104
-			$this->appConfig->updateLazy($appId, $entry->getKey(), $entry->isLazy());
105
-		}
106
-	}
107
-
108
-	/**
109
-	 * Apply modification on the lexicon to the stored user preferences values:
110
-	 *
111
-	 * - Upgrade UserConfig entries if set as indexed/not-indexed
112
-	 * - Upgrade UserConfig entries if set as lazy/not-lazy
113
-	 */
114
-	private function updateLexiconUserConfigEntries(string $appId): void {
115
-		$lexicon = $this->userConfig->getConfigDetailsFromLexicon($appId);
116
-		foreach ($lexicon['entries'] as $entry) {
117
-			// upgrade based on index flag
118
-			$this->userConfig->updateGlobalIndexed($appId, $entry->getKey(), $entry->isFlagged(IUserConfig::FLAG_INDEXED));
119
-			// update laziness
120
-			$this->userConfig->updateGlobalLazy($appId, $entry->getKey(), $entry->isLazy());
121
-		}
122
-	}
123
-
124
-	/**
125
-	 * config services cannot be load at __construct() or install will fail
126
-	 */
127
-	private function loadConfigServices(): void {
128
-		if ($this->appConfig === null) {
129
-			$this->appConfig = Server::get(IAppConfig::class);
130
-		}
131
-		if ($this->userConfig === null) {
132
-			$this->userConfig = Server::get(IUserConfig::class);
133
-		}
134
-	}
135
-
136
-	/**
137
-	 * Get details from lexicon related to AppConfig and search for entries with rename to initiate
138
-	 * a migration to new config key
139
-	 */
140
-	private function migrateAppConfigKeys(string $appId): void {
141
-		$lexicon = $this->appConfig->getConfigDetailsFromLexicon($appId);
142
-		foreach ($lexicon['entries'] as $entry) {
143
-			// only interested in entries with rename set
144
-			if ($entry->getRename() === null) {
145
-				continue;
146
-			}
147
-
148
-			// only migrate if rename config key has a value and the new config key hasn't
149
-			if ($this->appConfig->hasKey($appId, $entry->getRename())
150
-				&& !$this->appConfig->hasKey($appId, $entry->getKey())) {
151
-				try {
152
-					$this->migrateAppConfigValue($appId, $entry);
153
-				} catch (TypeConflictException $e) {
154
-					$this->logger->error('could not migrate AppConfig value', ['appId' => $appId, 'entry' => $entry, 'exception' => $e]);
155
-					continue;
156
-				}
157
-			}
158
-
159
-			// we only delete previous config value if migration went fine.
160
-			$this->appConfig->deleteKey($appId, $entry->getRename());
161
-		}
162
-	}
163
-
164
-	/**
165
-	 * Get details from lexicon related to UserConfig and search for entries with rename to initiate
166
-	 * a migration to new config key
167
-	 */
168
-	private function migrateUserConfigKeys(string $appId): void {
169
-		$lexicon = $this->userConfig->getConfigDetailsFromLexicon($appId);
170
-		foreach ($lexicon['entries'] as $entry) {
171
-			// only interested in keys with rename set
172
-			if ($entry->getRename() === null) {
173
-				continue;
174
-			}
175
-
176
-			foreach ($this->userConfig->getValuesByUsers($appId, $entry->getRename()) as $userId => $value) {
177
-				if ($this->userConfig->hasKey($userId, $appId, $entry->getKey())) {
178
-					continue;
179
-				}
180
-
181
-				try {
182
-					$this->migrateUserConfigValue($userId, $appId, $entry);
183
-				} catch (TypeConflictException $e) {
184
-					$this->logger->error('could not migrate UserConfig value', ['userId' => $userId, 'appId' => $appId, 'entry' => $entry, 'exception' => $e]);
185
-					continue;
186
-				}
187
-
188
-				$this->userConfig->deleteUserConfig($userId, $appId, $entry->getRename());
189
-			}
190
-		}
191
-	}
192
-
193
-
194
-	/**
195
-	 * converting value from rename to the new key
196
-	 *
197
-	 * @throws TypeConflictException if previous value does not fit the expected type
198
-	 */
199
-	private function migrateAppConfigValue(string $appId, Entry $entry): void {
200
-		$value = $this->appConfig->getValueMixed($appId, $entry->getRename(), lazy: null);
201
-		switch ($entry->getValueType()) {
202
-			case ValueType::STRING:
203
-				$this->appConfig->setValueString($appId, $entry->getKey(), $value);
204
-				return;
205
-
206
-			case ValueType::INT:
207
-				$this->appConfig->setValueInt($appId, $entry->getKey(), $this->convertToInt($value));
208
-				return;
209
-
210
-			case ValueType::FLOAT:
211
-				$this->appConfig->setValueFloat($appId, $entry->getKey(), $this->convertToFloat($value));
212
-				return;
213
-
214
-			case ValueType::BOOL:
215
-				$this->appConfig->setValueBool($appId, $entry->getKey(), $this->convertToBool($value, $entry));
216
-				return;
217
-
218
-			case ValueType::ARRAY:
219
-				$this->appConfig->setValueArray($appId, $entry->getKey(), $this->convertToArray($value));
220
-				return;
221
-		}
222
-	}
223
-
224
-	/**
225
-	 * converting value from rename to the new key
226
-	 *
227
-	 * @throws TypeConflictException if previous value does not fit the expected type
228
-	 */
229
-	private function migrateUserConfigValue(string $userId, string $appId, Entry $entry): void {
230
-		$value = $this->userConfig->getValueMixed($userId, $appId, $entry->getRename(), lazy: null);
231
-		switch ($entry->getValueType()) {
232
-			case ValueType::STRING:
233
-				$this->userConfig->setValueString($userId, $appId, $entry->getKey(), $value);
234
-				return;
235
-
236
-			case ValueType::INT:
237
-				$this->userConfig->setValueInt($userId, $appId, $entry->getKey(), $this->convertToInt($value));
238
-				return;
239
-
240
-			case ValueType::FLOAT:
241
-				$this->userConfig->setValueFloat($userId, $appId, $entry->getKey(), $this->convertToFloat($value));
242
-				return;
243
-
244
-			case ValueType::BOOL:
245
-				$this->userConfig->setValueBool($userId, $appId, $entry->getKey(), $this->convertToBool($value, $entry));
246
-				return;
247
-
248
-			case ValueType::ARRAY:
249
-				$this->userConfig->setValueArray($userId, $appId, $entry->getKey(), $this->convertToArray($value));
250
-				return;
251
-		}
252
-	}
253
-
254
-	public function convertToInt(string $value): int {
255
-		if (!is_numeric($value) || (float)$value <> (int)$value) {
256
-			throw new TypeConflictException('Value is not an integer');
257
-		}
258
-
259
-		return (int)$value;
260
-	}
261
-
262
-	public function convertToFloat(string $value): float {
263
-		if (!is_numeric($value)) {
264
-			throw new TypeConflictException('Value is not a float');
265
-		}
266
-
267
-		return (float)$value;
268
-	}
269
-
270
-	public function convertToBool(string $value, ?Entry $entry = null): bool {
271
-		if (in_array(strtolower($value), ['true', '1', 'on', 'yes'])) {
272
-			$valueBool = true;
273
-		} elseif (in_array(strtolower($value), ['false', '0', 'off', 'no'])) {
274
-			$valueBool = false;
275
-		} else {
276
-			throw new TypeConflictException('Value cannot be converted to boolean');
277
-		}
278
-		if ($entry?->hasOption(Entry::RENAME_INVERT_BOOLEAN) === true) {
279
-			$valueBool = !$valueBool;
280
-		}
281
-
282
-		return $valueBool;
283
-	}
284
-
285
-	public function convertToArray(string $value): array {
286
-		try {
287
-			$valueArray = json_decode($value, true, flags: JSON_THROW_ON_ERROR);
288
-		} catch (JsonException) {
289
-			throw new TypeConflictException('Value is not a valid json');
290
-		}
291
-		if (!is_array($valueArray)) {
292
-			throw new TypeConflictException('Value is not an array');
293
-		}
294
-
295
-		return $valueArray;
296
-	}
28
+    /** @var AppConfig|null $appConfig */
29
+    private ?IAppConfig $appConfig = null;
30
+    /** @var UserConfig|null $userConfig */
31
+    private ?IUserConfig $userConfig = null;
32
+
33
+    public function __construct(
34
+        private readonly LoggerInterface $logger,
35
+    ) {
36
+    }
37
+
38
+    public function clearConfigCaches(): void {
39
+        $this->loadConfigServices();
40
+        $this->appConfig->clearCache();
41
+        $this->userConfig->clearCacheAll();
42
+    }
43
+
44
+
45
+    /**
46
+     * Use the rename values from the list of ConfigLexiconEntry defined in each app ConfigLexicon
47
+     * to migrate config value to a new config key.
48
+     * Migration will only occur if new config key has no value in database.
49
+     * The previous value from the key set in rename will be deleted from the database when migration
50
+     * is over.
51
+     *
52
+     * This method should be mainly called during a new upgrade or when a new app is enabled.
53
+     *
54
+     * @param string|null $appId when set to NULL the method will be executed for all enabled apps of the instance
55
+     *
56
+     * @internal
57
+     * @since 32.0.0
58
+     * @see Entry
59
+     */
60
+    public function migrateConfigLexiconKeys(?string $appId = null): void {
61
+        if ($appId === null) {
62
+            $this->migrateConfigLexiconKeys('core');
63
+            $appManager = Server::get(IAppManager::class);
64
+            foreach ($appManager->getEnabledApps() as $app) {
65
+                $this->migrateConfigLexiconKeys($app);
66
+            }
67
+
68
+            return;
69
+        }
70
+
71
+        $this->loadConfigServices();
72
+
73
+        // it is required to ignore aliases when moving config values
74
+        $this->appConfig->ignoreLexiconAliases(true);
75
+        $this->userConfig->ignoreLexiconAliases(true);
76
+
77
+        $this->migrateAppConfigKeys($appId);
78
+        $this->migrateUserConfigKeys($appId);
79
+
80
+        // switch back to normal behavior
81
+        $this->appConfig->ignoreLexiconAliases(false);
82
+        $this->userConfig->ignoreLexiconAliases(false);
83
+    }
84
+
85
+    /**
86
+     * Upgrade stored data in case of changes in the lexicon.
87
+     * Heavy process to be executed on core and app upgrade.
88
+     */
89
+    public function updateLexiconEntries(string $appId): void {
90
+        $this->loadConfigServices();
91
+        $this->updateLexiconAppConfigEntries($appId);
92
+        $this->updateLexiconUserConfigEntries($appId);
93
+    }
94
+
95
+    /**
96
+     * Apply modification on the lexicon to the stored app config values:
97
+     *
98
+     * - Upgrade AppConfig entries if set as lazy/not-lazy
99
+     */
100
+    private function updateLexiconAppConfigEntries(string $appId): void {
101
+        $lexicon = $this->appConfig->getConfigDetailsFromLexicon($appId);
102
+        foreach ($lexicon['entries'] as $entry) {
103
+            // update laziness
104
+            $this->appConfig->updateLazy($appId, $entry->getKey(), $entry->isLazy());
105
+        }
106
+    }
107
+
108
+    /**
109
+     * Apply modification on the lexicon to the stored user preferences values:
110
+     *
111
+     * - Upgrade UserConfig entries if set as indexed/not-indexed
112
+     * - Upgrade UserConfig entries if set as lazy/not-lazy
113
+     */
114
+    private function updateLexiconUserConfigEntries(string $appId): void {
115
+        $lexicon = $this->userConfig->getConfigDetailsFromLexicon($appId);
116
+        foreach ($lexicon['entries'] as $entry) {
117
+            // upgrade based on index flag
118
+            $this->userConfig->updateGlobalIndexed($appId, $entry->getKey(), $entry->isFlagged(IUserConfig::FLAG_INDEXED));
119
+            // update laziness
120
+            $this->userConfig->updateGlobalLazy($appId, $entry->getKey(), $entry->isLazy());
121
+        }
122
+    }
123
+
124
+    /**
125
+     * config services cannot be load at __construct() or install will fail
126
+     */
127
+    private function loadConfigServices(): void {
128
+        if ($this->appConfig === null) {
129
+            $this->appConfig = Server::get(IAppConfig::class);
130
+        }
131
+        if ($this->userConfig === null) {
132
+            $this->userConfig = Server::get(IUserConfig::class);
133
+        }
134
+    }
135
+
136
+    /**
137
+     * Get details from lexicon related to AppConfig and search for entries with rename to initiate
138
+     * a migration to new config key
139
+     */
140
+    private function migrateAppConfigKeys(string $appId): void {
141
+        $lexicon = $this->appConfig->getConfigDetailsFromLexicon($appId);
142
+        foreach ($lexicon['entries'] as $entry) {
143
+            // only interested in entries with rename set
144
+            if ($entry->getRename() === null) {
145
+                continue;
146
+            }
147
+
148
+            // only migrate if rename config key has a value and the new config key hasn't
149
+            if ($this->appConfig->hasKey($appId, $entry->getRename())
150
+                && !$this->appConfig->hasKey($appId, $entry->getKey())) {
151
+                try {
152
+                    $this->migrateAppConfigValue($appId, $entry);
153
+                } catch (TypeConflictException $e) {
154
+                    $this->logger->error('could not migrate AppConfig value', ['appId' => $appId, 'entry' => $entry, 'exception' => $e]);
155
+                    continue;
156
+                }
157
+            }
158
+
159
+            // we only delete previous config value if migration went fine.
160
+            $this->appConfig->deleteKey($appId, $entry->getRename());
161
+        }
162
+    }
163
+
164
+    /**
165
+     * Get details from lexicon related to UserConfig and search for entries with rename to initiate
166
+     * a migration to new config key
167
+     */
168
+    private function migrateUserConfigKeys(string $appId): void {
169
+        $lexicon = $this->userConfig->getConfigDetailsFromLexicon($appId);
170
+        foreach ($lexicon['entries'] as $entry) {
171
+            // only interested in keys with rename set
172
+            if ($entry->getRename() === null) {
173
+                continue;
174
+            }
175
+
176
+            foreach ($this->userConfig->getValuesByUsers($appId, $entry->getRename()) as $userId => $value) {
177
+                if ($this->userConfig->hasKey($userId, $appId, $entry->getKey())) {
178
+                    continue;
179
+                }
180
+
181
+                try {
182
+                    $this->migrateUserConfigValue($userId, $appId, $entry);
183
+                } catch (TypeConflictException $e) {
184
+                    $this->logger->error('could not migrate UserConfig value', ['userId' => $userId, 'appId' => $appId, 'entry' => $entry, 'exception' => $e]);
185
+                    continue;
186
+                }
187
+
188
+                $this->userConfig->deleteUserConfig($userId, $appId, $entry->getRename());
189
+            }
190
+        }
191
+    }
192
+
193
+
194
+    /**
195
+     * converting value from rename to the new key
196
+     *
197
+     * @throws TypeConflictException if previous value does not fit the expected type
198
+     */
199
+    private function migrateAppConfigValue(string $appId, Entry $entry): void {
200
+        $value = $this->appConfig->getValueMixed($appId, $entry->getRename(), lazy: null);
201
+        switch ($entry->getValueType()) {
202
+            case ValueType::STRING:
203
+                $this->appConfig->setValueString($appId, $entry->getKey(), $value);
204
+                return;
205
+
206
+            case ValueType::INT:
207
+                $this->appConfig->setValueInt($appId, $entry->getKey(), $this->convertToInt($value));
208
+                return;
209
+
210
+            case ValueType::FLOAT:
211
+                $this->appConfig->setValueFloat($appId, $entry->getKey(), $this->convertToFloat($value));
212
+                return;
213
+
214
+            case ValueType::BOOL:
215
+                $this->appConfig->setValueBool($appId, $entry->getKey(), $this->convertToBool($value, $entry));
216
+                return;
217
+
218
+            case ValueType::ARRAY:
219
+                $this->appConfig->setValueArray($appId, $entry->getKey(), $this->convertToArray($value));
220
+                return;
221
+        }
222
+    }
223
+
224
+    /**
225
+     * converting value from rename to the new key
226
+     *
227
+     * @throws TypeConflictException if previous value does not fit the expected type
228
+     */
229
+    private function migrateUserConfigValue(string $userId, string $appId, Entry $entry): void {
230
+        $value = $this->userConfig->getValueMixed($userId, $appId, $entry->getRename(), lazy: null);
231
+        switch ($entry->getValueType()) {
232
+            case ValueType::STRING:
233
+                $this->userConfig->setValueString($userId, $appId, $entry->getKey(), $value);
234
+                return;
235
+
236
+            case ValueType::INT:
237
+                $this->userConfig->setValueInt($userId, $appId, $entry->getKey(), $this->convertToInt($value));
238
+                return;
239
+
240
+            case ValueType::FLOAT:
241
+                $this->userConfig->setValueFloat($userId, $appId, $entry->getKey(), $this->convertToFloat($value));
242
+                return;
243
+
244
+            case ValueType::BOOL:
245
+                $this->userConfig->setValueBool($userId, $appId, $entry->getKey(), $this->convertToBool($value, $entry));
246
+                return;
247
+
248
+            case ValueType::ARRAY:
249
+                $this->userConfig->setValueArray($userId, $appId, $entry->getKey(), $this->convertToArray($value));
250
+                return;
251
+        }
252
+    }
253
+
254
+    public function convertToInt(string $value): int {
255
+        if (!is_numeric($value) || (float)$value <> (int)$value) {
256
+            throw new TypeConflictException('Value is not an integer');
257
+        }
258
+
259
+        return (int)$value;
260
+    }
261
+
262
+    public function convertToFloat(string $value): float {
263
+        if (!is_numeric($value)) {
264
+            throw new TypeConflictException('Value is not a float');
265
+        }
266
+
267
+        return (float)$value;
268
+    }
269
+
270
+    public function convertToBool(string $value, ?Entry $entry = null): bool {
271
+        if (in_array(strtolower($value), ['true', '1', 'on', 'yes'])) {
272
+            $valueBool = true;
273
+        } elseif (in_array(strtolower($value), ['false', '0', 'off', 'no'])) {
274
+            $valueBool = false;
275
+        } else {
276
+            throw new TypeConflictException('Value cannot be converted to boolean');
277
+        }
278
+        if ($entry?->hasOption(Entry::RENAME_INVERT_BOOLEAN) === true) {
279
+            $valueBool = !$valueBool;
280
+        }
281
+
282
+        return $valueBool;
283
+    }
284
+
285
+    public function convertToArray(string $value): array {
286
+        try {
287
+            $valueArray = json_decode($value, true, flags: JSON_THROW_ON_ERROR);
288
+        } catch (JsonException) {
289
+            throw new TypeConflictException('Value is not a valid json');
290
+        }
291
+        if (!is_array($valueArray)) {
292
+            throw new TypeConflictException('Value is not an array');
293
+        }
294
+
295
+        return $valueArray;
296
+    }
297 297
 }
Please login to merge, or discard this patch.
core/AppInfo/ConfigLexicon.php 1 patch
Indentation   +77 added lines, -77 removed lines patch added patch discarded remove patch
@@ -20,87 +20,87 @@
 block discarded – undo
20 20
  * Please Add & Manage your Config Keys in that file and keep the Lexicon up to date!
21 21
  */
22 22
 class ConfigLexicon implements ILexicon {
23
-	public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares';
24
-	public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens';
25
-	public const SHARE_LINK_PASSWORD_DEFAULT = 'shareapi_enable_link_password_by_default';
26
-	public const SHARE_LINK_PASSWORD_ENFORCED = 'shareapi_enforce_links_password';
27
-	public const SHARE_LINK_EXPIRE_DATE_DEFAULT = 'shareapi_default_expire_date';
28
-	public const SHARE_LINK_EXPIRE_DATE_ENFORCED = 'shareapi_enforce_expire_date';
29
-	public const USER_LANGUAGE = 'lang';
30
-	public const OCM_DISCOVERY_ENABLED = 'ocm_discovery_enabled';
31
-	public const OCM_INVITE_ACCEPT_DIALOG = 'ocm_invite_accept_dialog';
23
+    public const SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES = 'shareapi_allow_federation_on_public_shares';
24
+    public const SHARE_CUSTOM_TOKEN = 'shareapi_allow_custom_tokens';
25
+    public const SHARE_LINK_PASSWORD_DEFAULT = 'shareapi_enable_link_password_by_default';
26
+    public const SHARE_LINK_PASSWORD_ENFORCED = 'shareapi_enforce_links_password';
27
+    public const SHARE_LINK_EXPIRE_DATE_DEFAULT = 'shareapi_default_expire_date';
28
+    public const SHARE_LINK_EXPIRE_DATE_ENFORCED = 'shareapi_enforce_expire_date';
29
+    public const USER_LANGUAGE = 'lang';
30
+    public const OCM_DISCOVERY_ENABLED = 'ocm_discovery_enabled';
31
+    public const OCM_INVITE_ACCEPT_DIALOG = 'ocm_invite_accept_dialog';
32 32
 
33
-	public const USER_LOCALE = 'locale';
34
-	public const USER_TIMEZONE = 'timezone';
33
+    public const USER_LOCALE = 'locale';
34
+    public const USER_TIMEZONE = 'timezone';
35 35
 
36
-	public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length';
37
-	public const UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST = 'unified_search_max_results_per_request';
36
+    public const UNIFIED_SEARCH_MIN_SEARCH_LENGTH = 'unified_search_min_search_length';
37
+    public const UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST = 'unified_search_max_results_per_request';
38 38
 
39
-	public const LASTCRON_TIMESTAMP = 'lastcron';
39
+    public const LASTCRON_TIMESTAMP = 'lastcron';
40 40
 
41
-	public function getStrictness(): Strictness {
42
-		return Strictness::IGNORE;
43
-	}
41
+    public function getStrictness(): Strictness {
42
+        return Strictness::IGNORE;
43
+    }
44 44
 
45
-	public function getAppConfigs(): array {
46
-		return [
47
-			new Entry(
48
-				key: self::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES,
49
-				type: ValueType::BOOL,
50
-				defaultRaw: true,
51
-				definition: 'adds share permission to public shares to allow adding them to your Nextcloud (federation)',
52
-			),
53
-			new Entry(
54
-				key: self::SHARE_CUSTOM_TOKEN,
55
-				type: ValueType::BOOL,
56
-				defaultRaw: fn (Preset $p): bool => match ($p) {
57
-					Preset::FAMILY, Preset::PRIVATE => true,
58
-					default => false,
59
-				},
60
-				definition: 'Allow users to customize share URL',
61
-				note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
62
-			),
63
-			new Entry(self::SHARE_LINK_PASSWORD_DEFAULT, ValueType::BOOL, false, 'Ask for a password when sharing document by default'),
64
-			new Entry(
65
-				key: self::SHARE_LINK_PASSWORD_ENFORCED,
66
-				type: ValueType::BOOL,
67
-				defaultRaw: fn (Preset $p): bool => match ($p) {
68
-					Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
69
-					default => false,
70
-				},
71
-				definition: 'Enforce password protection for shared documents'
72
-			),
73
-			new Entry(
74
-				key: self::SHARE_LINK_EXPIRE_DATE_DEFAULT,
75
-				type: ValueType::BOOL,
76
-				defaultRaw: fn (Preset $p): bool => match ($p) {
77
-					Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
78
-					default => false,
79
-				},
80
-				definition: 'Default expiration date for shares via link or mail'
81
-			),
82
-			new Entry(
83
-				key: self::SHARE_LINK_EXPIRE_DATE_ENFORCED,
84
-				type: ValueType::BOOL,
85
-				defaultRaw: fn (Preset $p): bool => match ($p) {
86
-					Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
87
-					default => false,
88
-				},
89
-				definition: 'Enforce expiration date for shares via link or mail'
90
-			),
91
-			new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'),
92
-			new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM'),
93
-			new Entry(self::OCM_INVITE_ACCEPT_DIALOG, ValueType::STRING, '', 'route to local invite accept dialog', note: 'set as empty string to disable feature'),
94
-			new Entry(self::UNIFIED_SEARCH_MIN_SEARCH_LENGTH, ValueType::INT, 1, 'Minimum search length to trigger the request', rename: 'unified-search.min-search-length'),
95
-			new Entry(self::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST, ValueType::INT, 25, 'Maximum results returned per search request', rename: 'unified-search.max-results-per-request'),
96
-		];
97
-	}
45
+    public function getAppConfigs(): array {
46
+        return [
47
+            new Entry(
48
+                key: self::SHAREAPI_ALLOW_FEDERATION_ON_PUBLIC_SHARES,
49
+                type: ValueType::BOOL,
50
+                defaultRaw: true,
51
+                definition: 'adds share permission to public shares to allow adding them to your Nextcloud (federation)',
52
+            ),
53
+            new Entry(
54
+                key: self::SHARE_CUSTOM_TOKEN,
55
+                type: ValueType::BOOL,
56
+                defaultRaw: fn (Preset $p): bool => match ($p) {
57
+                    Preset::FAMILY, Preset::PRIVATE => true,
58
+                    default => false,
59
+                },
60
+                definition: 'Allow users to customize share URL',
61
+                note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
62
+            ),
63
+            new Entry(self::SHARE_LINK_PASSWORD_DEFAULT, ValueType::BOOL, false, 'Ask for a password when sharing document by default'),
64
+            new Entry(
65
+                key: self::SHARE_LINK_PASSWORD_ENFORCED,
66
+                type: ValueType::BOOL,
67
+                defaultRaw: fn (Preset $p): bool => match ($p) {
68
+                    Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
69
+                    default => false,
70
+                },
71
+                definition: 'Enforce password protection for shared documents'
72
+            ),
73
+            new Entry(
74
+                key: self::SHARE_LINK_EXPIRE_DATE_DEFAULT,
75
+                type: ValueType::BOOL,
76
+                defaultRaw: fn (Preset $p): bool => match ($p) {
77
+                    Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
78
+                    default => false,
79
+                },
80
+                definition: 'Default expiration date for shares via link or mail'
81
+            ),
82
+            new Entry(
83
+                key: self::SHARE_LINK_EXPIRE_DATE_ENFORCED,
84
+                type: ValueType::BOOL,
85
+                defaultRaw: fn (Preset $p): bool => match ($p) {
86
+                    Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
87
+                    default => false,
88
+                },
89
+                definition: 'Enforce expiration date for shares via link or mail'
90
+            ),
91
+            new Entry(self::LASTCRON_TIMESTAMP, ValueType::INT, 0, 'timestamp of last cron execution'),
92
+            new Entry(self::OCM_DISCOVERY_ENABLED, ValueType::BOOL, true, 'enable/disable OCM'),
93
+            new Entry(self::OCM_INVITE_ACCEPT_DIALOG, ValueType::STRING, '', 'route to local invite accept dialog', note: 'set as empty string to disable feature'),
94
+            new Entry(self::UNIFIED_SEARCH_MIN_SEARCH_LENGTH, ValueType::INT, 1, 'Minimum search length to trigger the request', rename: 'unified-search.min-search-length'),
95
+            new Entry(self::UNIFIED_SEARCH_MAX_RESULTS_PER_REQUEST, ValueType::INT, 25, 'Maximum results returned per search request', rename: 'unified-search.max-results-per-request'),
96
+        ];
97
+    }
98 98
 
99
-	public function getUserConfigs(): array {
100
-		return [
101
-			new Entry(self::USER_LANGUAGE, ValueType::STRING, definition: 'language'),
102
-			new Entry(self::USER_LOCALE, ValueType::STRING, definition: 'locale'),
103
-			new Entry(self::USER_TIMEZONE, ValueType::STRING, definition: 'timezone'),
104
-		];
105
-	}
99
+    public function getUserConfigs(): array {
100
+        return [
101
+            new Entry(self::USER_LANGUAGE, ValueType::STRING, definition: 'language'),
102
+            new Entry(self::USER_LOCALE, ValueType::STRING, definition: 'locale'),
103
+            new Entry(self::USER_TIMEZONE, ValueType::STRING, definition: 'timezone'),
104
+        ];
105
+    }
106 106
 }
Please login to merge, or discard this patch.