10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)

3,943 views

Published on

Published in: Technology
1 Comment
6 Likes
Statistics
Notes
No Downloads
Views
Total views
3,943
On SlideShare
0
From Embeds
0
Number of Embeds
129
Actions
Shares
0
Downloads
0
Comments
1
Likes
6
Embeds 0
No embeds

No notes for slide

10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)

  1. 1. 10 Things Every PluginDeveloper Should Know Dave Donaldson Co-founder Max Foundry
  2. 2. Overview• Enable Debugging• Prefix Your Functions• Enqueue Scripts and Styles• Your JS/CSS On Your Admin Pages Only• AJAX in the Admin• Extensibility Hooks• Support Multisite• Internationalization and Localization• Security• Helper Functions and Constants
  3. 3. 1. ENABLE DEBUGGING
  4. 4. Enable Debugging• Don’t develop without it• Don’t develop without it• Don’t develop without it• Don’t develop without it• Don’t develop without it• Don’t develop without it• Don’t develop without it
  5. 5. Enable DebuggingIn wp-config.php, comment out this line:define(‘WP_DEBUG’, false);And replace with these:// Turns WP debugging ondefine(‘WP_DEBUG’, true);// Tells WP to log everything to the /wp-content/debug.log filedefine(‘WP_DEBUG_LOG’, true);// Doesn’t force the PHP ‘display_errors’ variable to be ondefine(‘WP_DEBUG_DISPLAY’, false);// Hides the errors from being displayed on-screen@ini_set(‘display_errors’, 0);
  6. 6. Enable Debugging• Visibility for WP errors and notices• Notices are important for deprecated functions• Becomes part of your cadence• Watch debug.log• Use Debug Bar and Blackbox plugins
  7. 7. 2. PREFIX YOUR FUNCTIONS
  8. 8. Prefix Your Functions• All functions get loaded into the same execution space…• … which requires each function to be uniquely named…• … which means you should prefix your functions
  9. 9. Prefix Your FunctionsDO NOT be generic:// Do you know how many people have// these *exact* same functions?function copy_file() {}function save_data() {}
  10. 10. Prefix Your FunctionsDO this instead:// Assuming the name of your plugin// is ‚My Awesome WordPress Plugin‛function mawp_copy_file() {}function mawp_save_data() {}
  11. 11. Prefix Your FunctionsClasses are the one caveat:class MawpCommon { function copy_file() { } function save_data() { }}
  12. 12. Prefix Your FunctionsClasses allow you to do this:$common = new MawpCommon();$common->copy_file();$common->save_data();
  13. 13. 3. ENQUEUE SCRIPTS ANDSTYLES
  14. 14. Enqueue Scripts and Styles• The WP enqueue functions are the proper way to include javascript and stylesheetswp_enqueue_script(‘thickbox’);wp_enqueue_script(‘path-to-my-script.js’, array(‘jquery’));wp_enqueue_style(‘thickbox’);wp_enqueue_style(‘path-to-my-styles.css’);
  15. 15. 4. YOUR JS/CSS ON YOURADMIN PAGES ONLY
  16. 16. Your JS/CSS On Your Admin Pages Only• Devs adding their javascript and styles to every admin page, including pages for other plugins, is a HUGE PITA• If you are one of these people, I have a bill to send you• These are your friends, and in turn, my friend: – admin_print_scripts-{hookname} – admin_print_styles-{hookname}
  17. 17. Your JS/CSS On Your Admin Pages Onlyadd_action(‘admin_menu’, ‘mawp_admin_menu’);function mawp_admin_menu() { $admin_pages = array(); $admin_pages[] = add_submenu_page(); $admin_pages[] = add_submenu_page(); foreach ($admin_pages as $admin_page) { add_action(‚admin_print_scripts-{$admin_page}‛, ‘mawp_admin_scripts’); add_action(‚admin_print_styles-{$admin_page}‛, ‘mawp_admin_styles’); }}function mawp_admin_scripts() { wp_enqueue_script();}function mawp_admin_styles() { wp_enqueue_style();}
  18. 18. 5. AJAX IN THE ADMIN
  19. 19. AJAX in the Admin• Very useful for creating an improved user experience• Consists of the following: – A nonce – A little jQuery – The wp_ajax hook
  20. 20. AJAX in the AdminA nonce:<form id=‚mawp_form‛ method=‚post‛> <?php wp_nonce_field(‚mawp_nonce_action‛, ‚mawp_nonce_name‛) ?></form>
  21. 21. AJAX in the AdminA little jQuery:<script type=‚text/javascript‛> jQuery(document).ready(function() { jQuery(‚#some_button‛).click(function() { var form_data = jQuery(‚#mawp_form‛).serialize(); form_data += ‚&action=mawp_do_stuff‛; jQuery.ajax({ type: ‚POST‛, url: ‚<?php echo admin_url(‘admin-ajax.php’) ?>‛, data: form_data, success: function(message) { // Display the message } }); }); });</script>
  22. 22. AJAX in the AdminThe wp_ajax hook:add_action(‘wp_ajax_mawp_do_stuff’, ‘mawp_do_stuff’);function mawp_do_stuff() { if (isset($_POST)) { if (check_admin_referer(‘mawp_nonce_action’, ‘mawp_nonce_name’)) { // Do some stuff $message = ‘Han shot first’; echo $message; die(); } }}
  23. 23. 6. EXTENSIBILITY HOOKS
  24. 24. Extensibility Hooks• Allows other devs to extend your plugin• A plugin with plugins is a mini-ecosystem• Actions and filters – Actions: used for executing functions – Filters: used for manipulating data
  25. 25. Extensibility Hooks• Actions – do_action() • Creates hookable location for custom actions – add_action() • Attaches a function to a hook created with do_action() – has_action() • Checks if an action has been created with do_action() – remove_action() • Removes an action that was created with do_action()
  26. 26. Extensibility Hooks• Filters – apply_filters() • Creates hookable location for custom filters – add_filter() • Attaches a filter to hook created with apply_filters() – has_filter() • Checks if a filter has been created with apply_filters() – remove_filter() • Removes a filter that was created with apply_filters()
  27. 27. Extensibility HooksAction example:function mawp_do_stuff() { do_action(‘mawp_do_stuff_before’); // Logic for doing stuff goes here do_action(‘mawp_do_stuff_after’);}add_action(‘mawp_do_stuff_before’, ‘your_before_action’);function your_before_action() { // Do stuff at the beginning of mawp_do_stuff}add_action(‘mawp_do_stuff_after’, ‘your_after_action’);function your_after_action() { // Do stuff at the end of mawp_do_stuff}
  28. 28. Extensibility HooksFilter example:function mawp_html_sample() { $html = ‘<div>’; $html .= ‘<p>Han shot first.</p>’; $html .= ‘</div>’; return apply_filters(‘mawp_html_filter’, $html);}add_filter(‘mawp_html_filter, ‘your_html_filter’);function your_html_filter($html) { $output = ‘<div class=‚outer-div‛>’; $output .= $html; $output .= ‘</div>’; return $output;}
  29. 29. Extensibility Hooks• 2 great examples: – bbPress – Shopp
  30. 30. 7. SUPPORT MULTISITE
  31. 31. Support Multisite• Important but often overlooked• Some people won’t use your plugin• Setup a local multisite install for testing
  32. 32. Support Multisiteregister_activation_hook(__FILE__, ‘mawp_do_activation’);register_deactivation_hook(__FILE__, ‘mawp_do_deactivation’);function mawp_do_activation($network_wide) { if ($network_wide) { mawp_call_function_for_each_site(‘mawp_activate’); } else { mawp_activate(); }}function mawp_do_deactivation($network_wide) { if ($network_wide) { mawp_call_function_for_each_site(‘mawp_deactivate’); } else { mawp_deactivate(); }}
  33. 33. Support Multisitefunction mawp_call_function_for_each_site($function) { global $wpdb; // Hold this so we can switch back to it $current_blog = $wpdb->blogid; // Get all blogs in the network and invoke function for each one $sql = ‚SELECT blog_id FROM $wpdb->blogs‛; $blog_ids = $wpdb->get_col($wpdb->prepare($sql)); foreach ($blog_ids as $blog_id) { switch_to_blog($blog_id); call_user_func($function); } // Now switch back to the root blog switch_to_blog($current_blog);}
  34. 34. 8. INTERNATIONALIZATION ANDLOCALIZATION
  35. 35. Internationalization and Localization• i18n: Internationalization• l10n: Localization• What’s the difference? – i18n: Changing software so it’s not hardwired to a single language/culture/locale – l10n: Adding resources to the software so that a particular language/culture/locale is supported
  36. 36. Internationalization and Localization• Don’t blindly discount non-English speaking cultures• Europe is a huge market• Some people won’t buy if not in their language• IT’S TOO EASY NOT TO DO FROM THE BEGINNING!
  37. 37. Internationalization and Localization• 4 basic functions: __(): Makes a string translatable _e(): Echoes translatable string _n(): For plural translations _x(): Provides translation context• Must type out the text domain, cannot store it as a variable
  38. 38. Internationalization and Localizationadd_action(‘init’, ‘mawp_load_textdomain’);function mawp_load_textdomain() { $languages_folder = dirname(plugin_basename(__FILE__)); $languages_folder .= ‘/languages/’; // 1st param is the text domain and must be unique, so best // practice is to name it the same as your plugin folder. The // 2nd param corresponds to a deprecated function, so you can // always set it to false. // IMPORTANT: text domain CANNOT include underscores! load_plugin_textdomain(‘mawp’, false, $languages_folder);}
  39. 39. Internationalization and Localization// Using __()$fact = __(‘Han shot first.’, ‘mawp’);// Using _e()_e(‘Han shot first.’, ‘mawp’);// Using _n()printf(_n(‘Saved %d item.’, ‘Saved %d items.’, $count, ‘mawp’), $count);// Using _x()echo _x(‘Comment’, ‘column name’, ‘mawp’);
  40. 40. Internationalization and Localization• Create the POT and MO files• These are the files that translators need• Generated by various tools – Poedit
  41. 41. 9. SECURITY
  42. 42. Security• Many WordPress vulnerabilities don’t come from the core• Data can’t be trusted• General rule: validate input, escape output• WP has many functions to help you
  43. 43. Security• For protecting against XSS attacks: esc_url() esc_url_raw() esc_js() esc_html() esc_attr() esc_textarea()
  44. 44. Security• For protecting against SQL injection attacks: $wpdb->prepare() $wpdb->insert() $wpdb->update() $wpdb->escape() esc_sql()
  45. 45. Security• For sanitizing data input: sanitize_email() sanitize_file_name() sanitize_user() sanitize_text_field() sanitize_html_class() sanitize_key() sanitize_option()
  46. 46. Security• You don’t want to be the next TimThumb• Big topic, lots to know• Tomorrow: “Secure All The Things!”, Dougal Campbell
  47. 47. 10. HELPER FUNCTIONS ANDCONSTANTS
  48. 48. Helper Functions and Constants• Useful for finding plugin and content folders• Folder locations in WP can be changed• Try to avoid hardcoded locations
  49. 49. Helper Functions and Constants• Functions: plugins_url() plugin_basename() themes_url() get_template_directory_uri() get_stylesheet_uri() home_url() admin_url() site_url() content_url() includes_url() wp_upload_dir() network_admin_url() network_site_url() network_home_url()
  50. 50. Helper Functions and Constants• Constants: DOING_AUTOSAVE WP_ADMIN WP_NETWORK_ADMIN ABSPATH WP_PLUGIN_DIR WP_PLUGIN_URL WP_CONTENT_DIR WP_CONTENT_URL MULTISITE COOKIE_DOMAIN
  51. 51. References• Debug Bar – http://wordpress.org/extend/plugins/debug-bar/• Blackbox Debug Bar – http://wordpress.org/extend/plugins/blackbox-debug-bar/• AJAX – http://codex.wordpress.org/AJAX_in_Plugins• Actions and Filters – http://wp.tutsplus.com/tutorials/plugins/writing-extensible-plugins-with-actions-and-filters/• Internationalization – http://codex.wordpress.org/I18n_for_WordPress_Developers• WordPress Constants – http://wpengineer.com/2382/wordpress-constants-overview/• Data Validation – http://codex.wordpress.org/Data_Validation – http://wp.tutsplus.com/tutorials/creative-coding/data-sanitization-and-validation-with-wordpress/• WP_Query – http://codex.wordpress.org/Class_Reference/WP_Query• dbDelta – http://codex.wordpress.org/Creating_Tables_with_Plugins
  52. 52. Thanks! Dave Donaldsondave@maxfoundry.com @arcware

×