Making WordPress.org

Changeset 2197


Ignore:
Timestamp:
12/17/2015 12:32:48 PM (9 years ago)
Author:
ocean90
Message:

Rosetta: Update roles plugin to use the new translation_editors table.

  • Introduce a new role for General Translation Editors.
  • Introduce a new capability to manage Translation Editors, assigned to General Translation Editors.
  • Fix wrong action name for bulk removal.
  • Remove custom "Role" column, obsolete with WordPress 4.4.
  • Introduce translation_editor_added, translation_editor_updated and translation_editor_removed actions.
  • Make "Translation Editors" a top-level menu.
  • Add views to the "Translation Editors" table.

See #1240.

Location:
sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/class-translation-editors-list-table.php

    r2001 r2197  
    88
    99    /**
    10      * Holds the role of a translation editor.
    11      *
    12      * @var string
    13      */
    14     public $user_role;
    15 
    16     /**
    17      * Holds the meta key of the project access list.
    18      *
    19      * @var string
    20      */
    21     public $project_access_meta_key;
     10     * Holds the roles for translation editors.
     11     *
     12     * @var arrays
     13     */
     14    public $user_roles;
     15
     16    /**
     17     * Holds the instance of the Rosetta_Roles class.
     18     *
     19     * @var Rosetta_Roles
     20     */
     21    public $rosetta_roles;
    2222
    2323    /**
     
    5656        ) );
    5757
    58         $this->user_role = $args['user_role'];
    59         $this->project_access_meta_key = $args['project_access_meta_key'];
    60         $this->projects = $args['projects'];
    61         $this->project_tree = $args['project_tree'];
    62         $this->user_can_promote = current_user_can( 'promote_users' );
     58        $this->user_roles       = $args['user_roles'];
     59        $this->projects         = $args['projects'];
     60        $this->project_tree     = $args['project_tree'];
     61        $this->rosetta_roles    = $args['rosetta_roles'];
     62        $this->user_can_promote = current_user_can( Rosetta_Roles::MANAGE_TRANSLATION_EDITORS_CAP );
    6363    }
    6464
     
    7171        $paged =    $this->get_pagenum();
    7272
     73        $role__in = $this->user_roles;
     74        if ( isset( $_REQUEST['role'] ) ) {
     75            $role__in = $_REQUEST['role'];
     76        }
     77
    7378        $args = array(
    74             'number' => $per_page,
    75             'offset' => ( $paged - 1 ) * $per_page,
    76             'role'   => $this->user_role,
    77             'search' => $search,
    78             'fields' => 'all_with_meta'
     79            'number'   => $per_page,
     80            'offset'   => ( $paged - 1 ) * $per_page,
     81            'role__in' => $role__in,
     82            'search'   => $search,
     83            'fields'   => 'all_with_meta'
    7984        );
    8085
     
    137142
    138143    /**
     144     * Provides a list of roles and user count for that role for easy
     145     * filtering of the table.
     146     *
     147     * @return array An array of HTML links, one for each view.
     148     */
     149    protected function get_views() {
     150        $class = '';
     151        $view_links = array();
     152
     153        $users_of_blog = count_users();
     154
     155        $count_translation_editors = isset( $users_of_blog['avail_roles'][ Rosetta_Roles::TRANSLATION_EDITOR_ROLE ] ) ? $users_of_blog['avail_roles'][ Rosetta_Roles::TRANSLATION_EDITOR_ROLE ] : 0 ;
     156        $count_general_translation_editors = isset( $users_of_blog['avail_roles'][ Rosetta_Roles::GENERAL_TRANSLATION_EDITOR_ROLE ] ) ? $users_of_blog['avail_roles'][ Rosetta_Roles::GENERAL_TRANSLATION_EDITOR_ROLE ] : 0 ;
     157        $total_translation_editors = $count_translation_editors + $count_general_translation_editors;
     158
     159        $all_inner_html = sprintf(
     160            _nx(
     161                'All <span class="count">(%s)</span>',
     162                'All <span class="count">(%s)</span>',
     163                $total_translation_editors,
     164                'translation editors'
     165            ),
     166            number_format_i18n( $total_translation_editors )
     167        );
     168
     169        if ( ! isset( $_REQUEST['role'] ) ) {
     170            $class = 'current';
     171        }
     172
     173        $view_links['all'] = $this->get_view_link( array(), $all_inner_html, $class );
     174
     175        if ( $count_translation_editors ) {
     176            $class = '';
     177            $translation_editors_inner_html = sprintf(
     178                _n(
     179                    'Translation Editor <span class="count">(%s)</span>',
     180                    'Translation Editor <span class="count">(%s)</span>',
     181                    $count_translation_editors
     182                ),
     183                number_format_i18n( $count_translation_editors )
     184            );
     185
     186            if ( isset( $_REQUEST['role'] ) && Rosetta_Roles::TRANSLATION_EDITOR_ROLE === $_REQUEST['role'] ) {
     187                $class = 'current';
     188            }
     189
     190            $view_links[ Rosetta_Roles::TRANSLATION_EDITOR_ROLE ] = $this->get_view_link( array( 'role' => Rosetta_Roles::TRANSLATION_EDITOR_ROLE ), $translation_editors_inner_html, $class );
     191        }
     192
     193        if ( $count_translation_editors ) {
     194            $class = '';
     195            $general_translation_editors_inner_html = sprintf(
     196                _n(
     197                    'General Translation Editor <span class="count">(%s)</span>',
     198                    'General Translation Editor <span class="count">(%s)</span>',
     199                    $count_general_translation_editors
     200                ),
     201                number_format_i18n( $count_general_translation_editors )
     202            );
     203
     204            if ( isset( $_REQUEST['role'] ) && Rosetta_Roles::GENERAL_TRANSLATION_EDITOR_ROLE === $_REQUEST['role'] ) {
     205                $class = 'current';
     206            }
     207
     208            $view_links[ Rosetta_Roles::GENERAL_TRANSLATION_EDITOR_ROLE ] = $this->get_view_link( array( 'role' => Rosetta_Roles::GENERAL_TRANSLATION_EDITOR_ROLE ), $general_translation_editors_inner_html, $class );
     209        }
     210
     211        return $view_links;
     212    }
     213
     214    /**
     215     * Helper to create view links with params.
     216     *
     217     * @param array  $args  URL parameters for the link.
     218     * @param string $label Link text.
     219     * @param string $class Optional. Class attribute. Default empty string.
     220     * @return string The formatted link string.
     221     */
     222    protected function get_view_link( $args, $label, $class = '' ) {
     223        $page_url = menu_page_url( 'translation-editors', false );
     224        $url = add_query_arg( $args, $page_url );
     225
     226        $class_html = '';
     227        if ( ! empty( $class ) ) {
     228             $class_html = sprintf(
     229                ' class="%s"',
     230                esc_attr( $class )
     231            );
     232        }
     233
     234        return sprintf(
     235            '<a href="%s"%s>%s</a>',
     236            esc_url( $url ),
     237            $class_html,
     238            $label
     239        );
     240    }
     241
     242    /**
    139243     * Return a list of bulk actions available on this table.
    140244     *
     
    143247    protected function get_bulk_actions() {
    144248        return array(
    145             'remove' => _x( 'Remove', 'translation editor', 'rosetta' ),
     249            'remove-translation-editors' => _x( 'Remove', 'translation editor', 'rosetta' ),
    146250        );
    147251    }
     
    210314     */
    211315    public function column_email( $user ) {
    212         echo "<a href='mailto:$user->user_email'>$user->user_email</a>";
     316        echo "<a href='" . esc_url( "mailto:$user->user_email" ) . "'>$user->user_email</a>";
    213317    }
    214318
     
    219323     */
    220324    public function column_projects( $user ) {
    221         $project_access_list = get_user_meta( $user->ID, $this->project_access_meta_key, true );
     325        $project_access_list = $this->rosetta_roles->get_users_projects( $user->ID );
    222326
    223327        if ( empty( $project_access_list ) ) {
     
    226330        }
    227331
    228         if ( in_array( 'all', $project_access_list ) ) {
     332        if ( in_array( 'all', $project_access_list, true ) ) {
    229333            _e( 'All projects', 'rosetta' );
    230334            return;
  • sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/js/rosetta-roles.js

    r2037 r2197  
    8989
    9090        initialize: function() {
    91             this.set( 'checked', _.contains( projects.settings.accessList, parseInt( this.get( 'id' ), 10 ) ) );
     91            this.set( 'checked', _.contains( projects.settings.accessList, this.get( 'id' ) ) );
    9292        }
    9393    });
  • sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php

    r2037 r2197  
    55 * Description: WordPress interface for managing roles.
    66 * Author: ocean90
    7  * Version: 1.0
     7 * Version: 1.1
    88 */
    99
     10if ( ! class_exists( 'GP_Locales' ) ) {
     11    require_once GLOTPRESS_LOCALES_PATH;
     12}
     13
    1014class Rosetta_Roles {
    1115    /**
     
    1519
    1620    /**
    17      * Holds the role of a translation editor.
    18      *
    19      * @var string
    20      */
    21     public $translation_editor_role = 'translation_editor';
    22 
    23     /**
    24      * Holds the meta key of the project access list.
    25      *
    26      * @var string
    27      */
    28     public $project_access_meta_key = 'translation_editor_project_access_list';
     21     * Database table for translation editors.
     22     */
     23    const TRANSLATION_EDITORS_TABLE = 'translate_translation_editors';
     24
     25    /**
     26     * Role of a per project translation editor.
     27     */
     28    const TRANSLATION_EDITOR_ROLE = 'translation_editor';
     29
     30    /**
     31     * Role of a general translation editor.
     32     */
     33    const GENERAL_TRANSLATION_EDITOR_ROLE = 'general_translation_editor';
     34
     35    /**
     36     * Capabaility to promote translation editor.
     37     */
     38    const MANAGE_TRANSLATION_EDITORS_CAP = 'manage_translation_editors';
     39
     40    /**
     41     * Holds the GlotPress locale of current site.
     42     *
     43     * @var GP_Locale
     44     */
     45    private $gp_locale = null;
    2946
    3047    /**
     
    3249     */
    3350    public function __construct() {
     51        global $wpdb;
     52
    3453        add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
     54
     55        $wpdb->wporg_translation_editors = self::TRANSLATION_EDITORS_TABLE;
    3556    }
    3657
     
    3960     */
    4061    public function plugins_loaded() {
     62        $locale = get_locale();
     63        $gp_locale = GP_Locales::by_field( 'wp_locale', $locale );
     64        if ( ! $gp_locale ) {
     65            return;
     66        }
     67
     68        $this->gp_locale = $gp_locale;
     69
    4170        add_filter( 'editable_roles', array( $this, 'editable_roles' ) );
    42         add_filter( 'manage_users_columns',  array( $this, 'add_roles_column' ) );
    43         add_filter( 'manage_users_custom_column',  array( $this, 'display_user_roles' ), 10, 3 );
    4471        add_action( 'admin_init', array( $this, 'role_modifications' ) );
    4572        add_action( 'set_user_role', array( $this, 'restore_translation_editor_role' ), 10, 3 );
    4673        add_filter( 'gettext_with_context', array( $this, 'rename_user_roles' ), 10, 4 );
    4774        add_action( 'admin_menu', array( $this, 'register_translation_editors_page' ) );
    48         add_filter( 'user_row_actions', array( $this, 'promote_user_to_translation_editor' ), 10, 2 );
    4975        add_filter( 'set-screen-option', array( $this, 'save_custom_screen_options' ), 10, 3 );
    50     }
    51 
    52     /**
    53      * Adds an action link to promote an user to a translation editor.
    54      *
    55      * @param array   $actions     An array of action links to be displayed.
    56      * @param WP_User $user_object WP_User object for the currently-listed user.
    57      * @return array $actions An array of action links to be displayed.
    58      */
    59     public function promote_user_to_translation_editor( $actions, $user ) {
    60         if ( in_array( $this->translation_editor_role, $user->roles ) || ! current_user_can( 'promote_users' ) ) {
    61             return $actions;
    62         }
    63 
    64         $url = menu_page_url( 'translation-editors', false );
    65         $url = add_query_arg( array(
    66             'action' => 'add-translation-editor',
    67             'user'   => $user->ID,
    68         ), $url );
    69         $url = wp_nonce_url( $url, 'add-translation-editor', '_nonce_add-translation-editor' );
    70         $actions['translation-editor'] = sprintf(
    71             '<a href="%s">%s</a>',
    72             esc_url( $url ),
    73             __( 'Promote to Translation Editor', 'rosetta' )
    74         );
    75 
    76         return $actions;
    77     }
    78 
    79     /**
    80      * Registers "Translation Editor" role and modifies editor role.
     76
     77        add_action( 'translation_editor_added', array( $this, 'update_wporg_profile_badge' ) );
     78        add_action( 'translation_editor_removed', array( $this, 'update_wporg_profile_badge' ) );
     79    }
     80
     81    /**
     82     * Registers "(General) Translation Editor" role and modifies editor role.
    8183     */
    8284    public function role_modifications() {
    83         if ( ! get_role( $this->translation_editor_role ) ) {
    84             add_role( $this->translation_editor_role, __( 'Translation Editor', 'rosetta' ), array( 'read' => true, 'level_0' => true ) );
     85        if ( ! get_role( self::TRANSLATION_EDITOR_ROLE ) ) {
     86            add_role( self::TRANSLATION_EDITOR_ROLE, __( 'Translation Editor', 'rosetta' ), array( 'read' => true, 'level_0' => true ) );
     87        }
     88
     89        if ( ! get_role( self::GENERAL_TRANSLATION_EDITOR_ROLE ) ) {
     90            add_role( self::GENERAL_TRANSLATION_EDITOR_ROLE, __( 'General Translation Editor', 'rosetta' ), array( 'read' => true, 'level_0' => true, self::MANAGE_TRANSLATION_EDITORS_CAP => true ) );
    8591        }
    8692
     
    9298            $editor_role->add_cap( 'remove_users' );
    9399        }
    94 
    95         // Remove deprecated validator role.
    96         $validator_role = get_role( 'validator' );
    97         if ( $validator_role ) {
    98             remove_role( 'validator' );
    99         }
    100     }
    101 
    102     /**
    103      * Restores the "Translation Editor" role if an user is promoted.
     100    }
     101
     102    /**
     103     * Restores the "(General) Translation Editor" role if an user is promoted.
    104104     *
    105105     * @param int    $user_id   The user ID.
     
    108108     */
    109109    public function restore_translation_editor_role( $user_id, $role, $old_roles ) {
    110         if ( ! in_array( $this->translation_editor_role, $old_roles ) ) {
    111             return;
    112         }
    113 
    114         $user = new WP_User( $user_id );
    115         $user->add_role( $this->translation_editor_role );
     110        if ( self::GENERAL_TRANSLATION_EDITOR_ROLE !== $role && in_array( self::TRANSLATION_EDITOR_ROLE, $old_roles ) ) {
     111            $user = new WP_User( $user_id );
     112            $user->add_role( self::TRANSLATION_EDITOR_ROLE );
     113        }
     114
     115        if ( self::TRANSLATION_EDITOR_ROLE !== $role && in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $old_roles ) ) {
     116            $user = new WP_User( $user_id );
     117            $user->add_role( self::GENERAL_TRANSLATION_EDITOR_ROLE );
     118        }
    116119    }
    117120
     
    126129     */
    127130    public function editable_roles( $roles ) {
    128         unset( $roles[ $this->translation_editor_role ] );
     131        unset( $roles[ self::TRANSLATION_EDITOR_ROLE ], $roles[ self::GENERAL_TRANSLATION_EDITOR_ROLE ] );
    129132
    130133        if ( ! is_super_admin() && ! is_main_site() ) {
     
    151154        if ( 'Translation Editor' === $text ) {
    152155            return __( 'Translation Editor', 'rosetta' );
     156        } elseif ( 'General Translation Editor' === $text ) {
     157            return __( 'General Translation Editor', 'rosetta' );
    153158        }
    154159
     
    157162
    158163    /**
    159      * Replaces the "Role" column with a "Roles" column.
    160      *
    161      * @param array $columns An array of column headers.
    162      * @return array An array of column headers.
    163      */
    164     public function add_roles_column( $columns ) {
    165         $posts = $columns['posts'];
    166         unset( $columns['role'], $columns['posts'] );
    167         reset( $columns );
    168         $columns['roles'] = __( 'Roles', 'rosetta' );
    169         $columns['posts'] = $posts;
    170 
    171         return $columns;
    172     }
    173 
    174     /**
    175      * Displays a comma separated list of user's roles.
    176      *
    177      * @param string $output      Custom column output.
    178      * @param string $column_name Column name.
    179      * @param int    $user_id     ID of the currently-listed user.
    180      * @return string Comma separated list of user's roles.
    181      */
    182     public function display_user_roles( $output, $column_name, $user_id ) {
    183         global $wp_roles;
    184 
    185         if ( 'roles' == $column_name ) {
    186             $user_roles = array();
    187             $user = new WP_User( $user_id );
    188             foreach ( $user->roles as $role ) {
    189                 $role_name = $wp_roles->role_names[ $role ];
    190                 $role_name = translate_user_role( $role_name );
    191                 $user_roles[] = $role_name;
    192             }
    193 
    194             return implode( ', ', $user_roles );
    195         }
    196 
    197         return $output;
    198     }
    199 
    200     /**
    201164     * Registers page for managing translation editors.
    202165     */
    203166    public function register_translation_editors_page() {
    204         $this->translation_editors_page = add_users_page(
     167        $this->translation_editors_page = add_menu_page(
    205168            __( 'Translation Editors', 'rosetta' ),
    206169            __( 'Translation Editors', 'rosetta' ),
    207             'list_users',
     170            self::MANAGE_TRANSLATION_EDITORS_CAP,
    208171            'translation-editors',
    209             array( $this, 'render_translation_editors_page' )
     172            array( $this, 'render_translation_editors_page' ),
     173            'dashicons-translation',
     174            71 // After Users
    210175        );
    211176
     
    221186     */
    222187    public function enqueue_scripts() {
    223         wp_enqueue_script( 'rosetta-roles', plugins_url( '/js/rosetta-roles.js', __FILE__ ), array( 'jquery', 'wp-backbone' ), '3', true );
     188        wp_enqueue_script( 'rosetta-roles', plugins_url( '/js/rosetta-roles.js', __FILE__ ), array( 'jquery', 'wp-backbone' ), '4', true );
    224189    }
    225190
     
    329294                    check_admin_referer( 'add-translation-editor', '_nonce_add-translation-editor' );
    330295
    331                     if ( ! current_user_can( 'promote_users' ) ) {
     296                    if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) {
    332297                        wp_redirect( $redirect );
    333298                        exit;
     
    360325                    }
    361326
    362                     if ( in_array( $this->translation_editor_role, $user_details->roles ) ) {
     327                    if ( in_array( self::TRANSLATION_EDITOR_ROLE, $user_details->roles ) || in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user_details->roles ) ) {
    363328                        wp_redirect( add_query_arg( array( 'error' => 'user-exists' ), $redirect ) );
    364329                        exit;
    365330                    }
    366331
    367                     $user_details->add_role( $this->translation_editor_role );
    368                     $this->notify_translation_editor_update( $user_details->ID, 'add' );
    369 
    370                     $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;
    371 
    372332                    $projects = empty( $_REQUEST['projects'] ) ? '' : $_REQUEST['projects'];
    373333                    if ( 'custom' === $projects ) {
    374                         update_user_meta( $user_details->ID, $meta_key, array() );
     334                        $this->update_translation_editor( $user_details );
     335
    375336                        $redirect = add_query_arg( 'user_id', $user_details->ID, $redirect );
    376337                        wp_redirect( add_query_arg( array( 'update' => 'user-added-custom-projects' ), $redirect ) );
    377338                        exit;
    378                     }
    379 
    380                     update_user_meta( $user_details->ID, $meta_key, array( 'all' ) );
    381 
    382                     wp_redirect( add_query_arg( array( 'update' => 'user-added' ), $redirect ) );
    383                     exit;
     339                    } else {
     340                        $this->update_translation_editor( $user_details, array( 'all' ) );
     341
     342                        wp_redirect( add_query_arg( array( 'update' => 'user-added' ), $redirect ) );
     343                        exit;
     344                    }
    384345                case 'remove-translation-editors':
    385346                    check_admin_referer( 'bulk-translation-editors' );
    386347
    387                     if ( ! current_user_can( 'promote_users' ) ) {
     348                    if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) {
    388349                        wp_redirect( $redirect );
    389350                        exit;
     
    396357
    397358                    $count = 0;
    398                     $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;
    399359                    $user_ids = array_map( 'intval', (array) $_REQUEST['translation-editors'] );
    400360                    foreach ( $user_ids as $user_id ) {
    401                         $user = get_user_by( 'id', $user_id );
    402                         $user->remove_role( $this->translation_editor_role );
    403                         delete_user_meta( $user_id, $meta_key );
    404                         $this->notify_translation_editor_update( $user_id, 'remove' );
     361                        $this->remove_translation_editor( $user_id );
    405362                        $count++;
    406363                    }
     
    411368                    check_admin_referer( 'remove-translation-editor' );
    412369
    413                     if ( ! current_user_can( 'promote_users' ) ) {
     370                    if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) {
    414371                        wp_redirect( $redirect );
    415372                        exit;
     
    422379
    423380                    $user_id = (int) $_REQUEST['translation-editor'];
    424                     $user = get_user_by( 'id', $user_id );
    425                     $user->remove_role( $this->translation_editor_role );
    426                     $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;
    427                     delete_user_meta( $user_id, $meta_key );
    428                     $this->notify_translation_editor_update( $user_id, 'remove' );
     381                    $this->remove_translation_editor( $user_id );
    429382
    430383                    wp_redirect( add_query_arg( array( 'update' => 'user-removed' ), $redirect ) );
     
    444397        $redirect = menu_page_url( 'translation-editors', false );
    445398
    446         if ( ! current_user_can( 'promote_users' ) ) {
     399        if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) {
    447400            wp_redirect( $redirect );
    448401            exit;
     
    461414        }
    462415
    463         if ( ! user_can( $user_details, $this->translation_editor_role ) ) {
     416        if ( ! in_array( self::TRANSLATION_EDITOR_ROLE, $user_details->roles ) && ! in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user_details->roles ) ) {
    464417            wp_redirect( add_query_arg( array( 'error' => 'user-cannot' ), $redirect ) );
    465418            exit;
     
    478431
    479432                $projects = (array) $_REQUEST['projects'];
    480                 if ( in_array( 'all', $projects ) ) {
    481                     $projects = array( 'all' );
     433                if ( in_array( 'all', $projects, true ) ) {
     434                    $this->update_translation_editor( $user_details, array( 'all' ) );
    482435                } else {
    483436                    $projects = array_map( 'intval', $projects );
    484437                    $projects = array_values( array_intersect( $all_projects, $projects ) );
     438                    $this->update_translation_editor( $user_details, $projects );
    485439                }
    486 
    487                 $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;
    488                 update_user_meta( $user_details->ID, $meta_key, $projects );
    489440
    490441                wp_redirect( add_query_arg( array( 'update' => 'user-updated' ), $redirect ) );
    491442                exit;
    492443        }
     444    }
     445
     446    /**
     447     * Removes a translation editor.
     448     *
     449     * @param int|WP_User $user User ID or object.
     450     * @return bool True on success, false on failure.
     451     */
     452    private function remove_translation_editor( $user ) {
     453        global $wpdb;
     454
     455        if ( ! $user instanceof WP_User ) {
     456            $user = get_user_by( 'id', $user );
     457        }
     458
     459        if ( ! $user->exists() ) {
     460            return false;
     461        }
     462
     463        if ( in_array( self::TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     464            $user->remove_role( self::TRANSLATION_EDITOR_ROLE );
     465        }
     466
     467        if ( in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     468            $user->remove_role( self::GENERAL_TRANSLATION_EDITOR_ROLE );
     469        }
     470
     471        $wpdb->query( $wpdb->prepare( "
     472            DELETE FROM {$wpdb->wporg_translation_editors}
     473            WHERE `user_id` = %d AND `locale` = %s
     474        ", $user->ID, $this->gp_locale->slug ) );
     475
     476        do_action( 'translation_editor_removed', $user->ID );
     477
     478        return true;
     479    }
     480
     481    /**
     482     * Creates or updates a translation editor.
     483     *
     484     * @param int|WP_User $user     User ID or object.
     485     * @param array       $projects The projects to which the user should get assigned.
     486     *                              Pass `array( 'all' )` to make their a general translation
     487     *                              editor.
     488     * @return bool True on success, false on failure.
     489     */
     490    private function update_translation_editor( $user, $projects = array() ) {
     491        global $wpdb;
     492
     493        if ( ! $user instanceof WP_User ) {
     494            $user = get_user_by( 'id', $user );
     495        }
     496
     497        if ( ! $user->exists() ) {
     498            return false;
     499        }
     500
     501        $update = in_array( self::TRANSLATION_EDITOR_ROLE, $user->roles ) || in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user->roles );
     502
     503        $projects = array_map( 'strval', $projects );
     504        $current_projects = $this->get_users_projects( $user->ID );
     505        $projects_to_add = $projects_to_remove = array();
     506
     507        if ( in_array( 'all', $projects, true ) ) {
     508            $projects_to_remove = array_diff( $current_projects, array( '0' ) );
     509            if ( ! in_array( '0', $current_projects, true ) ) {
     510                $projects_to_add[] = '0';
     511            }
     512
     513            if ( in_array( self::TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     514                $user->remove_role( self::TRANSLATION_EDITOR_ROLE );
     515            }
     516
     517            if ( ! in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     518                $user->add_role( self::GENERAL_TRANSLATION_EDITOR_ROLE );
     519            }
     520        } else {
     521            $projects_to_remove = array_diff( $current_projects, $projects );
     522            $projects_to_add = array_diff( $projects, $current_projects );
     523
     524            if ( in_array( self::GENERAL_TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     525                $user->remove_role( self::GENERAL_TRANSLATION_EDITOR_ROLE );
     526            }
     527
     528            if ( ! in_array( self::TRANSLATION_EDITOR_ROLE, $user->roles ) ) {
     529                $user->add_role( self::TRANSLATION_EDITOR_ROLE );
     530            }
     531        }
     532
     533        $values_to_add = array();
     534        foreach ( $projects_to_add as $project_id ) {
     535            $values_to_add[] = $wpdb->prepare( '(%d, %d, %s, %s)',
     536                $user->ID,
     537                $project_id,
     538                $this->gp_locale->slug,
     539                'default'
     540            );
     541        }
     542
     543        if ( $values_to_add ) {
     544            $wpdb->query( "
     545                INSERT INTO {$wpdb->wporg_translation_editors}
     546                (`user_id`,`project_id`, `locale`, `locale_slug`)
     547                VALUES " . implode( ', ', $values_to_add ) . "
     548            " );
     549        }
     550
     551        $values_to_remove = array_map( 'intval', $projects_to_remove );
     552        if ( $values_to_remove ) {
     553            $wpdb->query( $wpdb->prepare( "
     554                DELETE FROM {$wpdb->wporg_translation_editors}
     555                WHERE `user_id` = %d AND `locale` = %s
     556                AND project_id IN (" . implode( ', ', $values_to_remove ) . ")
     557            ", $user->ID, $this->gp_locale->slug ) );
     558        }
     559
     560        if ( $update ) {
     561            do_action( 'translation_editor_updated', $user->ID );
     562        } else {
     563            do_action( 'translation_editor_added', $user->ID );
     564        }
     565
     566        return true;
     567    }
     568
     569    /**
     570     * Handles the update of the translation editor badges on
     571     * profiles.wordpress.org.
     572     *
     573     * @param int $user_id User ID.
     574     */
     575    public function update_wporg_profile_badge( $user_id ) {
     576        $action = 'translation_editor_added' === current_filter() ? 'add' : 'remove';
     577
     578        $this->notify_profiles_wporg_translation_editor_update( $user_id, $action );
     579    }
     580
     581    /**
     582     * Retrieves the assigned projects of a user
     583     *
     584     * @param int $user_id User ID.
     585     * @return array List of project IDs.
     586     */
     587    public function get_users_projects( $user_id ) {
     588        global $wpdb;
     589
     590        $projects = $wpdb->get_col( $wpdb->prepare( "
     591            SELECT project_id FROM
     592            {$wpdb->wporg_translation_editors}
     593            WHERE user_id = %d AND locale = %s
     594        ", $user_id, $this->gp_locale->slug ) );
     595
     596        if ( ! $projects ) {
     597            return array();
     598        }
     599
     600        if ( in_array( '0', $projects, true ) ) {
     601            return array( 'all' );
     602        }
     603
     604        return $projects;
    493605    }
    494606
     
    524636        $project_tree = array_values( $project_tree );
    525637
    526         $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;
    527         $project_access_list = get_user_meta( $user_id, $meta_key, true );
    528         if ( ! $project_access_list ) {
    529             $project_access_list = array();
    530         }
     638        $project_access_list = $this->get_users_projects( $user_id );
    531639
    532640        wp_localize_script( 'rosetta-roles', '_rosettaProjectsSettings', array(
     
    608716
    609717        $args = array(
    610             'user_role'               => $this->translation_editor_role,
    611             'projects'                => $projects,
    612             'project_tree'            => $project_tree,
    613             'project_access_meta_key' => $wpdb->get_blog_prefix() . $this->project_access_meta_key,
     718            'user_roles'    => array( self::TRANSLATION_EDITOR_ROLE, self::GENERAL_TRANSLATION_EDITOR_ROLE ),
     719            'projects'      => $projects,
     720            'project_tree'  => $project_tree,
     721            'rosetta_roles' => $this,
    614722        );
    615723        $list_table = new Rosetta_Translation_Editors_List_Table( $args );
     
    624732     * @param  string $action  Can be 'add' or 'remove'.
    625733     */
    626     private function notify_translation_editor_update( $user_id, $action ) {
     734    private function notify_profiles_wporg_translation_editor_update( $user_id, $action ) {
    627735        $args = array(
    628736            'body' => array(
  • sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/views/translation-editors.php

    r1942 r2197  
    1717    </form>
    1818
     19    <?php $list_table->views(); ?>
     20
    1921    <form method="post">
    2022        <?php $list_table->display(); ?>
    2123    </form>
    2224
    23     <?php if ( current_user_can( 'promote_users' ) ) : ?>
     25    <?php if ( current_user_can( Rosetta_Roles::MANAGE_TRANSLATION_EDITORS_CAP ) ) : ?>
    2426        <h3><?php _e( 'Add Translation Editor', 'rosetta' ); ?></h3>
    2527        <p><?php _e( 'Enter the email address or username of an existing user on wordpress.org.', 'rosetta' ); ?></p>
Note: See TracChangeset for help on using the changeset viewer.