Skip to content

Instantly share code, notes, and snippets.

@igorbenic
Last active February 21, 2024 21:32
Show Gist options
  • Save igorbenic/0c822bfb80cc5fe7485a709553f4f667 to your computer and use it in GitHub Desktop.
Save igorbenic/0c822bfb80cc5fe7485a709553f4f667 to your computer and use it in GitHub Desktop.
How to add custom WordPress Profile Fields
<?php
abstract class WordPressSettings {
/**
* ID of the settings
* @var string
*/
public $settings_id = '';
/**
* Tabs for the settings page
* @var array
*/
public $tabs = array(
'general' => 'General' );
/**
* Settings from database
* @var array
*/
protected $settings = array();
/**
* Array of fields for the general tab
* array(
* 'tab_slug' => array(
* 'field_name' => array(),
* ),
* )
* @var array
*/
protected $fields = array();
/**
* Data gotten from POST
* @var array
*/
protected $posted_data = array();
/**
* Get the settings from the database
* @return void
*/
public function init_settings() {
$this->settings = (array) get_option( $this->settings_id );
foreach ( $this->fields as $tab_key => $tab ) {
foreach ( $tab as $name => $field ) {
if( isset( $this->settings[ $name ] ) ) {
$this->fields[ $tab_key ][ $name ]['default'] = $this->settings[ $name ];
}
}
}
}
/**
* Save settings from POST
* @return [type] [description]
*/
public function save_settings(){
$this->posted_data = $_POST;
if( empty( $this->settings ) ) {
$this->init_settings();
}
foreach ($this->fields as $tab => $tab_data ) {
foreach ($tab_data as $name => $field) {
$this->settings[ $name ] = $this->{ 'validate_' . $field['type'] }( $name );
}
}
update_option( $this->settings_id, $this->settings );
}
/**
* Gets and option from the settings API, using defaults if necessary to prevent undefined notices.
*
* @param string $key
* @param mixed $empty_value
* @return mixed The value specified for the option or a default value for the option.
*/
public function get_option( $key, $empty_value = null ) {
if ( empty( $this->settings ) ) {
$this->init_settings();
}
// Get option default if unset.
if ( ! isset( $this->settings[ $key ] ) ) {
$form_fields = $this->fields;
foreach ( $this->tabs as $tab_key => $tab_title ) {
if( isset( $form_fields[ $tab_key ][ $key ] ) ) {
$this->settings[ $key ] = isset( $form_fields[ $tab_key ][ $key ]['default'] ) ? $form_fields[ $tab_key ][ $key ]['default'] : '';
}
}
}
if ( ! is_null( $empty_value ) && empty( $this->settings[ $key ] ) && '' === $this->settings[ $key ] ) {
$this->settings[ $key ] = $empty_value;
}
return $this->settings[ $key ];
}
/**
* Validate text field
* @param string $key name of the field
* @return string
*/
public function validate_text( $key ){
$text = $this->get_option( $key );
if ( isset( $this->posted_data[ $key ] ) ) {
$text = wp_kses_post( trim( stripslashes( $this->posted_data[ $key ] ) ) );
}
return $text;
}
/**
* Validate textarea field
* @param string $key name of the field
* @return string
*/
public function validate_textarea( $key ){
$text = $this->get_option( $key );
if ( isset( $this->posted_data[ $key ] ) ) {
$text = wp_kses( trim( stripslashes( $this->posted_data[ $key ] ) ),
array_merge(
array(
'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true )
),
wp_kses_allowed_html( 'post' )
)
);
}
return $text;
}
/**
* Validate WPEditor field
* @param string $key name of the field
* @return string
*/
public function validate_wpeditor( $key ){
$text = $this->get_option( $key );
if ( isset( $this->posted_data[ $key ] ) ) {
$text = wp_kses( trim( stripslashes( $this->posted_data[ $key ] ) ),
array_merge(
array(
'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true )
),
wp_kses_allowed_html( 'post' )
)
);
}
return $text;
}
/**
* Validate select field
* @param string $key name of the field
* @return string
*/
public function validate_select( $key ) {
$value = $this->get_option( $key );
if ( isset( $this->posted_data[ $key ] ) ) {
$value = stripslashes( $this->posted_data[ $key ] );
}
return $value;
}
/**
* Validate radio
* @param string $key name of the field
* @return string
*/
public function validate_radio( $key ) {
$value = $this->get_option( $key );
if ( isset( $this->posted_data[ $key ] ) ) {
$value = stripslashes( $this->posted_data[ $key ] );
}
return $value;
}
/**
* Validate checkbox field
* @param string $key name of the field
* @return string
*/
public function validate_checkbox( $key ) {
$status = '';
if ( isset( $this->posted_data[ $key ] ) && ( 1 == $this->posted_data[ $key ] ) ) {
$status = '1';
}
return $status;
}
/**
* Adding fields
* @param array $array options for the field to add
* @param string $tab tab for which the field is
*/
public function add_field( $array, $tab = 'general' ) {
$allowed_field_types = array(
'text',
'textarea',
'wpeditor',
'select',
'radio',
'checkbox' );
// If a type is set that is now allowed, don't add the field
if( isset( $array['type'] ) &&$array['type'] != '' && ! in_array( $array['type'], $allowed_field_types ) ){
return;
}
$defaults = array(
'name' => '',
'title' => '',
'default' => '',
'placeholder' => '',
'type' => 'text',
'options' => array(),
'default' => '',
'desc' => '',
);
$array = array_merge( $defaults, $array );
if( $array['name'] == '' ) {
return;
}
foreach ( $this->fields as $tabs ) {
if( isset( $tabs[ $array['name'] ] ) ) {
trigger_error( 'There is alreay a field with name ' . $array['name'] );
return;
}
}
// If there are options set, then use the first option as a default value
if( ! empty( $array['options'] ) && $array['default'] == '' ) {
$array_keys = array_keys( $array['options'] );
$array['default'] = $array_keys[0];
}
if( ! isset( $this->fields[ $tab ] ) ) {
$this->fields[ $tab ] = array();
}
$this->fields[ $tab ][ $array['name'] ] = $array;
}
/**
* Adding tab
* @param array $array options
*/
public function add_tab( $array ) {
$defaults = array(
'slug' => '',
'title' => '' );
$array = array_merge( $defaults, $array );
if( $array['slug'] == '' || $array['title'] == '' ){
return;
}
$this->tabs[ $array['slug'] ] = $array['title'];
}
/**
* Rendering fields
* @param string $tab slug of tab
* @return void
*/
public function render_fields( $tab ) {
if( ! isset( $this->fields[ $tab ] ) ) {
echo '<p>' . __( 'There are no settings on these page.', 'textdomain' ) . '</p>';
return;
}
foreach ( $this->fields[ $tab ] as $name => $field ) {
$this->{ 'render_' . $field['type'] }( $field );
}
}
/**
* Render text field
* @param string $field options
* @return void
*/
public function render_text( $field ){
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<input type="<?php echo $type; ?>" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="<?php echo $default; ?>" placeholder="<?php echo $placeholder; ?>" />
<?php if( $desc != '' ) {
echo '<p class="description">' . $desc . '</p>';
}?>
</td>
</tr>
<?php
}
/**
* Render textarea field
* @param string $field options
* @return void
*/
public function render_textarea( $field ){
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<textarea name="<?php echo $name; ?>" id="<?php echo $name; ?>" placeholder="<?php echo $placeholder; ?>" ><?php echo $default; ?></textarea>
<?php if( $desc != '' ) {
echo '<p class="description">' . $desc . '</p>';
}?>
</td>
</tr>
<?php
}
/**
* Render WPEditor field
* @param string $field options
* @return void
*/
public function render_wpeditor( $field ){
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<?php wp_editor( $default, $name, array('wpautop' => false) ); ?>
<?php if( $desc != '' ) {
echo '<p class="description">' . $desc . '</p>';
}?>
</td>
</tr>
<?php
}
/**
* Render select field
* @param string $field options
* @return void
*/
public function render_select( $field ) {
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<select name="<?php echo $name; ?>" id="<?php echo $name; ?>" >
<?php
foreach ($options as $value => $text) {
echo '<option ' . selected( $default, $value, false ) . ' value="' . $value . '">' . $text . '</option>';
}
?>
</select>
<?php if( $desc != '' ) {
echo '<p class="description">' . $desc . '</p>';
}?>
</td>
</tr>
<?php
}
/**
* Render radio
* @param string $field options
* @return void
*/
public function render_radio( $field ) {
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<?php
foreach ($options as $value => $text) {
echo '<input name="' . $name . '" id="' . $name . '" type="'. $type . '" ' . checked( $default, $value, false ) . ' value="' . $value . '">' . $text . '</option><br/>';
}
?>
<?php if( $desc != '' ) {
echo '<p class="description">' . $desc . '</p>';
}?>
</td>
</tr>
<?php
}
/**
* Render checkbox field
* @param string $field options
* @return void
*/
public function render_checkbox( $field ) {
extract( $field );
?>
<tr>
<th>
<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
</th>
<td>
<input <?php checked( $default, '1', true ); ?> type="<?php echo $type; ?>" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="1" placeholder="<?php echo $placeholder; ?>" />
<?php echo $desc; ?>
</td>
</tr>
<?php
}
}
<?php
/*
Plugin Name: Ibenic
Plugin URI: http://wordpress.org/plugins/hello-dolly/
Description: This is not just a plugin, it symbolizes the hope and enthusiasm of an entire generation summed up in two words sung most famously by Louis Armstrong: Hello, Dolly. When activated you will randomly see a lyric from <cite>Hello, Dolly</cite> in the upper right of your admin screen on every page.
Author: Igor Benic
Version: 1.6
Author URI: http://ma.tt/
*/
class IBenic_WordPressUser_Fields {
/**
* Social Fields
*/
public $fields = array();
protected $title = '';
protected $slug = '';
public function __construct( $title, $slug, $fields = array() ) {
$this->title = $title;
$this->slug = $slug;
$this->fields = apply_filters( 'ibenic_user_fields_' . $this->slug, $fields );
add_action( 'show_user_profile', array( $this, 'render_admin_fields' ) );
add_action( 'edit_user_profile', array( $this, 'render_admin_fields' ) );
add_action( 'personal_options_update', array( $this, 'save_fields' ) );
add_action( 'edit_user_profile_update', array( $this, 'save_fields' ) );
}
public function render_admin_fields( $user ){
$data = get_user_meta($user->ID, $this->slug, true);
echo '<h2>' . $this->title . '</h2>';
echo '<table class="form-table">';
foreach ($this->fields as $field_name => $field) {
$value = '';
if( isset( $data[ $field_name ] ) ) {
$value = $data[ $field_name ];
}
echo '<tr>';
echo '<th><label for="' . $field_name . '">' . $field['title'] . '</label></th>';
echo '<td><input type="' . $field['type'] . '" class="regular-text" id="' . $field_name . '" name="' . $this->slug . '[' . $field_name . ']" value="' . $value . '" /></td>';
echo '</tr>';
}
echo '</table>';
}
public function save_fields( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) ) {
return false;
}
$posted_data = $_POST[ $this->slug ];
$previous_data = get_user_meta($user_id, $this->slug, true);
$sanitized_data = array();
foreach ( $this->fields as $field_name => $field ) {
if( ! isset( $posted_data[ $field_name ] ) ) {
continue;
}
$data = $posted_data[ $field_name ];
if( isset( $field['sanitize'] ) && $field['sanitize'] != '' ) {
$sanitize_function = $field['sanitize'];
$data = $sanitize_function( $data );
if( $data ) {
$sanitized_data[ $field_name ] = $data;
}
} else {
$sanitized_data[ $field_name ] = $data;
}
}
if( empty( $sanitized_data ) ) {
return false;
}
update_user_meta( $user_id, $this->slug, $sanitized_data, $previous_data );
}
}
$fields = array(
'facebook' => array(
'title' => 'Facebook',
'type' => 'url',
'placeholder' => 'Insert Facebook Profile URL',
'sanitize' => 'esc_url_raw',
),
'twitter' => array(
'title' => 'Twitter',
'type' => 'url',
'placeholder' => 'Insert Twitter Profile URL',
'sanitize' => 'esc_url_raw',
)
);
new IBenic_WordPressUser_Fields( 'Social Profiles', 'ibenic_social_profiles', $fields);
<?php
$social_fields = new IBenic_WordPressUser_FieldsSettings( 'Social Fields', 'social_fields' );
$social_fields->add_field(
array(
'name' => 'facebook',
'title' => 'Facebook',
'desc' => 'Insert Full URL for Facebook' ));
$social_fields->add_field(
array(
'name' => 'twitter',
'title' => 'Twitter',
'type' => 'text',
'desc' => 'Insert Full URL for twitter' ));
<?php
// Getting the values
$social_fields = get_user_meta( $user_id, 'social_fields');
$facebook = $social_fields['facebook'];
<?php
class IBenic_WordPressUser_FieldsSettings extends WordPressSettings {
// Title of our section
protected $title = '';
// Slug of our settings
protected $slug = '';
// User ID for which we save
protected $user_id = 0;
// Constructor method
function __construct( $title, $slug ) {
$this->title = $title;
$this->slug = $slug;
$this->settings_id = $this->slug;
add_action( 'show_user_profile', array( $this, 'render_admin_fields' ) );
add_action( 'edit_user_profile', array( $this, 'render_admin_fields' ) );
add_action( 'personal_options_update', array( $this, 'save_profile_settings' ) );
add_action( 'edit_user_profile_update', array( $this, 'save_profile_settings' ) );
}
// ...
}
<?php
class IBenic_WordPressUser_FieldsSettings extends WordPressSettings {
// ...
// Rendering the admin fields
public function render_admin_fields( $user ){
$this->user_id = $user->ID;
$this->init_settings();
echo '<h2>' . $this->title . '</h2>';
echo '<table class="form-table">';
$this->render_fields( 'general' );
echo '</table>';
}
// ...
}
<?php
class IBenic_WordPressUser_FieldsSettings extends WordPressSettings {
// ...
/**
* Get the settings from the database
* @return void
*/
public function init_settings() {
$user_id = $this->user_id;
$this->settings = get_user_meta( $user_id, $this->settings_id, true );
foreach ( $this->fields as $tab_key => $tab ) {
foreach ( $tab as $name => $field ) {
if( isset( $this->settings[ $name ] ) ) {
$this->fields[ $tab_key ][ $name ]['default'] = $this->settings[ $name ];
}
}
}
}
// ...
}
<?php
class IBenic_WordPressUser_FieldsSettings extends WordPressSettings {
// ...
// Wrapper to get the user id and then save the settings
public function save_profile_settings( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) ) {
return false;
}
$this->user_id = $user_id;
$this->save_settings();
}
/**
* Save settings from POST
* @return [type] [description]
*/
public function save_settings(){
$this->posted_data = $_POST;
if( empty( $this->settings ) ) {
$this->init_settings();
}
foreach ($this->fields as $tab => $tab_data ) {
foreach ($tab_data as $name => $field) {
$this->settings[ $name ] = $this->{ 'validate_' . $field['type'] }( $name );
}
}
update_user_meta( $this->user_id, $this->settings_id, $this->settings );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment