Making WordPress.org


Ignore:
Timestamp:
02/04/2015 06:37:01 PM (10 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.