Creating WordPress Plugins

Kelly Dwan

Moving very fast, just glimpses of how you can do things, see these slides and full-length version at rrn/slides

A plugin is added functionality

Every site is different and has different needs

Themes do this too - lots of themes have functionality built in -- this is bad (if you ever think you might maybe want to change themes). Move your site's functions.php into a plugin, so when you change themes, you don't loose it.

Plugin header syntax

            
                <?php
                  /*
                    Plugin Name: Name Of The Plugin
                    Plugin URI: http://URI_Of_Page_Describing_Plugin
                    Description: A brief description of the Plugin.
                    Version: The Plugin's Version Number, e.g.: 1.0
                    Author: Name Of The Plugin Author
                    Author URI: http://URI_Of_The_Plugin_Author
                    License: A "Slug" license name e.g. GPL2
                  */
                  function something(){
                    ...
                ?>
            
        

Populates the plugin listing in admin

Only the name is required to show up in the listing, but description and version are useful.

Before you start

Stop for questions?


Comment & Organize your code well from the start.

Might be difficult at first, but you should be able to read through your plugin and know what it's doing.

Look at the WP coding standards, if you're new to writing code. (or in general)


Use unique function & option names

Anything you create to be used by WP should be unique

Avoid collisions by two plugins with the function 'install' -- Using classes also works.

Debug Mode


check while you're writing code that you're not causing errors left & right, much easier to do as you go than after everything's done. This will show errors with any plugin on your site, so if others are throwing errors deactivate them


			/**
			 * This will log all errors notices and warnings to a file called
			 * debug.log in wp-content only when WP_DEBUG is true
			 */
			define('WP_DEBUG', true); // false
			if (WP_DEBUG) {
			  define('WP_DEBUG_LOG', true);
			  define('WP_DEBUG_DISPLAY', false);
			  @ini_set('display_errors',0);
			}
		

Types of plugins



We're covering normal plugins, but it's good to know that these exist.

Writing Code

[the scary part]

Stop for questions?

Where am I?


home_url(): Site address (URL)

site_url(): WordPress address (URL)

plugins_url('style.css',__FILE__): URL to other files inside your plugin folder

dirname(__FILE__): Absolute path to this file

Don't assume default directory structure.

People can (and do) change where wp-content is, rename it, etc

Creating a Template Tag


Good to start with, because you can later add a widget that just executes this function - you don't have to mess with any other WP APIs

If you wanted to display an image (like your logo) anywhere, you could create the template tag

Show My Logo


            
                <?php
                  /*
                    Plugin Name: Show My Logo
                    Description: A template tag to show my logo wherever I want.
                  */
                  function show_my_logo(){
                    $logo_path = get_stylesheet_directory_uri() . "/image.png";
                    echo "<img src='$logo_path' class='my-logo'/>";
                  }
                ?>
            
        

That's a plugin. Looks for image.png in the theme directory, and prints it. If you're at all intimidated by making a plugin, don't be - they're not all complicated monsters, and they're generally better if they're not.

How to use your new tag


Use it anywhere, like you do with the_title(), etc. Anywhere you put it, it will output your logo.

            
                <?php
                if ( function_exists('show_my_logo') )
                    show_my_logo();
                ?>
            
        

Wrap it in function_exists(), so that if you disable the plugin it doesn't break your theme.

Hooks: Actions & Filters

A hook is a part of WordPress that you can connect your plugin to. When the hook is activated, it will run whatever has been connected to it.

What are filters?


For example...

capital_P_dangit: This function hooks into the the_title, the_content, & comment_text filter hooks, looks for any instance of 'Wordpress' and changes it to 'WordPress'.

What are actions?


Example actions

The actions that run (and the order they run in) is determined by the page requested (admin pages run different actions than non-admin pages). When run, the action will run whatever has been hooked into it.

Using hooks

for a useful example, I'm actually grabbing someone else's example.

Adding a new color scheme to Twenty Eleven (from theme.fm's How to Child Theme Twenty Eleven)

            
                <?php
					function twentyeleven_color_schemes_orange( $color_schemes ) {
					    $color_schemes['orange'] = array(
					        'value' => 'orange',
					        'label' => __( 'Orange', 'twentyeleven' ),
					        'thumbnail' => get_stylesheet_directory_uri() . '/orange.png',
					        'default_link_color' => '#FFA500',
					    );
					    return $color_schemes;
					} add_filter( 'twentyeleven_color_schemes', 'twentyeleven_color_schemes_orange' );
                ?>
            
        

add_filter takes the filter hook you want to use, and then the function you want to run as arguments.

Both this and add_action also have priority and arguments parameters - default priority is 10: a priority 5 filter will run before a priority 12. If you wanted to make another function that overwrites this orange value, give it a higher priority and it will run after (therefore overwriting the value). Arguments is the number of arguments given in the hook & expected by the function -- they should match.

Create your own hooks

Can be used like any other hooks now:


	    	add_action('your_action', 'a_function', 10, 2);
	    

Will call a_function($arg1,$arg2) wherever you put the do_action, at priority 10 (normal).

Adding your own hooks makes your plugin easily customized by others, just like WP itself. Can have multiple arguments, just need to match with function & add_action

Stop for questions

Creating a shortcode


We're pretending that the show my logo function had a parameter $large just to show using attributes. The $content var gets what is between the shortcode tags


	        function showlogo_shortcode_handler($atts, $content=null, $code="") {
			    $a = shortcode_atts( array(
			        'large' => false
			    ), $atts );
			    show_my_logo($a['large']);
			} add_shortcode('show-my-logo', 'showlogo_shortcode_handler');
        

Gives us the shortcode [show-my-logo] with (optional) attribute 'large' (defaults to false).

[show-my-logo large=true]

[show-my-logo]

Won't break a site if the plugin gets disabled (like a function call (without if function_exists) would), but it will display the shortcode on the site.

Creating a widget


There's also a cheating way of doing this involving shortcodes, look it up if you're interested.

Questions?

Interacting with the Database

Saving settings, user input, etc

Adding options


add_option uses the pre-existing wp_options table to store your data.

Each option you add creates a new row in the database, so best practice is to only use one 'option' per plugin, and store your data as an array.

You can store arrays in option-rows, allowing you to still store as much information as you need. WP will automatically serialize them

Adding post meta



        	add_post_meta($post_id, 'co_author', 'John Smith', true);
        	//post id, meta key, meta value, unique
        	update_post_meta($post_id, 'co_author', 'John Smith');
        	//post id, meta key, new value, [optional value to change if the key is not unique]
        	$co_author = get_post_meta($post_id, 'co_author', true);
        	//post id, meta key, [optional 'single']
        

This is best for information closely associated with posts. You'll need to know the post ID, but once you do, you can just use add_post_meta or update_post_meta. This adds a custom field to the post. If your key starts with '_', such as _count, it shouldn't be shown to users. Otherwise, it will display in the 'custom fields' section. update automatically adds if the key doesn't exist, add will only add it if it's not there (or if it's not unique). In get_post_meta, if you leave out single it will return an array, even if you only have one value. If you have multiple values and set single to true, it will grab the first.

Creating a new table

(if you have to)

If you have information that requires a new table, WP has a class ($wpdb) that abstracts the database. Even with this abstraction, you still need to know MySQL syntax to create/update the table correctly.

If you do feel comfortable enough to do this, there is a page on the codex which will help: http://codex.wordpress.org/Creating_Tables_with_Plugins.

Definitely out of the scope of this talk, but for awareness - if you need to create a new table, use the class abstraction.

Questions?

Some Best Practices

Deactivation Function



	    	register_deactivation_hook(__FILE__,'my_p_deactivate');
	    	function my_p_deactivate(){
	    		// undo any changes you made to WP
	    		// but don't delete data!
	    	}
    	

i18n (internationalization)

You can allow for translations of your plugin text by adding a domain and outputting your strings with __('your string', 'myp_domain') or _e('your string','myp_domain')

            
            	function my_p_add_domain(){
	                load_plugin_textdomain( 'myp_domain', false, 
	                	dirname(plugin_basename( __FILE__ )) . '/translations/' 
	                );
	            } add_action('init','my_p_add_domain');
            
        

your plugin's domain string, a deprecated var, and then the location to the .mo files

plugin_basename gets the directory after plugins/, so your plugin folder & filename

Data Validation

Are good things to do, look up on codex if running out of time

You can validate/sanitize your data before it goes into the database by using register_setting.


        	register_setting( 'my_p_options_group', 'my_p_int_option', 'intval') );
	        register_setting( 'my_p_options_group', 'my_p_options', 'my_p_validate') );
	        function my_p_validate( $input ){
	        	$input['text'] = wp_filter_nohtml_kses($input['text']);
	        	$input['an_int'] = intval($input['an_int']);
	        	$input['a_bool'] = ( $input['a_bool'] == 1 ? 1 : 0 );
	        	return $input;
	        }
        

The end

WP Codex
Writing a plugin
Plugin API Overview
Widget API Overview
All WP hooks
Working directly with the DB
Shortcode API
Coding standards
WP Code
Trac Browser
PHP X Ref
List of Drop-ins
Plugin How-to's
Creating a 'Functionality Plugin'
Creating a plugin with OOP techniques (classes)

These slides will be availible at redradar.net/slides