Customize: Improve behavior and extensibility of theme loading and searching.

* Introduce `WP_Customize_Themes_Section::$filter_type`, which has built-in functionality for `local` and `remote` filtering. When this set to `local`, all themes are assumed to be loaded from Ajax when the section is first loaded, and subsequent searching/filtering is applied to the loaded collection of themes within the section. This is how the core "Installed" section behaves - third-party sources with limited numbers of themes may consider leveraging this implementation. When this is set to `remote`, searching and filtering always triggers a new remote query via Ajax. The core "WordPress.org" section uses this approach, as it has over 5000 themes to search.
* Refactor `filterSearch()` to accept a raw term string as input. This enables a feature filter to be used on a section where `filter_type` is `local`.
* Refactor `filter()` on a theme control to check for an array of terms. Also sort the results by the number of matches. Rather than searching for an exact match, this will now search for each word in a search distinctly, allowing things like tags to rank in search results more accurately.
* Split `loadControls()` into two functions for themes section JS: `loadThemes()` to initiate and manage an Ajax request and `loadControls()` to create theme controls based on the results of the Ajax call. If third-party sections need to change the way controls are loaded, such as by using a custom control subclass of `WP_Customize_Theme_Control`, this allows them to use the core logic for managing the Ajax call and only override the actual control-creation process.
* Introduce `customize_load_themes` filter to facilitate loading themes from third-party sources (or modifying the results of the core sections).
* Bring significant improvements to the installed themes search filter.

Props celloexpressions.
Amends [41648].
See #37661.
Fixes #42049.


git-svn-id: https://develop.svn.wordpress.org/trunk@41807 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Weston Ruter
2017-10-10 07:08:51 +00:00
parent 33a0ff50b7
commit f2f3a883d7
3 changed files with 194 additions and 87 deletions

View File

@@ -4415,6 +4415,7 @@ final class WP_Customize_Manager {
$this->add_section( new WP_Customize_Themes_Section( $this, 'wporg_themes', array(
'title' => __( 'WordPress.org themes' ),
'action' => 'wporg',
'filter_type' => 'remote',
'capability' => 'install_themes',
'panel' => 'themes',
'priority' => 5,
@@ -4947,23 +4948,48 @@ final class WP_Customize_Manager {
}
$theme_action = sanitize_key( $_POST['theme_action'] );
$themes = array();
$args = array();
// Define query filters based on user input.
if ( ! array_key_exists( 'search', $_POST ) ) {
$args['search'] = '';
} else {
$args['search'] = sanitize_text_field( wp_unslash( $_POST['search'] ) );
}
if ( ! array_key_exists( 'tags', $_POST ) ) {
$args['tag'] = '';
} else {
$args['tag'] = array_map( 'sanitize_text_field', wp_unslash( (array) $_POST['tags'] ) );
}
if ( ! array_key_exists( 'page', $_POST ) ) {
$args['page'] = 1;
} else {
$args['page'] = absint( $_POST['page'] );
}
require_once ABSPATH . 'wp-admin/includes/theme.php';
if ( 'installed' === $theme_action ) {
// Load all installed themes from wp_prepare_themes_for_js().
$themes = array( 'themes' => wp_prepare_themes_for_js() );
foreach ( $themes['themes'] as &$theme ) {
$theme['type'] = 'installed';
$theme['active'] = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme['id'] );
}
} elseif ( 'wporg' === $theme_action ) {
// Load WordPress.org themes from the .org API and normalize data to match installed theme objects.
if ( ! current_user_can( 'install_themes' ) ) {
wp_die( -1 );
}
// Arguments for all queries.
$args = array(
$wporg_args = array(
'per_page' => 100,
'page' => isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 1,
'fields' => array(
'screenshot_url' => true,
'description' => true,
@@ -4979,18 +5005,7 @@ final class WP_Customize_Manager {
),
);
// Define query filters based on user input.
if ( ! array_key_exists( 'search', $_POST ) ) {
$args['search'] = '';
} else {
$args['search'] = sanitize_text_field( wp_unslash( $_POST['search'] ) );
}
if ( ! array_key_exists( 'tags', $_POST ) ) {
$args['tag'] = '';
} else {
$args['tag'] = array_map( 'sanitize_text_field', wp_unslash( (array) $_POST['tags'] ) );
}
$args = array_merge( $wporg_args, $args );
if ( '' === $args['search'] && '' === $args['tag'] ) {
$args['browse'] = 'new'; // Sort by latest themes by default.
@@ -5061,6 +5076,26 @@ final class WP_Customize_Manager {
unset( $theme->author );
} // End foreach().
} // End if().
/**
* Filters the theme data loaded in the customizer.
*
* This allows theme data to be loading from an external source,
* or modification of data loaded from `wp_prepare_themes_for_js()`
* or WordPress.org via `themes_api()`.
*
* @since 4.9.0
*
* @see wp_prepare_themes_for_js()
* @see themes_api()
* @see WP_Customize_Manager::__construct()
*
* @param array $themes Nested array of theme data.
* @param array $args List of arguments, such as page, search term, and tags to query for.
* @param WP_Customize_Manager $manager Instance of Customize manager.
*/
$themes = apply_filters( 'customize_load_themes', $themes, $args, $this );
wp_send_json_success( $themes );
}