Making WordPress.org


Ignore:
Timestamp:
02/04/2015 06:37:01 PM (12 years ago)
Author:
obenland
Message:

WP.org Themes: Remove approval workflow.

Theme Review Admins do a final check on Trac and set themes live from there.
For the off chance that a ticket needs manual adjustment, version statuses can
be changed in the edit screen of a repopackage item.

This also removes Trac syncing, in order for it to be added as a script on the
dotorg side.

See https://wordpress.slack.com/archives/meta/p1423071510000491
See #745.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/theme-directory.php

    r1145 r1219  
    2121include_once plugin_dir_path( __FILE__ ) . 'upload.php';
    2222
    23 /**
    24  * Things to change on activation.
    25  */
    26 function wporg_themes_activate() {
    27 
    28         // Give Editors the ability to approve a theme.
    29         // Can be split to different roles in the future.
    30         $admin = get_role( 'editor' );
    31         $admin->add_cap( 'approve_themes' );
    32 }
    33 register_activation_hook( __FILE__, 'wporg_themes_activate' );
    3423
    3524/**
     
    10089function wporg_themes_map_meta_cap( $caps, $cap, $user_id, $args ) {
    10190        switch ( $cap ) {
    102                 case 'approve_theme':
    103                         $caps[] = 'approve_themes';
    104                         unset( $caps[ array_search( $cap, $caps ) ] );
    105 
    106                         // Don't allow Admins to approve their own themes.
    107                         if ( isset( $args[0] ) && get_post( $args[0] )->post_author == $user_id ) {
    108                                 $caps[] = 'do_not_allow';
    109                         }
    110                         break;
    111 
    11291                case 'delete_categories':
    11392                case 'edit_categories':
     
    138117}
    139118add_filter( 'pre_insert_term', 'wporg_themes_pre_insert_term' );
    140 
    141 /**
    142  * Grabs theme review results from Trac and updates theme version number statuses accordingly.
    143  *
    144  * We're only checking for new results when on the edit screen for themes, and only for updates since the last time we
    145  * checked.
    146  */
    147 function wporg_themes_sync_review_results() {
    148         if ( 'repopackage' != $GLOBALS['typenow'] || ! defined( 'THEME_TRACBOT_PASSWORD' ) ) {
    149                 return;
    150         }
    151 
    152         if ( ! class_exists( 'Trac' ) ) {
    153                 require_once ABSPATH . WPINC . '/class-IXR.php';
    154                 require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';
    155                 require_once WPORGPATH . 'bb-theme/themes/lib/class-trac.php';
    156         }
    157 
    158         $trac         = new Trac( 'themetracbot', THEME_TRACBOT_PASSWORD, 'https://themes.trac.wordpress.org/login/xmlrpc' );
    159         $last_request = get_option( 'wporg-themes-last-trac-sync', strtotime( '-2 days' ) );
    160 
    161         foreach ( array( 'live', 'not-approved' ) as $resolution ) {
    162                 // Get array of tickets.
    163                 $tickets = (array) $trac->ticket_query( add_query_arg( array(
    164                         'status'     => 'closed',
    165                         'resolution' => $resolution,
    166                         'order'      => 'changetime',
    167                         'changetime' => date( 'c', $last_request ),
    168                         'desc'       => 1,
    169                 ) ) );
    170 
    171                 foreach ( $tickets as $ticket_id ) {
    172                         // Get the theme associated with that ticket.
    173                         $post_ids = get_posts( array(
    174                                 'fields'         => 'ids',
    175                                 'meta_query'     => array(
    176                                         array(
    177                                                 'value'   => $ticket_id,
    178                                                 'compare' => 'IN',
    179                                         ),
    180                                 ),
    181                                 'post_status'    => 'any',
    182                                 'posts_per_page' => - 1,
    183                                 'post_type'      => 'repopackage',
    184                         ) );
    185 
    186                         if ( empty( $post_ids ) ) {
    187                                 continue;
    188                         }
    189 
    190                         $post_id = array_pop( $post_ids );
    191                         $version = array_search( $ticket_id, (array) get_post_meta( $post_id, '_ticket_id', true ) );
    192                         if ( ! $version ) {
    193                                 continue;
    194                         }
    195 
    196                         // Bail if the the theme is not new.
    197                         if ( 'new' != wporg_themes_get_version_status( $post_id, $version ) ) {
    198                                 continue;
    199                         }
    200 
    201                         // Approved themes:
    202                         if ( 'live' == $resolution ) {
    203                                 wporg_themes_update_version_status( $post_id, $version, 'pending' );
    204 
    205                         // Unapproved themes:
    206                         } else {
    207                                 wporg_themes_update_version_status( $post_id, $version, 'old' );
    208                         }
    209                 }
    210         }
    211 
    212         update_option( 'wporg-themes-last-trac-sync', time() );
    213 }
    214 add_action( 'load-edit.php', 'wporg_themes_sync_review_results' );
    215119
    216120/**
     
    259163                        break;
    260164
    261                 case 'pending':
    262                         // Discard all previous pending versions.
    263                         foreach ( array_keys( $meta, $new_status ) as $version ) {
    264                                 if ( version_compare( $version, $current_version, '<' ) ) {
    265                                         $meta[ $version ] = 'old';
    266                                 }
    267                         }
    268 
    269                         // Mark the current version as pending.
    270                         $meta[ $current_version ] = $new_status;
    271 
    272                         // Register the pending version.
    273                         update_post_meta( $post_id, '_has_pending_version', $current_version );
    274                         break;
    275 
    276165                // Marking a version as Old, does not have repercussions on other versions.
    277166                case 'old':
     
    303192
    304193/**
    305  * Filters repopackages to only contain themes that are ready to be approved, when on the corresponding view.
    306  *
    307  * @param WP_Query $wp_query
    308  * @return WP_Query
    309  */
    310 function wporg_themes_filter_repopackages( $wp_query ) {
    311         if ( 'edit.php' == $GLOBALS['pagenow'] && 'repopackage' == $GLOBALS['typenow'] && current_user_can( 'approve_theme' ) && ! empty( $_REQUEST['meta_key'] ) && '_has_pending_version' == $_REQUEST['meta_key'] ) {
    312                 $wp_query->set( 'meta_key', '_has_pending_version' );
    313         }
    314 
    315         return $wp_query;
    316 }
    317 add_filter( 'pre_get_posts', 'wporg_themes_filter_repopackages' );
    318 
    319 /**
    320  * Adds a view for Themes awaiting approval.
    321  *
    322  * @param array $views
    323  * @return array
    324  */
    325 function wporg_themes_status_pending_view( $views ) {
    326         $total_posts = count( get_posts(array(
    327                 'fields'         => 'ids',
    328                 'meta_key'       => '_has_pending_version',
    329                 'post_status'    => 'any',
    330                 'posts_per_page' => - 1,
    331                 'post_type'      => 'repopackage',
    332         ) ) );
    333 
    334         if ( current_user_can( 'approve_themes' ) && ! empty( $total_posts ) ) {
    335                 $class = '';
    336                 if ( isset( $_REQUEST['meta_key'] ) && '_has_pending_version' == $_REQUEST['meta_key'] ) {
    337                         $class = ' class="current"';
    338                 }
    339 
    340                 $views['status_pending'] = "<a href='edit.php?post_type=repopackage&post_status=any&meta_key=_has_pending_version'$class>" . sprintf( _nx( 'Pending Approval <span class="count">(%s)</span>', 'Pending Approval <span class="count">(%s)</span>', $total_posts, 'posts', 'wporg-themes' ), number_format_i18n( $total_posts ) ) . '</a>';
    341         }
    342 
    343         return $views;
    344 }
    345 add_filter( 'views_edit-repopackage', 'wporg_themes_status_pending_view' );
    346 
    347 /**
    348  * Adds an action to approve themes.
    349  *
    350  * @param array   $actions
    351  * @param WP_Post $post
    352  * @return array
    353  */
    354 function wporg_themes_post_row_actions( $actions, $post ) {
    355         if ( 'repopackage' == $post->post_type ) {
    356                 $before = array_slice( $actions, 0, - 1, true );
    357                 $after  = array_slice( $actions, - 1, 1, true );
    358 
    359                 if ( current_user_can( 'approve_theme', $post->ID ) && isset( $_REQUEST['meta_key'] ) && '_has_pending_version' == $_REQUEST['meta_key'] ) {
    360                         $before['approve_theme'] = sprintf( '<a class="submit-approve_theme" title="%1$s" href="%2$s">%3$s</a>', esc_attr__( 'Approve this item', 'wporg-themes' ), esc_url( wporg_themes_get_approve_url( $post ) ), __( 'Approve', 'wporg-themes' ) );
    361                 }
    362 
    363                 $actions = array_merge( $before, $after );
    364         }
    365 
    366         return $actions;
    367 }
    368 add_filter( 'post_row_actions', 'wporg_themes_post_row_actions', 10, 2 );
    369 
    370 /**
    371  * Action link to approve a theme version.
    372  *
    373  * @param WP_Post $post
    374  * @return string URL
    375  */
    376 function wporg_themes_get_approve_url( $post ) {
    377         return wp_nonce_url( add_query_arg( 'action', 'approve', admin_url( sprintf( get_post_type_object( $post->post_type )->_edit_link, $post->ID ) ) ), "approve-post_{$post->ID}" );
    378 }
    379 
    380 /**
    381  * Approve a theme version.
    382  */
    383 function wporg_themes_approve_theme() {
    384         if ( isset( $_GET['post'] ) ) {
    385                 $post_id = (int) $_GET['post'];
    386         }
    387 
    388         if ( ! $post_id ) {
    389                 wp_redirect( admin_url( 'edit.php' ) );
    390                 exit();
    391         }
    392 
    393         check_admin_referer( 'approve-post_' . $post_id );
    394 
    395         $version = get_post_meta( $post_id, '_has_pending_version', true );
    396 
    397         if ( ! $version ) {
    398                 wp_die( __( 'This item has already been approved.', 'wporg-themes' ) );
    399         }
    400 
    401         $post = get_post( $post_id );
    402 
    403         if ( ! get_post_type_object( $post->post_type ) ) {
    404                 wp_die( __( 'Unknown post type.' ) );
    405         }
    406 
    407         if ( ! current_user_can( 'approve_theme', $post_id ) || 'repopackage' != $post->post_type ) {
    408                 wp_die( __( 'You are not allowed to approve this item.', 'wporg-themes' ) );
    409         }
    410 
    411         wporg_themes_update_version_status( $post_id, $version, 'live' );
    412         delete_post_meta( $post_id, '_has_pending_version' );
    413 
    414         $ticket_id = get_post_meta( $post_id, '_trac_ticket_' . $version, true );
    415         if ( 'publish' == $post->post_status ) {
    416                 $email_subject  = sprintf( __( '[WordPress Themes] %1$s %2$s is now live', 'wporg-themes' ), $post->post_title, $version );
    417                 $email_content  = sprintf( __( 'Version %1$s of %2$s is now live at https://wordpress.org/themes/%3$s.', 'wporg-themes' ), $version, $post->post_title, $post->post_name ) . "\n\n";
    418                 $email_content .= sprintf( __( 'Any feedback items are at %s.', 'wporg-themes' ), "https://themes.trac.wordpress.org/ticket/$ticket_id" ) . "\n\n--\n";
    419                 $email_content .= __( 'The WordPress.org Themes Team', 'wporg' ) . "\n";
    420                 $email_content .= 'theme-reviewers@lists.wordpress.org';
    421 
    422         } else {
    423                 $email_subject  = sprintf( __( '[WordPress Themes] %s has been approved!', 'wporg-themes' ), $post->post_title );
    424                 $email_content  = sprintf( __( 'Congratulations, your new theme %1$s is now available to the public at https://wordpress.org/themes/%2$s.', 'wporg-themes' ), $post->post_title, $post->post_name ) . "\n\n";
    425                 $email_content .= sprintf( __( 'Any feedback items are at %s.', 'wporg-themes' ), "https://themes.trac.wordpress.org/ticket/$ticket_id" ) . "\n\n--\n";
    426                 $email_content .= __( 'The WordPress.org Themes Team', 'wporg' ) . "\n";
    427                 $email_content .= 'theme-reviewers@lists.wordpress.org';
    428         }
    429 
    430         wp_mail( get_user_by( 'id', $post->post_author )->user_email, $email_subject, $email_content, 'From: theme-reviewers@lists.wordpress.org' );
    431 
    432 
    433         // Update the theme's post status.
    434         wp_update_post( array(
    435                 'ID'          => $post_id,
    436                 'post_status' => 'publish',
    437         ) );
    438 
    439         wp_redirect( add_query_arg( 'approved', 1, remove_query_arg( array( 'trashed', 'untrashed', 'deleted', 'ids' ), wp_get_referer() ) ) );
    440         exit();
    441 }
    442 add_filter( 'admin_action_approve', 'wporg_themes_approve_theme' );
    443 
    444 /**
    445194 * Prevents repopackages from being deleted.
    446195 *
     
    455204}
    456205add_filter( 'before_delete_post', 'wporg_theme_no_delete_repopackage' );
    457 
    458 /**
    459  * Give the user feedback after approving a theme.
    460  */
    461 function wporg_themes_admin_notices() {
    462         if ( ! empty( $_GET['approved'] ) ) {
    463                 $approved = absint( $_GET['approved'] );
    464                 $message  = _n( '%s theme approved.', '%s themes approved.', $approved );
    465                 add_settings_error( 'wporg_themes', 'approved', sprintf( $message, $approved ), 'updated' );
    466         }
    467 
    468         // Display admin notices, if any.
    469         settings_errors( 'wporg_themes' );
    470 }
    471 add_filter( 'admin_notices', 'wporg_themes_admin_notices' );
    472206
    473207/**
     
    551285                                <option value="new" <?php selected( $status, 'new' ); ?>><?php esc_html_e( 'New', 'wporg-themes' ); ?></option>
    552286                                <option value="live" <?php selected( $status, 'live' ); ?>><?php esc_html_e( 'Live', 'wporg-themes' ); ?></option>
    553                                 <option value="pending" <?php selected( $status, 'pending' ); ?>><?php esc_html_e( 'Pending', 'wporg-themes' ); ?></option>
    554287                                <option value="old" <?php selected( $status, 'old' ); ?>><?php esc_html_e( 'Old', 'wporg-themes' ); ?></option>
    555288                        </select>
Note: See TracChangeset for help on using the changeset viewer.