API Authentication discussion!

I was chatting with @rmccue and we though it’d be a good decision to have an open discussion regarding potential avenues for API Authentication on Thursday, February 18th at 22:00 UTC in the #core-passwords channel in Slack.

We’ll be addressing everything from OAuth 1.0a, OAuth 2.0, Application Passwords, and what limitations should be used to scope assorted tokens.

Relevant background reading: http://stephanis.info/2016/02/14/on-core-rest-api-authentication/

#api, #application-passwords, #authentication, #rest-api

Customizer Improvements in 4.0

Building on the addition of Widgets to the Customizer in 3.9, and alongside my GSoC Menu Customizer project, @westonruter, @ocean90 and I have been working on a series of Customizer improvements for 4.0. In this post, I’ll summarize the changes and proposed changes that we’d like to get in before beta. Anything with an asterisk (*) still needs to be committed but has a patch. Keep in mind that everything here is liable to change before 4.0 is released.

We currently have eight enhancements and feature requests that need to be completed before beta, but half of them are already marked for commit and all have patches. If you’re interested in helping out with these changes, we could still use help reviewing and testing many of them (especially for UI/UX). Huge thanks to everyone who’s helped out so far this cycle.

Terminology Notes

We recently renamed the Appearance trac component to Customize. I’d like to clarify a few things regarding terminology used to describe the Customizer:

  • We’re shifting toward using “Customizer” rather than “Theme Customizer”, as it isn’t necessarily theme-specific (though most of its uses currently are).
  • “Customize” is the action, “Customizer” is the thing. Most UI elements use “Customize” or “customizing”, but most documentation should probably use “Customizer”. If you’re questioning which to use, consider whether you’re looking for a noun or a verb and pick accordingly. Feel free to conjugate the verb form (eg. “customizing”).
  • “Customize” could refer to anything. That’s the point; it could be used to customize any part of a site. The Customizer can be used for anything, and we’d like to encourage more experimentation with different uses of the Customizer.

UI Changes

In 4.0, most of the Customizer UI changes are for the Customizer itself; the user experience inside the Customizer. I’m expecting a focus on the experience of accessing and navigating through the Customizer in future releases. In 4.0:

  • Widget areas are all grouped into a “Widgets” context, implemented via the new “Panels” API. Panels are a way to group Customizer sections, just like sections are a way to group controls. Panels slide over to the side, rather than expanding down, and contain vertically-expanding sub-sections. This could use some more work on the UI/UX side, see #27406 for details.
  • Only show “You are previewing / [theme name]” and the theme details & screenshot section when the Customizer is previewing an inactive theme. Otherwise, show “You are customizing / [site title]”, with a short description of the customizer. This matches panel headings, which are displayed as “You are customizing / [panel title]”, with the panel description as that heading section’s contents. #28550.
  • Replace Customizer close button with an “X” icon. This fits better with the arrow icon used to exit panels and makes the Customizer controls feel more like a modal/panel that is contextual to the front-end of the site, rather than a confusing mix between the admin and the front-end. We’d also replace the mess of buttons in the theme-install previewer (which looks like the Customizer) with icons and move them around. #28655.
  • Prevent loss of unsaved changes in the Customizer by warning users with an AYS if they try to close the customizer and there are unsaved changes. #25439.
  • Always return to the screen that the Customizer was opened from in the admin, like on the front-end. Look for more work here in the future. #25457.
  • All core customizer controls now support descriptions (#27981), complementing the ability to add descriptions to sections and panels. We could potentially add descriptions to some core controls if they seem needed, might want to do a UI/UX audit of the core Customizer controls and/or user testing.

Here’s a screencast demonstrating some of these UI changes:

API Additions & Improvements

Customizer Panels

The Customizer now includes a new way to group options together: panels. Just like a section is a container for controls, a panel is a container for sections. This was implemented in #27406. The Panels API is easy-to-use and works almost identically to the existing customizer section API. Add a panel with the following, within the customize_register action:

$wp_customize->add_panel( 'panel_id', array(
	'priority'       => 10,
	'capability'     => 'edit_theme_options',
	'theme_supports' => '',
	'title'          => '',
	'description'    => '',
) );

As always, only use the arguments where you aren’t using the default values. Note that the panel will not be displayed unless sections are assigned to it. To add a section to a panel, just use the panel id for the new panel argument:

$wp_customize->add_section( 'section_id', array(
	'priority'       => 10,
	'capability'     => 'edit_theme_options',
	'theme_supports' => '',
	'title'          => '',
	'description'    => '',
	'panel'  => 'panel_id',
) );

You may notice that $wp_customize->add_panel and $wp_customize->add_section have the same arguments (other than panel, of course). This is because panels are a special type of section; technically speaking, WP_Customize_Panel extends WP_Customize_Section. Your sections are backwards-compatible: you can add the panel argument to existing sections without issues. However, you do need to check for the existence of WP_Customize_Manager->add_panel() if you’re maintaining pre-4.0 compatibility. As with Customizer Sections, you can access and modify Panels via:

  • $wp_customize->get_panel( $id );
  • $wp_customize->remove_panel( $id );

New Built-in Customizer Controls

WordPress core now provides support for a much wider array of Customizer controls. Implemented in #28477, these changes eliminate the need to create custom controls for most common use cases. The textarea type is now supported in core. For any type of input that uses an input element, you can simply specify the type attribute using the type parameter of $wp_customize->add_control().
Here’s an example:

$wp_customize->add_control( 'setting_id', array(
	'type'     => 'url',
	'priority' => 10,
	'section'  => 'title_tagline',
	'label'    => 'URL Field',
) );

Which results in the following markup in the Customizer:

<li id="customize-control-setting_id" class="customize-control customize-control-url">
	<label>
		<span class="customize-control-title">URL Field</span>
		<input type="url" value="" data-customize-setting-link="setting_id">
	</label>
</li>

This is pretty powerful, as you can now use the built-in WP_Customize_Control for most common use-cases rather than creating a custom control. But what about input types like number and range that require additional attributes like min, max, and step?

New Built-in Customizer Control Parameters

First of all, all of the built-in Customizer controls (including the custom controls such as WP_Customizer_Color_Control) now support descriptions, just like Customizer sections have descriptions (see #27981). This was much-needed and allows for inline help text at the control level.

More interestingly, to complement the new support for arbitrary input types, a new input_attrs parameter allows you to add attributes to the input element (also implemented in #28477). This extends beyond just using min, max, and step for number and range, to the ability to add custom classes, placeholders, the pattern attribute, and anything else you need to the input element. Here’s an example:

$wp_customize->add_control( 'setting_id', array(
	'type'        => 'range',
	'priority'    => 10,
	'section'     => 'title_tagline',
	'label'       => 'Range',
	'description' => 'This is the range control description.',
	'input_attrs' => array(
		'min'   => 0,
		'max'   => 10,
		'step'  => 2,
		'class' => 'test-class test',
		'style' => 'color: #0a0',
	),
) );

Which results in the following markup in the Customizer:

<li id="customize-control-setting_id" class="customize-control customize-control-range">
	<label>
		<span class="customize-control-title">Range</span>
		<strong><span class="description customize-control-description">This is the range control description.</span></strong>
		<input type="range" min="0" max="10" step="2" class="test-class test" style="color: #0a0;" value="" data-customize-setting-link="setting_id">
	</label>
</li>

Which displays as follows (in Chrome 35):

customizer-4.0-range-control

The ability to add classes is particularly useful if you need to target specific controls with CSS or JS, but you don’t need any special markup. I’m using this in the Menu Customizer for the Menu Name field, which is just an ordinary text control with a special setting type.

Contextual Controls

Customizer controls can now be displayed or hidden based on the Customizer’s preview context. For example, options that are only relevant to the front page can be shown only when the user is previewing their front page in the Customizer (see #27993). This is already implemented in core for Widgets; Widgets have always been contextually faded and shown/hidden based on their visibility in the preview, but this functionality is now built off of the core active_callback API in both PHP and JS. There are three different ways to specify whether a given control should only be displayed in a certain context. The first, and most straightforward, is to use the active_callback argument in $wp_customize->add_control().

$wp_customize->add_control( 'front_page_greeting', array(
	'label'           => __( 'Greeting' ),
	'section'         => 'title_tagline',
	'active_callback' => 'is_front_page',
) );

Note that you may use either built-in conditional functions or a custom function. If you have a custom control (via a subclass of WP_Customize_Control) and a custom callback function, you can skip the active_callback argument and override the active_callback method instead:

class WP_Greeting_Control extends WP_Customize_Control {
	// ...

	function active_callback() {
		return is_front_page();
	}
}

Finally, the customize_control_active filter will override all of the other active callback options and may be a better solution in certain cases (note that this particular example will be avoidable with future work on expanding the Customizer’s JS API, and does not hide the title_tagline section, only the controls in it):

function title_tagline_control_filter( $active, $control ) {
	if ( 'title_tagline' === $control->section ) {
		$active = is_front_page();
	}
	return $active;
}
add_filter( 'customize_control_active', 'title_tagline_control_filter', 10, 2 );

In addition to the PHP API for contextual controls, you can override the control-visibility-toggle function on the JS side. By default, controls will slideUp and slideDown as they become visible or hidden when the Customizer preview is navigated. If you’re familiar with the Customizer control JS API (see wp-admin/js/customize-controls.js, and wp.customize.Control), the Widgets implementation of a custom toggle function is a good example:

api.Widgets.WidgetControl = api.Control.extend({
// ...
	/**
	* Update widget control to indicate whether it is currently rendered.
	*
	* Overrides api.Control.toggle()
	*
	* @param {Boolean} active
	*/
	toggle: function ( active ) {
		this.container.toggleClass( 'widget-rendered', active );
	},
// ...
) };

/**
 * Extends wp.customize.controlConstructor with control constructor for widget_form.
 */
$.extend( api.controlConstructor, {
	widget_form: api.Widgets.WidgetControl,
} );

Changes to the customize_update_ and customize_preview_ Actions

You probably already know that the Customizer supports both option and theme_mod types for settings. But did you know that you can register arbitrary types? Since this is generally undocumented, I’ll show how it works (this has been in place since 3.4):

$wp_customize->add_setting( 'setting_id', array(
	'type'                 => 'custom_type',
	'capability'           => 'edit_theme_options',
	'theme_supports'       => '',
	'default'              => '',
	'transport'            => 'refresh',
	'sanitize_callback'    => '',
	'sanitize_js_callback' => '',
) );

There are a few actions that you can use to handle saving and previewing of custom types (option and theme_mod are handled automatically). Namely, customize_update_$type and customize_preview_$type are useful here. Previously, the value of the setting was passed to these actions, but there was no context. In 4.0, via #27979, the WP_Customize_Setting instance is passed to these actions, allowing more advanced saving and previewing operations. Here’s an example from my Menu Customizer project:

function menu_customizer_update_menu_name( $value, $setting ) {
...
	// Update the menu name with the new $value.
	wp_update_nav_menu_object( $setting->menu_id, array( 'menu-name' => trim( esc_html( $value ) ) ) );
}
add_action( 'customize_update_menu_name', 'menu_customizer_update_menu_name' );

This part of the Customizer API is a bit too complex to fully explain here, as most of it already existed, but suffice it to say that the addition of the setting instance to these actions greatly expands the possibilities of working with custom setting types in the Customizer.

New “customize” Meta Capability

The Customizer has been essentially decoupled from edit_theme_options in favor of a customize meta capability (mapped to edit_theme_options by default), which is assigned only to administrators by default. This allows for wider use of the Customizer’s extensive capability-access options, which are built into panels, sections, and settings. Additionally, this makes it possible to allow non-administrators to use the customizer for, for example, customizing posts. This change is an important step toward expanding the scope of the Customizer beyond themes. See #28605.

function allow_users_who_can_edit_posts_to_customize( $caps, $cap, $user_id ) {
        $required_cap = 'edit_posts';
        if ( 'customize' === $cap && user_can( $user_id, $required_cap ) ) {
                $caps = array( $required_cap );
        }
        return $caps;
}
add_filter( 'map_meta_cap', 'allow_users_who_can_edit_posts_to_customize', 10, 3 );

Customizer Conditional Function

The new is_customize_preview() conditional function can be used to check whether the front-end is being displayed in the Customizer. The naming derives from the fact that the term “preview” applies to both theme previews and previewing changes before saving them. See #23509 for some sample use-cases from WordPress.com.

Future Work

Most of the changes in 4.0 focus on the Customizer’s PHP API and the user experience within the Customizer. In the next few releases, we’ll probably shift focus to building out the Customizer JS API (#28709) and work on the user experience of accessing and navigating through the customizer (potentially with something like #28602 and related), as well as improving the experience on mobile (#28784). The Customizer can be very slow currently but we’re exploring ways to improve performance; for example, controls could be dynamically loaded on an as-needed basis once a more complete JS API is in place (#28580). We’ll work on improving custom background images and potentially add menus and/or theme-switching to the Customizer eventually. We’ll also want to address what to do with screens that the Customizer effectively replaces (headers and backgrounds, maybe eventually widgets, menus, and themes).  Check out the future release Customize component tickets for more ideas.

Thanks again to everyone who’s helped out with the Customizer in 4.0. If any of the outstanding items here pique your interest, feel free to jump in on trac!

 

Update: all UI changes have been committed. Additional work to improve focus styling will happen during beta, see #28267.

Update 2: everything here is in WordPress 4.0 beta 1, with the exception of the customize capability. The capability will most likely be implemented as a meta capability, not a primitive one, see #28605 for details.

Update 3: customize meta capability is now in trunk, will be in 4.0 beta 2. Added usage example.

#4-0, #api, #customize, #dev-notes

JSON Encoding and SSL for api.wordpress.org Communication in WordPress 3.7

There are two changes to the way WordPress communicates with api.wordpress.org in 3.7: JSON encoding and SSL.

JSON Encoding

In versions prior to WordPress 3.7, data that WordPress sends to (and receives from) api.wordpress.org is serialized using PHP’s native serialization functions. PHP-serialization has two main problems:

  • Security: It has the potential to lead to security exploits via PHP object injection.
  • Portability: It’s hard to unserialize these strings in other languages besides PHP.

In WordPress 3.7, most API calls have now changed so they send and receive JSON encoded data instead. The three major ones are:

  • Core update checks
  • Plugin update checks
  • Theme update checks

The following calls have also changed, but you’re probably not so interested in these:

  • Importers list
  • Credits list
  • Browse Happy (the browser version check)

How might this affect plugin or theme developers?

In general this won’t affect developers at all. If your plugin or theme just consumes the API then you don’t have to make any changes. The API calls that send and received JSON encoded data have all had their version numbers bumped from 1.0 to 1.1 (for example, api.wordpress.org/plugins/update-check/1.1/. If you are consuming the version 1.0 endpoints you’ll continue to get PHP-serialized data. If you want JSON encoded data, you can switch to using the version 1.1 endpoints.

There is one situation that developers may need to account for. If your plugin or theme hooks into the update API requests in order to remove certain plugins or themes from the update checks, your code may need updating.

A common method for removing a plugin or theme from the update checks is to hook into http_request_args, unserialize the data being sent to the API, remove the given theme or plugin from the data, and serialize it again. This will no longer work in WordPress 3.7 and your code will need to be updated so it decodes and encodes the data as JSON instead.

An example of a plugin which has been updated to handle JSON encoding along with fallback support for PHP-serialization (depending on the version number in the API call) can be seen here: https://github.com/cftp/external-update-api/compare/f4d58e2…281a0ef

Note that there are two API calls which have not yet changed to using JSON encoding:

  • Plugin info
  • Theme info

These two calls will most likely be updated to use JSON encoding in WordPress 3.8.

SSL Communication

As part of the hardening process of this release, WordPress 3.7 will only communicate with api.wordpress.org using SSL (HTTPS) when the server supports it. This is an especially important security enhancement, given that automatic background updates are now a part of WordPress. Indeed, automatic background updates are disabled if the server cannot communicate securely with the api.wordpress.org.

How might this affect plugin or theme developers?

Again, this won’t affect developers in general. If your plugin or theme hooks into API calls you may need to update your code to it handles calls to https://api.wordpress.org/ in addition to https://api.wordpress.org/.

JSON encoding and support for SSL means the WordPress.org APIs are in a much better position going forward.

#3-7, #api, #dev-notes

Javascript changes in 3.3

#3-3, #api

New and improved this morning, we have a…

New and improved this morning, we have a two-fer.

First, on the extend plugin directory, you may notice some new pie chart fun on the stats tab for each plugin. This shows a percentage breakdown of the versions being actively used by that plugin’s users. Only slices greater than 1.0% are shown.

Secondly, since data kept in a box is not very useful, there’s a new API for getting this data. Usage is fairly obvious from just a simple example, which gets the version breakdown of one of my own plugins:
https://api.wordpress.org/stats/plugin/1.0/simple-facebook-connect?callback=demo
The callback parameter is optional, of course, and provided for people who want JSONP usage.

Note that the version data is relatively new, so we don’t have it for all plugins at present. It will get better as reporting continues. For those interested, it’s saving the total counts of the version numbers as reported by the plugin update-checks over the last week. Since the data at present is only from one day, it’s not very accurate.

#api, #plugin-directory, #wporg

Previously we’d talked about putting up…

Previously we’d talked about putting up a stats page on WordPress.org (WPORG) so that more people could see what was happening. While working on some of the new stats processing code on WPORG I realized that people would likely end up scraping this data for their own uses. That seemed like a waste, so instead as a first run the stats numbers are available in JSON format via:

https://api.wordpress.org/stats/wordpress/1.0/
https://api.wordpress.org/stats/php/1.0/
https://api.wordpress.org/stats/mysql/1.0/

A few notes about these numbers. First, they are summary percentages for the previous day (where day is based on GMT). You’ll also notice that these numbers don’t really line up with each other, this is because the system normalizes the version numbers and throws out odd/invalid versions (I was surprised by how many odd version strings there are out there). As a result each category is best compared to itself, instead of trying to compare PHP with MySQL numbers.

The content type returned for this data is ‘application/json’, your browser may or may not display them correctly.

This is a start, there are more things to be added to this in the future. One obvious item is support for getting numbers for previous days and date ranges. Another would be to add some pretty graphs to WPORG to display this data.

#api, #stats

API status check

Updates for the API reference project: duck_ was out of town, Aaron has been working on the handbooks, and Koop and I have been working on GSoC (done!), but I think we can still have some good stuff done in the next few weeks.

Koop and I have been playing with a parser written by duck that seems like it is an excellent base for what we want to do, which is in turn excellent. Ideally we’ll have a working prototype soon, with the goal to have something launched in beta early in the 3.1 cycle.

I’ll send that code over our api-dev list and hopefully kickstart some more progress.

#3-org, #api

Deprecated clean_url() in favor of esc_u…

Deprecated clean_url() in favor of esc_url(), and deprecated sanitize_url() in favor of esc_url_raw().

#api, #escaping, #esc_url_raw, #security

Deprecated wp_specialchars() in favor of…

Deprecated wp_specialchars() in favor of esc_html() (also: esc_html__() and esc_html_e()). Using wp_specialchars() with more than one param works for backwards compat. Also, esc_html() (or wp_specialchars() with one param) escapes quotes, just like esc_attr(). This buys security for plugin authors who were mistakenly using a one-param wp_specialchars() call in an HTML attribute. See this wp-hackers message for more detail.

#api, #escaping, #security

Standardizing and shortening the WP secu…

Standardizing and shortening the WP security escaping functions.

attribute_escape() is now esc_attr()

Additionally, you can do attribute escaping and translation in one go. Just add the translation function to the end. Like so:

  • esc_attr__() — translate and return, attribute-escaped.
  • esc_attr_e() — translate and echo, attribute-escaped.

Will be following up with esc_html (with __() and _e() variants), esc_url(), maybe some more. Will be nice, short, predictable, and allow you do translate/escape in one go without a lot of nested parenthesis.

#api, #escaping, #security