Skip to content

Commit eaae5e1

Browse files
Merge pull request #54158 from nextcloud/feat/preset/profile-visibility+presetmanager
feat(preset): profile visibility
2 parents 8783679 + bbc9ed1 commit eaae5e1

File tree

11 files changed

+127
-62
lines changed

11 files changed

+127
-62
lines changed

core/Command/Config/Preset.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,17 @@
88
*/
99
namespace OC\Core\Command\Config;
1010

11-
use OC\Config\ConfigManager;
11+
use OC\Config\PresetManager;
1212
use OC\Core\Command\Base;
1313
use OCP\Config\Lexicon\Preset as ConfigLexiconPreset;
14-
use OCP\IConfig;
1514
use Symfony\Component\Console\Input\InputArgument;
1615
use Symfony\Component\Console\Input\InputInterface;
1716
use Symfony\Component\Console\Input\InputOption;
1817
use Symfony\Component\Console\Output\OutputInterface;
1918

2019
class Preset extends Base {
2120
public function __construct(
22-
private readonly IConfig $config,
23-
private readonly ConfigManager $configManager,
21+
private readonly PresetManager $presetManager,
2422
) {
2523
parent::__construct();
2624
}
@@ -49,10 +47,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4947
return self::INVALID;
5048
}
5149

52-
$this->configManager->setLexiconPreset($preset);
50+
$this->presetManager->setLexiconPreset($preset);
5351
}
5452

55-
$current = ConfigLexiconPreset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? ConfigLexiconPreset::NONE;
53+
$current = $this->presetManager->getLexiconPreset();
5654
$this->writeArrayInOutputFormat($input, $output, [$current->name], 'current preset: ');
5755
return self::SUCCESS;
5856
}

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,7 @@
12191219
'OC\\Comments\\ManagerFactory' => $baseDir . '/lib/private/Comments/ManagerFactory.php',
12201220
'OC\\Config' => $baseDir . '/lib/private/Config.php',
12211221
'OC\\Config\\ConfigManager' => $baseDir . '/lib/private/Config/ConfigManager.php',
1222+
'OC\\Config\\PresetManager' => $baseDir . '/lib/private/Config/PresetManager.php',
12221223
'OC\\Config\\UserConfig' => $baseDir . '/lib/private/Config/UserConfig.php',
12231224
'OC\\Console\\Application' => $baseDir . '/lib/private/Console/Application.php',
12241225
'OC\\Console\\TimestampFormatter' => $baseDir . '/lib/private/Console/TimestampFormatter.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
12601260
'OC\\Comments\\ManagerFactory' => __DIR__ . '/../../..' . '/lib/private/Comments/ManagerFactory.php',
12611261
'OC\\Config' => __DIR__ . '/../../..' . '/lib/private/Config.php',
12621262
'OC\\Config\\ConfigManager' => __DIR__ . '/../../..' . '/lib/private/Config/ConfigManager.php',
1263+
'OC\\Config\\PresetManager' => __DIR__ . '/../../..' . '/lib/private/Config/PresetManager.php',
12631264
'OC\\Config\\UserConfig' => __DIR__ . '/../../..' . '/lib/private/Config/UserConfig.php',
12641265
'OC\\Console\\Application' => __DIR__ . '/../../..' . '/lib/private/Console/Application.php',
12651266
'OC\\Console\\TimestampFormatter' => __DIR__ . '/../../..' . '/lib/private/Console/TimestampFormatter.php',

lib/private/AppConfig.php

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
use JsonException;
1414
use OC\AppFramework\Bootstrap\Coordinator;
1515
use OC\Config\ConfigManager;
16+
use OC\Config\PresetManager;
1617
use OCP\Config\Lexicon\Entry;
1718
use OCP\Config\Lexicon\ILexicon;
18-
use OCP\Config\Lexicon\Preset;
1919
use OCP\Config\Lexicon\Strictness;
2020
use OCP\Config\ValueType;
2121
use OCP\DB\Exception as DBException;
@@ -27,7 +27,6 @@
2727
use OCP\IConfig;
2828
use OCP\IDBConnection;
2929
use OCP\Security\ICrypto;
30-
use OCP\Server;
3130
use Psr\Log\LoggerInterface;
3231

3332
/**
@@ -66,13 +65,14 @@ class AppConfig implements IAppConfig {
6665
/** @var array<string, array{entries: array<string, Entry>, aliases: array<string, string>, strictness: Strictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */
6766
private array $configLexiconDetails = [];
6867
private bool $ignoreLexiconAliases = false;
69-
private ?Preset $configLexiconPreset = null;
7068
/** @var ?array<string, string> */
7169
private ?array $appVersionsCache = null;
7270

7371
public function __construct(
7472
protected IDBConnection $connection,
7573
protected IConfig $config,
74+
private readonly ConfigManager $configManager,
75+
private readonly PresetManager $presetManager,
7676
protected LoggerInterface $logger,
7777
protected ICrypto $crypto,
7878
) {
@@ -520,8 +520,7 @@ private function getTypedValue(
520520
// interested to check options in case a modification of the value is needed
521521
// ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN
522522
if ($origKey !== $key && $type === self::VALUE_BOOL) {
523-
$configManager = Server::get(ConfigManager::class);
524-
$value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0';
523+
$value = ($this->configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0';
525524
}
526525

527526
return $value;
@@ -1108,7 +1107,7 @@ public function getKeyDetails(string $app, string $key): array {
11081107
$this->assertParams($app, $key);
11091108
try {
11101109
$details = $this->getDetails($app, $key);
1111-
} catch (AppConfigUnknownKeyException $e) {
1110+
} catch (AppConfigUnknownKeyException) {
11121111
$details = [
11131112
'app' => $app,
11141113
'key' => $key
@@ -1129,13 +1128,13 @@ public function getKeyDetails(string $app, string $key): array {
11291128
'valueType' => $lexiconEntry->getValueType(),
11301129
'valueTypeName' => $lexiconEntry->getValueType()->name,
11311130
'sensitive' => $lexiconEntry->isFlagged(self::FLAG_SENSITIVE),
1132-
'default' => $lexiconEntry->getDefault($this->getLexiconPreset()),
1131+
'default' => $lexiconEntry->getDefault($this->presetManager->getLexiconPreset()),
11331132
'definition' => $lexiconEntry->getDefinition(),
11341133
'note' => $lexiconEntry->getNote(),
11351134
]);
11361135
}
11371136

1138-
return array_filter($details);
1137+
return array_filter($details, static fn ($v): bool => ($v !== null));
11391138
}
11401139

11411140
/**
@@ -1228,7 +1227,6 @@ public function deleteApp(string $app): void {
12281227
public function clearCache(bool $reload = false): void {
12291228
$this->lazyLoaded = $this->fastLoaded = false;
12301229
$this->lazyCache = $this->fastCache = $this->valueTypes = $this->configLexiconDetails = [];
1231-
$this->configLexiconPreset = null;
12321230

12331231
if (!$reload) {
12341232
return;
@@ -1714,7 +1712,7 @@ private function matchAndApplyLexiconDefinition(
17141712
$lazy = $lexiconEntry->isLazy();
17151713
// only look for default if needed, default from Lexicon got priority
17161714
if ($default !== null) {
1717-
$default = $lexiconEntry->getDefault($this->getLexiconPreset()) ?? $default;
1715+
$default = $lexiconEntry->getDefault($this->presetManager->getLexiconPreset()) ?? $default;
17181716
}
17191717

17201718
if ($lexiconEntry->isFlagged(self::FLAG_SENSITIVE)) {
@@ -1802,14 +1800,6 @@ public function ignoreLexiconAliases(bool $ignore): void {
18021800
$this->ignoreLexiconAliases = $ignore;
18031801
}
18041802

1805-
private function getLexiconPreset(): Preset {
1806-
if ($this->configLexiconPreset === null) {
1807-
$this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE;
1808-
}
1809-
1810-
return $this->configLexiconPreset;
1811-
}
1812-
18131803
/**
18141804
* Returns the installed versions of all apps
18151805
*

lib/private/Config/ConfigManager.php

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@
1414
use OCP\Config\Exceptions\TypeConflictException;
1515
use OCP\Config\IUserConfig;
1616
use OCP\Config\Lexicon\Entry;
17-
use OCP\Config\Lexicon\Preset;
1817
use OCP\Config\ValueType;
1918
use OCP\IAppConfig;
20-
use OCP\IConfig;
2119
use OCP\Server;
2220
use Psr\Log\LoggerInterface;
2321

@@ -27,20 +25,23 @@
2725
* @since 32.0.0
2826
*/
2927
class ConfigManager {
30-
/** @since 32.0.0 */
31-
public const PRESET_CONFIGKEY = 'config_preset';
32-
3328
/** @var AppConfig|null $appConfig */
3429
private ?IAppConfig $appConfig = null;
3530
/** @var UserConfig|null $userConfig */
3631
private ?IUserConfig $userConfig = null;
3732

3833
public function __construct(
39-
private readonly IConfig $config,
4034
private readonly LoggerInterface $logger,
4135
) {
4236
}
4337

38+
public function clearConfigCaches(): void {
39+
$this->loadConfigServices();
40+
$this->appConfig->clearCache();
41+
$this->userConfig->clearCacheAll();
42+
}
43+
44+
4445
/**
4546
* Use the rename values from the list of ConfigLexiconEntry defined in each app ConfigLexicon
4647
* to migrate config value to a new config key.
@@ -81,17 +82,6 @@ public function migrateConfigLexiconKeys(?string $appId = null): void {
8182
$this->userConfig->ignoreLexiconAliases(false);
8283
}
8384

84-
/**
85-
* store in config.php the new preset
86-
* refresh cached preset
87-
*/
88-
public function setLexiconPreset(Preset $preset): void {
89-
$this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value);
90-
$this->loadConfigServices();
91-
$this->appConfig->clearCache();
92-
$this->userConfig->clearCacheAll();
93-
}
94-
9585
/**
9686
* config services cannot be load at __construct() or install will fail
9787
*/
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OC\Config;
10+
11+
use OCP\Config\Lexicon\Preset;
12+
use OCP\IConfig;
13+
14+
/**
15+
* tools to maintains configurations
16+
*/
17+
class PresetManager {
18+
private const PRESET_CONFIGKEY = 'config_preset';
19+
20+
private ?Preset $configLexiconPreset = null;
21+
22+
public function __construct(
23+
private readonly IConfig $config,
24+
private readonly ConfigManager $configManager,
25+
) {
26+
}
27+
28+
/**
29+
* store in config.php the new preset
30+
* refresh cached preset
31+
*/
32+
public function setLexiconPreset(Preset $preset): void {
33+
$this->config->setSystemValue(self::PRESET_CONFIGKEY, $preset->value);
34+
$this->configLexiconPreset = $preset;
35+
$this->configManager->clearConfigCaches();
36+
}
37+
38+
/**
39+
* returns currently selected Preset
40+
*/
41+
public function getLexiconPreset(): Preset {
42+
if ($this->configLexiconPreset === null) {
43+
$this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(self::PRESET_CONFIGKEY, 0)) ?? Preset::NONE;
44+
}
45+
46+
return $this->configLexiconPreset;
47+
}
48+
}

lib/private/Config/UserConfig.php

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use OCP\Config\IUserConfig;
1919
use OCP\Config\Lexicon\Entry;
2020
use OCP\Config\Lexicon\ILexicon;
21-
use OCP\Config\Lexicon\Preset;
2221
use OCP\Config\Lexicon\Strictness;
2322
use OCP\Config\ValueType;
2423
use OCP\DB\Exception as DBException;
@@ -27,7 +26,6 @@
2726
use OCP\IConfig;
2827
use OCP\IDBConnection;
2928
use OCP\Security\ICrypto;
30-
use OCP\Server;
3129
use Psr\Log\LoggerInterface;
3230

3331
/**
@@ -68,11 +66,12 @@ class UserConfig implements IUserConfig {
6866
/** @var array<string, array{entries: array<string, Entry>, aliases: array<string, string>, strictness: Strictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */
6967
private array $configLexiconDetails = [];
7068
private bool $ignoreLexiconAliases = false;
71-
private ?Preset $configLexiconPreset = null;
7269

7370
public function __construct(
7471
protected IDBConnection $connection,
7572
protected IConfig $config,
73+
private readonly ConfigManager $configManager,
74+
private readonly PresetManager $presetManager,
7675
protected LoggerInterface $logger,
7776
protected ICrypto $crypto,
7877
) {
@@ -772,8 +771,7 @@ private function getTypedValue(
772771
// interested to check options in case a modification of the value is needed
773772
// ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN
774773
if ($origKey !== $key && $type === ValueType::BOOL) {
775-
$configManager = Server::get(ConfigManager::class);
776-
$value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0';
774+
$value = ($this->configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0';
777775
}
778776

779777
return $value;
@@ -1636,7 +1634,6 @@ public function clearCache(string $userId, bool $reload = false): void {
16361634
public function clearCacheAll(): void {
16371635
$this->lazyLoaded = $this->fastLoaded = [];
16381636
$this->lazyCache = $this->fastCache = $this->valueDetails = $this->configLexiconDetails = [];
1639-
$this->configLexiconPreset = null;
16401637
}
16411638

16421639
/**
@@ -1937,7 +1934,7 @@ private function matchAndApplyLexiconDefinition(
19371934

19381935
// only look for default if needed, default from Lexicon got priority if not overwritten by admin
19391936
if ($default !== null) {
1940-
$default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault($this->getLexiconPreset()) ?? $default;
1937+
$default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault($this->presetManager->getLexiconPreset()) ?? $default;
19411938
}
19421939

19431940
// returning false will make get() returning $default and set() not changing value in database
@@ -2039,12 +2036,4 @@ private function getLexiconEntry(string $appId, string $key): ?Entry {
20392036
public function ignoreLexiconAliases(bool $ignore): void {
20402037
$this->ignoreLexiconAliases = $ignore;
20412038
}
2042-
2043-
private function getLexiconPreset(): Preset {
2044-
if ($this->configLexiconPreset === null) {
2045-
$this->configLexiconPreset = Preset::tryFrom($this->config->getSystemValueInt(ConfigManager::PRESET_CONFIGKEY, 0)) ?? Preset::NONE;
2046-
}
2047-
2048-
return $this->configLexiconPreset;
2049-
}
20502039
}

lib/private/Profile/ProfileManager.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
namespace OC\Profile;
1111

1212
use OC\AppFramework\Bootstrap\Coordinator;
13+
use OC\Config\PresetManager;
1314
use OC\Core\Db\ProfileConfig;
1415
use OC\Core\Db\ProfileConfigMapper;
1516
use OC\Core\ResponseDefinitions;
@@ -25,6 +26,7 @@
2526
use OCP\App\IAppManager;
2627
use OCP\AppFramework\Db\DoesNotExistException;
2728
use OCP\Cache\CappedMemoryCache;
29+
use OCP\Config\Lexicon\Preset;
2830
use OCP\IConfig;
2931
use OCP\IUser;
3032
use OCP\L10N\IFactory;
@@ -85,6 +87,7 @@ public function __construct(
8587
private IFactory $l10nFactory,
8688
private LoggerInterface $logger,
8789
private Coordinator $coordinator,
90+
private readonly PresetManager $presetManager,
8891
) {
8992
$this->configCache = new CappedMemoryCache();
9093
}
@@ -315,12 +318,38 @@ private function getDefaultProfileConfig(IUser $targetUser, ?IUser $visitingUser
315318
// Construct the default config for account properties
316319
$propertiesConfig = [];
317320
foreach (self::DEFAULT_PROPERTY_VISIBILITY as $property => $visibility) {
321+
$this->applyDefaultProfilePreset($property, $visibility);
318322
$propertiesConfig[$property] = ['visibility' => $visibility];
319323
}
320324

321325
return array_merge($actionsConfig, $propertiesConfig);
322326
}
323327

328+
/**
329+
* modify property visibility, based on current Preset
330+
*
331+
* @psalm-suppress UnhandledMatchCondition if conditions are not met, we do not change $visibility
332+
*/
333+
private function applyDefaultProfilePreset(string $property, string &$visibility): void {
334+
try {
335+
$overwrite = match ($this->presetManager->getLexiconPreset()) {
336+
Preset::SHARED, Preset::SCHOOL, Preset::UNIVERSITY => match ($property) {
337+
IAccountManager::PROPERTY_ADDRESS, IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_PHONE => self::VISIBILITY_HIDE,
338+
},
339+
Preset::PRIVATE, Preset::FAMILY, Preset::CLUB => match ($property) {
340+
IAccountManager::PROPERTY_EMAIL => self::VISIBILITY_SHOW,
341+
},
342+
Preset::SMALL, Preset::MEDIUM, Preset::LARGE => match ($property) {
343+
IAccountManager::PROPERTY_EMAIL, IAccountManager::PROPERTY_PHONE => self::VISIBILITY_SHOW,
344+
},
345+
};
346+
} catch (\UnhandledMatchError) {
347+
return;
348+
}
349+
350+
$visibility = $overwrite;
351+
}
352+
324353
/**
325354
* Return the profile config of the target user,
326355
* if a config does not already exist a default config is created and returned

0 commit comments

Comments
 (0)