• Feed RSS

7 Simple Rules: WordPress Plugin Development Best Practices

"We’ve been talking a lot about “Best Practices” here on Wptuts lately. Today, we’ll cover some important best practices for creating a WordPress plugin. From security tips to namespacing tricks, follow these rules and you’ll do no wrong. Whether you’re a budding new plugin developer or a time-tested veteran, these simple rules and suggestions will make you a better developer (and the community will thank you for it!)


Rule 01: Have a Strategy

Yes, a strategy. Try this checklist:
  • Is my plugin just for fun/demonstration purposes or for everyday use in the real world?
  • Am I writing it to contribute to the community, to promote myself or to earn income?
  • Can I afford the time to offer support to users?
  • Have similar plugins already been written? Check the WordPress Plugin Repository.
These questions are important because they impact on how seriously you need to take issues such as coding standards, updates, security, support and documentation. Even if you’re just writing a plugin for your own use or for the use of your colleagues, you need to think hard about how you’re going to go about it so that you don’t make a rod for your own back.

Rule 02: Use Consistent and Clear Coding Standards

Which do you prefer, this?
function parsefile($imagedata,$file){
if(!in_array($imagedata['mime'], array('image/jpeg','image/png','image/gif'))){
 $result['error']='Your image must be a jpeg, png or gif!';
 }elseif(($file['size']>200000)){
 $result['error']='Your image was '.$file['size'].' bytes! It must not exceed '.MAX_UPLOAD_SIZE.' bytes.';
 }
 return $result;
}
Or this?
/*
processes the uploaded image, checking against file type and file size
*/
function parse_file($image_data, $file){

 if(!in_array($image_data['mime'], unserialize(TYPE_WHITELIST))){

   $result['error'] = 'Your image must be a jpeg, png or gif!';

 }elseif(($file['size'] > MAX_UPLOAD_SIZE)){

   $result['error'] = 'Your image was ' . $file['size'] . ' bytes! It must not exceed ' . MAX_UPLOAD_SIZE . ' bytes.';

 }

 return $result;

}
Simple things like consistent spacing, indenting, informative variable naming and succinct comments are a good place to start. That’s the only difference in the examples above. WordPress has an excellent guide to coding standards. If you code to a standard your code will be easier to understand, edit and debug.

Use Namespacing

There are two ways to construct a WordPress plugin: as a bunch of functions or as a class. Keep in mind that the functions in your plugin get thrown into the global namespace with all the other non-namespaced functions, which means that if you have a function named plugin_init then it’s probably going to conflict with the same function written by someone else at some point. The obvious way to fix this issue is to prefix the function name with something unique. I like to use the first letters of my plugin name, so if I had a plugin called My Great Plugin, I would call the above function mgp_plugin_init, and the same for the rest of my functions.
But a better way is to create a class for your plugin, that way all functions will be namespaced under the name of the class and even better, you can now use short, common method (function) names.
class my_class{

 function hello_world(){

   return 'Hello World!';

 }

 function goodbye_world(){

   return 'Goodbye World!';

 }

}
Then you could access your class methods under the its own namespace:
$my_new_plugin = new my_class();

echo $my_new_plugin->hello_world();

echo $my_new_plugin->goodbye_world();

Rule 03: Take Security Seriously

Making your plugin secure is the single most important step to take, but many developers discount security or relegate it to the status of an afterthought. Don’t make that mistake.

Sanitize inputs, escape outputs

You should especially make yourself familiar with:
If you use a function such as wp_insert_post, WordPress will sanitize that data for you. Similarly, if you use the database methods $wpdb->insert or $wpdb->update, WordPress will sanitize the data. But if you choose to access the database more directly with something like $wpdb->get_result, then you should use wpdb->prepare to prevent sql injections of malicious code.
Instead of:
$admin_posts = $wpdb->get_results(
 "SELECT ID, post_title FROM $wpdb->posts WHERE post_status = 'publish' AND post_author = 1"
 );
You would use:
$admin_posts = $wpdb->get_results($wpdb->prepare(
 "SELECT ID, post_title FROM $wpdb->posts WHERE post_status = %s AND post_author = %d",
 'publish', 1
 ));
In the above example, %s is a placeholder for string input (publish) and %d is a placeholder for numeric input (1). You can use as many placeholders as you need.

Use Nonces for Form and URL Verification

It’s important to know that when a form or url is posted back to WordPress, that it was your WordPress site that actually generated it and not some third party or malicious agent. To take care of this aspect of security, we use nonces. A nonce is a number used once.
For a form, we generate a nonce field using wp_nonce_field that will be included in our form as a hidden field:
wp_nonce_field('my_nonce', 'my_nonce_submit');
Because it’s now a hidden field in our form, it’ll come back to us when the form is submitted. We can then check that the nonce is valid using wp_verify_nonce:
wp_verify_nonce($_POST['my_nonce_submit'], 'my_nonce') )
That will return true if the nonce verifies.
For a url (links in emails, browser urls), you can create a nonced url with wp_nonce_url:
$nonced_url = wp_nonce_url('http://my_site.com?action=register&id=123456', 'register_nonce');
That would create a url like this…
http://my_site.com?action=register&id=123456&_wpnonce=250d696dc6
…which you could send in a registration confirmation email. You would then check the incoming url for a nonce with the same id using the check_admin_referer function and proceed with verification if true.
if($_GET['action'] == 'register'){

 if(check_admin_referer('register_nonce')){

   if(verify_id($_GET['id'])){

     echo 'Registration verified!';

   }

 }else{

   echo 'Registration verification FAILED!';

 }
}

Rule 04: Access Web Services Intelligently

The internet is full of web services providing us with everything from weather forecasts to stock quotes to the latest tweets from Twitter. The most efficient way for a plugin to access remote data is to use the HTTP API which will handle your request in the background, using the most efficient of the five possible remote methods that PHP exposes. It’s like a one-stop shop for webservice access.
This uses the wp_remote_get method (a wrapper function of the HTTP class) to get a page body:
$page_data = wp_remote_get('http://site.com/page');

if($page_data['response']['code'] == 200){

 $body = $page_data['body'];

}
Same with wp_remote_post to login:
$args = array(
 'login' => 'login_name',
 'password' => 'my_password'
 );

$response = wp_remote_post('http://site.com/login', $args);

Rule 05: Internationalization

This doesn’t have to be a big deal but is essential if you want to reach the widest audience possible. At a minimum all you need do is prepare your plugin with the _e() and __() functions and worry about the texdomain afterwards.
It’s all explained very well in this wp.tutsplus article by Tom McFarlin and here at the WordPress codex.

Rule 06: Load Only What You Need

When you go away overnight, you don’t take as much with you as you would if you were going on vacation for a month. So treat your plugin the same way: only load the stylesheets, javascript and other scripts that you need for that page or section of the site. At the very least, don’t load admin scripts on the frontend and vice-versa.
if(is_admin()){

 //load my plugin stuff for the admin pages

}else{

 //load my plugin stuff for the frontend

}

Rule 07: Tidy Up After Yourself

When you activate a plugin, you will see a deactivate link appear in the plugins admin page. But deactivating only stops the plugin from functioning. After deactivation, you then get a delete link. The delete link is the key to tidying up after yourself. It should really be called uninstall.
If you create a file named uninstall.php in the same directory as you plugin, the code in this file will be run when the user clicks delete.
if(defined('WP_UNINSTALL_PLUGIN') ){

 //delete options, tables or anything else

}
The above code checks for the WP_UNINSTALL_PLUGIN constant which WordPress sets when you hit delete. Then you can proceed to delete any options or custom tables that your plugin created when it was activated.

Bonus Tips

Turn on debug

The WordPress debugger will find errors in your code that while they may not crash you plugin should still be corrected to make sure that you’re doing things correctly. So, turn on WordPress debug by placing this in your /wp-config.php:
define('WP_DEBUG', TRUE);

Study the WordPress function library

WordPress often has functions that will solve a programming task in one function that you may have written many lines of code to achieve. Check out the function library to make sure you’re not writing more code than you need to.

Get some peer review

Getting others to look at your code is a strong form of quality control. Other users will find faults that you haven’t noticed in your own testing. Don’t be afraid to post your code: everyone makes mistakes.

Don’t use deprecated functions!

WordPress is full of outdated functions that while still supported for current versions may not be in future releases. You may have used code from an old tutorial. Look it up in the WordPress codex to see if it is marked as deprecated. There will be a link to the newer function.

Use a good WordPress code forum

If you have a problem, ask others. There are plenty of forums for WordPress solutions. One of my favorites is WordPress Answers from the wonderful Stack Exchange network.

Take some pride in your work!

It’s easy to release a plugin with a rider that you take no responsibility for the effects of your code. Now, that’s a necessary given: you can’t be responsible for how your plugin will be used. But you can take a professional pride in how you go about your work. Always do your best. Your reputation will be the better for it."
read more

Changing the Fonts of Your WordPress – Part 2: Theme Integration

"WordPress continually proves itself time, time, and again that it has very few limitations, and is rapidly pushing itself to being, if not the best, but certainly the most versatile CMS available. Out of the box it is certainly not perfect, but you can change it however you want. In the previous tutorial, we went over how to add fonts to your theme via a plugin. Now, we’ll integrate font options directly into the theme’s options.

Again, we will be using Google Web Fonts because it’s easy, fast and, most importantly, free. With Google Web Fonts there is no need to worry about using the proper font formats, everything is handled by Google.

Step 1 Add a Settings Page

First, make sure you have a theme options page. If you don’t know how to make one, I suggest reading Create a Settings Page by Jarkko Laine. In this tutorial, I’m going to assume that you know the basics and build from there. So let’s go into our functions.php file and add a simple typography settings page:
add_action( 'admin_menu', 'my_fonts' );
function my_fonts() {
   add_theme_page( 'Fonts', 'Fonts', 'edit_theme_options', 'fonts', 'fonts' );
}

Step 2 Add the Form

Now that we’ve added a settings page, we have to code the callback function we’re using to render the page itself, which would be typography. All we need is a basic form that shows a dropdown of all the fonts that users can choose from and allow them to change it.
function fonts() {
?>
   <div class="wrap">
       <div><br></div>
       <h2>Fonts</h2>

       <form method="post" action="options.php">
           <?php wp_nonce_field( 'update-fonts' ); ?>
           <?php settings_fields( 'fonts' ); ?>
           <?php do_settings_sections( 'fonts' ); ?>
           <?php submit_button(); ?>
       </form>
   </div>
<?php
}
Okay, we’ve added our fonts form to the page, just some basic settings_fields, but WordPress has no idea. Now we use the admin_init action to initialize our settings and add the callbacks:
add_action( 'admin_init', 'font_init' );
function font_init() {
   register_setting( 'fonts', 'fonts' );

   // Settings fields and sections
   add_settings_section( 'font_section', 'Typography Options', 'font_description', 'fonts' );
   add_settings_field( 'body-font', 'Body Font', 'body_font_field', 'fonts', 'font_section' );
}
All we’re doing here is creating a settings section for our fonts forms and the field for a single font, you can add more if you want, in this tutorial I’m only going over the body tag. Just add more by copying that field and replace body with something else like h1. We also now have a setting called fonts, where we will be storing our font data/options. Let’s go ahead and define the callback functions, font_description and body_font_field.
function font_description() {
   echo 'Use the form below to change fonts of your theme.';
}
function body_font_field() {
   $options = (array) get_option( 'fonts' );
   $fonts = get_fonts();

   if ( isset( $options['body-font'] ) )
       $current = $options['body-font'];
   else
    $current = 'arial';

   ?>
       <select name="fonts[body-font]">
       <?php foreach( $fonts as $key => $font ): ?>
           <option <?php if($key == $current) echo "SELECTED"; ?> value="<?php echo $key; ?>"><?php echo $font['name']; ?></option>
       <?php endforeach; ?>
       </select>
   <?php
}
We have to get the font options that we just made in the init action and the fonts we have available, get_fonts(). Set the current font in the form to whatever is in the options, otherwise it’ll default to Arial. Then, use a foreach loop to go through our array of available fonts. You can also add a description or make it a brief tutorial on how to use it.

Step 3 Getting the Fonts

As you noticed in the previous snippet of code, we need to define the get_fonts() function to retrieve the fonts we need. You can either include the Google Webfonts or just stick with the basic CSS fonts. We’ll just use an array to store all of the fonts, and then distinguish them by their font name. You can do this with any fonts, but for the purposes of this tutorial, we’ll just be using Arial, Ubuntu and Lobster.
function get_fonts() {
   $fonts = array(
       'arial' => array(
           'name' => 'Arial',
           'font' => '',
           'css' => "font-family: Arial, sans-serif;"
       ),
       'ubuntu' => array(
           'name' => 'Ubuntu',
           'font' => '@import url(http://fonts.googleapis.com/css?family=Ubuntu);',
           'css' => "font-family: 'Ubuntu', sans-serif;"
       ),
       'lobster' => array(
           'name' => 'Lobster',
           'font' => '@import url(http://fonts.googleapis.com/css?family=Lobster);',
           'css' => "font-family: 'Lobster', cursive;"
       )
   );

   return apply_filters( 'get_fonts', $fonts );
}
Note: You are not limited to only using Google Webfonts. If you want to use a custom font that is hosted on your FTP or on Amazon S3, then replace @import with @font-face and change the url to where your font file is hosted.

Step 4 Add the CSS

Before you apply any of fonts in your CSS, you should remove all instances of Google Webfonts of in your CSS files. This way when we make the import call to get the Ubuntu font, we’re not wasting an extra 100 ms getting the Lobster font too.
Now that we have all of our fonts set, we have to create a wp_head action that adds the styling to your WordPress. If you are using this script for multiple tags, simply duplicate the code, just changing “body” to whichever tag you’re editing.
add_action( 'wp_head', 'font_head' );
function font_head() {
   $options = (array) get_option( 'fonts' );
   $fonts = get_fonts();
   $body_key = 'arial';

   if ( isset( $options['body-font'] ) )
       $body_key = $options['body-font'];

   if ( isset( $fonts[ $body_key ] ) ) {
       $body_font = $fonts[ $body_key ];

       print_ '<style>';
       echo $body_font['font'];
       echo 'body { ' . $body_font['css'] . ' } ';
       echo '</style>';
   }
}
We start by checking if a font is chosen in our options, if not, then set the font to our default, Arial. Now we print out the style tag, the import statement and our CSS code.

What You Get in the End

This is what you should’ve ended up with:
The final font options page.

Full Source Code

For anyone who is having some trouble putting it all together. Here is the full source code, ready to just paste into the functions.php file:
<?
// Changing the Fonts of Your WordPress - Part 2: Theme Integration
// Tutorial on WP Tuts
// by Fouad Matin
// Please credit this tutorial, by putting a link back to http://wp.tutsplus.com/tutorials/changing-the-fonts-of-your-wordpress-site-part-2-theme-integration/
// Enjoy!
add_action( 'admin_menu', 'my_fonts' );
function my_fonts() {
   add_theme_page( 'Fonts', 'Fonts', 'edit_theme_options', 'fonts', 'fonts' );
}
function fonts() {
?>
   <div class="wrap">
       <div><br></div>
       <h2>Fonts</h2>

       <form method="post" action="options.php">
           <?php wp_nonce_field( 'update-fonts' ); ?>
           <?php settings_fields( 'fonts' ); ?>
           <?php do_settings_sections( 'fonts' ); ?>
           <?php submit_button(); ?>
           </form>
       <img style="float:right; border:0;" src="http://i.imgur.com/1qqJG.png" />
   </div>
<?php
}

add_action( 'admin_init', 'my_register_admin_settings' );
function my_register_admin_settings() {
   register_setting( 'fonts', 'fonts' );
   add_settings_section( 'font_section', 'Font Options', 'font_description', 'fonts' );
   add_settings_field( 'body-font', 'Body Font', 'body_font_field', 'fonts', 'font_section' );
   add_settings_field( 'h1-font', 'Header 1 Font', 'h1_font_field', 'fonts', 'font_section' );
}
function font_description() {
   echo 'Use the form below to change fonts of your theme.';
}
function get_fonts() {
   $fonts = array(
       'arial' => array(
           'name' => 'Arial',
           'font' => '',
           'css' => "font-family: Arial, sans-serif;"
       ),
       'ubuntu' => array(
           'name' => 'Ubuntu',
           'font' => '@import url(http://fonts.googleapis.com/css?family=Ubuntu);',
           'css' => "font-family: 'Ubuntu', sans-serif;"
       ),
       'lobster' => array(
           'name' => 'Lobster',
           'font' => '@import url(http://fonts.googleapis.com/css?family=Lobster);',
           'css' => "font-family: 'Lobster', cursive;"
       )
   );

   return apply_filters( 'get_fonts', $fonts );
}
function body_font_field() {
   $options = (array) get_option( 'fonts' );
   $fonts = get_fonts();
   $current = 'arial';

   if ( isset( $options['body-font'] ) )
       $current = $options['body-font'];
   ?>
       <select name="fonts[body-font]">
       <?php foreach( $fonts as $key => $font ): ?>
           <option <?php if($key == $current) echo "SELECTED"; ?> value="<?php echo $key; ?>"><?php echo $font['name']; ?></option>
       <?php endforeach; ?>
       </select>
   <?php
}
function h1_font_field() {
   $options = (array) get_option( 'fonts' );
   $fonts = get_fonts();
   $current = 'arial';

   if ( isset( $options['h1-font'] ) )
       $current = $options['h1-font'];

   ?>
       <select name="fonts[h1-font]">
       <?php foreach( $fonts as $key => $font ): ?>
           <option <?php if($key == $current) echo "SELECTED"; ?> value="<?php echo $key; ?>"><?php echo $font['name']; ?></option>
       <?php endforeach; ?>
       </select>
   <?php
}

add_action( 'wp_head', 'font_head' );
function font_head() {
   $options = (array) get_option( 'fonts' );
   $fonts = get_fonts();
   $body_key = 'arial';

   if ( isset( $options['body-font'] ) )
       $body_key = $options['body-font'];

   if ( isset( $fonts[ $body_key ] ) ) {
       $body_font = $fonts[ $body_key ];

       echo '<style>';
       echo $body_font['font'];
       echo 'body  { ' . $body_font['css'] . ' } ';
       echo '</style>';
   }

   $h1_key = 'arial';

   if ( isset( $options['h1-font'] ) )
       $h1_key = $options['h1-font'];

   if ( isset( $fonts[ $h1_key ] ) ) {
       $h1_key = $fonts[ $h1_key ];

       echo '<style>';
       echo $h1_key['font'];
       echo 'h1  { ' . $h1_key['css'] . ' } ';
       echo '</style>';
   }
}
?>

Conclusion

By now, you should know how to add a font settings page, get fonts from the Google Webfonts directory, and apply those fonts to the theme. If you have any additional suggestions or questions regarding custom typography, feel free to leave a comment!"
read more