From 56cc5d6dfb252224291e7892e00fb3bbd040207c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 29 Sep 2025 22:21:42 +0200 Subject: [PATCH] feat(setting): Migrate to declarative settings Signed-off-by: Joas Schilling --- js/settings.js | 68 --------------- lib/AppInfo/Application.php | 2 + lib/CheckQuota.php | 65 +++++---------- lib/Job/User.php | 21 ++--- lib/Migration/Install.php | 25 ++---- lib/Migration/Uninstall.php | 19 ++--- lib/Settings.php | 50 ----------- lib/SettingsForm.php | 141 ++++++++++++++++++++++++++++++++ templates/settings.php | 65 --------------- tests/Migration/InstallTest.php | 16 ++-- 10 files changed, 187 insertions(+), 285 deletions(-) delete mode 100644 js/settings.js delete mode 100644 lib/Settings.php create mode 100644 lib/SettingsForm.php delete mode 100644 templates/settings.php diff --git a/js/settings.js b/js/settings.js deleted file mode 100644 index 3d415fb..0000000 --- a/js/settings.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - - -(function(OC, OCA, _) { - OCA.QuotaWarning = { - timeouts: { - 'info_percentage': undefined, - 'warning_percentage': undefined, - 'alert_percentage': undefined - }, - - init: function() { - $('.percentage-option > input').on('change keyup', function() { - var $el = $(this); - OCA.QuotaWarning._saveInput($el); - }); - - $('.email-option > input').on('change', function() { - var $el = $(this); - OCA.QuotaWarning._saveCheckbox($el); - }); - }, - - _saveInput: function($el) { - var field = $el.attr('id').substring(14); - if (!_.isUndefined(this.timeouts[field])) { - clearTimeout(this.timeouts[field]); - } - - this.timeouts[field] = setTimeout(_.bind(this._saveInputHandler, this, field, $el.val()), 750); - }, - - _saveInputHandler: function(field, value) { - OC.msg.startAction('#quota_warning_feedback', t('quota_warning', 'Saving…')); - OCP.AppConfig.setValue( - 'quota_warning', - field, - value, - { - success: function() { - OC.msg.finishedSuccess('#quota_warning_feedback', t('quota_warning', 'Saved!')); - } - } - ); - }, - - _saveCheckbox: function($el) { - OC.msg.startAction('#quota_warning_feedback', t('quota_warning', 'Saving…')); - OCP.AppConfig.setValue( - 'quota_warning', - $el.attr('id').substring(14), - $el.prop('checked') ? 'yes' : 'no', - { - success: function() { - OC.msg.finishedSuccess('#quota_warning_feedback', t('quota_warning', 'Saved!')); - } - } - ); - } - }; -})(OC, OCA, _); - -$(document).ready(function(){ - OCA.QuotaWarning.init(); -}); diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 627cc76..ffd6bc4 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -10,6 +10,7 @@ use OCA\QuotaWarning\Job\User; use OCA\QuotaWarning\Notification\Notifier; +use OCA\QuotaWarning\SettingsForm; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; @@ -25,6 +26,7 @@ public function __construct() { #[\Override] public function register(IRegistrationContext $context): void { + $context->registerDeclarativeSettings(SettingsForm::class); } #[\Override] diff --git a/lib/CheckQuota.php b/lib/CheckQuota.php index 48b0043..085eef5 100644 --- a/lib/CheckQuota.php +++ b/lib/CheckQuota.php @@ -10,6 +10,7 @@ use OCA\QuotaWarning\AppInfo\Application; use OCA\QuotaWarning\Job\User; +use OCP\AppFramework\Services\IAppConfig; use OCP\BackgroundJob\IJobList; use OCP\Files\FileInfo; use OCP\Files\NotFoundException; @@ -22,42 +23,16 @@ use Psr\Log\LoggerInterface; class CheckQuota { - - /** @var IConfig */ - protected $config; - - /** @var LoggerInterface */ - protected $logger; - - /** @var IMailer */ - protected $mailer; - - /** @var IFactory */ - protected $l10nFactory; - - /** @var IUserManager */ - protected $userManager; - - /** @var IJobList */ - protected $jobList; - - /** @var IManager */ - protected $notificationManager; - - public function __construct(IConfig $config, - LoggerInterface $logger, - IMailer $mailer, - IFactory $l10nFactory, - IUserManager $userManager, - IJobList $jobList, - IManager $notificationManager) { - $this->config = $config; - $this->logger = $logger; - $this->mailer = $mailer; - $this->l10nFactory = $l10nFactory; - $this->userManager = $userManager; - $this->jobList = $jobList; - $this->notificationManager = $notificationManager; + public function __construct( + private readonly IAppConfig $appConfig, + private readonly IConfig $config, + private readonly LoggerInterface $logger, + private readonly IMailer $mailer, + private readonly IFactory $l10nFactory, + private readonly IUserManager $userManager, + private readonly IJobList $jobList, + private readonly IManager $notificationManager, + ) { } /** @@ -73,27 +48,27 @@ public function check(string $userId): void { $usage = $this->getRelativeQuotaUsage($userId); - if ($usage > $this->config->getAppValue('quota_warning', 'alert_percentage', '95')) { + if ($usage > $this->appConfig->getAppValueInt('alert_percentage', 95)) { if ($this->shouldIssueWarning($userId, 'alert')) { $this->issueWarning($userId, $usage); - if ($this->config->getAppValue('quota_warning', 'alert_email', 'no') === 'yes') { + if ($this->appConfig->getAppValueBool('alert_email')) { $this->sendEmail($userId, $usage); } } $this->updateLastWarning($userId, 'alert'); - } elseif ($usage > $this->config->getAppValue('quota_warning', 'warning_percentage', '90')) { + } elseif ($usage > $this->appConfig->getAppValueInt('warning_percentage', 90)) { if ($this->shouldIssueWarning($userId, 'warning')) { $this->issueWarning($userId, $usage); - if ($this->config->getAppValue('quota_warning', 'warning_email', 'no') === 'yes') { + if ($this->appConfig->getAppValueBool('warning_email')) { $this->sendEmail($userId, $usage); } } $this->updateLastWarning($userId, 'warning'); $this->removeLastWarning($userId, 'alert'); - } elseif ($usage > $this->config->getAppValue('quota_warning', 'info_percentage', '85')) { + } elseif ($usage > $this->appConfig->getAppValueInt('info_percentage', 85)) { if ($this->shouldIssueWarning($userId, 'info')) { $this->issueWarning($userId, $usage); - if ($this->config->getAppValue('quota_warning', 'info_email', 'no') === 'yes') { + if ($this->appConfig->getAppValueBool('info_email')) { $this->sendEmail($userId, $usage); } } @@ -112,7 +87,7 @@ public function check(string $userId): void { public function getRelativeQuotaUsage(string $userId): float { try { $storage = $this->getStorageInfo($userId); - } catch (NotFoundException $e) { + } catch (NotFoundException) { return 0.0; } @@ -173,7 +148,7 @@ protected function sendEmail(string $userId, float $percentage): void { $emailTemplate->addHeader(); $emailTemplate->addHeading($l->t('Nearing your storage quota'), false); - $link = $this->config->getAppValue('quota_warning', 'plan_management_url'); + $link = $this->appConfig->getAppValueString('plan_management_url'); $help = $l->t('You are using more than %d%% of your storage quota. Try to free up some space by deleting old files you don\'t need anymore.', [$percentage]); if ($link !== '') { @@ -236,7 +211,7 @@ protected function shouldIssueWarning(string $userId, string $level): bool { return true; } - $days = (int)$this->config->getAppValue('quota_warning', 'repeat_warning', '7'); + $days = $this->appConfig->getAppValueInt('repeat_warning', 7); if ($days <= 0) { return false; diff --git a/lib/Job/User.php b/lib/Job/User.php index 1079886..5392e20 100644 --- a/lib/Job/User.php +++ b/lib/Job/User.php @@ -13,24 +13,13 @@ use OCP\BackgroundJob\TimedJob; class User extends TimedJob { - - /** @var CheckQuota */ - protected $checkQuota; - - public function __construct(ITimeFactory $time, - CheckQuota $checkQuota) { + public function __construct( + ITimeFactory $time, + protected CheckQuota $checkQuota, + ) { parent::__construct($time); - $this->checkQuota = $checkQuota; $this->setInterval(86400); - - if (method_exists($this, 'setTimeSensitivity')) { - /** - * This constant is always defined when setTimeSensitivity exists, - * Psalm can not know this :( - * @psalm-suppress UndefinedConstant - */ - $this->setTimeSensitivity(TimedJob::TIME_INSENSITIVE); - } + $this->setTimeSensitivity(self::TIME_INSENSITIVE); } #[\Override] diff --git a/lib/Migration/Install.php b/lib/Migration/Install.php index 6769f4d..cca9844 100644 --- a/lib/Migration/Install.php +++ b/lib/Migration/Install.php @@ -8,33 +8,20 @@ namespace OCA\QuotaWarning\Migration; -use OCA\QuotaWarning\AppInfo\Application; use OCA\QuotaWarning\Job\User; +use OCP\AppFramework\Services\IAppConfig; use OCP\BackgroundJob\IJobList; -use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class Install implements IRepairStep { - - /** @var IUserManager */ - protected $userManager; - - /** @var IJobList */ - protected $jobList; - /** @var IConfig */ - protected $config; - public function __construct( - IUserManager $userManager, - IJobList $jobList, - IConfig $config, + protected IUserManager $userManager, + protected IJobList $jobList, + protected IAppConfig $appConfig, ) { - $this->userManager = $userManager; - $this->jobList = $jobList; - $this->config = $config; } #[\Override] @@ -44,7 +31,7 @@ public function getName(): string { #[\Override] public function run(IOutput $output): void { - if ($this->config->getAppValue(Application::APP_ID, 'initialised', 'no') === 'yes') { + if ($this->appConfig->getAppValueBool('initialised')) { return; } @@ -58,6 +45,6 @@ public function run(IOutput $output): void { }); $output->finishProgress(); - $this->config->setAppValue(Application::APP_ID, 'initialised', 'yes'); + $this->appConfig->setAppValueBool('initialised', true); } } diff --git a/lib/Migration/Uninstall.php b/lib/Migration/Uninstall.php index 14b7754..c9b25f1 100644 --- a/lib/Migration/Uninstall.php +++ b/lib/Migration/Uninstall.php @@ -13,28 +13,19 @@ use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; -/** - * Repair step called when disabling the quota_warning application. This will - * remove all the jobs from the job lists. - * - * @author Carl Schwan - */ class Uninstall implements IRepairStep { - - /** @var IJobList */ - private $jobList; - - public function __construct(IJobList $jobList) { - $this->jobList = $jobList; + public function __construct( + private readonly IJobList $jobList, + ) { } #[\Override] - public function getName() { + public function getName(): string { return 'Remove QuotaWarning background jobs'; } #[\Override] - public function run(IOutput $output) { + public function run(IOutput $output): void { // Remove all the background jobs $this->jobList->remove(User::class); } diff --git a/lib/Settings.php b/lib/Settings.php deleted file mode 100644 index c7abb4c..0000000 --- a/lib/Settings.php +++ /dev/null @@ -1,50 +0,0 @@ -config = $config; - } - - #[\Override] - public function getForm(): TemplateResponse { - $response = new TemplateResponse('quota_warning', 'settings'); - $response->setParams([ - 'info_percentage' => $this->config->getAppValue('quota_warning', 'info_percentage', '85'), - 'info_email' => $this->config->getAppValue('quota_warning', 'info_email', 'no') === 'yes', - 'warning_percentage' => $this->config->getAppValue('quota_warning', 'warning_percentage', '90'), - 'warning_email' => $this->config->getAppValue('quota_warning', 'warning_email', 'no') === 'yes', - 'alert_percentage' => $this->config->getAppValue('quota_warning', 'alert_percentage', '95'), - 'alert_email' => $this->config->getAppValue('quota_warning', 'alert_email', 'no') === 'yes', - 'plan_management_url' => $this->config->getAppValue('quota_warning', 'plan_management_url'), - 'repeat_warning' => $this->config->getAppValue('quota_warning', 'repeat_warning', '7'), - ]); - - return $response; - } - - #[\Override] - public function getSection(): string { - return 'additional'; - } - - #[\Override] - public function getPriority(): int { - return 50; - } -} diff --git a/lib/SettingsForm.php b/lib/SettingsForm.php new file mode 100644 index 0000000..624e2e8 --- /dev/null +++ b/lib/SettingsForm.php @@ -0,0 +1,141 @@ + 'quota_warning', + 'priority' => 50, + 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, + 'section_id' => 'additional', + 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL, + 'title' => $this->l->t('Quota warning'), + 'fields' => [ + [ + 'id' => 'info_percentage', + 'title' => $this->l->t('First notification'), + 'type' => DeclarativeSettingsTypes::NUMBER, + 'default' => 85, + ], + [ + 'id' => 'info_email', + 'title' => '', + 'label' => $this->l->t('Send an email'), + 'type' => DeclarativeSettingsTypes::CHECKBOX, + 'default' => false, + ], + [ + 'id' => 'warning_percentage', + 'title' => $this->l->t('Second notification'), + 'type' => DeclarativeSettingsTypes::NUMBER, + 'default' => 90, + ], + [ + 'id' => 'warning_email', + 'title' => '', + 'label' => $this->l->t('Send an email'), + 'type' => DeclarativeSettingsTypes::CHECKBOX, + 'default' => false, + ], + [ + 'id' => 'alert_percentage', + 'title' => $this->l->t('Final notification'), + 'type' => DeclarativeSettingsTypes::NUMBER, + 'default' => 95, + ], + [ + 'id' => 'alert_email', + 'title' => '', + 'label' => $this->l->t('Send an email'), + 'type' => DeclarativeSettingsTypes::CHECKBOX, + 'default' => false, + ], + [ + 'id' => 'repeat_warning', + 'title' => $this->l->t('Resend notifications after … days'), + 'description' => $this->l->t('Set to 0 if the user should only receive one notification.'), + 'type' => DeclarativeSettingsTypes::NUMBER, + 'default' => 95, + ], + [ + 'id' => 'plan_management_url', + 'title' => $this->l->t('Link to quota management'), + 'type' => DeclarativeSettingsTypes::URL, + 'default' => '', + 'placeholder' => 'https://…' + ], + ] + ]; + } + + #[\Override] + public function getValue(string $fieldId, IUser $user): mixed { + if ($fieldId === 'info_percentage') { + return $this->appConfig->getAppValueInt($fieldId, 85); + } + if ($fieldId === 'warning_percentage') { + return $this->appConfig->getAppValueInt($fieldId, 90); + } + if ($fieldId === 'alert_percentage') { + return $this->appConfig->getAppValueInt($fieldId, 95); + } + if ($fieldId === 'repeat_warning') { + return $this->appConfig->getAppValueInt($fieldId, 7); + } + if (in_array($fieldId, [ + 'info_email', + 'warning_email', + 'alert_email', + ], true)) { + return $this->appConfig->getAppValueBool($fieldId); + } + if ($fieldId === 'plan_management_url') { + return $this->appConfig->getAppValueString($fieldId); + } + return null; + } + + #[\Override] + public function setValue(string $fieldId, mixed $value, IUser $user): void { + if (in_array($fieldId, [ + 'info_percentage', + 'warning_percentage', + 'alert_percentage', + 'repeat_warning', + ], true)) { + if ($value >= 0 && ($value <= 100 || $fieldId === 'repeat_warning')) { + $this->appConfig->setAppValueInt($fieldId, (int)$value); + } + } elseif (in_array($fieldId, [ + 'info_email', + 'warning_email', + 'alert_email', + ], true)) { + $this->appConfig->setAppValueBool($fieldId, (bool)$value); + } elseif ($fieldId === 'plan_management_url') { + $this->appConfig->setAppValueString($fieldId, (string)$value); + } + + } + +} diff --git a/templates/settings.php b/templates/settings.php deleted file mode 100644 index 30bac9d..0000000 --- a/templates/settings.php +++ /dev/null @@ -1,65 +0,0 @@ - - -
-

- t('Quota warning')); ?> -

- - -

- - -

- - -

- - -

- - -

- - -

- - -

- - -

- -

- - - t('Set to 0 if the user should only receive one notification.')) ?> -

-
diff --git a/tests/Migration/InstallTest.php b/tests/Migration/InstallTest.php index de6f6b4..775d535 100644 --- a/tests/Migration/InstallTest.php +++ b/tests/Migration/InstallTest.php @@ -10,8 +10,8 @@ use OCA\QuotaWarning\Job\User; use OCA\QuotaWarning\Migration\Install; +use OCP\AppFramework\Services\IAppConfig; use OCP\BackgroundJob\IJobList; -use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; use OCP\Migration\IOutput; @@ -20,7 +20,7 @@ class InstallTest extends \Test\TestCase { protected IUserManager&MockObject $userManager; protected IJobList&MockObject $jobList; - protected IConfig&MockObject $config; + protected IAppConfig&MockObject $appConfig; protected Install $migration; protected function setUp(): void { @@ -28,12 +28,12 @@ protected function setUp(): void { $this->userManager = $this->createMock(IUserManager::class); $this->jobList = $this->createMock(IJobList::class); - $this->config = $this->createMock(IConfig::class); + $this->appConfig = $this->createMock(IAppConfig::class); $this->migration = new Install( $this->userManager, $this->jobList, - $this->config + $this->appConfig, ); } @@ -88,10 +88,10 @@ public function testRunSkipped(): void { $output->expects($this->never()) ->method('finishProgress'); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('quota_warning', 'initialised', 'no') - ->willReturn('yes'); + $this->appConfig->expects($this->once()) + ->method('getAppValueBool') + ->with('initialised') + ->willReturn(true); $this->userManager->expects($this->never()) ->method('callForSeenUsers');