Changeset 2197 for sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php
- Timestamp:
- 12/17/2015 12:32:48 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/global.wordpress.org/public_html/wp-content/mu-plugins/roles/rosetta-roles.php
r2037 r2197 5 5 * Description: WordPress interface for managing roles. 6 6 * Author: ocean90 7 * Version: 1. 07 * Version: 1.1 8 8 */ 9 9 10 if ( ! class_exists( 'GP_Locales' ) ) { 11 require_once GLOTPRESS_LOCALES_PATH; 12 } 13 10 14 class Rosetta_Roles { 11 15 /** … … 15 19 16 20 /** 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; 29 46 30 47 /** … … 32 49 */ 33 50 public function __construct() { 51 global $wpdb; 52 34 53 add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) ); 54 55 $wpdb->wporg_translation_editors = self::TRANSLATION_EDITORS_TABLE; 35 56 } 36 57 … … 39 60 */ 40 61 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 41 70 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 );44 71 add_action( 'admin_init', array( $this, 'role_modifications' ) ); 45 72 add_action( 'set_user_role', array( $this, 'restore_translation_editor_role' ), 10, 3 ); 46 73 add_filter( 'gettext_with_context', array( $this, 'rename_user_roles' ), 10, 4 ); 47 74 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 );49 75 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. 81 83 */ 82 84 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 ) ); 85 91 } 86 92 … … 92 98 $editor_role->add_cap( 'remove_users' ); 93 99 } 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. 104 104 * 105 105 * @param int $user_id The user ID. … … 108 108 */ 109 109 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 } 116 119 } 117 120 … … 126 129 */ 127 130 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 ] ); 129 132 130 133 if ( ! is_super_admin() && ! is_main_site() ) { … … 151 154 if ( 'Translation Editor' === $text ) { 152 155 return __( 'Translation Editor', 'rosetta' ); 156 } elseif ( 'General Translation Editor' === $text ) { 157 return __( 'General Translation Editor', 'rosetta' ); 153 158 } 154 159 … … 157 162 158 163 /** 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 /**201 164 * Registers page for managing translation editors. 202 165 */ 203 166 public function register_translation_editors_page() { 204 $this->translation_editors_page = add_ users_page(167 $this->translation_editors_page = add_menu_page( 205 168 __( 'Translation Editors', 'rosetta' ), 206 169 __( 'Translation Editors', 'rosetta' ), 207 'list_users',170 self::MANAGE_TRANSLATION_EDITORS_CAP, 208 171 'translation-editors', 209 array( $this, 'render_translation_editors_page' ) 172 array( $this, 'render_translation_editors_page' ), 173 'dashicons-translation', 174 71 // After Users 210 175 ); 211 176 … … 221 186 */ 222 187 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 ); 224 189 } 225 190 … … 329 294 check_admin_referer( 'add-translation-editor', '_nonce_add-translation-editor' ); 330 295 331 if ( ! current_user_can( 'promote_users') ) {296 if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) { 332 297 wp_redirect( $redirect ); 333 298 exit; … … 360 325 } 361 326 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 ) ) { 363 328 wp_redirect( add_query_arg( array( 'error' => 'user-exists' ), $redirect ) ); 364 329 exit; 365 330 } 366 331 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 372 332 $projects = empty( $_REQUEST['projects'] ) ? '' : $_REQUEST['projects']; 373 333 if ( 'custom' === $projects ) { 374 update_user_meta( $user_details->ID, $meta_key, array() ); 334 $this->update_translation_editor( $user_details ); 335 375 336 $redirect = add_query_arg( 'user_id', $user_details->ID, $redirect ); 376 337 wp_redirect( add_query_arg( array( 'update' => 'user-added-custom-projects' ), $redirect ) ); 377 338 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 } 384 345 case 'remove-translation-editors': 385 346 check_admin_referer( 'bulk-translation-editors' ); 386 347 387 if ( ! current_user_can( 'promote_users') ) {348 if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) { 388 349 wp_redirect( $redirect ); 389 350 exit; … … 396 357 397 358 $count = 0; 398 $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;399 359 $user_ids = array_map( 'intval', (array) $_REQUEST['translation-editors'] ); 400 360 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 ); 405 362 $count++; 406 363 } … … 411 368 check_admin_referer( 'remove-translation-editor' ); 412 369 413 if ( ! current_user_can( 'promote_users') ) {370 if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) { 414 371 wp_redirect( $redirect ); 415 372 exit; … … 422 379 423 380 $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 ); 429 382 430 383 wp_redirect( add_query_arg( array( 'update' => 'user-removed' ), $redirect ) ); … … 444 397 $redirect = menu_page_url( 'translation-editors', false ); 445 398 446 if ( ! current_user_can( 'promote_users') ) {399 if ( ! current_user_can( self::MANAGE_TRANSLATION_EDITORS_CAP ) ) { 447 400 wp_redirect( $redirect ); 448 401 exit; … … 461 414 } 462 415 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 ) ) { 464 417 wp_redirect( add_query_arg( array( 'error' => 'user-cannot' ), $redirect ) ); 465 418 exit; … … 478 431 479 432 $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' ) ); 482 435 } else { 483 436 $projects = array_map( 'intval', $projects ); 484 437 $projects = array_values( array_intersect( $all_projects, $projects ) ); 438 $this->update_translation_editor( $user_details, $projects ); 485 439 } 486 487 $meta_key = $wpdb->get_blog_prefix() . $this->project_access_meta_key;488 update_user_meta( $user_details->ID, $meta_key, $projects );489 440 490 441 wp_redirect( add_query_arg( array( 'update' => 'user-updated' ), $redirect ) ); 491 442 exit; 492 443 } 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; 493 605 } 494 606 … … 524 636 $project_tree = array_values( $project_tree ); 525 637 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 ); 531 639 532 640 wp_localize_script( 'rosetta-roles', '_rosettaProjectsSettings', array( … … 608 716 609 717 $args = array( 610 'user_role ' => $this->translation_editor_role,611 'projects' 612 '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, 614 722 ); 615 723 $list_table = new Rosetta_Translation_Editors_List_Table( $args ); … … 624 732 * @param string $action Can be 'add' or 'remove'. 625 733 */ 626 private function notify_ translation_editor_update( $user_id, $action ) {734 private function notify_profiles_wporg_translation_editor_update( $user_id, $action ) { 627 735 $args = array( 628 736 'body' => array(
Note: See TracChangeset
for help on using the changeset viewer.