Overview

The new plugin configuration settings support in MT 3.2 takes some getting used to but it is well worth the effort. One of the issues, however, is that for many plugins that have per weblog configuration data, it would be handy to use the system level settings as another level of defaults so that any weblog that wasn’t explicitly configured would use the system settings instead of the hardwired defaults. This turns out to be achievable with a reasonable amount of effort.

Implementation

There are two places which have to be dealt with to achieve the desired effect:

This description presumes that you have created your plugin as a subclass of MT::Plugin as is recommended. The implementation consists of adding two methods to your plugin class and then using those methods elsewhere in the plugin.

Using system settings as weblog defaults

The MT 3.2 distribution has no mechanism for detecting whether a weblog has a specific configuraiton. This can be remedied by putting a subroutine to do that in to your plugin class.

# Return the config object for the scope if it exists, undef otherwise.
sub test_config_obj {
    my $plugin = shift;
    my ($scope_id) = @_;
    my $key;
    my $scope = $scope_id;
    if ($scope && $scope ne 'system') {
        $scope =~ s/:.*//; # strip off id, leave identifier
        $key = 'configuration:'.$scope_id;
    } else {
        $scope_id = 'system';
        $scope = 'system';
        $key = 'configuration';
    }
    # if it's already in the cache, return it.
    return $plugin->{__config_obj}{$scope_id}
      if $plugin->{__config_obj}{$scope_id};
    # otherwise try to load it.
    require MT::PluginData;
    my $pdata_obj = MT::PluginData->load({plugin => $plugin->name(),
					  key => $key});
    # if we succeed in loading, cache it
    $plugin->{__config_obj}{$scope_id} = $pdata_obj if ($pdata_obj);
    return $pdata_obj;
}

This is a modified clone of the get_config_obj subroutine. If the configuration is found, it is cached to make subsequent calls to retrieve it fast. Therefore it’s not a Bad Idea to call the test method and then the get method.

Once this is present, then defaulting to system settings for non-configured weblogs is easy, presuming that $plugin is set to your plugin object.

        if ($plugin->test_config_obj($scope)) {
            $settings = $plugin->get_config_hash($scope);
        } else {
            $settings = $plugin->get_config_hash('system');
        }

After this, $settings is set to the weblogs specific settings, if present, otherwise the system settings or, if those are missing, the hardwired defaults.

My personal preference is to use an “operation” class for my plugin logic that is instantiated when the plugin has to do its work. That class loads up the settings using this logic during construction (in the new subroutine) and caches them for use everywhere else.

Using system settings as default weblog configuration

If a user goes to configure the plugin for a specific weblog and there is no configuration data for that weblog, the defaults loaded in to the configuration interface should be the system defaults because

  • Those are the values that will be used, so to do otherwise is to provide bogus data to the user.
  • If the user wants to tweak, then the starting point should be the system settings if available.

We can do this by overriding the default logic in the base class for our plugin class with this subroutine:

sub apply_default_settings {
    my ($self, $data, $scope_id) = @_;
    # If the defaults are being applied to a weblog, then copy down
    # from the system settings to supply the default values.
    if ($scope_id =~ m/:/) {
        my $system_data = $self->get_config_hash('system');
        foreach (keys %$system_data) {
            $data->{$_} = $system_data->{$_}
              if not exists $data->{$_} or not defined $data->{$_};
        }
    }
    return $self->SUPER::apply_default_settings($data, $scope_id);
}

Other issues that work out automagically

How do I reset a weblog to system defaults?
Just use the “Reset to Defaults” button. What that does is destroy the configuration data for the weblog. After that, the tweaked up default logic will pull in the system settings automagically.
Don't I have to handle creating weblog specific configurations?
No. The base MT logic handles that correctly, once everything else is set up. MT uses the default value logic to populate data for unconfigured weblogs and handles all the scoping automagically. In fact, the plugin for which I worked this out doesn’t even have separate subroutines for the system and weblog configuration templates.