Last active
February 21, 2024 21:32
-
-
Save igorbenic/0c822bfb80cc5fe7485a709553f4f667 to your computer and use it in GitHub Desktop.
How to add custom WordPress Profile Fields
This file contains 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 | |
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 | |
} | |
} |
This file contains 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 | |
/* | |
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); |
This file contains 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 | |
$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' )); |
This file contains 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 | |
// Getting the values | |
$social_fields = get_user_meta( $user_id, 'social_fields'); | |
$facebook = $social_fields['facebook']; |
This file contains 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 | |
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' ) ); | |
} | |
// ... | |
} |
This file contains 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 | |
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>'; | |
} | |
// ... | |
} |
This file contains 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 | |
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 ]; | |
} | |
} | |
} | |
} | |
// ... | |
} |
This file contains 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 | |
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