Intro to WordPress Plugin Development
Brad Williams @williamsba
Brad WilliamsCo-Founder of WebDevStudios.com
Organizer Philly WordPress Meetup
& WordCamp Philly
Co-Author of Professional WordPress
(http://bit.ly/pro-wp)
& Professional WordPress Plugin Development (http://amzn.to/plugindevbook)
Who Am I?
Slides available at: http://www.slideshare.net/williamsba
What is a Plugin? Types of Plugins Sanity Practices and Plugin Foundation Determining Paths in a Plugin Activation, Deactivation, and Uninstall Methods Shortcodes, Menus, and Settings Overview Hooks: Actions and Filters Explained Resources for Plugin Developers
Topics
What is a Plugin?
A plugin in WordPress is a PHP script that extends, or alters, the core
functionality of WordPress.
Quite simply plugins are files installed in WordPress to add a feature, or set of
features, to WordPress.
What is a Plugin?
http://wordpress.org/extend/plugins/
Types and Statuses of Plugins
Active – Plugin is active and running in WordPress Inactive – Plugin is installed but not active. No code from the plugin is
executed Must-Use – All plugins installed in wp-content/mu-plugins. All plugins
are loaded automatically. Only way to deactivate is to remove. Drop-ins – Core functionality of WordPress can be replaced by Drop-in
plugins. advanced-cache-php – Advanced caching plugin db.php – Custom database class maintenance.php – Custom maintenance message sunrise.php – Domain mapping And more…
Plugin Header Requirements<?php/*Plugin Name: WordPress NYC MeetupPlugin URI: http://webdevstudios.com/support/wordpress-plugins/Description: Plugin for the WordPress NYC MeetupVersion: 1.0Author: Brad WilliamsAuthor URI: http://webdevstudios.comLicense: GPLv2*/?>
Plugin is now available to be activated in WordPress!
Sanity Practices
update_option() //BAD FUNCTION NAME
bw_nycmeetup_update_option() //GOOD FUNCTION NAME!
$settings //BAD VARIABLE NAME
$bw_nycmeetup_settings //GOOD VARIABLE NAME!
Prefix Everything!
Organized Folder Structure• /unique-plugin-name
• unique-plugin-name.php• uninstall.php• /js• /css• /includes• /images
Keeping your files organized using a clean folder structure can make it much easier to track the flow of your plugin over time.
Determining Paths
<?php//display local path to my plugin directoryecho plugin_dir_path( __FILE__ );?>
__FILE__ is a “magical” PHP constant containing the full path and filename of the file
Local Paths
Would display: /public_html/wp-content/plugins/my-new-plugin/
<?php//display local path to my includes/functions.php fileecho plugin_dir_path( __FILE__ ) .’includes/functions.php’;?>
Would display: /public_html/wp-content/plugins/my-new-plugin/includes/functions.php
Determining Paths
<?php//display the URL to images/icon.pngecho plugins_url( 'images/icon.png', __FILE__ );?>
Plugin is now available to be activated in WordPress!
URL Paths
Would display: http://example.com/wp-content/plugins/my-new-plugin/images/icon.png
Advantages of plugins_url()• Supports the mu-plugins directory• Auto detects SSL, so if enabled the URL would return https• Uses the WP_PLUGIN_URL constant, meaning it can detect the correct path even if /wp-content has been moved• Supports Multisite using the WPMU_PLUGIN_URL constant
Important Techniques
<?phpregister_activation_hook( __FILE__, 'bw_nycmeetup_install' );
function bw_nycmeetup_install() { If ( version_compare( get_bloginfo( 'version' ), ‘4.0', '<' ) ) { deactivate_plugins( plugin_basename( __FILE__ ) ); // Deactivate our plugin wp_die( 'This plugin requires WordPress version 4.0 or higher.' ); }}?>
Plugin Activation Function
register_activation_hook( $file, $function )
Parameters:• $file (string) (required) – Path to the primary plugin file• $function (string) (required) – Function to be executed when plugin is activated
http://codex.wordpress.org/Function_Reference/register_activation_hook
Important Techniques
<?phpregister_deactivation_hook( __FILE__, 'bw_nycmeetup_deactivate' );
function bw_nycmeetup_deactivate() { //do stuff}?>
Plugin Deactivation Function
register_deactivation_hook( $file, $function )
Parameters:• $file (string) (required) – Path to the primary plugin file• $function (string) (required) – Function to be executed when plugin is deactivated
http://codex.wordpress.org/Function_Reference/register_deactivation_hook
REMEMBER: Deactivating is NOT uninstalling. Always assume your users will reactivate at a later date.
Important Techniques
<?phpif( !defined( 'WP_UNINSTALL_PLUGIN' ) ) exit (); // Delete option from options tabledelete_option( ‘bw_nycmeetup_options' );?>
Plugin Uninstall
http://jacobsantos.com/2008/general/wordpress-27-plugin-uninstall-methods/
If the WP_UNINSTALL_PLUGIN constant is not defined we know WordPress did not call this file. This is a security measure in WordPress
1. Create a uninstall.php file in the root directory of your plugin2. Add all uninstall code to this file
Uninstall.php is the recommended uninstall method, but there is another method called register_uninstall_hook()
What is a Hook?
Hooks enable plugin developers to “hook” into WordPress and change how it works without modifying the core code
http://jacobsantos.com/2008/general/wordpress-27-plugin-uninstall-methods/
There are two kinds of hooks: Actions and Filters
Hooks
<?phpadd_action( 'user_register', 'bw_nycmeetup_welcome_email' );
function bw_nycmeetup_welcome_email( $user_id ) {
$user_info = get_userdata( $user_id );
//populate email values $email_to = is_email( $user_info->user_email ); $email_subject = 'Welcome!'; $email_msg = 'Thank you for registering on my website!';
//send welcome email wp_mail( $email_to, $email_subject, $email_msg );
}?>
Action Hooks
http://codex.wordpress.org/Plugin_API/Action_Reference
Enables you to execute a function at specific points in the WordPress loading process
HooksCommon Action Hooks
http://codex.wordpress.org/Plugin_API/Action_Reference
• plugins_loaded – Earliest hook in the WP loading process, after all plugins have been loaded• init – Fire after most of WP is set up so all information is available admin_menu – Runs when the basic admin menu structure is in place• template_redirect – Executed just before the theme template is chosen• wp_head – Executed on the front end of WordPress between the <head> tags• wp_footer – Runs in the footer of your theme• admin_head – Executed on the admin side of WordPress between the <head> tags• admin_footer – Runs in the footer of the admin side of WordPress• user_register – Executes when a new user account is created• save_post – Runs when a post or page is created or updated
Hooks
<?phpadd_filter( 'the_content', 'bw_nycmeetup_filter_content' );
function bw_nycmeetup_filter_content( $text ) {
$text = str_replace( 'Drupal', 'WordPress', $text );
return $text; }?>
Filter Hooks
http://codex.wordpress.org/Plugin_API/Filter_Reference
Enables you to manipulate the output of code and content in WordPress
Change every instance of Drupal to WordPress in your content >:)
REMEMBER: Using a filter does NOT change the content in the database, it simply alters it prior to displaying
Hooks
<?phpadd_filter ( 'the_content', 'insertFootNote' );
function insertFootNote( $content ) {
if( !is_feed() && !is_home() ) { $content .= "<div class='subscribe'>"; $content .= "<h4>Enjoyed this article?</h4>"; $content .= "<p>Subscribe to my <a href='http://feeds2.feedburner.com/strangework'>RSS feed</a>!</p>"; $content .= "</div>"; }
return $content;}?>
Filter Hooks
http://codex.wordpress.org/Plugin_API/Filter_Reference
HooksCommon Filter Hooks
http://codex.wordpress.org/Plugin_API/Filter_Reference
• the_content – Filter applied to the content of the post or page• the_title – Applied to the post title• body_class – Applied to the <body> tag class parameter• default_content – Applied to the content on a new post or page• comment_text – Applied to the comment text of a comment
HooksNumber of Hooks in WordPress by Version
http://adambrown.info/p/wp_hooks
Plugin Foundation
It’s important to start with a solid foundation
Plugin Foundation
<?php/*Plugin Name: WordPress NYC MeetupPlugin URI: http://webdevstudios.com/support/wordpress-plugins/Description: Plugin for the WordPress NYC MeetupVersion: 1.0Author: Brad WilliamsAuthor URI: http://webdevstudios.comLicense: GPLv2*/
// DEFINE CONSTANTSdefine( 'BWNYCMEETUP_VERSION', '1.0' );define( 'BWNYCMEETUP_TEXTDOMAIN', 'bwnycmeetup_plugin' );define( 'BWNYCMEETUP_BASENAME', plugin_basename(__FILE__) );define( 'BWNYCMEETUP_DIR', plugin_dir_path( __FILE__ ) );define( 'BWNYCMEETUP_URL', plugins_url( 'my-new-plugin/' ) );
require_once( BWNYCMEETUP_DIR . 'includes/core.php' );?>
Example Plugin Foundation
Shortcode Example
<?php// Register a new shortcode: [book]add_shortcode( 'book', 'bw_nycmeetup_book' );
// The callback function that will replace [book]function bw_nycmeetup_book() {
return '<a href="http://amzn.to/plugindevbook">Professional WordPress Plugin Development</a>';}?>
Example
Menu Example
<?phpadd_action( 'admin_menu', 'bw_nycmeetup_create_menu' );
function bw_nycmeetup_create_menu() {
//create custom top-level menuadd_menu_page( 'NYC Meetup Settings Page', 'NYC Meetup',
'manage_options', 'nyc-meetup-plugin', 'bw_nycmeetup_settings_page' );
//create submenu itemsadd_submenu_page( 'nyc-meetup-plugin', 'About My Plugin', 'About',
'manage_options', 'nyc-meetup-plugin_about', 'bw_nycmeetup_about_page' );add_submenu_page( 'nyc-meetup-plugin', 'Help with My Plugin', 'Help',
'manage_options', 'nyc-meetup-plugin_help', 'bw_nycmeetup_help_page' );add_submenu_page( 'nyc-meetup-plugin', 'Uinstall My Plugin', 'Uninstall',
'manage_options', 'nyc-meetup-plugin_uninstall', 'bw_nycmeetup_uninstall_page' );
}?>
Example Custom Menu
Menu Exampleadd_menu_page()Parameters: $page_title – The title tag text $menu_title – The menu name $capability - Capability required to view menu $menu_slug – Unique slug to reference menu by $function – Function that displays the pages content $icon_url – URL for a custom menu icon $position – Position the menu should appear
add_submenu_page()Parameters: $parent_slug – Slug name for the parent menu $page_title – The title tag text $menu_title – The submenu name $capability – Capability required to view submenu $menu_slug – Unique slug to reference menu by $function – Function that displays the pages content
Menu Example
<?phpadd_action( 'admin_menu', 'bw_nycmeetup_create_menu' );
function bw_nycmeetup_create_menu() {
//create submenu itemsadd_submenu_page( 'edit.php?post_type=movies', 'About My Plugin', 'About',
'manage_options', 'nyc-meetup-plugin_about', 'bw_nycmeetup_about_page' );
}?>
Add Submenu to Custom Post Type
You can easily add a submenu to any Custom Post Type menu by setting the $parent_slug to edit.php?post_type=POSTTYPENAME
Menu Example
<?phpadd_action( 'admin_menu', 'bw_nycmeetup_create_menu' );
function bw_nycmeetup_create_menu() {
//create Settings submenu page add_options_page('NYC Meetup Settings Page', 'NYC Meetup',
'manage_options', 'nyc-meetup-plugin', 'bw_nycmeetup_settings_page' );
}
function bw_nycmeetup_settings_page() { //settings page}?>
Add Submenu to Existing Menu
Menu Exampleadd_options_page()Parameters: $page_title – The title tag text $menu_title – The menu name $capability - Capability required to view menu $menu_slug – Unique slug to reference menu by $function – Function that displays the pages content
add_dashboard_page()add_posts_page()add_media_page()add_links_page()add_pages_page()add_comments_page()add_theme_page()add_plugins_page()add_users_page()add_management_page()add_options_page()
Basic Settings Page Example
add_action('admin_init', 'bw_nycmeetup_register_settings');
// WordPress Settings APIfunction bw_nycmeetup_register_settings(){
register_setting( 'bw_nycmeetup_settings_group', 'bw_nycmeetup_settings', 'bw_nycmeetup_settings_validate' );}
Register your settings
register_setting()
Parameters: $option_group – A unique settings group name $option_name – A unique option name for the group $sanitize_callback – Callback function to sanitize the option's values
Menu Exampleadd_menu_page()Parameters: $page_title – The title tag text $menu_title – The menu name $capability - Capability required to view menu $menu_slug – Unique slug to reference menu by $function – Function that displays the pages content $icon_url – URL for a custom menu icon $position – Position the menu should appear
add_submenu_page()Parameters: $parent_slug – Slug name for the parent menu $page_title – The title tag text $menu_title – The submenu name $capability – Capability required to view submenu $menu_slug – Unique slug to reference menu by $function – Function that displays the pages content
Basic Settings Page Example// Plugin settings pagefunction bw_nycmeetup_settings_page() { ?> <div class="wrap"> <div class="icon32" id="icon-options-general"><br /></div> <h2>My Plugin Settings</h2> <form method="post" action="options.php"> <?php settings_fields( 'bw_nycmeetup_settings_group' ); ?> <?php $options = get_option( 'bw_nycmeetup_settings' ); ?> <table class="form-table"> <tr valign="top"><th scope="row">Name:</th> <td><input name="bw_nycmeetup_settings[name]" type="text" value="<?php echo esc_attr( $options['name'] ); ?>" /></td> </tr> <tr valign="top"><th scope="row">Favorite Color:</th> <td> <select name="bw_nycmeetup_settings[color]"> <option value="orange" <?php selected( $options['color'], 'orange' ); ?>>Orange</option> <option value="black" <?php selected( $options['color'], 'black' ); ?>>Black</option> </select> </td> </tr> <tr valign="top"><th scope="row">Enable Rage Mode?</th> <td><input type="checkbox" name="bw_nycmeetup_settings[rage]" <?php if ( isset( $options['rage'] ) ) checked( $options['rage'], 'on' ); ?>/> </td> </tr> </table> <p class="submit"> <input type="submit" class="button-primary" value="Save Settings" /> </p> </form> </div><?php }
Basic Settings Page Example
// Validationfunction bw_nycmeetup_settings_validate($input) {
$input['name'] = strip_tags( $input['name'] ); $input['color'] = strip_tags( $input['color'] ); $input['rage'] = ( isset( $input['rage'] ) ) ? strip_tags( $input['rage'] ) : null;
return $input;}
Register your settings
Basic Settings Page Example
Now you have a settings page!
Official Resources
› WordPress Core!
› http://wordpress.org/extend/plugins/
› http://codex.wordpress.org/Writing_a_Plugin
› http://codex.wordpress.org/Data_Validation
› http://wordpress.org/support/forum/hacks
› http://lists.automattic.com/mailman/listinfo/wp-hackers
› http://codex.wordpress.org/IRC ( #wordpress channel
› http://wpdevel.wordpress.com/
› http://wordpress.org/extend/ideas/
Developer Websites
› http://wpengineer.com
› http://phpxref.ftwr.co.uk/wordpress/
› http://adambrown.info/p/wp_hooks
Plugin Developer Resources
Brad [email protected]
Blog: strangework.com
Twitter: @williamsba
IRC: WDS-Brad
http://www.slideshare.net/williamsba
Contact