intro to wordpress plugin development
DESCRIPTION
Brad Williams, the co-author of Professional WordPress Plugin Development, gives his presentation on Intro to WordPress Plugin Development to the NYC WordPress Meetup group in March 2011.TRANSCRIPT
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