Ajustes declarativos¶
Resumen¶
Esta página explica cómo definir los ajustes de una app de forma declarativa: cómo registrar el esquema con una clase o con un listener de eventos, cómo se almacenan los valores de forma interna o externa y qué tipos de campo admite el esquema, con un ejemplo de cada uno. Está dirigida a quienes desarrollan apps.
Fuente: documentación de Nextcloud, «developer_manual/digging_deeper/declarative_settings», versión 3ad9158, licencia CC BY 3.0; traducida y adaptada para APS Conecta Gestión.
Nuevo en la versión 29.0.0.
Con APS Conecta Gestión 29 hay una nueva forma de definir los ajustes de una app de manera declarativa. Esto significa que basta con registrar el esquema de ajustes, sin escribir código personalizado de frontend ni de backend para gestionar los ajustes (salvo cuando se requiere una lógica o un diseño de ajustes más complejos).
Registrar el esquema de ajustes¶
Hay dos formas de registrar un esquema de ajustes declarativos:
Basada en clases, usando la interfaz
OCP\Settings\IDeclarativeSettingsFormUsando un listener de eventos para
OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent
Además, se pueden registrar varios esquemas de parámetros declarativos por aplicación.
Nota
Los ids de los campos del formulario (configkeys) deben ser únicos dentro de una app.
Registro del esquema basado en clases¶
Para registrar un esquema de ajustes declarativos mediante una clase, hay que crear una clase que implemente la interfaz OCP\Settings\IDeclarativeSettingsForm:
<?php
declare(strict_types=1);
namespace OCA\MyApp\DeclarativeSettings;
use OCP\Settings\DeclarativeSettingsTypes;
use OCP\Settings\IDeclarativeSettingsForm;
class MyDeclarativeSettingsForm implements IDeclarativeSettingsForm {
public function getSchema(): array {
return [
'id' => 'my_declarative_settings_form', // unique form id
'priority' => 10, // declarative section priority (ordering)
'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, // admin, personal
'section_id' => 'my_section_id', // existing section id or your custom section id
'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL, // external, internal (handled by core to store in appconfig and preferences)
'title' => 'MyApp settings title', // NcSettingsSection name
'description' => 'My app settings section description', // NcSettingsSection description
'doc_url' => '', // NcSettingsSection doc_url for documentation or help page, empty string if not needed
'fields' => [
[
'id' => 'my_field_key', // configkey
'title' => 'Field title', // name or label
'description' => 'Additional setting hint or description', // hint
'type' => DeclarativeSettingsTypes::MULTI_SELECT,
'options' => ['foo', 'bar', 'baz'],
'placeholder' => 'Select some multiple options', // input placeholder
'default' => ['foo', 'bar'],
],
]
];
}
}
La interfaz OCP\Settings\IDeclarativeSettingsForm tiene un solo método, getSchema, que debe devolver un array con el esquema de ajustes.
Después se puede registrar la clase del esquema con el método IRegistrationContext->registerDeclarativeSettings:
<?php
declare(strict_types=1);
namespace OCA\MyApp\AppInfo;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCA\MyApp\DeclarativeSettings\MyDeclarativeSettingsForm;
class Application extends App {
public function __construct(array $urlParams = []) {
parent::__construct('my_app', $urlParams);
}
public function register(IRegistrationContext $context): void {
$context->registerDeclarativeSettings(MyDeclarativeSettingsForm::class);
}
}
Registro del esquema basado en eventos¶
Para registrar un esquema de ajustes declarativos mediante el sistema de eventos, hay que implementar un listener de eventos para 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
]);
}
}
Y registrar el listener de eventos como de costumbre en el contexto de registro de AppInfo/Application.php:
<?php
declare(strict_types=1);
namespace OCA\MyApp\AppInfo;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent;
use OCA\MyApp\Listener\RegisterDeclarativeSettingsListener;
class Application extends App {
public function __construct(array $urlParams = []) {
parent::__construct('my_app', $urlParams);
}
public function register(IRegistrationContext $context): void {
$context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, RegisterDeclarativeSettingsListener::class);
}
}
Gestionar el almacenamiento de los ajustes¶
Se admiten dos tipos de storage_type del esquema:
interno
OCP\Settings\DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL- los cambios de los valores de los ajustes los gestiona el núcleoexterno
OCP\Settings\DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL- los cambios de los valores de los ajustes los gestionan los manejadores de la app (listeners de eventos).
Tipo de almacenamiento interno¶
El tipo de almacenamiento interno (storage_type='internal') lo gestiona el núcleo; no hace falta implementar manejadores adicionales para él.
Tipo de sección admin¶
Para un esquema de ajustes declarativos con section_type establecido en DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, los valores de los ajustes
se almacenan en la tabla appconfig.
Accesibles mediante la interfaz OCP\IConfig->getAppValue.
Tipo de sección personal¶
Para un esquema de ajustes declarativos con section_type establecido en DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL, los valores de los ajustes
son específicos de cada usuario y se almacenan en la tabla preferences.
Accesibles mediante la interfaz OCP\IConfig->getUserValue.
Tipo de almacenamiento externo¶
La gestión de un tipo de almacenamiento externo (storage_type='external') se hace siempre escuchando los siguientes eventos:
OCP\Settings\Events\DeclarativeSettingsGetValueEvent- para devolver el valor del ajuste declarativo desde el almacenamiento propioOCP\Settings\Events\DeclarativeSettingsSetValueEvent- para guardar el valor del ajuste declarativo donde se quiera
Ejemplo de listener del evento DeclarativeSettingsGetValueEvent:
<?php
declare(strict_types=1);
namespace OCA\MyApp\Listener;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IConfig;
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
class GetDeclarativeSettingsValueListener implements IEventListener {
public function __construct(private IConfig $config) {
}
public function handle(Event $event): void {
if (!$event instanceof DeclarativeSettingsGetValueEvent) {
return;
}
// Always check if the event is related to your app declarative settings
if ($event->getApp() !== 'my_app') {
return;
}
$value = $this->config->getUserValue($event->getUser()->getUID(), $event->getApp(), $event->getFieldId());
$event->setValue($value);
}
}
Ejemplo de listener del evento DeclarativeSettingsSetValueEvent:
<?php
declare(strict_types=1);
namespace OCA\MyApp\Listener;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IConfig;
use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
class SetDeclarativeSettingsValueListener implements IEventListener {
public function __construct(private IConfig $config) {
}
public function handle(Event $event): void {
if (!$event instanceof DeclarativeSettingsSetValueEvent) {
return;
}
// Always check if the event is related to your app declarative settings
if ($event->getApp() !== 'my_app') {
return;
}
$this->config->setUserValue($event->getUser()->getUID(), $event->getApp(), $event->getFieldId(), $event->getValue());
}
}
Registrar los listeners get/set¶
<?php
declare(strict_types=1);
namespace OCA\MyApp\AppInfo;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
use OCA\MyApp\Listener\GetDeclarativeSettingsValueListener;
use OCA\MyApp\Listener\SetDeclarativeSettingsValueListener;
class Application extends App {
public function __construct(array $urlParams = []) {
parent::__construct('my_app', $urlParams);
}
public function register(IRegistrationContext $context): void {
$context->registerEventListener(DeclarativeSettingsGetValueEvent::class, GetDeclarativeSettingsValueListener::class);
$context->registerEventListener(DeclarativeSettingsSetValueEvent::class, SetDeclarativeSettingsValueListener::class);
}
}
Tipos de campo del esquema¶
Los tipos de campo admitidos se declaran en la clase OCP\Settings\DeclarativeSettingsTypes:
DeclarativeSettingsTypes::TEXT- input de tipo textDeclarativeSettingsTypes::PASSWORD- input de tipo passwordDeclarativeSettingsTypes::EMAIL- input de tipo emailDeclarativeSettingsTypes::TEL- input de tipo telDeclarativeSettingsTypes::URL- input de tipo urlDeclarativeSettingsTypes::NUMBER- input de tipo numberDeclarativeSettingsTypes::CHECKBOX- input de tipo checkboxDeclarativeSettingsTypes::MULTI_CHECKBOX- varias casillas de verificación que representan un ajuste con varias opcionesDeclarativeSettingsTypes::RADIO- input de tipo radio para un ajuste con una sola opciónDeclarativeSettingsTypes::SELECT- input de tipo select para un ajuste con una sola opciónDeclarativeSettingsTypes::MULTI_SELECT- input de tipo select para un ajuste con varias opciones
A continuación se listan los ejemplos de cada tipo de campo.
Nota
El orden de los campos es el mismo que en el array del esquema.
Tipos de input básicos¶
Para text, password, email, tel, url y number, el esquema es similar:
[
'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',
],
Casilla de verificación y casillas de verificación múltiples¶
[
'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¶
[
'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'
],
],
],
Selección y selección múltiple¶
[
'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',
],
[
'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'],
],
Tipo de campo sensible¶
Desde APS Conecta Gestión 32 hay un nuevo atributo de campo, sensitive: true/false, disponible para los tipos DeclarativeSettingsTypes::TEXT y DeclarativeSettingsTypes::PASSWORD.
Los valores de estos campos se almacenan cifrados en la base de datos y no se exponen en la interfaz de usuario.
[
'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
],