Config sets that instances can share
Some inlay types have several/many instances whose configuration includes a lot of duplication.
Inlay type configuration For example, someone might be using InlayPay to make 3 donation forms for their site, and they have some custom CSS that they want to share between all the instances. Copy-and-pasting this between inlay instances is tedious and error prone. If it could be configured for the Inlay Type, we might not need it on the inlay instance config forms; or those could provide a way to override the system wide default.
Multiple sets of configuration Taking the same example, maybe a site has a bunch of donation forms and a few payment-for-things forms; they want to share config for the payment forms and a different config for the donation forms. The instance config forms could offer to use a configured configuration from a list.
How would this work?
The \Civi\Inlay\Type
subclass that defines the inlay (e.g. Pay), returns an array of schema keys from a getConfigSetNames()
method indicating that this inlay type supports custom sets of configuration. In the example above where we want two sets of CSS styles, the Pay class could return ['stylesets' => 'Styling']
meaning that it defines schemas/has use for sets of configurations for different stylings. The instance configuration form would need to load the names of each type of config it needs (just stylesets
here), and, for example offer a "Styling" drop-down listing the possible configurations.
The main inlay listing page can thereby know to offer a link to a set of configurations for that type. This screen is part of Inlay core extension (this extension).
The type configurations page lists the schemas and configurations that are defined; lets these be deleted, created, edited. Each set has an administrative name like "donation forms" / "shop forms", and a machine name that would be used as the FK from the inlay instance configuration.
It's also feasible that the system could generate type configurations in some business logic process, such as an install/upgrade, or in reaction to some hook or the arrival of certain data types; an instance edit form could include a "create new ... configuration" button for example.
The schema(s) for these type configurations is set by the inlay type which must provide a URL (e.g. angular page) to edit the config sets, much like they do for the main inlay config, one per schema it provides.
Storage
An InlayTypeConfiguration
DAO entity would have fields:
- id (may be referenced as a FK by inlay's own configs)
-
inlay_type (e.g.Prefer namespaced schema.Civi\Inlay\Pay
) - schema (e.g.
inlaypay_styleset
) - setname (e.g.
default
orcampaign_123
) May be referenced as a FK by inlay's own configs. See note below. - label (e.g. 'Donation forms styling')
- config (JSON data)
Then all configurations for a given type and schema could be loaded easily.
Nb. Why use a machine name, why not just use the id as the FK? I thought it possible that the name might be generated and referenced programmatically for some inlays' needs. (note to self: like 'campaigns' in grpet)
Inlay\Type methods
public getConfigSets() :array {
return [
// Something that will be shared between *all* inlays of this type,
// We require one set and one set only.
// The key is the machine name.
'inlaypay_defaults' => [
'label' => 'Shared defaults',
'required' => TRUE,
'multiple' => FALSE,
],
// We might optionally allow sets of CSS
'inlaypay_styleset' => [
'label' => 'Styling type',
'required' => FALSE,
'multiple' => TRUE,
],
// .. ditto for button values.
'inlaypay_button_values' => [
'label' => 'Reusable sets of button value presets',
'required' => FALSE,
'multiple' => TRUE,
]
];
}
/**
* returns all the keys required by a schema, along with default values.
*/
public function getConfigSetDefaults(string $schema) :array {
if ($schema == 'styleset') {
return ['css' => 'body { color: red !important; }'];
}
// ...
}
/**
* (defined on \Civi\Inlay not per-type, typically)
* @var string $schema e.g. inlaypay_
*/
public function fetchConfigSet(string $schema, string $machine_name = 'default') {
$defined = InlayTypeConfiguration::get()
->addWhere('schema', '=', $schema)
// ->addwhere('type', '=', get_class($this)) - we probably use the namespaced schemas instead
->addWhere('name', '=', $machine_name)
->execute()->first() ?? [];
$defaults = $this->getConfigSetDefaults($schema);
// Apply and limit keys to the defaults.
return array_intersect_key($defined, $defaults) + $defaults;
}