WordPress.org

Making WordPress.org

Changeset 8729


Ignore:
Timestamp:
05/03/2019 07:03:20 AM (3 years ago)
Author:
dd32
Message:

Plugin Directory: Introduce localised screenshots, allowing plugins to have translated screenshots on the website and within the wp-admin plugin installer.

This works by allowing screenshots located in the /assets/ folder to define the locale of the image, eg. screenshot-1-de_DE.png or screenshot-1-ary.png.

Props ck3lee, dd32.
See #3935.

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/fields/plugin/class-screenshots.php

    r6287 r8729  
    99
    1010    /**
    11      * Banners constructor.
     11     * Screenshots constructor.
    1212     */
    1313    public function __construct() {
     
    2828     */
    2929    public function get_screenshots( $object ) {
    30         $descriptions = get_post_meta( $object['id'], 'screenshots', true ) ?: [];
    31         $screen_shots = get_post_meta( $object['id'], 'assets_screenshots', true ) ?: [];
    32         $response     = [];
    33 
    34         foreach ( $screen_shots as $image ) {
    35             $screen_shot = [
    36                 'src' => esc_url( Template::get_asset_url( $object['id'], $image ) ),
    37             ];
    38 
    39             if ( $descriptions && ! empty( $descriptions[ (int) $image['resolution'] ] ) ) {
    40                 $caption                = $descriptions[ (int) $image['resolution'] ];
    41                 $screen_shot['caption'] = Plugin_I18n::instance()->translate( 'screenshot-' . $image['resolution'], $caption, [ 'post_id' => $object['id'] ] );
    42             }
    43 
    44             $response[] = $screen_shot;
    45         }
    46 
    47         return $response;
     30        // Reduce the Screenshots to the required fields.
     31        return array_values( array_map(
     32            function( $image ) {
     33                return [
     34                    'src'     => $image['src'],
     35                    'caption' => $image['caption'],
     36                ];
     37            },
     38            Template::get_screenshots( $object['id'] )
     39        ) );
    4840    }
    4941}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin.php

    r7282 r8729  
    155155        $result['download_link']     = Template::download_link( $post );
    156156
    157         $result['screenshots'] = array();
    158         $descriptions          = get_post_meta( $post->ID, 'screenshots', true ) ?: array();
    159         $screen_shots          = get_post_meta( $post->ID, 'assets_screenshots', true ) ?: array();
    160 
    161         /*
    162          * Find the image that corresponds with the text.
    163          * The image numbers are stored within the 'resolution' key.
    164          */
    165         foreach ( $screen_shots as $image ) {
    166             $src     = Template::get_asset_url( $post, $image );
    167             $caption = '';
    168             if ( $descriptions && ! empty( $descriptions[ (int) $image['resolution'] ] ) ) {
    169                 $caption = $descriptions[ (int) $image['resolution'] ];
    170                 $caption = Plugin_I18n::instance()->translate( 'screenshot-' . $image['resolution'], $caption, [ 'post_id' => $post->ID ] );
    171             }
    172 
    173             $result['screenshots'][ $image['resolution'] ] = compact( 'src', 'caption' );
    174         }
     157        // Reduce images to caption + src
     158        $result['screenshots'] = array_map(
     159            function( $image ) {
     160                return [
     161                    'src'     => $image['src'],
     162                    'caption' => $image['caption'],
     163                ];
     164            },
     165            Template::get_screenshots( $post )
     166        );
    175167
    176168        if ( $result['screenshots'] ) {
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-template.php

    r8546 r8729  
    365365            'developers',
    366366        );
    367         if ( ! get_post_meta( $plugin->ID, 'screenshots', true ) && ! get_post_meta( $plugin->ID, 'assets_screenshots', true ) ) {
     367        if ( ! get_post_meta( $plugin->ID, 'assets_screenshots', true ) ) {
    368368            unset( $default_sections[ array_search( 'screenshots', $default_sections ) ] );
    369369        }
     
    980980        return $link;
    981981    }
     982
     983    /**
     984     * Fetch plugin Screenshots, accounting for localised screenshots.
     985     *
     986     * @static
     987     *
     988     * @param object|int $plugin The plugin to fetch screenshots for. Optional.
     989     * @param string     $locale The locale requested. Optional.
     990     * @return array Screenshots for the plugin, localised if possible.
     991     */
     992    public static function get_screenshots( $plugin = null, $locale = null ) {
     993        $plugin = get_post( $plugin );
     994
     995        if ( ! $locale ) {
     996            $locale = get_locale();
     997        }
     998
     999        // All indexed from 1. The Image 'number' is stored in the 'resolution' key
     1000        $screen_shots = get_post_meta( $plugin->ID, 'assets_screenshots', true ) ?: array();
     1001        $descriptions = get_post_meta( $plugin->ID, 'screenshots', true ) ?: array();
     1002
     1003        if ( empty( $screen_shots ) ) {
     1004            return array();
     1005        }
     1006
     1007        $sorted = array();
     1008        foreach ( $screen_shots as $image ) {
     1009            if ( ! isset( $sorted[ $image['resolution'] ] ) ) {
     1010                $sorted[ $image['resolution'] ] = array();
     1011            }
     1012
     1013            if ( empty( $image['locale'] ) ) {
     1014                // if the image has no locale, always insert to the last element (lowerst priority).
     1015                $sorted[ $image['resolution'] ][] = $image;
     1016            } elseif ( $locale === $image['locale'] ) {
     1017                // if the locale is a full match, always insert to the first element (highest priority).
     1018                array_unshift( $sorted[ $image['resolution'] ], $image );
     1019            } else {
     1020                // TODO: de_DE_informal should probably fall back to de_DE before de_CH. Maybe this can wait until Core properly supports locale hierarchy.
     1021
     1022                $image_locale_parts = explode( '_', $image['locale'] );
     1023                $locale_parts       = explode( '_', $locale );
     1024                // if only the language matches.
     1025                if ( $image_locale_parts[0] === $locale_parts[0] ) {
     1026                    // image with locale has a higher priority than image without locale.
     1027                    $last_image = end( $sorted[ $image['resolution'] ] );
     1028                    if ( empty( $last_image['locale'] ) ) {
     1029                        array_splice( $sorted[ $image['resolution'] ], count( $sorted[ $image['resolution'] ] ), 0, array( $image ) );
     1030                    } else {
     1031                        $sorted[ $image['resolution'] ][] = $image;
     1032                    }
     1033                }
     1034            }
     1035        }
     1036
     1037        // Sort
     1038        ksort( $sorted, SORT_NATURAL );
     1039
     1040        // Reduce images to singulars and attach metadata
     1041        foreach ( $sorted as $index => $items ) {
     1042            // The highest priority image is the first.
     1043            $image = $items[0];
     1044
     1045            // Attach caption data
     1046            $image['caption'] = false;
     1047            if ( isset( $descriptions[ (int) $index ] ) ) {
     1048                $image['caption'] = $descriptions[ (int) $index ];
     1049                $image['caption'] = Plugin_I18n::instance()->translate(
     1050                    'screenshot-' . $image['resolution'],
     1051                    $image['caption'],
     1052                    [ 'post_id' => $plugin->ID ]
     1053                );
     1054            }
     1055
     1056            // Attach URL information for the asset
     1057            $image['src'] = Template::get_asset_url( $plugin, $image );
     1058
     1059            $sorted[ $index ] = $image;
     1060        }
     1061
     1062        return $sorted;
     1063    }
    9821064}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/cli/class-import.php

    r8654 r8729  
    365365        if ( $svn_assets_folder ) { // /assets/ may not exist.
    366366            foreach ( $svn_assets_folder as $asset ) {
    367                 // screenshot-0(-rtl).(png|jpg|jpeg|gif)  ||  icon.svg
    368                 if ( ! preg_match( '!^(?P<type>screenshot|banner|icon)(-(?P<resolution>[\dx]+)(-rtl)?\.(png|jpg|jpeg|gif)|\.svg)$!i', $asset['filename'], $m ) ) {
     367                // screenshot-0(-rtl)(-de_DE).(png|jpg|jpeg|gif)  ||  icon.svg
     368                if ( ! preg_match( '!^(?P<type>screenshot|banner|icon)(?:-(?P<resolution>[\dx]+)(-rtl)?(?:-(?P<locale>[a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?))?\.(png|jpg|jpeg|gif)|\.svg)$!i', $asset['filename'], $m ) ) {
    369369                    continue;
    370370                }
     
    375375                $location   = 'assets';
    376376                $resolution = isset( $m['resolution'] ) ? $m['resolution'] : false;
    377 
    378                 $assets[ $type ][ $asset['filename'] ] = compact( 'filename', 'revision', 'resolution', 'location' );
     377                $locale     = isset( $m['locale'] )     ? $m['locale']     : false;
     378
     379                $assets[ $type ][ $asset['filename'] ] = compact( 'filename', 'revision', 'resolution', 'location', 'locale' );
    379380            }
    380381        }
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-screenshots.php

    r6287 r8729  
    1616     */
    1717    static function display() {
    18         $plugin = get_post();
    1918        $output = '';
    2019
    21         // All indexed from 1.
    22         $descriptions = get_post_meta( $plugin->ID, 'screenshots', true ) ?: array();
    23         $screen_shots = get_post_meta( $plugin->ID, 'assets_screenshots', true ) ?: array();
     20        $screenshots = Template::get_screenshots();
    2421
    25         if ( empty( $screen_shots ) ) {
     22        if ( ! $screenshots ) {
    2623            return '';
    2724        }
    2825
    29         ksort( $screen_shots, SORT_NATURAL );
    30 
    31         /*
    32          * Find the image that corresponds with the text.
    33          * The image numbers are stored within the 'resolution' key.
    34          */
    35         foreach ( $screen_shots as $image ) {
     26        foreach ( $screenshots as $image ) {
    3627            $screen_shot = sprintf(
    3728                '<a href="%1$s" rel="nofollow"><img class="screenshot" src="%1$s" alt="" /></a>',
    38                 esc_url( Template::get_asset_url( $plugin, $image ) )
     29                esc_url( $image['src'] )
    3930            );
    4031
    41             if ( $descriptions && ! empty( $descriptions[ (int) $image['resolution'] ] ) ) {
    42                 $caption = $descriptions[ (int) $image['resolution'] ];
    43                 $caption = Plugin_I18n::instance()->translate( 'screenshot-' . $image['resolution'], $caption, [ 'post_id' => $plugin->ID ] );
    44 
    45                 $screen_shot .= '<figcaption>' . $caption . '</figcaption>';
     32            if ( $image['caption'] ) {
     33                $screen_shot .= '<figcaption>' . $image['caption'] . '</figcaption>';
    4634            }
    4735
Note: See TracChangeset for help on using the changeset viewer.