diff --git a/wordpress.org/public_html/wp-content/plugins/theme-directory/class-themes-api.php b/wordpress.org/public_html/wp-content/plugins/theme-directory/class-themes-api.php index 9f0685bc4e..2f3fa99c36 100644 --- a/wordpress.org/public_html/wp-content/plugins/theme-directory/class-themes-api.php +++ b/wordpress.org/public_html/wp-content/plugins/theme-directory/class-themes-api.php @@ -64,6 +64,7 @@ class Themes_API { 'requires' => false, 'requires_php' => false, 'trac_tickets' => false, + 'patterns' => false, ); /** @@ -894,6 +895,33 @@ public function fill_theme( $theme ) { } + if ( $this->fields['patterns'] ) { + $pattern_meta = get_post_meta( $theme->ID, '_patterns', true ); + $patterns_data = array(); + + if ( ! empty( $pattern_meta ) ) { + switch_to_blog( 699 ); // Pattern Directory + + $args = array( + 'post_name__in' => $pattern_meta, + 'post_type' => 'wporg-pattern', + 'post_status' => 'publish', + ); + + foreach ( get_posts( $args ) as $pattern_post ) { + $p = array(); + $p['name'] = $pattern_post->post_title; + $p['link'] = get_permalink( $pattern_post ); + + $patterns_data[] = $p; + } + + restore_current_blog(); + } + + $phil->patterns = $patterns_data; + } + wp_cache_set( $cache_key, $phil, $this->cache_group, $this->cache_life ); return $phil; diff --git a/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php b/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php index 0d9a4e7d4c..8a844ab0e0 100644 --- a/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php +++ b/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php @@ -75,6 +75,13 @@ class WPORG_Themes_Upload { */ public $theme; + /** + * The uploaded theme.json. + * + * @var WP_Theme_JSON + */ + public $theme_json = null; + /** * The theme slug being uploaded. * @@ -370,6 +377,9 @@ protected function import( $args = array() ) { // We have a stylesheet, let's set up the theme, theme post, and author. $this->theme = new WP_Theme( basename( dirname( $style_css ) ), dirname( dirname( $style_css ) ) ); + // Get Theme.json data if it exists + $this->theme_json = $this->get_theme_json( $theme_files ); + // We need a screen shot. People love screen shots. if ( ! $this->has_screenshot( $theme_files ) ) { $style_errors->add( @@ -1299,6 +1309,10 @@ public function create_or_update_theme_post() { '_screenshot' => $this->theme->screenshot, ); + if ( ! empty( $this->theme_json ) && $this->theme_json->get_patterns() ) { + $post_meta[ '_patterns' ] = $this->theme_json->get_patterns(); + } + // Store readme.txt data if present. foreach ( $this->readme as $field => $data ) { $post_meta[ "_{$field}" ] = $data; @@ -1865,4 +1879,27 @@ public function log_to_slack( $status = 'allowed' ) { $send->send( '#themereview-firehose' ); } + + /** + * Returns WP_THEME_JSON information if it exists. + * + * @return WP_Theme_JSON|null + */ + public function get_theme_json( $theme_files ) { + $theme_json = preg_grep( '/theme.json/i', $theme_files ); + + if ( ! $theme_json ) { + return null; + } + + $file_path = (string) array_pop( $theme_json ); + + $decoded_file = wp_json_file_decode( $file_path, array( 'associative' => true ) ); + + if ( ! is_array( $decoded_file ) ) { + return null; + } + + return new WP_Theme_JSON( $decoded_file, 'default' ); + } } diff --git a/wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php b/wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php index eacb5ef8c9..85246373df 100644 --- a/wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php +++ b/wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php @@ -889,6 +889,7 @@ function wporg_themes_get_themes_for_query() { 'active_installs' => true, 'requires' => true, 'requires_php' => true, + 'patterns' => true, ); $api_result = wporg_themes_query_api( 'query_themes', $request ); @@ -930,6 +931,7 @@ function wporg_themes_theme_information( $slug ) { 'active_installs' => true, 'requires' => true, 'requires_php' => true, + 'patterns' => true ) ) ); } diff --git a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/css/components/_main.scss b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/css/components/_main.scss index 5b500a0f2f..c2c24727ad 100644 --- a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/css/components/_main.scss +++ b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/css/components/_main.scss @@ -563,6 +563,10 @@ body.author .theme-browser .theme .theme-author { font-size: 13px; } +.theme-wrap .theme-patterns { + font-size: 13px; +} + .theme-wrap .theme-downloads .total-downloads { color: #555; font-size: 14px; diff --git a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/js/theme.js b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/js/theme.js index 488ea53740..6e37b7f573 100644 --- a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/js/theme.js +++ b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/js/theme.js @@ -355,6 +355,7 @@ window.wp = window.wp || {}; photon_screenshots: true, active_installs: true, requires_php: true, + patterns: true, } }, request); @@ -524,6 +525,11 @@ window.wp = window.wp || {}; return '' + translated_tag + ''; }).join( ', ' ); + // Make patterns click-able and separated by a comma. + data.patterns = _.map( data.patterns, function( pattern ) { + return '' + pattern.name + ''; + }).join( ', ' ); + data.path = themes.data.settings.path; // Active Installs text diff --git a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/theme-single.php b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/theme-single.php index 2f64778c27..e3d8beb0f4 100644 --- a/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/theme-single.php +++ b/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/theme-single.php @@ -111,6 +111,25 @@ + patterns ) { ?> +