3232use OCP \ILazyConfig ;
3333use Psr \Log \LoggerInterface ;
3434
35+ /**
36+ * Lazy load of your app config values.
37+ *
38+ * store a value:
39+ * $this->lazyConfig->setValueString('my_app', 'my_param', 'configuration_value');
40+ *
41+ * retrieve a value:
42+ * $this->lazyConfig->getValueString('my_app', 'my_param', 'default_value');
43+ *
44+ * The caching is made in a way that all configured value of my_app
45+ * are retrieved when getValue*() is called for the first time
46+ *
47+ * There is a way to get values only when needed, without filling the cache with rarely needed values
48+ * when getValue*() is called with 'my_app'. A group of values can be set by using 'my_app.my_group':
49+ *
50+ * $this->lazyConfig->setValueString('my_app.my_group', 'my_param', 'configuration_value');
51+ * $this->lazyConfig->getValueString('my_app.my_group', 'my_param', 'default_value');
52+ *
53+ * Values set in group 'my_group' are not cached when calling getValue*() on 'my_app', but
54+ * only when using 'my_app.my_group'.
55+ *
56+ * @since 29.0.0
57+ */
3558class LazyConfig implements ILazyConfig {
36- private array $ cache = [];
59+ public const APP_EXTRA_SEPARATOR = '. ' ;
60+
61+ private array $ cache = []; // cached config
62+ private array $ extra = []; // list of loaded extra config
3763 protected array $ sensitiveValues = [
3864 'circles ' => [
3965 '/^key_pairs$/ ' ,
@@ -178,8 +204,8 @@ public function getApps(bool $loadValues = true): array {
178204 * @since 29.0.0
179205 */
180206 public function getKeys (string $ app ): array {
181- $ this ->loadConfig ($ app );
182- return array_keys ($ this ->cache [$ app ]);
207+ $ appId = $ this ->loadConfig ($ app );
208+ return array_keys ($ this ->cache [$ appId ]);
183209 }
184210
185211 /**
@@ -188,12 +214,11 @@ public function getKeys(string $app): array {
188214 *
189215 * @inheritDoc
190216 * @return bool
191- * @throws DBException
192217 * @since 29.0.0
193218 */
194219 public function hasKey (string $ app , string $ key ): bool {
195- $ this ->loadConfig ($ app );
196- return isset ($ this ->cache [$ app ][$ key ]);
220+ $ appId = $ this ->loadConfig ($ app );
221+ return isset ($ this ->cache [$ appId ][$ key ]);
197222 }
198223
199224 /**
@@ -202,20 +227,19 @@ public function hasKey(string $app, string $key): bool {
202227 *
203228 * @inheritDoc
204229 * @return array
205- * @throws DBException
206230 * @since 29.0.0
207231 */
208232 public function getValues (string $ app , string $ key = '' ): array {
209- $ this ->loadConfig ($ app );
233+ $ appId = $ this ->loadConfig ($ app, true );
210234
211235 if ($ key === '' ) {
212- return $ this ->cache [$ app ] ?? [];
236+ return $ this ->cache [$ appId ] ?? [];
213237 }
214238
215239 $ values = [];
216- foreach (($ this ->cache [$ app ] ?? []) as $ configkey => $ configvalue ) {
217- if (str_starts_with ($ configkey , $ key )) {
218- $ values [$ configkey ] = $ configvalue ;
240+ foreach (($ this ->cache [$ appId ] ?? []) as $ configKey => $ configValue ) {
241+ if (str_starts_with ($ configKey , $ key )) {
242+ $ values [$ configKey ] = $ configValue ;
219243 }
220244 }
221245
@@ -251,12 +275,12 @@ public function getFilteredValues(string $app): array {
251275 * @since 29.0.0
252276 */
253277 public function getValueString (string $ app , string $ key , string $ default = '' ): string {
254- $ this ->loadConfig ($ app );
278+ $ appId = $ this ->loadConfig ($ app );
255279 if (!$ this ->hasKey ($ app , $ key )) {
256280 return $ default ;
257281 }
258282
259- return $ this ->cache [$ app ][$ key ];
283+ return $ this ->cache [$ appId ][$ key ];
260284 }
261285
262286 /**
@@ -315,15 +339,17 @@ public function getValueArray(string $app, string $key, array $default = []): ar
315339 * @since 29.0.0
316340 */
317341 public function setValueString (string $ app , string $ key , string $ value ): bool {
318- $ this ->loadConfig ($ app );
342+ $ appId = $ this ->loadConfig ($ app );
319343 $ updated = !$ this ->hasKey ($ app , $ key ) || $ value !== $ this ->getValueString ($ app , $ key );
320344 if (!$ updated ) {
321345 return false ;
322346 }
323347
348+ [, $ extra ] = $ this ->parseExtra ($ app );
324349 $ insert = $ this ->connection ->getQueryBuilder ();
325350 $ insert ->insert ('appconfig_lazy ' )
326- ->setValue ('app_id ' , $ insert ->createNamedParameter ($ app ))
351+ ->setValue ('app_id ' , $ insert ->createNamedParameter ($ appId ))
352+ ->setValue ('extra ' , $ insert ->createNamedParameter ($ extra ))
327353 ->setValue ('config_key ' , $ insert ->createNamedParameter ($ key ))
328354 ->setValue ('config_value ' , $ insert ->createNamedParameter ($ value ));
329355 try {
@@ -336,6 +362,7 @@ public function setValueString(string $app, string $key, string $value): bool {
336362 $ update = $ this ->connection ->getQueryBuilder ();
337363 $ update ->update ('appconfig_lazy ' )
338364 ->set ('config_value ' , $ update ->createNamedParameter ($ value ))
365+ ->set ('extra ' , $ update ->createNamedParameter ($ extra ))
339366 ->where ($ update ->expr ()->eq ('app_id ' , $ update ->createNamedParameter ($ app )))
340367 ->andWhere ($ update ->expr ()->eq ('config_key ' , $ update ->createNamedParameter ($ key )));
341368 $ update ->executeStatement ();
@@ -422,56 +449,109 @@ public function unsetKey(string $app, string $key): void {
422449 * @since 29.0.0
423450 */
424451 public function deleteApp (string $ app ): void {
425- $ this ->loadConfig ($ app );
452+ $ appId = $ this ->loadConfig ($ app );
453+ //[$appId,] = $this->parseExtra($app);
426454
427455 $ sql = $ this ->connection ->getQueryBuilder ();
428456 $ sql ->delete ('appconfig_lazy ' )
429- ->where ($ sql ->expr ()->eq ('app_id ' , $ sql ->createNamedParameter ($ app )));
457+ ->where ($ sql ->expr ()->eq ('app_id ' , $ sql ->createNamedParameter ($ appId )));
430458 $ sql ->executeStatement ();
431459
432- $ this ->clearCache ($ app );
460+ $ this ->clearCache ($ appId );
433461 }
434462
435463 /**
436464 * @param string $app
437465 *
438- * @throws DBException
466+ * @return array<string, string>
439467 */
440- private function loadConfig (string $ app ): void {
441- if (array_key_exists ($ app , $ this -> cache )) {
442- return ;
468+ private function parseExtra (string $ app ): array {
469+ if (! strpos ($ app , self :: APP_EXTRA_SEPARATOR )) {
470+ return [ $ app , '' ] ;
443471 }
444472
445- $ this ->cache [$ app ] = [];
473+ return explode (self ::APP_EXTRA_SEPARATOR , $ app , 2 );
474+ }
446475
447- $ sql = $ this ->connection ->getQueryBuilder ();
448- $ sql ->select ('config_key ' , 'config_value ' )
476+ /**
477+ * @param string $app
478+ * @param bool $includeExtras
479+ *
480+ * @return string
481+ */
482+ private function loadConfig (string $ app , bool $ includeExtras = false ): string {
483+ [$ appId , $ extra ] = $ this ->parseExtra ($ app );
484+ if ($ this ->isLoaded ($ appId , $ extra )) {
485+ return $ appId ;
486+ }
487+
488+ if (!array_key_exists ($ appId , $ this ->cache )) {
489+ $ this ->cache [$ appId ] = [];
490+ $ this ->extra [$ appId ] = [];
491+ }
492+
493+ $ qb = $ this ->connection ->getQueryBuilder ();
494+ $ qb ->select ('config_key ' , 'config_value ' )
449495 ->from ('appconfig_lazy ' )
450- ->where ($ sql ->expr ()->eq ('app_id ' , $ sql ->createNamedParameter ($ app )));
451- $ result = $ sql ->execute ();
496+ ->where ($ qb ->expr ()->eq ('app_id ' , $ qb ->createNamedParameter ($ appId )));
497+
498+ if (!$ includeExtras ) {
499+ $ qb ->andWhere ($ qb ->expr ()->eq ('extra ' , $ qb ->createNamedParameter ($ extra )));
500+ }
501+ $ result = $ qb ->execute ();
452502
453503 $ rows = $ result ->fetchAll ();
454504 foreach ($ rows as $ row ) {
455- $ this ->cache [$ app ][$ row ['config_key ' ]] = $ row ['config_value ' ];
505+ $ this ->cache [$ appId ][$ row ['config_key ' ]] = $ row ['config_value ' ];
506+ $ this ->setLoadedStatus ($ appId , $ extra );
456507 }
457508 $ result ->closeCursor ();
509+
510+ return $ appId ;
458511 }
459512
460513 /**
461514 * @throws DBException
462515 */
463516 private function loadConfigAll (): void {
464517 $ sql = $ this ->connection ->getQueryBuilder ();
465- $ sql ->select ('app_id ' , 'config_key ' , 'config_value ' )
518+ $ sql ->select ('app_id ' , 'extra ' , ' config_key ' , 'config_value ' )
466519 ->from ('appconfig_lazy ' );
467520 $ result = $ sql ->execute ();
468521
469522 $ rows = $ result ->fetchAll ();
470523 foreach ($ rows as $ row ) {
471524 $ this ->cache [$ row ['app_id ' ]][$ row ['config_key ' ]] = $ row ['config_value ' ];
525+ $ this ->setLoadedStatus ($ row ['app_id ' ], $ row ['extra ' ]);
526+ }
527+ }
528+
529+
530+ private function isLoaded (string $ appId , string $ extra ): bool {
531+ if (!array_key_exists ($ appId , $ this ->cache )) {
532+ return false ;
533+ }
534+
535+ if (!in_array ($ extra , $ this ->extra [$ appId ])) {
536+ return false ;
537+ }
538+
539+ return true ;
540+ }
541+
542+ public function currentCache (): void {
543+ echo 'current cache: ' . json_encode ($ this ->cache , JSON_PRETTY_PRINT ) . "\n" ;
544+ }
545+
546+ private function setLoadedStatus (string $ appId , string $ extra ): void {
547+ if (in_array ($ extra , $ this ->extra [$ appId ] ?? [])) {
548+ return ;
472549 }
550+
551+ $ this ->extra [$ appId ][] = $ extra ;
473552 }
474553
554+
475555 /**
476556 * @inheritDoc
477557 * @param string $app
@@ -481,6 +561,7 @@ private function loadConfigAll(): void {
481561 public function clearCache (string $ app = '' ): void {
482562 if ($ app !== '' ) {
483563 unset($ this ->cache [$ app ]);
564+ unset($ this ->extra [$ app ]);
484565 return ;
485566 }
486567
0 commit comments