Create WordPress Options Page

<?php
class MySettingsPage
{
/**
* Holds the values to be used in the fields callbacks
*/
private $options;

/**
* Start up
*/
public function __construct()
{
add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
add_action( 'admin_init', array( $this, 'page_init' ) );
}

/**
* Add options page
*/
public function add_plugin_page()
{
// This page will be under "Settings"
add_options_page(
'Settings Admin',
'My Settings',
'manage_options',
'my-setting-admin',
array( $this, 'create_admin_page' )
);
}

/**
* Options page callback
*/
public function create_admin_page()
{
// Set class property
$this->options = get_option( 'my_option_name' );
?>
<div class="wrap">
<?php screen_icon(); ?>
<h2>My Settings</h2>
<form method="post" action="options.php">
<?php
// This prints out all hidden setting fields
settings_fields( 'my_option_group' );
do_settings_sections( 'my-setting-admin' );
submit_button();
?>
</form>
</div>
<?php
}

/**
* Register and add settings
*/
public function page_init()
{
register_setting(
'my_option_group', // Option group
'my_option_name', // Option name
array( $this, 'sanitize' ) // Sanitize
);

add_settings_section(
'setting_section_id', // ID
'My Custom Settings', // Title
array( $this, 'print_section_info' ), // Callback
'my-setting-admin' // Page
);

add_settings_field(
'id_number', // ID
'ID Number', // Title
array( $this, 'id_number_callback' ), // Callback
'my-setting-admin', // Page
'setting_section_id' // Section
);

add_settings_field(
'title',
'Title',
array( $this, 'title_callback' ),
'my-setting-admin',
'setting_section_id'
);
}

/**
* Sanitize each setting field as needed
*
* @param array $input Contains all settings fields as array keys
*/
public function sanitize( $input )
{
$new_input = array();
if( isset( $input['id_number'] ) )
$new_input['id_number'] = absint( $input['id_number'] );

if( isset( $input['title'] ) )
$new_input['title'] = sanitize_text_field( $input['title'] );

return $new_input;
}

/**
* Print the Section text
*/
public function print_section_info()
{
print 'Enter your settings below:';
}

/**
* Get the settings option array and print one of its values
*/
public function id_number_callback()
{
printf(
'<input type="text" id="id_number" name="my_option_name[id_number]" value="%s" />',
isset( $this->options['id_number'] ) ? esc_attr( $this->options['id_number']) : ''
);
}

/**
* Get the settings option array and print one of its values
*/
public function title_callback()
{
printf(
'<input type="text" id="title" name="my_option_name[title]" value="%s" />',
isset( $this->options['title'] ) ? esc_attr( $this->options['title']) : ''
);
}
}

if( is_admin() )
$my_settings_page = new MySettingsPage();

Post Meta Filter

<?php
/*
Plugin Name: CFInterceptor
Plugin URI: http://hyperspatial.com
Description: CFInterceptor is used for wordpress filters that need to load early in execution
Version: 1.0
Author: Adam J Nowak
Author URI: http://hyperspatial.com
License: GPL2
*/

/*
* CFInterceptor is designed to work with the CFProjectFilters class
*
* Calling actions/filters here registers them before the plugins are loaded
* Write callbacks in the CFProjectFilters class here: /wp-content/plugins/cf-project/includes/project-filters.php
*/

//Project Type Meta Filter
add_filter( 'get_post_metadata', array( 'CFProjectFilters', 'project_type_meta_filter' ), 10, 4 );

?>

<?php
/*
* CFProjectFilters is a class to package action and filter callbacks
*
* WP add_action() or add_filter() can be called in /wp-content/mu-plugins/interceptor.php
* Calling in the mu-plugins forces the actions/filters to be registered before the plugins are loaded
*/

class CFProjectFilters{
/* ~~~~~~~~~~ Project Type Meta Filter ~~~~~~~~~~ */
public function project_type_meta_filter( $metadata, $object_id, $meta_key, $single ){
if( $meta_key != '_project_type' ) return;
$meta_cache = wp_cache_get( $object_id, 'post_meta' );
$project_type = $meta_cache['_project_type'][0];

if( $project_type == 3 ) $metadata = 'Project type 3 is now a string, yay';
return $metadata;
}
}
?>