In my new position at WebDevStudios, I’m wading deep into the world of WordPress multi-site functionality. In version 1.2 of Toppa Plugin Libraries, there’s a new method which makes it easy for plugin authors to make their plugins WordPress multi-site compatible. It is based on the excellent code Shibashake made available for doing this. I took that articles’s 3 separate (but almost identical) functions for activating, deactivating, and uninstalling a plugin, and abstracted them into a single method. Why? Because “duplicate code is the root of all evil in software design.”
As a plugin author, all you need to do is write your activation or deactivation function as you normally would, and then:
$functionsFacade = new ToppaFunctionsFacadeWp(); $functionsFacade->callFunctionForNetworkSites('yourActivationFunction');
This will call your activation (or deactivation) function for every site in the network, including the parent site.
Or in an object context, after passing the FunctionsFacade to your object:
$this->functionsFacade->callFunctionForNetworkSites(array($this, 'yourActivationMethod'));
For uninstalling, you need to pass a 2nd argument, which indicates that the “networkwide” flag should not be checked (for some reason, WordPress multisite uses this flag for activating and deactivating plugins, but not for uninstalling).
$this->functionsFacade->callFunctionForNetworkSites(array($this, 'yourUninstallMethod'), false);
I’m going to release the next version of Shashin soon, which uses this method to make it multi-site compatible, so I wanted to get this Toppa Plugin Libaries release out first. Enjoy!
In the last episode of WP Late Night, there was a brief debate about plugin size. Ryan expressed a preference for smaller plugins with tightly focused functionality. It’s natural to worry that, as the number of lines of code increases, so does the likelihood of bugs, and performance slowdowns.
This concern makes sense if you’re assuming plugin code is not very well organized and not very well tested. Unfortunately, that’s a safe assumption with many plugins. As plugin authors, we should have higher standards for our work. There are two things that come to mind:
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason – including blind stupidity.
Wulf, W. A. “A Case Against the GOTO,” Proceedings of the 25th National ACM Conference, August 1972, pp. 791-97.
The rule of thumb is to optimize for readability and maintainability first. If a performance problem comes up, it is likely stemming from a small area of the code, and you can focus your performance optimization efforts there. As one person put it: “There is far, far more money wasted on fixing and customizing and maintaining hard-to-read code than there is lost on inefficient code.”
There are many techniques involved with writing clean code. A foundational one is following the Single Responsibility Principle (SRP). Bob Martin has a very succinct definition of the SRP: “a class should have only one reason to change.” In his book Agile Software Development, he explains further:
If a class has more than one responsibility [more than one reason to change], then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the ability of the class to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.
If you follow the SRP, then it doesn’t matter how big your plugin is. What matters is how you use it.
The trick, of course, is figuring out what it means to have a single responsibility. WordPress itself helps you figure this out. When you call a WordPress hook or filter, it’s likely that you will want to create a class that implements what you intend to do for that hook or filter call. For example, if you call add_shortcode
, then you should have it instantiate a class that implements your shortcode. If that class needs to change, it will be only because your needs for the shortcode have changed. The shortcode logic is not tightly coupled to other parts of the code. Removing that coupling is an important step towards also removing that sinking feeling of fear when you start monkeying with the innards of some gigantic application.
Not every hook and filter call deserves its own class. Some are merely stepping stones to others and do not need their own class. For example, if you call admin_menu
simply for the sake of calling add_options_page
, one class is enough. Others may need more than one class to support them. But for getting your feet wet, having a class per hook or filter is a good place to start.
My Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" has a total of 55 classes and subclasses (you can see the code on GitHub). How can you find what you’re looking for in all those classes? It sounds horribly bloated for a WordPress plugin, right? It’s actually the opposite.
A coding habit that goes hand in hand with the SRP is the use of meaningful names. Each class in Shashin serves a specific purpose, and has a name that tells me what it does. If I need to make a change to the settings, I go to the Settings class; if I need to make a change to how album synchronizing is done with Picasa, I go to the PicasaSynchronizer class, etc. The majority of the classes are less than a couple hundred lines. With small, well-named classes and methods with clear purposes, when there is a bug, it’s usually not hard to find. And if I need to change something, I can make that change in one place with a greatly reduced fear of breaking something unrelated.
By using a class autoloader, such as Post to Post Links II error: No post found with slug "toppa-plugin-libraries-for-wordpress", you can also save yourself the trouble of figuring out where to put require_once
statements, for loading your class files. With an autoloader, a class file is loaded only when “new” is called (so if you are worrying about performance with so many objects, they are only loaded when they are actually needed). How you keep track of object dependencies, and when and how you instantiate your classes, are what I’ll write about in my next post, which will cover using an injection container.
A feature of WordPress 3.3 is the new QuickTags API, which makes it possible for developers to add buttons to WordPress’ HTML Editor button bar. My Extensible HTML Editor Buttons plugin uses this API to allow non-developers to easily add buttons. It includes a WYSIWYG settings form for creating new buttons. You can use it to specify the label for your button, the tag you want it to insert, and whether it is a self-closing tag (such as an <img> tag). If you’re comfortable with HTML (and you should be, since you’re using the HTML Editor!), you can also create a custom dialog for your button to launch. This is handy if your tag has multiple attributes (such as class, title, etc). And for plugin developers, it has an API that uses a simple method call where you can register your own button. This is useful if, for example, your plugin uses a shortcode and you’d like to create a button for it, without having to delve into the QuickTags API yourself.
Something I quickly learned working with the QuickTags API is that it’s fairly limited. It’s really designed just for adding simple buttons. Supporting custom dialogs through it required me to do some jQuery gymnastics – see my buttonController.js file if you want the gory details.
If you’re interested in the QuickTags API itself, the qt.addButton function in wp-includes/js/quicktags.dev.js has detailed explanatory comments, and there’s a good, simple working example in this gist file.
Aficiondos of toppa.com (if there are any such people) may notice this plugin sounds a lot like my old Koumpounophobia plugin. That plugin did a lot of jQuery-based scraping of the HTML Editor to make it possible to add custom buttons, since there didn’t used to be an API, and it ceased to work with the rewrite of QuickTags in WordPress 3.3. Also, the name I gave it was a poor choice (it means “fear of buttons” – totally obscure and a little too clever…). So I took the opportunity to re-write it and give it a much more descriptive name.
This past summer I started attending the Philly WordPress meetups, which led to an opportunity for me to speak at Philly WordCamp, which led to an amazing opportunity to work at WebDevStudios, with an amazing team. Today – Monday – was my first day on the job. I’m doing custom development work and soon I’ll get involved with project management. I’m starting with some enhancements to Baja.com. Friday was my last day at Penn, so my head is spinning a bit from the transition.
I’ve been part of the web team in Penn’s School of Medicine since 2004, and I’ve been Director for the past 2 years. My team had a lot of demands placed on them, with the need for projects outpacing what we could provide. One of the first things I did as Director was learn Agile practices so I could teach them to my team (and I brought in a scrum coach to help). These two graphics illustrate the two primary challenges we faced – not enough staff, and too much chaos:
For many months my work spilled over into nights and weekends as I tried to move things forward. I can’t say we entirely solved these problems, but we made a lot of progress, and got the wheels turning in higher levels of administration to address the situation (“turning the aircraft carrier,” as one of our project managers put it – change is not easy to implement in a huge institution). Deciding to leave was hard, but an opportunity to turn my WordPress plugin development hobby into a job, to work with Brad (@williamsba) and the WebDevStudios team, and having the flexibility of working at home… it was too good to pass up. I’m especially looking forward to having more time to code again. If the past 2 years have taught me anything, it’s that I have a passion for software development, and always striving to do it better.
WordPress 3.3 introduced a new, unified media menu, where the functionality that used to be accessed through several different menus is now all in one. If you are a plugin developer, and you want to create a custom media menu, you will discover WordPress’ media menu is an arcane and fickle beast. The general reason it’s challenging to work with is that the media menu lacks a complete API. I put several hours of code archaeology work into teasing out its functionality, so this post can guide you through using it. There are two approaches.
The WordPress media menu is displayed using ThickBox. One approach is to simply invoke ThickBox directly from your own media button, and not rely on WordPress’ filters or hooks beyond that. This is the simplest approach, and is suitable for many purposes, but it prevents you from using WordPress’ filters and hooks for applying stylesheets to it, or using menu tabs. This is the approach used by the Gravity Forms plugin. Here is the relevant parts of the Gravity Forms code, slightly re-arranged, to show how it all fits together:
add_action('media_buttons_context', array('RGForms', 'add_form_button')); public static function add_form_button($context){ $image_btn = GFCommon::get_base_url() . "/images/form-button.png"; $out = '<a href="#TB_inline?width=480&inlineId=select_gravity_form" class="thickbox" id="add_gform" title="' . __("Add Gravity Form", 'gravityforms') . '"><img src="'.$image_btn.'" alt="' . __("Add Gravity Form", 'gravityform') . '" /></a>'; return $context . $out; }
if(in_array(RG_CURRENT_PAGE, array('post.php', 'page.php', 'page-new.php', 'post-new.php'))){ add_action('admin_footer', array('RGForms', 'add_mce_popup')); }
send_to_editor
passes the resulting Gravity Forms shortcode to the editor window. After that is the html code that displays the form. The display: none
style is important: the form is hidden at the bottom of the editor page, and then shown in the ThickBox window when the media button is clicked (the media button link refers to the id of this div). I’ve also removed the input form, which has all its CSS styling done inline (with this approach, there’s no straightforward way to call an external stylesheet).
function add_mce_popup(){ // ...not shown - javascript that reads the form inputs window.send_to_editor("[gravityform id=\"" + form_id + "\" name=\"" + form_name + "\"" + title_qs + description_qs + ajax_qs + "]"); // ... <div id="select_gravity_form" style="display:none;"> // ...not shown - html for the form }
Due to a code change in WordPress 3.3, you can no longer use your own media button if you want to create a menu with custom tabs (or, at least, I couldn’t figure out how). With this approach, your menu will be accessible as a new tab in WordPress 3.3’s unified media menu. I’ll use code from my Shashin plugin as an example.
$tabs
contains the pre-defined WordPress menu tabs)
add_filter('media_upload_tabs', array($this, 'addMediaMenuTabs')); public function addMediaMenuTabs($tabs) { $shashinTabs = array( 'shashinPhotos' => __('Shashin Photos', 'shashin'), 'shashinAlbums' => __('Shashin Albums', 'shashin') ); return array_merge($tabs, $shashinTabs); }
media_upload_*
action to register the functions that will load the contents for the Shashin menus. It’s crucial that the last portion of the action name match the array keys added to the tabs in the previous step.
add_action('media_upload_shashinPhotos', array($this, 'initPhotoMediaMenu')); add_action('media_upload_shashinAlbums', array($this, 'initAlbumMediaMenu'));
admin_print_styles
with -media-upload-popup
lets you pass your own css file to the media menu, for your custom tab. wp_iframe
loads your html into menu.
public function initPhotoMediaMenu() { add_action('admin_print_styles-media-upload-popup', array($this, 'displayMediaMenuCss')); return wp_iframe(array($this, 'mediaDisplayPhotoMenu')); }
public function displayMediaMenuCss() { $cssUrl = plugins_url('/Display/', __FILE__) .'media.css'; wp_enqueue_style('shashinMediaMenuStyle', $cssUrl, false, $this->version); }
media_upload_header
loads the menu tabs. After that, put in your javascript and html for what you want to display for this tab. Like the Gravity Forms example above, you need to call WordPress’ send_to_editor javascript function to insert the final result into the editor.
public function mediaDisplayPhotoMenu() { media_upload_header(); // ... not shown - javascript and html for the menu }
Before WordPress 3.3, the Shashin plugin had its own media button, that launched a media menu with two custom tabs. From what I can tell, there is no straightforward way to do this in WordPress 3.3. It used to be possible to have tabs that were independent of the tabs that are part of the standard WordPress media uploader. But now if you want to have custom tabs, you can’t have them as part of a custom menu – you have to add them to the existing media uploader tabs. So for Shashin, I decided to take this approach, as the only alternative would be to add two buttons to the media button bar, and have two separate media menus instead of one menu with two tabs.
Update 12/13: the Shashin media menu is not working in WordPress 3.3. I’ll see how they’ve changed the media menu and try to have a fix in the next few days. In the meantime, you can still add shortcodes by hand (you can see the album ids and photo ids in the Shashin Tools menu).
Update 12/14: ….And I just uploaded a fix – version 3.0.9. Note that the Shashin media menus are now available as tabs within WordPress 3.3’s new, unified media menu. So Shashin no longer has it’s own media button. I’ll explain why in an upcoming post.
Last night I uploaded Shashin 3.0.8. If you were browsing photos in one album after another, in some circumstances you’d get spurious Highslide navbars stacking up on the top left side of the page. It’s fixed now. It had to do with the complexities of having different kinds of photo groupings going on at the same time in Shashin – there can be multiple groups of albums on a page, groups of photos within albums, photo-by-photo navigation within Highslide, and “page-by-page” navigation using the Shashin “next” and “previous” links. Getting all of them working together seamlessly has proven to be the most challenging (and therefore rewarding!) part of working on Shashin.
I expect this to be the last maintenance release for Shashin 3.0 (knocking on wood, crossing fingers…). For 3.1 I am planning to add support for Highslide thumbstrips and introduce lazy loading of the photos. I had done some initial work on adding Flickr support, but the Flickr API is fairly complex, so I’m going to put off Flickr to version 3.2, as I’ve been getting a lot of requests for the thumbstrips feature.
Please use the comments section for any support questions.
Video of my Clean Code for WordPress presentation at WordCamp Philly is available at wordpress.tv. You can also check out the other presentation videos available so far. Every session was recorded, so eventually they’ll all be online (Doug Stewart is doing a great job editing them, so they’re worth the wait). Poka Yoke Design provided the photography, and they’ve posted a bunch of great pictures. Here are a few they took of me.
Update 11/21: I’ve upload Shashin 3.0.5, which fixes this issue, reported in the wordpress.org forums
I uploaded two updates to wordpress.org last night – one for Post to Post Links II error: No post found with slug "shashin-wordpress-plugin" and one for Post to Post Links II error: No post found with slug "toppa-plugin-libraries-for-wordpress". They address a couple bugs in Shashin:
Another cause of the album thumbnail clicks not working is the jQuery form validation plugin. This plugin comes with the Arras theme. I’m still investigating why (there are no forms in Shashin, so offhand I don’t know why there would be a conflict). If you want to temporarily disable the form validation in Arras, go to line 46 in its header.php file and comment it out, like this:
//wp_enqueue_script('jquery-validate', get_template_directory_uri() . '/js/jquery.validate.min.js', 'jquery', null, false);
The Toppa Plugin Libraries update also include a new class for simplifying management of plugin settings (for any plugin that wants to use it). I’ll document it shortly.
Please use the comments section of this post to report any other issues.
I uploaded some Shashin fixes yesterday. Thanks everyone for the feedback. These were the changes:
Please use the comment section for reporting problems. I have a hectic week coming up, so it may take me a few days to respond to feedback. Thanks for your patience.
Update 11/21: Video of my presentation is now available at wordpress.tv, and I put up a post yesterday with more pictures.
WordCamp Philly this past weekend was a blast, and I met a lot of great people. The vibrancy of the WordPress community here in Philly is impressive. Giving my Clean code for WordPress presentation was also a lot of fun. I got vigorous agreement from the audience that more evangelism for clean code in WordPress plugins is definitely needed. Video of my presentation will be online at wordpress.tv in a few weeks.
The youngest attendee was 10 years old. He came to the developers’ day on Sunday too. The organizers were planning to guide him through fixing a bug in WordPress core, so he could be the youngest contributor to WordPress and get his name on the official credits. I spent the developers’ day getting started on adding Flickr support to Post to Post Links II error: No post found with slug "shashin-wordpress-plugin". I’m not a Flickr user, but I was sitting next to Captin Shmit, who is, and he had a lot of useful suggestions. Thanks Captin! (yes that’s how he spells it).
Below are the slides from my presentation (if you click the link, it will take you to slideshare.net, where you can also see my notes for the slides).