The Difference Between WordPress Plugins, Must-Use Plugins, and Drop-In Plugins

Anyone familiar with WordPress probably has heard of plugins. They can add new functionality to any WordPress-powered site. But probably not everyone is familiar with two other types of plugins, referred to as Must-Use plugins and Drop-In plugins. Yes there are three types of plugins for WordPress: regular plugins, must-use plugins, and drop-in plugins. Each of these enables you to extend and modify WordPress features with a few clicks. This DigWP post explains the difference between all three. And as a bonus, explains a fourth way to extend WordPress, via the theme functions file. Let’s dig in..

Contents

Regular Plugins

Central to WordPress functionality is its extensibility. WordPress makes it easy for site administrators to add, modify, and remove just about anything that is needed. Simply visit the Plugins screen in the WordPress Admin Area and you’re off to the races. From there you can browse available plugins via the WP Plugin Directory, which currently offers over 59,000 free plugins. That’s a LOT of ways to customize and extend WordPress.

Screenshot showing the WordPress Plugins screen (including some added plugins)

From the simplest one-line-of-code plugins to more advanced plugins that provide many features, WordPress plugins make it easy for any admin to install and activate with a few clicks. Once activated, many WordPress plugins provide a settings screen, where users can learn more about available features and customize options to suit their needs. Other plugins do not provide a settings screen; they simply work with no configuration required.

To help users familiarize themselves with plugins and how they work, the default WordPress installation includes two pre-installed plugins:

  • Hello Dolly — a simple plugin that displays quotes from a song
  • Akismet — a more advanced plugin that can help protect against comment spam

But enough about “regular” WordPress plugins, let’s look at the next type of plugin: the Must-Use plugin..

Must-Use Plugins

Used mostly by developers and advanced users, Must-Use plugins (also known as “mu-plugins”) are installed inside of their own folder named mu-plugins, located in WordPress’ /wp-content/ directory. Here is a visual:

Screenshot showing the location of the must-use plugins (mu-plugins) directory
Note: The /mu-plugins/ directory is not included with default WordPress installations, so you will need to add it manually if you want to add some must-use plugins to your site.

To add a must-use plugin to your site, simply upload it to the /mu-plugins/ directory. There it will be enabled and loaded automatically until removed. For example, on my development sites, I always add a must-use plugin to enable strict PHP error reporting. The content of this mu-plugin is very simple, just a file header comment and one line of code:

<?php 
/*
	Plugin Name: PHP - Strict Error Reporting
	Description: Enable strict error reporting for testing PHP.
*/
error_reporting(E_ALL | E_STRICT);

After adding your must-use plugin to the /wp-content/ directory, you can visit the Plugins screen in the Admin Area. It won’t be listed along with the regular plugins, but rather is given its own sub-screen as shown here:

From the Plugins screen, click the “Must-Use” link to view a list of active mu-plugins

That’s pretty much full story on must-use plugins. There are however some important things to keep in mind when deciding to use mu-plugins:

  • Mu-plugins must be single .php files, not stored in folders
  • There are no notifications for updates for must-use plugins
  • Activation hooks are not executed in the /mu-plugins/ folder
  • Must-use plugins are active and executed until removed
  • Must-use plugins run in alphabetical order before regular plugins

Pro Tip

To change the location of the must-use directory, you can add the following definitions to your site’s wp-config.php file. Then edit the definition values with the new directory location.

define('WPMU_PLUGIN_DIR', WP_CONTENT_DIR .'/mu-plugins');
define('WPMU_PLUGIN_URL', WP_CONTENT_URL .'/mu-plugins');

To learn more about must-use plugins, visit the official documentation at WordPress.org.

Drop-In Plugins

Perhaps the most unknown type of WordPress plugin is the “drop-in” plugin. Drop-in plugins enable developers to modify numerous core features by adding specifically named PHP files to a specific location in the WordPress directory structure. Drop-in plugins are not included with WordPress by default, but rather can be added as needed by developers and site administrators.

For example, I like to add a drop-in plugin to handle any database errors. This is done by adding a file named db-errors.php to the WordPress /wp-content/ directory. Here is a screenshot showing its location:

Screenshot showing the location of the db-error.php drop-in plugin inside the /wp-content/ folder
Note: Drop-in plugins are not included with default WordPress installations, but rather are added manually on an as-needed basis.

Currently WordPress supports 12 drop-in plugins. For a current list, crack open /wp-admin/includes/plugins.php in the WP core. There you will find a function named _get_dropins() that shows all supported drop-in plugins, the file name, description, and when they are loaded. Currently looks like this:

function _get_dropins() {
	$dropins = array(
		'advanced-cache.php'      => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ),  // WP_CACHE
		'db.php'                  => array( __( 'Custom database class.' ), true ),          // Auto on load.
		'db-error.php'            => array( __( 'Custom database error message.' ), true ),  // Auto on error.
		'install.php'             => array( __( 'Custom installation script.' ), true ),     // Auto on installation.
		'maintenance.php'         => array( __( 'Custom maintenance message.' ), true ),     // Auto on maintenance.
		'object-cache.php'        => array( __( 'External object cache.' ), true ),          // Auto on load.
		'php-error.php'           => array( __( 'Custom PHP error message.' ), true ),       // Auto on error.
		'fatal-error-handler.php' => array( __( 'Custom PHP fatal error handler.' ), true ), // Auto on error.
	);

	if ( is_multisite() ) {
		$dropins['sunrise.php']        = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE
		$dropins['blog-deleted.php']   = array( __( 'Custom site deleted message.' ), true );   // Auto on deleted blog.
		$dropins['blog-inactive.php']  = array( __( 'Custom site inactive message.' ), true );  // Auto on inactive blog.
		$dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // Auto on archived or spammed blog.
	}

	return $dropins;
}

So you can use that function as a reference to add your own drop-in plugins as needed. As mentioned above, all of these drop-in files must be located in the /wp-content/ directory in order to work. They will not work if placed in any other location. Also, the file names must be exact.

Tip: Just because you can modify functionality with drop-in plugins, doesn’t always mean you should. Use caution and do your research before making changes.

After adding your drop-in plugin(s) to the /wp-content/ directory, you can visit the Plugins screen in the Admin Area. It won’t be listed along with the regular plugins, but rather is given its own sub-screen as shown here:

From the Plugins screen, click the “Drop-in” link to view a list of active drop-in plugins

That’s pretty much full story on drop-in plugins. There are however some important things to keep in mind before adding your own:

  • The best way to learn more about drop-in plugins and how they work, is to search the WordPress core for “_get_dropins()”.
  • Drop-in plugins are loaded in the order provided by _get_dropins(), and before any regular plugins or must-use plugins.
  • Drop-in plugins must be named as defined in _get_dropins(), and must be located in the /wp-content/ directory.

Bonus: Theme functions

While not technically a type of plugin, the WordPress functions.php file provides yet another way to extend and customize any WordPress-powered site. The functions file can be added to any WordPress theme, whether Classic theme, Block theme, or Child theme. Here is a screenshot showing location:

Screenshot showing the location of the theme functions.php file

Inside the functions file, you can call core WordPress functions and define your own custom functions. To get an idea of the types of things commonly done with functions.php, check out these related posts here at DigWP.com:

Any function or code that can be added via regular plugin, also can be added via the theme functions.php file. There are however some important differences:

Code added via regular plugin

  • Requires specific header text in the main plugin file
  • Plugin files usually are included in their own directory
  • Located at /wp-content/plugins/your-plugin/
  • Can be managed via the Plugins screen in the Admin Area
  • When active, plugins are executed on every page load
  • Plugin functions always are applied to the current active theme
  • Usually each plugin focuses on one specific task or feature
  • Plugins hosted at WordPress.org can be automatically updated

Code added via theme functions

  • No specific header text required
  • Located at /wp-content/themes/your-theme/functions.php
  • Functions in functions.php are not displayed on the Plugins screen
  • Executed only when the functions file exists in the active theme
  • Theme functions apply only to the theme in which they are defined
  • May contain numerous functions and codes for different purposes
  • Theme functions are updated manually, or when the theme is updated

To learn more about theme functions, check out the following docs at WordPress.org:

So that’s all fine and good, but how do you know when to use a plugin and when to use theme functions.php? Let’s break it all down with a quick wrap-up summary..

Quick Summary

So when do you use regular plugins? Must-use? Drop-in? Theme functions? Here is a quick rundown of the four different methods:

Regular plugins

Usually the best way to customize WordPress. Plugins work across all themes, and can be managed and updated via the WordPress Admin Area. Plugins provide a very robust and flexible way to extend core WordPress functionality.

If in doubt, make it a plugin.

Must-use plugins

Must-use plugins are best used for adding functions that must take precedence over regular functions and theme functions. They usually serve very specific, singular purposes, like enabling strict error reporting. Must-use functions always run before regular plugins.

Drop-in plugins

Drop-in plugins are used to customize specific core features, like handling PHP and database errors. Drop-in plugins always run before regular plugins AND must-use plugins.

Theme functions

Theme functions are best suited for adding or modifying functionality that is specific to a specific theme. Any code or functions contained within a theme’s functions.php file will be executed only when the theme is active, and will not apply to any other themes. If that sounds like you, then theme functions are the way to go. Otherwise, to add functionality that applies for any/all themes, then go with a plugin is best.

⭐ That’s all folks! Let me know if I missed anything by leaving a comment below, thanks! :)


How to Prevent Changes to Plugins, Themes, and WordPress Core Files

This is a common question I get from folks in the WordPress community. How can I “lock things down” and prevent any changes to plugins, themes, and WordPress core files. For example, how to prevent any themes and/or plugins from being updated or deleted, and how to prevent any new plugins from being installed. This is useful for certain projects where it’s necessary to lock a website to a static version. Fortunately, WordPress makes this super easy with a couple of PHP constants. Let’s take a quick look..

Contents

Prevent Changes via File Editor

Did you know that WordPress provides a Plugin File Editor and Theme File Editor in the WP Admin Area. You can find them:

  • Under the Appearance menu ▸ Theme File Editor
  • Under the Plugins menu ▸ Plugin File Editor

These tools enable admins to make changes to any plugin or theme files. Huge convenience for those that need it. For those that don’t, you can disable any changes via the file editors by adding the following line to your site’s wp-config.php file, which resides in the root WordPress directory:

// disable file changes via plugin and theme editors
define('DISALLOW_FILE_EDIT', true);

Once this line is included in the site’s configuration file, all file-editing via the Admin Area will be disabled. No menu items, no editing, nada. It’s another layer of security that effectively minimizes your site’s attack surface, so sensitive files cannot be modified by any user, including admins. This helps to protect against any changes that could compromise or crash your site.

Note: As explained at WordPress.org, disabling the file editors via DISALLOW_FILE_EDIT constant may affect any plugins that check for sufficient capabilities using current_user_can('edit_plugins'). Plugins should check if the constant is set, and if so display an appropriate error message.

Prevent All Changes via Admin Area

While the previous technique disables changes to plugins and themes via the file editors, this next technique prevents all changes to any files from inside the Admin Area. This includes:

  • Updating, deleting, installing plugins
  • Updating, deleting, installing themes
  • Updating the WordPress core files

It also includes changes made via the plugin and theme file editors. Basically this technique staticizes a site to its current version. So if that sounds like you, here is the magic code to lock it down:

// disable all changes to all files via admin area
define('DISALLOW_FILE_MODS', true);

Once this line is included in the site’s configuration file, all changes (installing, updating, deleting) to plugins and themes will be disabled. Note that the above line also disables updates to the WordPress core files, so trying to update WordPress via Dashboard ▸ Updates will not work.

Of course, it always is possible for changes to be made directly on the server via SFTP or similar method. But any file changes from within the Admin Area will be disabled completely.

Note: As mentioned, the above line disables all changes from anywhere within the Admin Area, including the file editors. So you do not need to set both DISALLOW_FILE_MODS and DISALLOW_FILE_EDIT. Just including DISALLOW_FILE_MODS takes care of everything.
Note: Be careful when adding DISALLOW_FILE_MODS to your site’s wp-config.php file. WordPress needs to be able to make changes in order to keep plugins, themes, and core files current via updates. So only disable changes if you are 100% certain that you don’t want any updates on your WordPress site.

The Difference Between Taxonomies, Categories, and Tags (Oh My!)

A common question for new WordPress users is, “what’s the difference between categories and tags?” Like everyone knows what a “category” is, but the idea of “tags” can seem very similar. And then you throw in related WordPress concepts like “taxonomy”, and things can get confusing very quickly. But no worries, it’s really not that complicated. Let’s break it down..

Contents

Taxonomies

In WordPress, Taxonomies are used to organize posts. There are different types of taxonomies. The two most familiar types of Taxonomies are Categories and Tags. Both are enabled by default when you install WordPress. So when you create a post, you can choose which categories and tags should be assigned.

Currently, WordPress provides three taxonomies by default:

  • Categories – hierarchical taxonomy
  • Tags – non-hierarchical taxonomy
  • Post Formats – non-hierarchical taxonomy

In addition to these default taxonomies, a WordPress site also may support some Custom Taxonomies that are provided by plugins. For example, an e-commerce plugin may add custom taxonomies for things like “Product Type”, “Price Range”, “Brand Name”, or any other attribute. And for each of these taxonomies, you can add any number of terms.

Note: You can learn more about Post Formats at WordPress.org.

Notice in the above list of default taxonomies, that Categories are hierarchical while Tags are not. This means that categories can have sub-categories (aka child categories), like this:

  • Hats
  • Shirts
  • Pants
  • Shoes
    • Fast shoes
    • Slow shoes
    • Nice shoes
      • Smooth shoes
      • Fancy shoes
      • Funny shoes

Categories can have as many sub-categories as needed. Tags on the other hand, are non-hierarchical, so there are no child tags or grandchild tags. It’s a “flat” taxonomy. Further, any custom taxonomies may be either hierarchical or non-hierarchical, depending on how they are configured.

Note: Some themes also provide their own custom taxonomies, although they shouldn’t. According to WordPress best practices, adding custom taxonomies is “plugin territory”. Only plugins should provide custom taxonomies.

Simple example

To illustrate, say we have a post that describes a store product, like shoes. It might have the following taxonomies (left column) and terms (right column):

Post = Shoes that don't leave any footprints

	Category:      Store
	Tags:          stealth, speed
	Product Type:  shoes
	Price Range:   $100-$300
	Brand Name:    Rolf Ahl

This shows how taxonomies are used to define relationships between posts. So on the front end, visitors can sort items based on their category, tags, product type, and so forth. Indeed, any aspect of your posts can be classified and organized with taxonomies.

Real-world example

To check out an effective use of taxonomies, visit Amazon.com and do a search for something like “shoes”. Then look in the sidebar at all the different ways to sort the results. Each of those sidebar sections (like “Shoe Size” and “Shoe Width”) are added via custom taxonomies. Amazon doesn’t actually run on WordPress, but it’s a great example of taxonomies.

Search results for 'shoe' at Amazon.comAll the sidebar options are examples of custom taxonomies.

As shown here, taxonomies enable your visitors to easily sort through your posts and find related and similar content.

Categories vs. Tags

As discussed, both Categories and Tags are types of Taxonomies. The only technical difference is that Categories are hierarchical, while Tags are not. So with categories, you can create sub-categories (or child categories). With tags, you cannot. Tags always have a “flat” organizational structure.

Other than that, the main difference between Categories and Tags has to do with scope. With WordPress:

  • Categories are used to broadly organize posts into groups
  • Tags are used to denote any specific post characteristics

I know that’s a bit abstract, so let’s go through some “real-world” examples..

Categories: real-world example

Let’s say it’s our job to clean up a house that has tons of junk in it. There are piles of stuff all over the place, and it’s our job to go in there and clean it all up. First we create two piles: “stuff that stays”, and “stuff that goes”. Those two piles represent categories.

After hauling away the “stuff that goes” pile, it’s time to organize the “stuff that stays”. Again, we use categories to make things easier. There are many ways we could categorize all the remaining items. We could organize by room, so our categories would be like:

  • Living Room
  • Kitchen
  • Bathroom
  • Bedroom

Makes sense, right? It’s the same idea with WordPress posts. Categories simply group similar types of posts together. For the purpose of organizing content and making it easier for visitors to find.

Categories: another example

Generally categories represent broad similarities among items, but you can get as specific as you’d like. For example, it’s common for a web-development site to group posts into the following categories:

  • CSS
  • HTML
  • PHP
  • JavaScript
  • Etc.

..such that each coding language gets its own category. That’s gonna keep posts broadly organized based just on the language. All posts about CSS go into the “CSS” category. All posts about HTML into the “HTML” category, and so forth.

But you can get more specific with categories. Say our tutorial site has a LOT of posts on all the coding languages. We might want to refine our categories to include version information, for example:

  • CSS
    • CSS 1.0
    • CSS 2.0
    • CSS 3.0
  • HTML
    • HTML 4.0
    • HTML 5.0
  • Etc.

Because categories can be hierarchical, we can get as specific or as broad as is necessary to organize your posts. And to organize things even further, we can throw tags into the mix..

Tags: real-world example

Returning to our “hoarder house” example, let’s look at how we can use tags to help further organize things. Recall that all the stuff currently is organized by room. So our categories are:

  • Living Room
  • Kitchen
  • Bathroom
  • Bedroom

In each room, we can further organize things by adding a tag to each item. For example, we tag the “chairs”, “tables”, “desks”, “electronics”, “clothes”, “food”, “towels”, and so on. And the nice thing about tags is that they can be added across categories. There may be “chairs” in both Living Room and Kitchen categories. Or there may be “electronics” in all categories. So when visitors arrive at your house, they can click the “food” tag and eat all of your food, regardless of which room it’s in :)

10-second summary

The difference between Taxonomies, Categories, and Tags:

  • Taxonomies are used to organize posts. WordPress provides two default Taxonomies: Categories and Tags. It’s also possible to create Custom Taxonomies. Taxonomies may be hierarchical or non-hierarchical.
  • Categories are used to broadly organize posts into groups. Categories may have a hierarchical structure.
  • Tags denote any specific post characteristics. Tags are non-hierarchical, flat organizational structure.

Resources


How to Disable Gutenberg Styles on the Frontend

By default the Gutenberg Block Editor loads its default CSS/stylesheet on the front-end of your WordPress site. This is fine for most cases, but there may be situations where you want to disable the Gutenberg styles for whatever reason. For example, my free WordPress plugin, Disable Gutenberg, enables users to disable the Gutenberg Block Editor and restore the Classic Editor. Included in the plugin settings is an option called “Enable Frontend” that lets users enable or disable the Gutenberg CSS/styles as desired. This quick DigWP tutorial explains programmatically how to disable Gutenberg styles on the front-end.

Bonus: Disable Gutenberg plugin also enables restoring of Classic Widgets!

Why?

One reason why people may want to remove extraneous/unnecessary CSS/stylesheets from loading is improved site performance. So by disabling the Gutenberg CSS when it’s not needed, that’s one less asset that needs to load for every page request. That can have a huge cumulative effect on the performance of your WordPress site.

FYI the default Gutenberg stylesheet looks like this when included in the source code of your web pages:

<link rel='stylesheet' id='wp-block-library-css'  href='https://example.com/wp-includes/css/dist/block-library/style.min.css' type='text/css' media='all' />

So you know what to look for.

Disable Gutenberg styles on the front-end

Without further ado, here is the magic code snippet sauce to add to your WordPress-powered site. You can add this code using a plugin such as Code Snippets, or you can add directly via theme (or child theme) functions.php, or add via simple custom plugin. Many ways to add the following code:

// disable gutenberg frontend styles @ https://m0n.co/15
function disable_gutenberg_wp_enqueue_scripts() {
	
	wp_dequeue_style('wp-block-library');
	wp_dequeue_style('wp-block-library-theme');
	
}
add_filter('wp_enqueue_scripts', 'disable_gutenberg_wp_enqueue_scripts', 100);

This script disables the default Gutenberg stylesheet wp-block-library, and it also disables the theme-specific Gutenberg stylesheet (if applicable) wp-block-library-theme. That’s all it does, plain and simple.

Note: To re-enable the Gutenberg styles, simply remove the above code snippet.

Bonus: Disable other block stylesheets

In general, any WordPress stylesheet can be disabled using the WP core function, wp_dequeue_style(). For example, if you are using WooCommerce and the Storefront theme, you may want to prevent their related Gutenberg Block CSS/stylesheets from loading on the front-end. To do it, modify the previous code snippet so it looks like this:

// disable gutenberg frontend styles @ https://m0n.co/15
function disable_gutenberg_wp_enqueue_scripts() {
	
	wp_dequeue_style('wp-block-library');
	wp_dequeue_style('wp-block-library-theme');
	
	wp_dequeue_style('wc-block-style'); // disable woocommerce frontend block styles
	wp_dequeue_style('storefront-gutenberg-blocks'); // disable storefront frontend block styles
	
}
add_filter('wp_enqueue_scripts', 'disable_gutenberg_wp_enqueue_scripts', 100);

The wp_dequeue_style() function is what’s doing all the work here. It is very effective and can be used to disable any stylesheet that is registered with WordPress. Check the docs at WordPress.org for more details.

One for the road..

The code techniques so far are kept very minimal for the sake of clarity. But as you probably know, there is much more that can be done when customizing asset loading and so forth. For example, you can add conditional logic so the stylesheets will be disabled only under certain conditions.

To give you an idea of the possibilities, here is a “real-world” example showing how Disable Gutenberg conditionally disables the front-end styles depending on user preference in the plugin settings.

// disable gutenberg frontend styles @ https://m0n.co/15
function disable_gutenberg_wp_enqueue_scripts() {
	
	global $wp_query;
	
	if (is_admin()) return;
	
	$post_id = isset($wp_query->post->ID) ? $wp_query->post->ID : null;
	
	$options = get_option('disable_gutenberg_options');
	
	$enable = isset($options['styles-enable']) ? $options['styles-enable'] : false;
	
	if (!$enable && !disable_gutenberg_whitelist($post_id)) {
		
		wp_dequeue_style('wp-block-library');
		wp_dequeue_style('wp-block-library-theme');
		
	}
	
}
add_filter('wp_enqueue_scripts', 'disable_gutenberg_wp_enqueue_scripts', 100);

Again this is just an example taken from an actively developed plugin. So much more is possible, as WordPress core provides all sorts of useful functions with which to work. So have fun and build something creative :)

Note: The above code snippet taken from the Disable Gutenberg plugin is for example purposes only; so don’t try to use it on any live site. Instead if you want to explore, download the plugin and examine the source code.

Related Posts

More of our posts on Gutenberg Block Editor:


Categories
Portfolio

Waitete Sawmills

This WordPress-driven website, for a saw-milling business based in Te Kuiti, milling and producing high-quality processed Radiata Pine for the building industry.

The project was contracted to Urban Legend web by Elan Design, who produced the custom designs. We converted the design to a custom WordPress theme, along with the necessary menus, posts, widgets, links etc to make the site easily editable to the client, or someone else with no knowledge of web languages.

Categories
Portfolio

Panmure Bridge Childcare

This site, for an Auckland childcare centre, was contracted to Urban Legend web via Elan Design, who provided the graphics and website content.

We coded the custom WordPress theme, comprising pages, posts and categories, widgets, etc. We installed and configured the necessary plugins.

Note that the client has yet to use the CMS to complete some of the content, including photo gallery, and events.

Categories
Otto on Wordpress

What’s new with the Customizer

Been a while since I wrote something. Let’s talk about some of the new stuff available in the Customizer.

Forget about some of part two

First, back in part two, I had a bit about Surfacing the Customizer. That bit is outdated now, WordPress does this for you in later versions. So, yeah, skip that.

Shiny new thing: Panels

Okay, so Panels aren’t that new. They were added in WordPress 4.0. Basically, they’re sliding containers for sections. Having trouble fitting all your settings on the screen? Group the various sections up into Panels. Panels show up as an item in the main list, and when you click the arrow next to them, the whole list glides off screen to show only those sections.

So, now we have four things: Panels, Sections, Controls, and Settings.

  • Panels group Sections together
  • Sections contain Controls
  • Controls are what the user changes
  • Settings define what the Controls change

Creating a panel is easy:

$wp_customize->add_panel( 'some_panel', array(
	'title' => 'Panel 1',
	'description' => 'This is a description of this panel',
	'priority' => 10,
) );

Adding a section to that panel is just as easy:

$wp_customize->add_section( 'themedemo_panel_settings', array(
	'title' => 'More Stuff',
	'priority' => 10,
	'panel'	=> 'some_panel',
) );

All that’s new is a panel setting to tell the section to go into that panel. Simple.

Active Callbacks

One of the problems with the Customizer was that it displayed settings and showed them changing on the site to your right, but the site being displayed is the actual site. Meaning that you can navigate on it. Sometimes, the controls being shown don’t necessarily apply to the actual site that you’re seeing.

Example: If you have a control to change the color of something in the sidebar, but then are looking at a page which has no sidebar, then you have no visual feedback to tell you what the change looks like.

To fix this, “active callbacks” are used.

The active_callback is simply a new parameter that you can pass into Panels, Sections, or Controls. It can contain the name of a function, and that function will be called when the page changes. The function should return true or false (or equivalent) to indicate whether or not the element of the customizer should be shown for that page.

So, if you have a whole Panel that only make sense when the user is looking at Front Page of the site (and not an individual post), then you can do this:

$wp_customize->add_panel( 'front_page_panel', array(
	'title' => 'Front Page Stuff',
	'description' => 'Stuff that you can change about the Front Page',
	'priority' => 10,
	'active_callback' => 'is_front_page',
) );

And voila, when the user is not looking at the front page, the panel simply disappears.

You can use any of the normal WordPress Template Tags for this, or write your own function if you want to be more specific about it.

If you do need to write your own callback function, note that the function receives the object in question when it’s called. So, if you attach an active_callback to a Panel, your function will get a argument of the WP_Customize_Panel object in question passed to it. Sections get WP_Customize_Section and such. You can use the information in these to decide whether the panel (or whatever) should be shown for that page.

So, how do we use that object? Well, you can use this to make whether certain controls show or not dependent on the values of other settings. All the various items you can use this on have a link back to the main WP_Customize_Manager. That class has a get_setting function, which you can use to determine what to do.

So, let’s make a control that causes other controls to appear, dependent on a setting.

First, let’s make a simple radio selection control:

$wp_customize->add_setting( 'demo_radio_control', array(
	'default'        => 'a',
) );

$wp_customize->add_control( 'demo_radio_control', array(
    'label'      => 'radio_control',
    'section'    => 'themedemo_panel_settings',
    'settings'   => 'demo_radio_control',
    'type'       => 'radio',
    'choices'    => array(
	'a' => 'Choice A',
	'b' => 'Choice B',
	),
) );

Now, we need to make two other controls, one for each choice. You can actually make as many as you like, we’ll keep it simple.

First, the control for choice A. Let’s make it a simple text control.

$wp_customize->add_setting( 'choice_a_text', array(
	'default' => '',
) );

$wp_customize->add_control( 'choice_a_text', array(
    'label'      => 'Choice A: ',
    'section'    => 'themedemo_panel_settings',
    'type'       => 'text',
    'active_callback' => 'choice_a_callback',
) );

We’ll need that callback function to detect if choice A is selected in the radio control, and return true if it is, and false otherwise. Like so:

function choice_a_callback( $control ) {
	if ( $control->manager->get_setting('demo_radio_control')->value() == 'a' ) {
		return true;
	} else {
		return false;
	}
}

You can simplify that if you like, I spelled it out with an if statement so as to be clear as to what is happening.

panel1

Now for choice B, let’s make it display a color control instead:

$wp_customize->add_setting( 'choice_b_color', array(
	'default' => '#123456',
) );

$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'choice_b_color', array(
	'label'   => 'Choice B',
	'section' => 'themedemo_panel_settings',
	'settings'   => 'choice_b_color',
	'active_callback' => 'choice_b_callback',
) ) );

And its callback:

function choice_b_callback( $control ) {
	if ( $control->manager->get_setting('demo_radio_control')->value() == 'b' ) {
		return true;
	} else {
		return false;
	}
}

panel1-b
Now, note that the callbacks are very similar. Seems like repeated code, doesn’t it? Well, it is, but remember that the $control here is the whole WP_Customize_Control object. We can use the same callback and simply check which control is calling it here instead.

function choice_callback( $control ) {
	$radio_setting = $control->manager->get_setting('demo_radio_control')->value();
	$control_id = $control->id;
	
	if ( $control_id == 'choice_a_text'  && $radio_setting == 'a' ) return true;
	if ( $control_id == 'choice_b_color' && $radio_setting == 'b' ) return true;
	
	return false;
}

So, instead of using two different callbacks, we just point our controls to this callback, which figures out what should show up for which setting. I’m sure you can simplify this further, depending on your particular needs.

One more thing: Customizing the Customizer

Not everybody likes the style of the Customizer. Maybe it clashes with your theme. Maybe you just want to tweak it a bit. Maybe you dislike that gray background color, and a more soothing blue would go better for your theme.

add_action( 'customize_controls_enqueue_scripts', 'themedemo_customizer_style');
function themedemo_customizer_style() {
	wp_add_inline_style( 'customize-controls', '.wp-full-overlay-sidebar { background: #abcdef }');
}

Or maybe you don’t think the Customizer area is wide enough… be careful with this one though, consider mobile users as well.

add_action( 'customize_controls_enqueue_scripts', 'themedemo_customizer_style');
function themedemo_customizer_style() {
	wp_add_inline_style( 'customize-controls', '.wp-full-overlay-sidebar { width: 400px } .wp-full-overlay.expanded { margin-left: 400px } ');
}

You can enqueue whole extra CSS files instead, if you like. Or, if you have special needs for javascript in some of your controls, and there’s libraries necessary to implement them, then you can enqueue those libraries here as well.

 

Categories
Otto on Wordpress

Better Know a Vulnerability: Cross Site Request Forgery (CSRF)

One of the easier to understand vulnerabilities is the CSRF. It’s also one of the most common issues we see in plugins and themes, because people rarely think about it.

Imagine that I have a form that takes input, like so:

<form action="http://example.com/example.php" method="GET">
<input type="text" name="demo" />
</form>

Now, that’s a simple form (and missing a submit button to boot), but you get the idea. It takes a text input. Presumably, something on the other end (at /example.php) processes that input, saves it in a database, something like that. Easy.

First question: Is this necessary?

The main question I see asked when this concept is explained to people is “why is this necessary?”. Some people believe that since you have to be logged in to access admin screens in the first place, then you can’t get to the forms and submit them. Why have all this protection and checking for a form submission when the form is hidden behind a login screen?

What you need to understand is the difference between “authority” and “intent“.

Authority

In real world cases where we are processing that input, we generally want to limit who is allowed to submit that form in some way. A plugin will want to only allow admins to change settings. A theme will only want to allow site owners to adjust the display of the site. Things of that nature. For these cases, we use methods of authentication.

There’s several ways to do this, we can check the current_user information. WordPress has capability checks for users to know what they are and are not allowed to do. When we check these, we’re verifying authority. Making sure that the user is allowed to do these things.

But something else that we need to check which most people don’t think about is intent. Did the user actually intend to submit that form, or did their browser submit it for them automatically, perhaps without their knowledge?

Examine that form again, and consider what would happen if you were to visit a webpage, anywhere on the internet, that contains this:

<img src="http://example.com/example.php?demo=pwned" />

Now, you might be thinking that this is a rather contrived example, and you’d be right on that score, but it serves to demonstrate the point. Your browser loads this URL and that is the equivalent action to submitting that form, with “pwned” as the text in question.

Here’s the kicker, all those authority checks do us no good in preventing this. You actually do have the authority to submit that form, and your browser, using your authority, just submitted it for you. Pwned, indeed.

(For those of you thinking “just use POST forms”, consider that javascript can submit POST forms. So that’s really no help.)

Intent

What we need is to verify intent. We need to know that the user submitted that form, and not just the browser doing it for them automatically.

WordPress used to do this (a looong time ago) using the referer. For those who don’t know, referer is a URL passed by your browser to indicate where a user came from. So one could check that the referer says that the form was submitted from the form’s page and not from some other page on the internet. The problem is that referer is not reliable. Some browsers have the ability for script to fake the referer. Firewalls and proxies often strip the referer out, for privacy concerns. And so forth.

Nonces

WordPress now does this using nonces. A nonce is a “number used once” in its purest form. Basically, it’s a one-time password. When we generate the form, we generate a number. When the form is submitted, we check the number. If the number is wrong or missing, we don’t allow the form to be submitted. A script cannot know the number in advance. Other sites cannot guess the number.

Now, technically, WordPress doesn’t use real nonces, because they’re not “used once”. Instead, WordPress nonces revolve on a 12 hour rotating system (where 24 hours are accepted). For any given 12 hour period, the nonce number for a given action will be the same. But it’s close enough to a real nonce to eliminate the issue, but notably it’s only for the issue of verifying intent. Don’t try to use WordPress nonces for anything else. :)

So, when we generate a form, we generate a nonce. This nonce is based on five things: site, user, time, the action being performed, and the object that the action is being performed on. Changing any of these gives us a different nonce.

Let’s say I want to delete a post. To do that, I need to know the nonce for deleting that specific post, as me, on my site, within the last 24 hours. Without that nonce, I cannot perform the action. More importantly, in order for somebody to “trick” my browser into doing it for me, they need to get that specific nonce and get my browser to load it within 24 hours. Tough to do. And even if they pull it off, they only have been able to perform that very specific action, the nonce obtained is useless for any other purpose. They don’t get any form of full control via this manner. They can’t make my browser do anything on mysite that they don’t have the nonce for.

Using nonces

So, let’s get down to brass tacks. Generating a nonce in WordPress is easy and can be done in many different ways depending on your particular needs. You might want to protect a simple link, or you might want to protect a form, or you might even need to protect a javascript ajax call.

Protecting a link can be done with wp_nonce_url(). It takes a URL and an action and adds a valid nonce onto that URL. It works like this:

$nonced_url = wp_nonce_url( $url, 'action_'.$object_id );

Here, we’re taking some URL, and adding a nonce onto it for a specific action on some specific object. This is important, actions and objects need to both be specified if there is some object being referred to. An example might be a link to delete a specific post. Such code would look like this:

wp_nonce_url( $url, 'trash-post_'.$post->ID )

The action is “trash-post” and the post being trashed has its ID number appended to that action. Thus, the nonce will let you trash that post and only that post.

On the other hand, maybe we have a form that we need to protect instead. Inside that form, we can add something like this:

wp_nonce_field( 'delete-comment_'.$comment_id );

This is the nonce for deleting a comment. It outputs a couple of form fields, like so:

<input type="hidden" id="_wpnonce" name="_wpnonce" value="1234567890" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />

The value for the nonce will be specific to deleting that comment, on that site, by that user.

Sometimes we just need to generate the nonce directly, in no specific format. One case might be for an AJAX type call, where the data is being submitted by jQuery. In such a case, you can use the wp_create_nonce function to get just that nonce value, like so:

wp_create_nonce( 'action_'.$object_id );

For AJAX requests, you’ll want to include that nonce value in the submitted data with a name of “_ajax_nonce”. Why that particular name? Because it’s what WordPress checks when verifying the nonce. Speaking of verification:

Verifying nonces

Generating these numbers is no good if you don’t check them as well. Fortunately, WordPress makes this easy. There’s two functions to verify incoming nonces.

check_admin_referer( 'action_'.$object_id );

The name of the function refers back to the time before nonces, when this function call was checking the referer value from the browser. Nowadays, it checks nonces instead. If the _wpnonce sent back in the form does not match the action and ID here, then this function stops further processing. This is the cause of the “Are you sure you want to do this?” screen that is sometimes reported by users. To avoid getting this screen, the nonce being checked has to match.

An alternative to checking forms or links is checking ajax requests, which is why we have this function:

check_ajax_referer( 'action_'.$object_id );

This performs the same basic check, but if it fails, it returns a simple “-1″ response and then halts processing. Your AJAX javascript code can recognise that response and take appropriate action based on it.

In either case, if the nonce fails, the script exits. No action is taken. The form is not processed, the post not deleted. That’s the sort of check you need to prevent CSRF attacks.

Bottom Line

If you have a plugin or a theme or any type of code that “does something” in WordPress, then you need to protect that action with a nonce. If you’re not protecting it with a nonce, then it’s possible for somebody else to trick your browser into performing that action on your behalf.

Also, note that it’s not enough to just name the action. You generally are taking action on some specific “thing”, and the ID of that thing needs to be included in your nonce as well. The more specific the action, the better.

Any form, any action, no matter how much “authentication” you have on checking it, can be exploited, because you’re not really authenticating the “user”, you’re authenticating that it’s coming from “the user’s browser”. You need to have something else that changes regularly, so that you can verify that the user did indeed load that particular form and submit it relatively recently, and thus probably intended to perform that action.

Nonces are easy to implement. So do it already. We have enough plugins not doing it that this clearly needs to be said. :)

Categories
Otto on Wordpress

Slides: A Presentation Theme

You know, when some people are asked to do a presentation on a subject, they start by thinking about what they’re going to say, how they’re going to say it, and what their presentation will contain.

Me, I just start writing code.

I was asked to present at WordCamp Seattle, on the specific subject of the GPL. Talking about licenses is pretty dry stuff, so I came up with some ideas and such and put them down and built a presentation. No problem. But naturally, I wanted to use WordPress to present it.

I’ve tried this sort of presentation-theme idea a couple years back, and didn’t really get anywhere good. HTML wasn’t up to the task at the time, not really. But in my searching for this again, I ran across the Google IO 2012 slides template.

It’s a neat template. Does some very cool stuff. HTML5, CSS3, clever Javascripty goodness. Bit annoying to adjust though, and very hardcoded. So, I turned it into a WordPress theme instead.

I call it “Slides”, because I’m bad at naming things.

If you want to skip straight to the download, you’ll find it at the bottom of the post, but I encourage you to read first, because if you just install it on an existing WordPress install, you’ll find your site to be instantly broken.

Now, for those people wanting to use this, note that it more or less takes over the whole WordPress install. The Posts menu is actually removed. So is Comments, for now, because I can’t think of a reasonably good way to show or allow comments on presentations yet. Might add them back later.

Since this takes over the whole WordPress install, the best way I can think to use it is on a multi-site install. I run multi-site myself, so creating a new subdomain site takes about 30 seconds. Just create a new site, give it a new domain mapping, and voila, done. So with this, I can easily pop off wcsea2013.ottopress.com as a new site, turn on the Slides theme, and create my presentation slides in there. Easy. So I recommend using this theme with multi-site if you’re planning on leaving the results online after the fact, sort of thing.

See, Presentations are not Blogs. The default WordPress “posts” model doesn’t really fit well. The “pages” model does, a bit, but there’s an inherent problem that Pages are difficult to put in a particular order. So I took a look around the plugin directory and found a plugin called Simple Page Ordering which fits the bill nicely. It lets you make all the Pages you want, and then drag and drop them in the Page list to re-order them. Very cool beans, and highly necessary for this sort of thing.

So I integrated “support” for this plugin, with the only real “support” being that if you don’t have the plugin installed, then the theme will give you a quick link to install it. :)

How the theme works:

  • The first three slides are hardcoded, the intro, the title, and the instructions.
  • Every “slide” after that is a Page.
  • There’s a custom taxonomy for picking individual slide options, which I’ll explain below
  • The Featured Image functionality is used for custom whole-slide backgrounds
  • The “Excerpt” is used as a “Presenter notes” field, which is awesome for reasons you’ll understand in a minute.

Now, let’s do a run-down of the theme:

First Slide

As you can see, it’s simply a logo with a “Follow along” message. The URL comes from WordPress itself, so it will be correct automatically. The logo can be changed through the Theme Customizer. All of the main configuration options are in the customizer in fact.

Customizer for slides

The Square Logo there, with my gravatar in it, is used on the next slide. The theme itself comes with a couple of default WordPress logos instead, BTW, not my scuba picture. :)

Second Slide

Here you can see where that square logo is used. I recommend using a transparent PNG here, for full effect. Additionally, you can see where the site title and subtitle become the name of the presentation. Just below that is the Event and Author Information, which is also configurable in the Theme Customizer screen.

Instructional Slide

The third slide is the instructions, and this is hardcoded for now. This is actually an important slide to have, because it shows that there are hotkey navigational controls. All these controls come from the original Google IO 2012 template, and boy are they cool. Look what happens when you hit P for example:

Speaker Note

Yes, those speaker notes you made in the excerpt fields pop up for the viewer to read directly. Your slides can be useful even if the person wasn’t able to attend the presentation itself. Very neat.

But the speaker notes play another important part too. There’s a hidden trick: Visit the site with the parameter ?presentme=true and you’ll get a new popup window.
(Note: Chrome’s popup blocker may block it, you’ll have to allow the popup.)
(Note 2: The theme will remember that you did this, visit it with ?presentme=false to turn it back off)

Popup Presenter Window

If you’ve used Keynote or Powerpoint’s various presenter modes, you’ll recognize this. This extra window lives separately from your main window, but has linked the navigation to it.

So, as a presenter, you’re connected to a projector or big screen. You have two screens connected to the computer, which are separate. You open the browser to your site, add the presentme=true parameter, and get this second window. You keep the second window on your display, and the main window on the big display (with the handy F hotkey to switch them both to fullscreen). When you click to the next slide in either window, both windows will change. You can see the next slide and your notes for this slide on your window only. And you don’t need anything more than a web browser; no presentation software required. Just a web browser, on any computer connected to the screens.

Speaking of any computer, the presentation looks pretty good on a touchscreen device too. Even takes advantage of touch motions for flipping slides. :)

You can press O to get an overview mode.

Overview mode

Want a full screen background in a particular slide? Set a Featured Image on that Page.

Full slide background

The normal black border background around the whole presentation is fully customizable too, in the Theme Customizer. It uses the normal WordPress Custom Background functionality for that.

Images and links work too. This is the web, after all.

Images in Slides

Now, these are slides, so the fonts need to be pretty big. If you find that the space is too limiting, then one of the available options in the custom taxonomy that Slides offers you is called, oddly enough, “smaller”. It makes somewhat smaller text.

Smaller text

Ooh, that page number doesn’t look too good in the bottom right though. No matter, there’s a “nobackground” option to eliminate that page number on specific slides:

No background

Not every slide has to look exactly the same though. Here’s a “segue” slide, which is a useful layout from transitioning from one larger idea to another. Note that the “title” is at the bottom, in lighter colored text, and the content goes up top.

Segue Slide

Finally, of course, there is a thank you slide, with a different layout entirely. Useful for the ending of a presentation. :)

slidesthankyou

There’s a “dark” option too, but the colors still need some work on that, so the less said, the better. The theme is a work in progress after all.

And being a work in progress, it’s still partially broken. :)

  • The Taxonomy stuff needs improvement. Right now, it has problems removing the items. Taxonomy was not meant to work with checkboxes, really.
  • There is a “build” class which you can add to any top-level wrapper (like a UL surrounding LIs), and this will cause fade-ins. That is, instead of going to the next slide, each line-item will fade in. The build class actually works on any nested tags, so a DIV with class=”build” that is surrounding P’s causes the fade-in effect to work just as well. But how to make that “easy” in the visual editor? I’m not sure.
  • The theme includes the “pretty print” code for doing code highlighting. Wrap the code in a PRE, give it a class=”prettyprint” and a data-lang=”language” for the language, and it will do code highlighting. However, the pretty print code in the original template did not include PHP, so I’ve added one I found elsewhere. But it needs testing. Additionally, in your “pre” code, add some B tags to surround a significant section. This will make the “H” hotkey cause the other code to fade-out when pressed, highlighting the code you want to draw attention to. This is all useful stuff, but a bit hard to use in the editor and thus needs a bit more work.

I’ve been screwing around with this for a while, and not making any real progress. But as they say, real developers ship, so what the heck. This is version 0.1-alpha-whiskey-tango-foxtrot. Try it out, on a test site. Use it for a presentation. Improve upon it. Send me patches.

But here’s the best thing about this theme: it works for the intended purpose. I presented using it at WordCamp Seattle… using nothing but my Chromebook. The Chromebook runs ChromeOS, which is little more than a glorified web browser. It has no other software but Chrome on it. But it does have a DisplayPort output, and with an HDMI converter cable, I connected it, dragged the main window to the big screen, and presented just fine with it. The browser alone is more than enough to do a presentation with. :)

DownloadDownload Slides-0.1.zip

Categories
Otto on Wordpress

I’m not a fan of orange…

blue
I’m not a fan of the color orange. Dunno why. I prefer soothing and relaxing colors, like blues and greens.

But the new Twenty Thirteen theme for the next version of WordPress is very, very orange.

Since I like to run the default themes over on my other site, this clearly could not stand.

So, I did a palette swap. Basically, I took the three header images, and swapped the Red and Blue channels, leaving the Green channel alone. Easy enough to do in Photoshop.

Then, I made a child theme, and put some minimalist code in the functions.php file to fiddle with the default header images to use the ones from my child theme instead of the normal ones. Finally, I did a search and replace for all the color references in the style.css file, swapped the R and B values in them, then put them in my new style.css file.

The result you can see over on my other blog. Yes, I know I don’t write often enough. Hell, I’ve been busy.

Child themes are fun to mess with. Here’s a copy if you want it for anything.

Twenty Thirteen – Blue

Enjoy! :)