I'm building a plugin and I have hard time handling options on it. I already did try several ways but I think i'm stuck on a structural problem here. I would like to have your input on all of this because I really don't know how to make this smarter.
My main functions about the options are
- get_options() - get the plugin's options. If it is not defined in the options table, get the default option. Override those options with get_presets() : presets have the priority over user defined options. There is a hook to filter the options.
- get_default_options() - the plugin's default options
- get_presets() - get the plugin's presets, which are empty, but external plugins can add presets using a filter hook. If a preset is defined, it will override the matching options and grey out the field in the backend, so the user cannot define a custom value for it.
The questions I have :
- I usually make a check to see if a variable ($options or $options_presets) is already defined. If it is, it is not populated again and the hook is not fired. I made this to make the code faster, but I'm not sure the idea is good ?
- If I try to add presets with the filter hook, the code is usually going crazy (infinite loops and so).
Here's a sample of my code (reduced). I would be glad to have your comments / ideas on it to make it better. Thanks !
class MyPlugin{
var $options = null;
var $options_presets = null;
function get_options($keys = null){
//populate only once
if ( $this->options === null ) {
$default = self::get_default_options();
//1 - override default options with custom options (user defined)
if ($custom = get_post_meta($this->post_id, 'myPluginOptions', true)){
$this->options = array_replace_recursive($default, $custom);
}
//2 - override custom options with presets (presets priority is higher)
if ( $presets = $this->get_presets() ){
$this->options = array_replace_recursive($this->options, $presets);
}
//allow plugins to filter the options when they are populated
$this->options = apply_filters('my_plugin_get_options',$this->options,$this);
}
return self::et_array_value($keys,$this->options);
}
function get_default_options($keys = null){
$defaults = array(...); //default options are set here
return self::get_array_value($keys,$defaults);
}
/**
* Get Presets :
* Allow external plugins to define presets; which will override custom options.
* In the plugin options form, a field will be greyed out if a preset is defined.
*/
function get_presets($keys = null){
//populate only once
if ( $this->options_presets === null ) {
$options = get_post_meta($this->post_id, 'myPluginOptions', true);
//allow plugins to filter the presets when they are populated
$this->options_presets = apply_filters('my_plugin_get_presets',$this->options_presets,$options,$this);
}
return self::get_array_value($keys,$this->options_presets);
}
/**
* Get a value in a multidimensional array
*/
function get_array_value($keys = null, $array){
if (!$keys) return $array;
if (is_string($keys) && isset($array[$keys])) return $array[$keys];
if (!isset($array[$keys[0]])) return false;
if(count($keys) > 1) {
return xspfpl_get_array_value(array_slice($keys, 1), $array[$keys[0]]);
}else{
return $array[$keys[0]];
}
}
}
function add_presets_example($presets,$meta_options,$plugin){
//get options will call get_presets and so the hook my_plugin_get_presets loop and crash the plugin.
//I could eventually unhook - rehook it with :
// remove_filter('my_plugin_get_presets','add_presets_example',10,3);
// add_filter('my_plugin_get_presets','add_presets_example',10,3);
// , but this is extra work and not very clean.
if ($website_url = $plugin->get_options('website_url')) {
...
}
return $presets;
}
add_filter('my_plugin_get_presets','add_presets_example',10,3);