Upload
barry-kooij
View
1.940
Download
2
Embed Size (px)
DESCRIPTION
The Plugin Development presentation I gave at WordCamp Norway 2014
Citation preview
Plugin DevelopmentWordCamp Norway 2014
Barry Kooij
• Senior Web Developer @ Yoast
• WordPress SEO (Premium),What The File, Sub Posts
• Contributor EDD, EDD extensions
• Moderator WPNL forum
• Twitter: @cageNL
Agenda
• Presentation
• Q&A
• Personal Q&A
Let’s get coding!
Hold up!
There more to a good plugin than good code!
Wait, what?
My Setup
My Setup
• MacBook Pro Retina
• PhpStorm
• GIT -> GitHub
• Vagrant w/ Varying Vagrant Vagrants (VVV) -10up
Debugging
Debuggingdefine( 'WP_DEBUG', true ); if ( WP_DEBUG ) { define( 'SCRIPT_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', true ); @ini_set( 'display_errors', 1 ); }
display_errors = On; error_reporting = E_ALL | E_STRICT;
Xdebug
WordPress Core
Open source
• WordPress is open source
• No really, literally OPEN SOURCE
• The code and documentation is all in your project
• Try command clicking a function
API• Dashboard Widgets API
• Database API
• HTTP API
• File Header API
• Filesystem API
• Metadata API
• Options API
• Plugin API
• Quicktags API
• Rewrite API
• Settings API
• Shortcode API
• Theme Modification API
• Theme Customization API
• Transients API
• Widgets API
• XML-RPC WordPress API
• Image Manipulation API
Hooks & Filters
• add_action( ‘hook_name’, ‘my_hook_callback’ );
• do_action( ‘hook_name’ );
!
• add_filter( ‘filter_name’, ‘my_filter_callback’ );
• $new_value = apply_filters( ‘filter_name’, $old_value );
JavaScript Hooks
• JavaScript events
• $('body').bind(’event’, function(event, the_value) { });
• $('body').trigger(’event', [ value ]);
Backwards Compatibility
Backwards Compatibility
• Don’t remove code, deprecate it
• Don’t change unit tests but add new unit tests to test your update
Code Standards
Naming Conventions
• function some_name( $some_variable ) { [...] }
• class Walker_Category extends Walker { [...] }
• class WP_HTTP { [...] }
• my-plugin-name.php
• class-my-class.php
Databases
• Always use the WP API!
• $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE `ID` = %d", $id );
PHP standards• if ( contidion )
• my_function( $parameter )
• $array[‘index’]
• $array[ $index ]
• WordPress coding standards configuration for PhpStorm by Rarst:https://gist.github.com/Rarst/1370155
Yoda Conditions
if ( true === $the_force ) { $victorious = you_will( $be ); }
!
A little bizarre, it is, to read. Get used to it, you will.
Code Templates
Code Templates
• Predefined code with parameters
• https://gist.github.com/barrykooij/7632945
The project
Open source your code!
What is someone ‘steals’ my code?!
What is someone tells me it’s poorly written?!
Open source your project
• Yes, it’s definitely scary.
• It’s what drives our community
• It’s the future, not only of code
Versioning
• Work with major, minor and bugfix release (x.y.z)
Changelog
• Always keep a public change log
• Give props to other people
WordPress.org Repository
WordPress repository
• Use a header image
• Have clear description what your plugin does
• Non consumers rate by downloads combined with rating
Ask for ratings
• Users don’t mind rating your plugin
• Don’t ask right away, let the user use your product first
• Make it a optional, and make this very clear!
Performance
Object Orientated Programming
• Write OOP code, period.
• Don’t know how? Learn it!
Conditional loading of code
• Don’t load every class on every page load
• Don’t initialise every class on every page load
• Split frontend and backend classes - is_admin()
• Use an autoloader
Documentation
Code documentation
• Write code documentation, people will love you for it!
• Write inline documentation directly after the function declaration
• You won’t ‘forget’ writing it afterwards
• You’re making yourself rethink what you function should do
• All good IDE’s will use the inline documentation for autocompletion
Inline documentation
• Explain what you’re doing
• Explain why you’re doing it
Security
Sanitizing data
• Checking if data is of an expected structure (e.g. email)
• is_email
• Reformatting data so it will be of expected structure (e.g. title)
• sanitize_title
http://codex.wordpress.org/Data_Validation#Input_Validation
Escaping data
• Prevent XSS attacks, escape your data!
• esc_url
• esc_html
Capabilities
• Is the user allowed to do this?
!
// Check capabilitiesif ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Cheatin’ uh?' ) ); }
Direct file access
• Don’t allow direct access to files
• Place this at the top of your files:
if ( ! defined( 'ABSPATH' ) ) { header( 'HTTP/1.0 403 Forbidden' ); die; }
Asynchronous Javascript And XML
AJAX
AJAX allows you to run server side scripts asynchronous
WordPress made AJAX really simple!
Register the AJAX action
• Tell WordPress your plugin is accepting AJAX requests
• add_action( ‘wp_ajax_my_ajax_action’, array( $this, ’callback’ ) );
• add_action( ‘wp_ajax_nopriv_my_ajax_action’, array( $this, ’callback’ ) );
Use jQuery to do the POSTjQuery.post( ajaxurl, { action : 'my_ajax_action', ajax_nonce : jQuery(‘.wpseo_redirects_ajax_nonce').val(), my_var : my_val }, function (response) { // Do something } );
Internationalisation
Make your plugin translatable
• load_plugin_textdomain( ‘my-textdomain', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
!
• __( ‘My String’, ‘my-textdomain’ );
• _e( ‘My String’, ‘my-textdomain’ );
Generate a .pot file
Unit Tests
An automated piece of code that invokes your application code to check a single assumption.
Unit Test examplefunction test_get_single_role_by_user_query() {
// Arrange $this->factory->user->create_many( 2, array( 'role' => 'subscriber' ) );
// Act $wp_user_search = new WP_User_Query( array( 'role' => 'subscriber' ) ); $users = $wp_user_search->get_results(); // Assert $this->assertEquals( 2, count( $users ) ); }
Code
Loading your plugin
// Create object - Plugin init add_action( 'plugins_loaded', create_function( '', 'new MyPlugin();' ) );
Plugin DIR & FILE
if ( ! defined( ’X_PLUGIN_DIR' ) ) { define( 'X_PLUGIN_DIR’, plugin_dir_path( __FILE__ ) ); }
if ( ! defined( ’X_PLUGIN_FILE' ) ) { define( ’X_PLUGIN_FILE', __FILE__ ); }
Namespaces are great!
But, you can’t use them.
Prefixing
• WordPress : PHP version 5.2.4 or greater
• Namespaces : 5.3.0 or greater
• Prefix your classes
• class WPSEO_Admin { [...] }
Test your plugin on PHP 5.2
Thank you. !
Find me on Twitter: @CageNL