Last active
February 21, 2024 21:34
-
-
Save igorbenic/21f56a48938a04fbd8fd74eb5ef251ae to your computer and use it in GitHub Desktop.
How to build WordPress Settings API as Framework | ibenic.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
/** | |
* Setting ID. Prefixes all options. | |
* @var string | |
*/ | |
protected $id = ''; | |
/** | |
* @var string | |
*/ | |
protected $page_title = ''; | |
/** | |
* @var string | |
*/ | |
protected $menu_title = ''; | |
/** | |
* @var string | |
*/ | |
protected $parent_menu = ''; | |
/** | |
* Settings Fields. | |
* @var array | |
*/ | |
protected $fields = []; | |
public function __construct() { | |
add_action( 'admin_menu', [ $this, 'register_page' ] ); | |
add_action( 'admin_init', [ $this, 'register_fields' ] ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// .. code before | |
public function register_page() { | |
if ( $this->parent_menu ) { | |
add_submenu_page( | |
$this->parent_menu, | |
$this->page_title, | |
$this->menu_title ?: $this->page_title, | |
'manage_options', | |
$this->id . '_settings_page', | |
[ $this, 'render_page'] | |
); | |
} else { | |
add_menu_page( | |
$this->page_title, | |
$this->menu_title ?: $this->page_title, | |
'manage_options', | |
$this->id . '_settings_page', | |
[ $this, 'render_page'] | |
); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
public function render_page() { | |
?> | |
<div class="wrap"> | |
<div id="icon-options-general" class="icon32"><br></div> | |
<h2><?php echo $this->page_title; ?></h2> | |
<form action="options.php" method="post"> | |
<?php | |
do_action( $this->id . '_settings_before_options' ); | |
// Prepare form to handle current page. | |
settings_fields( $this->id . '_settings_page' ); | |
// Render fields and sections. | |
do_settings_sections( $this->id . '_settings_page' ); | |
do_action( 'pmpro_' . $this->id . '_settings_before_submit_button' ); | |
submit_button( __( 'Save Settings', 'your_textdomain' ) ); | |
do_action( $this->id . '_settings_after_submit_button' ); | |
?> | |
</form> | |
<?php do_action( $this->id . '_settings_after_form' ); ?> | |
</div> | |
<?php | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before... | |
public function get_settings_id() { | |
return $this->id; | |
} | |
public function add_field( $field ) { | |
$this->fields = array_merge( $this->fields, $field ); | |
} | |
/** | |
* Get Settings Fields. | |
* | |
* @return mixed|null | |
*/ | |
public function get_fields() { | |
return apply_filters( $this->id . '_get_fields', $this->fields ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
/** | |
* Register Fields | |
* | |
* @return void | |
*/ | |
public function register_fields() { | |
$fields = $this->get_fields(); | |
register_setting( | |
$this->id . '_settings_page', | |
$this->id . '_options', | |
[ | |
'sanitize_callback' => [ $this, 'sanitize' ] | |
] | |
); | |
foreach ( $fields as $field ) { | |
if ( 'section' === $field['type'] ) { | |
add_settings_section( | |
$this->id . '_' . $field['name'] . '_section', | |
$field['title'], | |
[ $this, 'render_section' ], | |
$this->id . '_settings_page', | |
$field | |
); | |
} else { | |
add_settings_field( | |
$this->id . '_' . $field['name'], | |
$field['title'], | |
[ $this, 'render_field' ], | |
$this->id . '_settings_page', | |
$this->id . '_' . $field['section'] . '_section', | |
$field | |
); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
/** | |
* Get option key. Useful for name attributes in forms. | |
* | |
* @param string $key Field Name. | |
* @return string | |
*/ | |
public function get_option_key( $key ) { | |
return $this->id . '_options[' . $key . ']'; | |
} | |
/** | |
* Get Option | |
* | |
* @param string $id Field Name | |
* @param mixed $default Default value if we don't have anything saved. | |
* @return mixed|string | |
*/ | |
public function get_option( $id, $default = '' ) { | |
$options = get_option( $this->id . '_options' ); | |
return isset( $options[ $id ] ) ? $options[ $id ] : $default; | |
} | |
public function render_section( $args ) { | |
if ( ! empty( $args['description'] ) ) { | |
?> | |
<p class="description"><?php echo wp_kses_post( $args['description'] ); ?></p> | |
<?php | |
} | |
} | |
/** | |
* Render Field | |
* @param array $args Field Arguments. | |
* @return void | |
*/ | |
public function render_field( $args ) { | |
$this->{'render_' . $args['type'] }( $args ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
public function sanitize( $input ) { | |
$fields = $this->get_fields(); | |
foreach ( $fields as $field ) { | |
// No need to sanitize sections. | |
if ( 'section' === $field['type'] ) { | |
continue; | |
} | |
if ( ! isset( $input[ $field['name'] ] ) ) { | |
continue; | |
} | |
switch ( $field['type'] ) { | |
case 'text': | |
$input[ $field['name'] ] = sanitize_text_field( $input[ $field['name'] ] ); | |
break; | |
} | |
} | |
do_action( $this->id . '_settings_sanitized', $input, $fields, $_POST, $this ); | |
return $input; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
/** | |
* Render Text input | |
* | |
* @param $args | |
* @return void | |
*/ | |
public function render_text( $args ) { | |
$default = ! empty( $args['default'] ) ? $args['default'] : ''; | |
?> | |
<input type="text" class="widefat" name="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" value="<?php echo esc_attr( $this->get_option( $args['name'], $default ) ); ?>" /> | |
<?php | |
if ( ! empty( $args['description'] ) ) { | |
?> | |
<p class="description"><?php echo esc_html( $args['description'] ); ?></p> | |
<?php | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
// code before ... | |
/** | |
* Render Checkbox input | |
* | |
* @param $args | |
* @return void | |
*/ | |
public function render_checkbox( $args ) { | |
$option_checked = $this->get_option($args['name']); | |
?> | |
<label for="<?php echo esc_attr($this->get_option_key($args['name'])); ?>"> | |
<input <?php checked( $option_checked, 1, true ); ?> id="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" type="checkbox" name="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" value="1" /> | |
<?php echo esc_html( $args['description'] ); ?> | |
</label> | |
<?php | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MySettingsFramework; | |
include_once 'path/to/class/class-settings.php'; | |
include_once 'path/to/class/class-page.php'; | |
new Page(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
class Page extends Settings { | |
public function __construct() { | |
$this->id = 'my_page'; | |
$this->page_title = 'My Page'; | |
$this->menu_title = 'Page'; | |
$this->define_fields(); | |
parent::__construct(); | |
} | |
protected function define_fields() { | |
$this->fields['my_section'] = [ | |
'name' => 'my_section', | |
'title' => 'My Custom Section', | |
'description' => 'My Custom Description', | |
'type' => 'section' | |
]; | |
$this->fields['my_text'] = [ | |
'name' => 'my_text', | |
'title' => 'My Text Field', | |
'description' => 'My Field Description', | |
'type' => 'text', | |
'section' => 'my_section' | |
]; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace MySettingsFramework; | |
abstract class Settings { | |
/** | |
* Setting ID. Prefixes all options. | |
* @var string | |
*/ | |
protected $id = ''; | |
/** | |
* @var string | |
*/ | |
protected $page_title = ''; | |
/** | |
* @var string | |
*/ | |
protected $menu_title = ''; | |
/** | |
* @var string | |
*/ | |
protected $parent_menu = ''; | |
/** | |
* Settings Fields. | |
* @var array | |
*/ | |
protected $fields = []; | |
public function __construct() { | |
add_action( 'admin_menu', [ $this, 'register_page' ] ); | |
add_action( 'admin_init', [ $this, 'register_fields' ] ); | |
} | |
public function register_page() { | |
if ( $this->parent_menu ) { | |
add_submenu_page( | |
$this->parent_menu, | |
$this->page_title, | |
$this->menu_title ?: $this->page_title, | |
'manage_options', | |
$this->id . '_settings_page', | |
[ $this, 'render_page'] | |
); | |
} else { | |
add_menu_page( | |
$this->page_title, | |
$this->menu_title ?: $this->page_title, | |
'manage_options', | |
$this->id . '_settings_page', | |
[ $this, 'render_page'] | |
); | |
} | |
} | |
public function render_page() { | |
?> | |
<div class="wrap"> | |
<div id="icon-options-general" class="icon32"><br></div> | |
<h2><?php echo $this->page_title; ?></h2> | |
<form action="options.php" method="post"> | |
<?php | |
do_action( $this->id . '_settings_before_options' ); | |
settings_fields( $this->id . '_settings_page' ); | |
do_settings_sections( $this->id . '_settings_page' ); | |
do_action( 'pmpro_' . $this->id . '_settings_before_submit_button' ); | |
submit_button( __( 'Save Settings', 'your_textdomain' ) ); | |
do_action( $this->id . '_settings_after_submit_button' ); | |
?> | |
</form> | |
<?php do_action( $this->id . '_settings_after_form' ); ?> | |
</div> | |
<?php | |
} | |
public function get_settings_id() { | |
return $this->id; | |
} | |
public function add_field( $field ) { | |
$this->fields = array_merge( $this->fields, $field ); | |
} | |
/** | |
* Get Settings Fields. | |
* | |
* @return mixed|null | |
*/ | |
public function get_fields() { | |
return apply_filters( $this->id . '_get_fields', $this->fields ); | |
} | |
/** | |
* Register Fields | |
* | |
* @return void | |
*/ | |
public function register_fields() { | |
$fields = $this->get_fields(); | |
register_setting( | |
$this->id . '_settings_page', | |
$this->id . '_options', | |
[ | |
'sanitize_callback' => [ $this, 'sanitize' ] | |
] | |
); | |
foreach ( $fields as $field ) { | |
if ( 'section' === $field['type'] ) { | |
add_settings_section( | |
$this->id . '_' . $field['name'] . '_section', | |
$field['title'], | |
[ $this, 'render_section' ], | |
$this->id . '_settings_page', | |
$field | |
); | |
} else { | |
add_settings_field( | |
$this->id . '_' . $field['name'], | |
$field['title'], | |
[ $this, 'render_field' ], | |
$this->id . '_settings_page', | |
$this->id . '_' . $field['section'] . '_section', | |
$field | |
); | |
} | |
} | |
} | |
public function render_section( $args ) { | |
if ( ! empty( $args['description'] ) ) { | |
?> | |
<p class="description"><?php echo wp_kses_post( $args['description'] ); ?></p> | |
<?php | |
} | |
} | |
/** | |
* Get option key. Useful for name attributes in forms. | |
* | |
* @param string $key Field Name. | |
* @return string | |
*/ | |
public function get_option_key( $key ) { | |
return $this->id . '_options[' . $key . ']'; | |
} | |
/** | |
* Get Option | |
* | |
* @param string $id Field Name | |
* @param mixed $default Default value if we don't have anything saved. | |
* @return mixed|string | |
*/ | |
public function get_option( $id, $default = '' ) { | |
$options = get_option( $this->id . '_options' ); | |
return isset( $options[ $id ] ) ? $options[ $id ] : $default; | |
} | |
/** | |
* Render Field | |
* @param array $args Field Arguments. | |
* @return void | |
*/ | |
public function render_field( $args ) { | |
$this->{'render_' . $args['type'] }( $args ); | |
} | |
/** | |
* Render Text input | |
* | |
* @param $args | |
* @return void | |
*/ | |
public function render_text( $args ) { | |
$default = ! empty( $args['default'] ) ? $args['default'] : ''; | |
?> | |
<input type="text" class="widefat" name="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" value="<?php echo esc_attr( $this->get_option( $args['name'], $default ) ); ?>" /> | |
<?php | |
if ( ! empty( $args['description'] ) ) { | |
?> | |
<p class="description"><?php echo esc_html( $args['description'] ); ?></p> | |
<?php | |
} | |
} | |
/** | |
* Render Checkbox input | |
* | |
* @param $args | |
* @return void | |
*/ | |
public function render_checkbox( $args ) { | |
$option_checked = $this->get_option($args['name']); | |
?> | |
<label for="<?php echo esc_attr($this->get_option_key($args['name'])); ?>"> | |
<input <?php checked( $option_checked, 1, true ); ?> id="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" type="checkbox" name="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>" value="1" /> | |
<?php echo esc_html( $args['description'] ); ?> | |
</label> | |
<?php | |
} | |
/** | |
* Render Checkbox input | |
* | |
* @param $args | |
* @return void | |
*/ | |
public function render_multi_checkbox( $args ) { | |
$selected_values = $this->get_option($args['name']); | |
if ( ! is_array( $selected_values ) ) { | |
$selected_values = array( $selected_values ); | |
} | |
if ( ! empty( $args['description'] ) ) { ?> | |
<p class="description"><?php echo esc_html( $args['description'] ); ?></p> | |
<?php | |
} | |
?> | |
<div class="scrollable"> | |
<?php | |
foreach ( $args['options'] as $option_value => $option_text ) { | |
$selected = in_array( $option_value, $selected_values ); | |
?> | |
<p> | |
<label for="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>_<?php echo esc_attr( $option_value ); ?>"> | |
<input | |
id="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>_<?php echo esc_attr( $option_value ); ?>" | |
<?php checked( $selected ); ?> | |
type="checkbox" | |
name="<?php echo esc_attr( $this->get_option_key( $args['name'] ) ); ?>[]" | |
value="<?php echo esc_attr( $option_value ); ?>" | |
/> | |
<?php echo esc_html( $option_text ); ?> | |
</label> | |
</p> | |
<?php | |
} | |
?> | |
</div> | |
<?php | |
} | |
public function sanitize( $input ) { | |
$fields = $this->get_fields(); | |
foreach ( $fields as $field ) { | |
// No need to sanitize sections. | |
if ( 'section' === $field['type'] ) { | |
continue; | |
} | |
if ( ! isset( $input[ $field['name'] ] ) ) { | |
continue; | |
} | |
switch ( $field['type'] ) { | |
case 'text': | |
$input[ $field['name'] ] = sanitize_text_field( $input[ $field['name'] ] ); | |
break; | |
} | |
} | |
do_action( $this->id . '_settings_sanitized', $input, $fields, $_POST, $this ); | |
return $input; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment