Can I save plugin setting as JSON or serialized array?

Can I save plugin setting as JSON or serialized array?

by Juho Jaakkola -
Number of replies: 8

I need to save multiple settings for a plugin.

Instead of having dozens of settings like this:

$CFG->local_foo_property1_type = 'bar';
$CFG->local_foo_property1_value = 'foobar';
$CFG->local_foo_property2_type = 'baz';
$CFG->local_foo_property2_value = 'foo,bar,baz';
etc...

I would like to save them in a single config value for example as a serialized array or JSON:

$settings = json_decode($CFG->local_foo);

$type1 = $settings['property1']['type'];
$value1 = $settings['property1']['value'];
etc...

Is this possible?

Average of ratings: -
In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Juho Jaakkola -

I would like the actual setting page to have multiple different form fields. So an ideal approach would be the ability to process the setting values into a structure of my own liking (and encoding that to JSON) before saving them to the database.

In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Michael Aherne -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers

Hi Juho, there's nothing to stop you doing that, but you probably shouldn't have to. The get_config() and set_config() functions in moodlelib.php allow you to manage multiple configuration values for a plugin.

For example, your code snippets would translate to something like this:

set_config('property1_type', 'bar', 'local_foo');
set_config('property1_value', 'foobar', 'local_foo');
set_config('property2_type', 'baz', 'local_foo');
set_config('property2_value', 'foo,bar,baz', 'local_foo');

and

$settings = get_config('local_foo');
$type1 = $settings->property1_type;
$value1 = $settings->property1_value;
In reply to Michael Aherne

Re: Can I save plugin setting as JSON or serialized array?

by Juho Jaakkola -
Yes, but where and how should I call set_config()?


Currently I have the file local/foo/settings.php which adds a new setting page:

if ($hassiteconfig) {
    $settings = new admin_settingpage('local_foo', get_string('pluginname', 'local_foo'));
    $ADMIN->add('localplugins', $settings);

    etc...

I assume I cannot add the settings page like this if I want to call set_config() manually?

In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Michael Aherne -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers

Ah, I didn't realise you were looking to use multiple settings values to construct a single control, but now I look at your example again I think I understand what you're trying to do. I'm not sure how you'd do that, though, sorry!

In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Darko Miletić -
Yes, you can do whatever is needed in terms of the value, but you need to ensure that proper encoding/decoding is performed wherever is needed.

What people usually use is serialized object encoded in base64 format. Example:
$value = base64_encode(serialize($data));
set_config('configname', $value, 'mypluginname');
data can be simple array or object, as you please. That upon reading you do decoding:
$value = get_config('configname', 'mypluginname');
if ($value !== false) {
$data = unserialize(base64_decode($value));
// Do something.
}


In reply to Darko Miletić

Re: Can I save plugin setting as JSON or serialized array?

by Juho Jaakkola -

Thanks, but there's still the question of how and where to implement the settings page and the code that processes multiple setting inputs into a single setting value.

In what file would you place your code example?

In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Juho Jaakkola -

I was able to achieve this by using the set_updatedcallback() method.

In /local/my_plugin/settings.php:

if ($hassiteconfig) {
    $settings = new admin_settingpage('local_foo', get_string('pluginname', 'local_foo'));
    $ADMIN->add('localplugins', $settings);

    $fields = array('...');

    foreach ($fields as $field) {
        $setting = new admin_setting_whatever("{$field}_name", '...');
        $setting->set_updatedcallback('local_foo_save_values');
        $settings->add($setting);

        $setting = new admin_setting_whatever("{$field}_type", '...');
        $setting->set_updatedcallback('local_foo_save_values');
        $settings->add($setting);
    }
}

In /local/my_plugin/lib.php:

function local_foo_save_values() {
    static $is_processed;

    if ($is_processed) {
        // Run only once per request
        return;
    }

    $fields = array('...');

    $config = array();
    foreach ($fields as $field) {
        $settings = new stdClass();
        $setting->name = required_param("{$field}_name", PARAM_RAW);
        $setting->type = required_param("{$field}_type", PARAM_RAW);
$config[$field][] = $settings; } set_config('fields', json_encode($config), 'local_foo'); $is_processed = true; }


The approach is quite hacky, but it does the trick.

In reply to Juho Jaakkola

Re: Can I save plugin setting as JSON or serialized array?

by Darko Miletić -

That is one way of addressing the issue at hand. Another one would be to create a custom setting class and implement all the logic there.

For example check implementation of admin_setting_configtime located in lib/adminlib.php .