@@ -71,6 +71,7 @@ class UserConfig implements IUserConfig {
7171
7272 public function __construct (
7373 protected IDBConnection $ connection ,
74+ protected IConfig $ config ,
7475 protected LoggerInterface $ logger ,
7576 protected ICrypto $ crypto ,
7677 ) {
@@ -228,7 +229,8 @@ public function isLazy(string $userId, string $app, string $key): bool {
228229 // there is a huge probability the non-lazy config are already loaded
229230 // meaning that we can start by only checking if a current non-lazy key exists
230231 if ($ this ->hasKey ($ userId , $ app , $ key , false )) {
231- return false ; // meaning key is not lazy.
232+ // meaning key is not lazy.
233+ return false ;
232234 }
233235
234236 // as key is not found as non-lazy, we load and search in the lazy config
@@ -263,7 +265,8 @@ public function getValues(
263265 $ values = array_filter (
264266 $ this ->formatAppValues ($ userId , $ app , ($ this ->fastCache [$ userId ][$ app ] ?? []) + ($ this ->lazyCache [$ userId ][$ app ] ?? []), $ filtered ),
265267 function (string $ key ) use ($ prefix ): bool {
266- return str_starts_with ($ key , $ prefix ); // filter values based on $prefix
268+ // filter values based on $prefix
269+ return str_starts_with ($ key , $ prefix );
267270 }, ARRAY_FILTER_USE_KEY
268271 );
269272
@@ -711,8 +714,9 @@ private function getTypedValue(
711714 ValueType $ type ,
712715 ): string {
713716 $ this ->assertParams ($ userId , $ app , $ key );
714- if (!$ this ->matchAndApplyLexiconDefinition ($ app , $ key , $ lazy , $ type , default: $ default )) {
715- return $ default ; // returns default if strictness of lexicon is set to WARNING (block and report)
717+ if (!$ this ->matchAndApplyLexiconDefinition ($ userId , $ app , $ key , $ lazy , $ type , default: $ default )) {
718+ // returns default if strictness of lexicon is set to WARNING (block and report)
719+ return $ default ;
716720 }
717721 $ this ->loadConfig ($ userId , $ lazy );
718722
@@ -1046,8 +1050,9 @@ private function setTypedValue(
10461050 ValueType $ type ,
10471051 ): bool {
10481052 $ this ->assertParams ($ userId , $ app , $ key );
1049- if (!$ this ->matchAndApplyLexiconDefinition ($ app , $ key , $ lazy , $ type , $ flags )) {
1050- return false ; // returns false as database is not updated
1053+ if (!$ this ->matchAndApplyLexiconDefinition ($ userId , $ app , $ key , $ lazy , $ type , $ flags )) {
1054+ // returns false as database is not updated
1055+ return false ;
10511056 }
10521057 $ this ->loadConfig ($ userId , $ lazy );
10531058
@@ -1100,7 +1105,8 @@ private function setTypedValue(
11001105 $ inserted = true ;
11011106 } catch (DBException $ e ) {
11021107 if ($ e ->getReason () !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION ) {
1103- throw $ e ; // TODO: throw exception or just log and returns false !?
1108+ // TODO: throw exception or just log and returns false !?
1109+ throw $ e ;
11041110 }
11051111 }
11061112 }
@@ -1195,7 +1201,8 @@ private function setTypedValue(
11951201 public function updateType (string $ userId , string $ app , string $ key , ValueType $ type = ValueType::MIXED ): bool {
11961202 $ this ->assertParams ($ userId , $ app , $ key );
11971203 $ this ->loadConfigAll ($ userId );
1198- $ this ->isLazy ($ userId , $ app , $ key ); // confirm key exists
1204+ // confirm key exists
1205+ $ this ->isLazy ($ userId , $ app , $ key );
11991206
12001207 $ update = $ this ->connection ->getQueryBuilder ();
12011208 $ update ->update ('preferences ' )
@@ -1287,7 +1294,8 @@ public function updateGlobalSensitive(string $app, string $key, bool $sensitive)
12871294 }
12881295 }
12891296
1290- $ this ->clearCacheAll (); // we clear all cache
1297+ // we clear all cache
1298+ $ this ->clearCacheAll ();
12911299 }
12921300
12931301 /**
@@ -1370,7 +1378,8 @@ public function updateGlobalIndexed(string $app, string $key, bool $indexed): vo
13701378 }
13711379 }
13721380
1373- $ this ->clearCacheAll (); // we clear all cache
1381+ // we clear all cache
1382+ $ this ->clearCacheAll ();
13741383 }
13751384
13761385 /**
@@ -1793,6 +1802,14 @@ private function convertTypedValue(string $value, ValueType $type): string|int|f
17931802 }
17941803
17951804
1805+ /**
1806+ * will change referenced $value with the decrypted value in case of encrypted (sensitive value)
1807+ *
1808+ * @param string $userId
1809+ * @param string $app
1810+ * @param string $key
1811+ * @param string $value
1812+ */
17961813 private function decryptSensitiveValue (string $ userId , string $ app , string $ key , string &$ value ): void {
17971814 if (!$ this ->isFlagged (self ::FLAG_SENSITIVE , $ this ->valueDetails [$ userId ][$ app ][$ key ]['flags ' ] ?? 0 )) {
17981815 return ;
@@ -1820,8 +1837,10 @@ private function decryptSensitiveValue(string $userId, string $app, string $key,
18201837 *
18211838 * @throws UnknownKeyException
18221839 * @throws TypeConflictException
1840+ * @return bool FALSE if conflict with defined lexicon were observed in the process
18231841 */
18241842 private function matchAndApplyLexiconDefinition (
1843+ string $ userId ,
18251844 string $ app ,
18261845 string $ key ,
18271846 bool &$ lazy ,
@@ -1837,20 +1856,50 @@ private function matchAndApplyLexiconDefinition(
18371856 /** @var ConfigLexiconEntry $configValue */
18381857 $ configValue = $ configDetails ['entries ' ][$ key ];
18391858 if ($ type === ValueType::MIXED ) {
1840- $ type = $ configValue ->getValueType (); // we overwrite if value was requested as mixed
1859+ // we overwrite if value was requested as mixed
1860+ $ type = $ configValue ->getValueType ();
18411861 } elseif ($ configValue ->getValueType () !== $ type ) {
18421862 throw new TypeConflictException ('The user config key ' . $ app . '/ ' . $ key . ' is typed incorrectly in relation to the config lexicon ' );
18431863 }
18441864
18451865 $ lazy = $ configValue ->isLazy ();
1846- $ default = $ configValue ->getDefault () ?? $ default ; // default from Lexicon got priority
18471866 $ flags = $ configValue ->getFlags ();
1848-
18491867 if ($ configValue ->isDeprecated ()) {
18501868 $ this ->logger ->notice ('User config key ' . $ app . '/ ' . $ key . ' is set as deprecated. ' );
18511869 }
18521870
1853- return true ;
1871+ $ enforcedValue = $ this ->config ->getSystemValue ('lexicon.default.userconfig.enforced ' , [])[$ app ][$ key ] ?? false ;
1872+ if (!$ enforcedValue && $ this ->hasKey ($ userId , $ app , $ key , $ lazy )) {
1873+ // if key exists there should be no need to extract default
1874+ return true ;
1875+ }
1876+
1877+ // default from Lexicon got priority but it can still be overwritten by admin
1878+ $ default = $ this ->getSystemDefault ($ app , $ configValue ) ?? $ configValue ->getDefault () ?? $ default ;
1879+
1880+ // returning false will make get() returning $default and set() not changing value in database
1881+ return !$ enforcedValue ;
1882+ }
1883+
1884+ /**
1885+ * get default value set in config/config.php if stored in key:
1886+ *
1887+ * 'lexicon.default.userconfig' => [
1888+ * <appId> => [
1889+ * <configKey> => 'my value',
1890+ * ]
1891+ * ],
1892+ *
1893+ * The entry is converted to string to fit the expected type when managing default value
1894+ */
1895+ private function getSystemDefault (string $ appId , ConfigLexiconEntry $ configValue ): ?string {
1896+ $ default = $ this ->config ->getSystemValue ('lexicon.default.userconfig ' , [])[$ appId ][$ configValue ->getKey ()] ?? null ;
1897+ if ($ default === null ) {
1898+ // no system default, using default default.
1899+ return null ;
1900+ }
1901+
1902+ return $ configValue ->convertToString ($ default );
18541903 }
18551904
18561905 /**
0 commit comments