Declarative settings

With Nextcloud 29 there is a new way to define app settings in a declarative way. This means that you can just register your settings schema without writing a custom settings handling front-end and back-end code (except when more complex settings logic or design is required).

Registering settings schema

There are two ways to register a declarative settings schema:

  1. Class-based using OCP\Settings\IDeclarativeSettingsForm interface

  2. By using an event listener for the OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent

Additionally, you can register multiple declarative parameter schemes per application.

Class-based schema registration

To register a declarative settings schema using a class, you need to create a class that implements the OCP\Settings\IDeclarativeSettingsForm interface:

The OCP\Settings\IDeclarativeSettingsForm interface has only one method getSchema that should return an array with the settings schema.

After that, you can register schema class using IRegistrationContext->registerDeclarativeSettings method:

Event-based schema registration

To register a declarative settings schema using an event system you need to implement event listener for OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent:

<?php

declare(strict_types=1);

namespace OCA\MyApp\Listener;

use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Settings\DeclarativeSettingsTypes;
use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;

class RegisterDeclarativeSettingsListener implements IEventListener {

    public function __construct() {
    }

    public function handle(Event $event): void {
        if (!($event instanceof DeclarativeSettingsRegisterFormEvent)) {
            return;
        }

        $event->registerSchema('my_app', [
            // your declarative settings schema here
        ]);
    }
}

And register the event listener as usually in your AppInfo/Application.php registration context:

Handling settings storage

There are two types of schema storage_type supported:

1. internal OCP\Settings\DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL - settings values changes handled by core 1. external OCP\Settings\DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL - settings values changes handled by your app handlers (event listeners).

Internal storage type

Internal (storage_type='internal') storage type is handled by core, you don't have to implement additional handlers for that.

Section type admin

For declarative settings schema with section_type set to DeclarativeSettingsTypes::SECTION_TYPE_ADMIN - settings values are stored in appconfig table.

Accessible via OCP\IConfig->getAppValue interface.

Section type personal

For declarative settings schema with section_type set to DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL - settings values are user specific and stored in preferences table.

Accessible via OCP\IConfig->getUserValue interface.

External storage type

Handling of an external (storage_type='external') storage type is always done via listening to the following events:

  1. OCP\Settings\Events\DeclarativeSettingsGetValueEvent - to return the declarative setting value from your storage

  2. OCP\Settings\Events\DeclarativeSettingsSetValueEvent - to save the declarative setting value where you want to

Example of DeclarativeSettingsGetValueEvent event listener:

Example of DeclarativeSettingsSetValueEvent event listener:

Register get/set listeners

Schema field types

Supported field types are declared in OCP\Settings\DeclarativeSettingsTypes class:

The examples of each field type are listed below.

Basic input types

For text, password, email, tel, url, number schema is similar:

Declarative settings input fields (text, password, email, tel, url, number)
[
    'id' => 'my_field_unique_id', // configkey
    'title' => 'Default text field', // label
    'description' => 'Set some simple text setting', // hint
    'type' => DeclarativeSettingsTypes::TEXT, // text, password, email, tel, url, number
    'placeholder' => 'Enter text setting', // placeholder
    'default' => 'foo',
],

Checkbox and Multi-checkbox

checkbox and multi-checkbox field types
[
    'id' => 'my_checkbox_field',
    'title' => 'Toggle something',
    'description' => 'Select checkbox option setting',
    'type' => DeclarativeSettingsTypes::CHECKBOX, // checkbox, multiple-checkbox
    'label' => 'Verify something if enabled',
    'default' => false,
],
[
    'id' => 'my_multicheckbox_field',
    'title' => 'Multiple checkbox toggles, describing one setting, checked options are saved as an JSON object {foo: true, bar: false}',
    'description' => 'Select checkbox option setting',
    'type' => DeclarativeSettingsTypes::MULTI_CHECKBOX, // checkbox, multi-checkbox
    'default' => ['foo' => true, 'bar' => true, 'baz' => true],
    'options' => [
        [
            'name' => 'Foo',
            'value' => 'foo', // multiple-checkbox configkey
        ],
        [
            'name' => 'Bar',
            'value' => 'bar',
        ],
        [
            'name' => 'Baz',
            'value' => 'baz',
        ],
        [
            'name' => 'Qux',
            'value' => 'qux',
        ],
    ],
],

Radio

radio field type
[
    'id' => 'my_radio_field',
    'title' => 'Radio toggles, describing one setting like single select',
    'description' => 'Select radio option setting',
    'type' => DeclarativeSettingsTypes::RADIO, // radio (NcCheckboxRadioSwitch type radio)
    'label' => 'Select single toggle',
    'default' => 'foo',
    'options' => [
        [
            'name' => 'First radio', // NcCheckboxRadioSwitch display name
            'value' => 'foo' // NcCheckboxRadioSwitch value
        ],
        [
            'name' => 'Second radio',
            'value' => 'bar'
        ],
        [
            'name' => 'Third radio',
            'value' => 'baz'
        ],
    ],
],

Select and Multi-select

select field type
[
    'id' => 'my_select_field',
    'title' => 'Selection',
    'description' => 'Select some option setting',
    'type' => DeclarativeSettingsTypes::SELECT, // select, radio, multi-select
    'options' => ['foo', 'bar', 'baz'],
    'placeholder' => 'Select some option setting',
    'default' => 'foo',
],
multi-select field type
[
    'id' => 'my_multi_select_field', // configkey
    'title' => 'Multi-selection', // name or label
    'description' => 'Select some option setting', // hint
    'type' => DeclarativeSettingsTypes::MULTI_SELECT, // select, radio, multi-select
    'options' => ['foo', 'bar', 'baz'], // simple options for select, radio, multi-select
    'placeholder' => 'Select some multiple options', // input placeholder
    'default' => ['foo', 'bar'],
],

Sensitive field type

Since Nextcloud 32 there is a new field attribute sensitive: true/false available for DeclarativeSettingsTypes::TEXT, DeclarativeSettingsTypes::PASSWORD types. The values of such fields are stored in an encrypted form in the database and are not exposed to the UI.

[
    'id' => 'test_sensitive_field',
    'title' => 'Sensitive text field',
    'description' => 'Set some secure value setting that is stored encrypted',
    'type' => DeclarativeSettingsTypes::TEXT,
    'label' => 'Sensitive field',
    'placeholder' => 'Set secure value',
    'default' => '',
    'sensitive' => true, // only for TEXT, PASSWORD types
],
[
    'id' => 'test_sensitive_field_2',
    'title' => 'Sensitive password field',
    'description' => 'Set some password setting that is stored encrypted',
    'type' => DeclarativeSettingsTypes::PASSWORD,
    'label' => 'Sensitive field',
    'placeholder' => 'Set secure value',
    'default' => '',
    'sensitive' => true, // only for TEXT, PASSWORD types
],
sensitive fields