Skip to content

Instantly share code, notes, and snippets.

@schlessera
Last active September 7, 2015 08:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schlessera/4022b525336084cea5b2 to your computer and use it in GitHub Desktop.
Save schlessera/4022b525336084cea5b2 to your computer and use it in GitHub Desktop.
Simple WordPress Settings API class example.

This is an example for a WordPress Settings API class.

It will not run in the present state, as it is coupled to other stuff in my core library, but it should nevertheless be able to serve as a demonstration of how to keep the configuration DRY.

<?php
/**
* OrderedInvokeTrait
*
* @package BrightNucleus_Core
* @author Alain Schlesser <alain.schlesser@gmail.com>
* @license GPL-2.0+
* @link http://www.brightnucleus.com/
* @copyright 2015 Alain Schlesser, Bright Nucleus
*/
namespace BrightNucleus\Core\Traits;
/**
* Trait to make the ordered_invoke function easily accessible inside classes.
*
* @since 1.0.0
*/
trait OrderedInvoke {
/**
* Check the accepted arguments for a given function and pass associative
* array values in the right order.
*
* @since 1.0.0
*
* @param string $function Name of the function to invoke.
* @param array $args Associative array that contains the arguments.
* @return mixed Return value of the invoked function.
*/
public function ordered_invoke( $function, array $args = array() ) {
$reflection = new \ReflectionFunction( $function );
$pass = array();
foreach ( $reflection->getParameters() as $param ) {
if ( isset( $args[ $param->getName() ] ) ) {
$pass[] = $args[ $param->getName() ];
} else {
$pass[] = $param->getDefaultValue();
}
}
return $reflection->invokeArgs( $pass );
}
}
<?php
/**
* Settings Module
*
* @package BrightNucleus_Core
* @author Alain Schlesser <alain.schlesser@gmail.com>
* @license GPL-2.0+
* @link http://www.brightnucleus.com/
* @copyright 2015 Alain Schlesser, Bright Nucleus
*/
namespace BrightNucleus\Core;
use BrightNucleus\Core\Base\AbstractModule;
use BrightNucleus\Core\Traits\OrderedInvoke;
use BrightNucleus\Core\Contracts\Config as ConfigInterface;
use BrightNucleus\Core\Contracts\Controller as ControllerInterface;
/**
* Settings screen in the admin dashboard.
*
* @since 1.0.0
*
* @package BrightNucleus_Core
* @author Alain Schlesser <alain.schlesser@gmail.com>
*/
class Settings extends AbstractModule {
use OrderedInvoke;
/**
* Hooks to the settings pages that have been registered.
*
* @since 1.0.0
*
* @var array
*/
protected $page_hooks = array();
/**
* Instantiate Settings object.
*
* @since 1.0.0
*
* @param ConfigInterface $config Configuration object.
* @param ControllerInterface $controller Controller instance.
*/
public function __construct( ConfigInterface $config, ControllerInterface $controller ) {
parent::__construct( $config, $controller );
}
/**
* Register necessary hooks
*
* @since 1.0.0
*/
public function register() {
add_action( 'admin_menu', [ $this, 'add_pages' ] );
add_action( 'admin_init', [ $this, 'init_settings' ] );
}
/**
* Add the pages from the configuration settings to the WordPress admin backend.
*
* @since 1.0.0
*/
public function add_pages() {
array_walk( $this->config['menu_pages'], [ $this, 'add_page' ], 'add_menu_page' );
array_walk( $this->config['submenu_pages'], [ $this, 'add_page' ], 'add_submenu_page' );
}
/**
* Add a single page to the WordPress admin backend.
*
* @since 1.0.0
*
* @param array $data Arguments for page creation function.
* @param string $key Current page name.
* @param string $function Page creation function to be used. Must be either
* 'add_menu_page' or 'add_submenu_page'.
*/
public function add_page( $data, $key, $function ) {
// Skip page creation if it already exists. This allows reuse of 1 page
// for several plugins.
if ( empty( $GLOBALS['admin_page_hooks'][ $data['menu_slug'] ] ) ) {
$data['function'] = function () use ( $data ) {
include( $data['view'] );
};
$page_hook = $this->ordered_invoke( $function, $data );
$this->page_hooks[] = $page_hook;
}
}
/**
* Initialize the settings page.
*
* @since 1.0.0
*/
public function init_settings() {
array_walk( $this->config['settings'], [ $this, 'add_setting' ] );
}
/**
* Add option groups.
*
* @since 1.0.0
*
* @param array $setting_data Arguments for the register_setting WP function.
* @param string $setting_name Name of the option group.
*/
public function add_setting( $setting_data, $setting_name ) {
register_setting( $setting_data['option_group'], $setting_name, $setting_data['sanitize_callback'] );
// Prepare array to pass to array_walk as third parameter.
$args['setting_name'] = $setting_name;
$args['page'] = $setting_data['option_group'];
array_walk( $setting_data['sections'], [ $this, 'add_section' ], $args );
}
/**
* Add options section.
*
* @since 1.0.0
*
* @param array $section_data Arguments for the add_settings_section WP function.
* @param string $section_name Name of the option section.
* @param string $args Additional arguments to pass on.
*/
public function add_section( $section_data, $section_name, $args ) {
add_settings_section(
$section_name,
$section_data['title'],
function () use ( $section_data ) {
include( $section_data['view'] );
},
$args['page']
);
// Extend array to pass to array_walk as third parameter.
$args['section'] = $section_name;
array_walk( $section_data['fields'], [ $this, 'add_field' ], $args );
}
/**
* Add options field.
*
* @since 1.0.0
*
* @param array $field_data Arguments for the add_settings_field WP function.
* @param string $field_name Name of the settings field.
* @param array $args Contains both page and section name.
*/
public function add_field( $field_data, $field_name, $args ) {
add_settings_field(
$field_name,
$field_data['title'],
function () use ( $field_data, $args ) {
// Fetch $options to pass into view.
$options = get_option( $args['setting_name'] );
include( $field_data['view'] );
},
$args['page'],
$args['section']
);
}
}
<?php
/**
* Config file for the Settings class.
*
* @package BN_SETTINGS_Sample_Plugin
* @author Alain Schlesser <alain.schlesser@gmail.com>
* @license GPL-2.0+
* @link http://www.brightnucleus.com/
* @copyright 2015 Alain Schlesser, Bright Nucleus
*/
namespace BrightNucleus\SettingsSamplePlugin;
return [
// Top-level pages
'menu_pages' => [],
// Second-level pages
'submenu_pages' => [
[
'parent_slug' => 'options-general.php',
'page_title' => _x( 'Settings Sample Plugin', 'Admin Menu: Page Title', 'bn_settings_sample_plugin' ),
'menu_title' => _x( 'Settings Sample Plugin', 'Admin Menu: Menu Title', 'bn_settings_sample_plugin' ),
'capability' => 'manage_options',
'menu_slug' => 'bn-settings-sample-plugin-options',
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/options/subpage-options.php',
],
[
'parent_slug' => 'tools.php',
'page_title' => _x( 'Settings Sample Plugin - Tool', 'Admin Menu: Page Title', 'bn_settings_sample_plugin' ),
'menu_title' => _x( 'Import Settings Sample Plugin', 'Admin Menu: Menu Title', 'bn_settings_sample_plugin' ),
'capability' => 'manage_options',
'menu_slug' => 'bn-settings-sample-plugin-tools',
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/sync/subpage-tools.php',
],
],
'settings' => [
'BN_SETTINGS_Sample_Plugin_Options' => [
'option_group' => 'BN_SETTINGS_Sample_Plugin_Options',
'sanitize_callback' => null,
'sections' => [
'BN_SETTINGS_Sample_Plugin_Options_Section' => [
'title' => __( 'Settings Sample Plugin Items', 'bn_settings_sample_plugin' ),
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/options/section-api.php',
'fields' => [
'BN_SETTINGS_Sample_Plugin_API_URL' => [
'title' => __( 'API URL', 'bn_settings_sample_plugin' ),
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/options/field-api-url.php',
],
'BN_SETTINGS_Sample_Plugin_App_Key' => [
'title' => __( 'App Key', 'bn_settings_sample_plugin' ),
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/options/field-app-key.php',
],
'BN_SETTINGS_Sample_Plugin_App_Secret' => [
'title' => __( 'App Secret', 'bn_settings_sample_plugin' ),
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/options/field-app-secret.php',
],
],
],
],
],
'BN_SETTINGS_Sample_Plugin_Tools' => [
'option_group' => 'BN_SETTINGS_Sample_Plugin_Tools',
'sanitize_callback' => null,
'sections' => [
'BN_SETTINGS_Sample_Plugin_Tools_Section' => [
'title' => __( 'Settings Sample Plugin Importer', 'bn_settings_sample_plugin' ),
'view' => BN_SETTINGS_Sample_Plugin_DIR . 'views/admin/tools/section-api.php',
'fields' => [],
],
],
],
],
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment