Making WordPress.org


Ignore:
Timestamp:
03/31/2016 08:25:15 PM (9 years ago)
Author:
ocean90
Message:

Translate: Display stats, contributors and language packs on theme project pages.

See #1388.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-routes/routes/wp-themes.php

    r2858 r2864  
    11<?php
    22
    3 class WPorg_GP_Route_WP_Plugins extends GP_Route {
     3class WPorg_GP_Route_WP_Themes extends WPorg_GP_Route_WP_Directory {
    44
    55    /**
     
    88     * @param string $project_slug Slug of a project.
    99     */
    10     public function get_plugin_projects( $project_slug ) {
     10    public function get_theme_projects( $project_slug ) {
    1111        global $wpdb;
    1212
    13         $project_path = 'wp-plugins/' . $project_slug;
     13        $project_path = 'wp-themes/' . $project_slug;
    1414        $project = GP::$project->by_path( $project_path );
    1515        if ( ! $project ) {
     
    2626                LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id
    2727            WHERE
    28                 p.parent_project_id = '{$project->id}'
     28                p.id = '{$project->id}'
    2929        " );
    3030
     
    3939                $locale_key = $set->locale . '/' . $set->locale_slug;
    4040            }
    41             $sub_project = str_replace( "$project_path/", '', $set->path );
    42             $sub_projects[ $sub_project ] = true;
    4341
    4442            /*
     
    4745             */
    4846            $percent_complete = (float) $set->percent_complete;
    49             $translation_locale_statuses[ $locale_key ][ $sub_project ] = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete );
     47            $translation_locale_statuses[ $locale_key ]['stable'] = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete );
    5048
    5149            // Increment the amount of waiting and untranslated strings.
     
    6260            ksort( $translation_locale_statuses[ $locale_key ], SORT_NATURAL );
    6361        }
    64 
    65         // Check if the plugin has at least one code project. These won't be created if a plugin
    66         // has no text domain defined.
    67         $sub_projects = array_keys( $sub_projects );
    68         $has_error = ( ! in_array( 'dev', $sub_projects ) && ! in_array( 'stable', $sub_projects ) );
    6962
    7063        unset( $project_path, $locale_key, $rows, $set, $sub_project, $sub_projects );
     
    9487        } );
    9588
    96         if ( function_exists( 'wporg_get_plugin_icon' ) ) {
    97             $project->icon = wporg_get_plugin_icon( $project->slug, 64 );
    98         } else {
    99             $project->icon = '<div class="default-icon"><span class="dashicons dashicons-admin-plugins"></span></div>';
    100         }
     89        $project->icon = $this->get_theme_icon( $project, 64 );
    10190
    102         $this->tmpl( 'projects-wp-plugins', get_defined_vars() );
     91        $this->tmpl( 'projects-wp-themes', get_defined_vars() );
    10392    }
    10493
     
    10897     * @param string $project_slug Slug of a project.
    10998     */
    110     public function get_plugin_contributors( $project_slug ) {
     99    public function get_theme_contributors( $project_slug ) {
    111100        global $wpdb;
    112101
    113         $project_path = 'wp-plugins/' . $project_slug;
     102        $project_path = 'wp-themes/' . $project_slug;
    114103        $project = GP::$project->by_path( $project_path );
    115104        if ( ! $project ) {
     
    117106        }
    118107
    119         if ( function_exists( 'wporg_get_plugin_icon' ) ) {
    120             $project->icon = wporg_get_plugin_icon( $project->slug, 64 );
    121         } else {
    122             $project->icon = '<div class="default-icon"><span class="dashicons dashicons-admin-plugins"></span></div>';
     108        $project->icon = $this->get_theme_icon( $project, 64 );
     109
     110        $contributors_by_locale = gp_get_meta( 'wp-themes', $project->id, 'contributors-by-locale' );
     111        if ( ! $contributors_by_locale || $contributors_by_locale['last_updated'] + HOUR_IN_SECONDS < time() ) {
     112            $contributors_by_locale = $this->get_contributors( $project );
     113            $contributors_by_locale['last_updated'] = time();
     114            gp_update_meta( $project->id, 'contributors-by-locale', $contributors_by_locale, 'wp-themes' );
    123115        }
    124116
    125         $contributors_by_locale = array();
    126         $default_value = array(
    127             'count' => 0,
    128             'editors' => array(),
    129             'contributors' => array(),
    130         );
    131 
    132         $translation_editors = $wpdb->get_results( $wpdb->prepare( "
    133             SELECT
    134                 `user_id`, `locale`
    135             FROM {$wpdb->wporg_translation_editors}
    136             WHERE `project_id` = %d
    137         ", $project->id ), OBJECT );
    138 
    139         foreach ( $translation_editors as $translation_editor ) {
    140             if ( ! isset( $contributors_by_locale[ $translation_editor->locale ] ) ) {
    141                 $contributors_by_locale[ $translation_editor->locale ] = $default_value;
    142             }
    143 
    144             $user = get_user_by( 'id', $translation_editor->user_id );
    145             if ( ! $user ) {
    146                 continue;
    147             }
    148 
    149             $contributors_by_locale[ $translation_editor->locale ]['editors'][ $translation_editor->user_id ] = (object) array(
    150                 'nicename'     => $user->user_nicename,
    151                 'display_name' => $this->_encode( $user->display_name ),
    152             );
    153 
    154             $contributors_by_locale[ $translation_editor->locale ]['count']++;
     117        $chart_data = gp_get_meta( 'wp-themes', $project->id, 'contributors-chart-data' );
     118        if ( ! $chart_data || $chart_data['last_updated'] + DAY_IN_SECONDS < time() ) {
     119            $chart_data = $this->get_contributors_chart_data( $project );
     120            $chart_data['last_updated'] = time();
     121            gp_update_meta( $project->id, 'contributors-chart-data', $chart_data, 'wp-themes' );
    155122        }
    156123
    157         unset( $translation_editors );
    158 
    159         $sub_projects = $wpdb->get_col( $wpdb->prepare( "
    160             SELECT id
    161             FROM {$wpdb->gp_projects}
    162             WHERE parent_project_id = %d
    163         ", $project->id ) );
    164 
    165         foreach ( $sub_projects as $sub_project ) {
    166             foreach( $this->get_translation_contributors_by_locale( $sub_project ) as $row ) {
    167                 if ( ! isset( $contributors_by_locale[ $row->locale ] ) ) {
    168                     $contributors_by_locale[ $row->locale ] = $default_value;
    169                 }
    170 
    171                 if ( isset( $contributors_by_locale[ $row->locale ]['editors'][ $row->user_id ] ) ) {
    172                     continue;
    173                 }
    174 
    175                 if ( isset( $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] ) ) {
    176                     continue;
    177                 }
    178 
    179                 $user = get_user_by( 'id', $row->user_id );
    180                 if ( ! $user ) {
    181                     continue;
    182                 }
    183 
    184                 $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] = (object) array(
    185                     'nicename'     => $user->user_nicename,
    186                     'display_name' => $this->_encode( $user->display_name ),
    187                 );
    188 
    189                 $contributors_by_locale[ $row->locale ]['count']++;
    190             }
    191         }
    192 
    193         $chart_data = $this->get_plugin_contributors_chart_data( $project->id, $sub_projects );
     124        unset( $contributors_by_locale['last_updated'], $chart_data['last_updated'] );
    194125
    195126        $this->tmpl( 'projects-wp-plugins-contributors', get_defined_vars() );
    196     }
    197 
    198     /**
    199      * Generates the chart data for contributors activity.
    200      *
    201      * @param  int    $project_id   The ID of a project. Used to store data as meta.
    202      * @param  array $sub_projects Optional. IDs of sub-projects.
    203      * @return array The data to build a chart via Chartist.js.
    204      */
    205     private function get_plugin_contributors_chart_data( $project_id, $sub_projects = null ) {
    206         $chart_data = gp_get_meta( 'wp-plugins', $project_id, 'contributors-chart-data' );
    207         if ( $chart_data ) {
    208             if ( $chart_data['last_updated'] + DAY_IN_SECONDS > time() ) {
    209                 return $chart_data;
    210             }
    211         }
    212 
    213         global $wpdb;
    214 
    215         if ( ! $sub_projects ) {
    216             $sub_projects = $wpdb->get_col( $wpdb->prepare( "
    217                 SELECT id
    218                 FROM {$wpdb->gp_projects}
    219                 WHERE parent_project_id = %d
    220             ", $$project_id ) );
    221         }
    222 
    223         $translation_set_ids = $wpdb->get_col( "
    224             SELECT `id` FROM {$wpdb->gp_translation_sets} WHERE `project_id` IN (" . implode( ',', $sub_projects ) . ")
    225         " );
    226 
    227         if ( ! $translation_set_ids ) {
    228             return array();
    229         }
    230 
    231         $date_begin = new DateTime( '-6 day' );
    232         $date_end = new DateTime( 'NOW' );
    233         $date_interval = new DateInterval( 'P1D' );
    234         $date_range = new DatePeriod( $date_begin, $date_interval, $date_end );
    235 
    236         $days = array();
    237         foreach( $date_range as $date ) {
    238             $days[] = $date->format( 'Y-m-d' );
    239         }
    240         $days[] = $date_end->format( 'Y-m-d' );
    241 
    242         $counts = $wpdb->get_results( "
    243             SELECT
    244                 DATE(date_modified) AS `day`, COUNT(*) AS `count`, `status`
    245             FROM {$wpdb->gp_translations}
    246             WHERE
    247                 `translation_set_id` IN (" . implode( ',', $translation_set_ids ) . ")
    248                 AND date_modified >= ( CURDATE() - INTERVAL 7 DAY )
    249             GROUP BY `status`, `day`
    250             ORDER BY `day` DESC
    251         " );
    252 
    253         $status = array( 'current', 'waiting', 'rejected' );
    254         $data = [];
    255         foreach ( $days as $day ) {
    256             $data[ $day ] = array_fill_keys( $status, 0 );
    257             foreach ( $counts as $count ) {
    258                 if ( $count->day !== $day || ! in_array( $count->status, $status ) ) {
    259                     continue;
    260                 }
    261 
    262                 $data[ $day ][ $count->status ] = (int) $count->count;
    263             }
    264         }
    265 
    266         $labels = array_keys( $data );
    267         array_pop( $labels );
    268         $labels[] = ''; // Don't show a label for today
    269 
    270         $series = array();
    271         $series_data = array_values( $data );
    272         foreach ( $status as $stati ) {
    273             $series[] = (object) array(
    274                 'name' => $stati,
    275                 'data' => wp_list_pluck( $series_data, $stati ),
    276             );
    277         }
    278 
    279         $last_updated = time();
    280         $chart_data = compact( 'labels', 'series', 'last_updated' );
    281 
    282         gp_update_meta( $project_id, 'contributors-chart-data', $chart_data, 'wp-plugins' );
    283 
    284         return $chart_data;
    285127    }
    286128
     
    290132     * @param string $project_slug Slug of a project.
    291133     */
    292     public function get_plugin_language_packs( $project_slug ) {
    293         $project_path = 'wp-plugins/' . $project_slug;
     134    public function get_theme_language_packs( $project_slug ) {
     135        $project_path = 'wp-themes/' . $project_slug;
    294136        $project = GP::$project->by_path( $project_path );
    295137        if ( ! $project ) {
     
    297139        }
    298140
    299         if ( function_exists( 'wporg_get_plugin_icon' ) ) {
    300             $project->icon = wporg_get_plugin_icon( $project->slug, 64 );
    301         } else {
    302             $project->icon = '<div class="default-icon"><span class="dashicons dashicons-admin-plugins"></span></div>';
    303         }
     141        $project->icon = $this->get_theme_icon( $project, 64 );
    304142
    305         $http_context = stream_context_create( array(
    306             'http' => array(
    307                 'user_agent' => 'WordPress.org Translate',
    308             ),
    309         ) );
    310         $json = file_get_contents( "https://api.wordpress.org/translations/plugins/1.0/?slug={$project_slug}", null, $http_context );
    311         $language_packs = $json && '{' == $json[0] ? json_decode( $json ) : null;
     143        $language_packs = $this->get_language_packs( 'theme', $project_slug );
    312144
    313145        $this->tmpl( 'projects-wp-plugins-language-packs', get_defined_vars() );
     
    315147
    316148    /**
    317      * Retrieves translators of a specific project.
     149     * Retrieves the icon of a theme.
    318150     *
    319      * @param int $project_id Project ID.
    320      * @return object Translators of the project.
     151     * @param GP_Project $project The theme project.
     152     * @param int        $size    Optional. The size of the icon. Default 64.
     153     * @return string HTML markup for the icon.
    321154     */
    322     private function get_translation_contributors_by_locale( $project_id ) {
    323         global $wpdb;
     155    private function get_theme_icon( $project, $size = 64 ) {
     156        $default = '<div class="default-icon"><span class="dashicons dashicons-admin-themes"></span></div>';
    324157
    325         $sql = $wpdb->prepare( "
    326             SELECT ts.`locale`, ts.`slug` AS `locale_slug`, t.`user_id`
    327             FROM `{$wpdb->gp_translations}` t, `{$wpdb->gp_translation_sets}` ts
    328             WHERE t.`translation_set_id` = ts.`id`
    329                 AND t.`user_id` IS NOT NULL AND t.`user_id` != 0
    330                 AND t.`date_modified` > %s
    331                 AND ts.`project_id` = %d
    332                 AND t.`status` <> 'rejected'
    333             GROUP BY ts.`locale`, ts.`slug`, t.`user_id`
    334         ", date( 'Y-m-d', time() - YEAR_IN_SECONDS ), $project_id );
     158        $screenshot = gp_get_meta( 'wp-themes', $project->id, 'screenshot' );
     159        if ( $screenshot ) {
     160            return sprintf(
     161                '<div class="icon"><img src="%s" alt="" width="%d" height="%d"></div>',
     162                esc_url( 'https://i0.wp.com/' . $screenshot . '?w=' . $size * 2 . '&strip=all' ),
     163                $size,
     164                $size
     165            );
     166        }
    335167
    336         return $wpdb->get_results( $sql );
    337     }
    338 
    339     private function _encode( $raw ) {
    340         $raw = mb_convert_encoding( $raw, 'UTF-8', 'ASCII, JIS, UTF-8, Windows-1252, ISO-8859-1' );
    341         return ent2ncr( htmlspecialchars_decode( htmlentities( $raw, ENT_NOQUOTES, 'UTF-8' ), ENT_NOQUOTES ) );
     168        return $default;
    342169    }
    343170}
Note: See TracChangeset for help on using the changeset viewer.