Making WordPress.org

Ticket #3029: 3029.patch

File 3029.patch, 36.6 KB (added by SergeyBiryukov, 7 years ago)
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/class-customizations.php

     
    4848                add_action( 'add_meta_boxes', array( $this, 'register_admin_metaboxes' ), 10, 2 );
    4949                add_action( 'do_meta_boxes', array( $this, 'replace_title_global' ) );
    5050
    51                 add_filter( 'postbox_classes_plugin_internal-notes',    array( __NAMESPACE__ . '\Metabox\Internal_Notes', 'postbox_classes' ) );
    52                 add_filter( 'postbox_classes_plugin_plugin-committers', array( __NAMESPACE__ . '\Metabox\Committers',     'postbox_classes' ) );
    53                 add_filter( 'wp_ajax_add-committer',    array( __NAMESPACE__ . '\Metabox\Committers', 'add_committer'    ) );
    54                 add_filter( 'wp_ajax_delete-committer', array( __NAMESPACE__ . '\Metabox\Committers', 'remove_committer' ) );
     51                add_filter( 'postbox_classes_plugin_internal-notes',      array( __NAMESPACE__ . '\Metabox\Internal_Notes', 'postbox_classes' ) );
     52                add_filter( 'postbox_classes_plugin_plugin-committers',   array( __NAMESPACE__ . '\Metabox\Committers',     'postbox_classes' ) );
     53                add_filter( 'postbox_classes_plugin_plugin-support-reps', array( __NAMESPACE__ . '\Metabox\Support_Reps',     'postbox_classes' ) );
     54                add_filter( 'wp_ajax_add-committer',        array( __NAMESPACE__ . '\Metabox\Committers', 'add_committer'    ) );
     55                add_filter( 'wp_ajax_delete-committer',     array( __NAMESPACE__ . '\Metabox\Committers', 'remove_committer' ) );
     56                add_filter( 'wp_ajax_add-support-rep',      array( __NAMESPACE__ . '\Metabox\Support_Reps', 'add_support_rep' ) );
     57                add_filter( 'wp_ajax_delete-support-rep',   array( __NAMESPACE__ . '\Metabox\Support_Reps', 'remove_support_rep' ) );
    5558                add_action( 'wp_ajax_plugin-author-lookup', array( __NAMESPACE__ . '\Metabox\Author', 'lookup_author' ) );
    5659
    5760        }
     
    114117                                        wp_enqueue_style( 'plugin-admin-post-css', plugins_url( 'css/edit-form.css', Plugin_Directory\PLUGIN_FILE ), array( 'edit' ), 4 );
    115118                                        wp_enqueue_script( 'plugin-admin-post-js', plugins_url( 'js/edit-form.js', Plugin_Directory\PLUGIN_FILE ), array( 'wp-util', 'wp-lists' ), 5 );
    116119                                        wp_localize_script( 'plugin-admin-post-js', 'pluginDirectory', array(
    117                                                 'approvePluginAYS'   => __( 'Are you sure you want to approve this plugin?', 'wporg-plugins' ),
    118                                                 'rejectPluginAYS'    => __( 'Are you sure you want to reject this plugin?', 'wporg-plugins' ),
    119                                                 'removeCommitterAYS' => __( 'Are you sure you want to remove this committer?', 'wporg-plugins' ),
     120                                                'approvePluginAYS'    => __( 'Are you sure you want to approve this plugin?', 'wporg-plugins' ),
     121                                                'rejectPluginAYS'     => __( 'Are you sure you want to reject this plugin?', 'wporg-plugins' ),
     122                                                'removeCommitterAYS'  => __( 'Are you sure you want to remove this committer?', 'wporg-plugins' ),
     123                                                'removeSupportRepAYS' => __( 'Are you sure you want to remove this support rep?', 'wporg-plugins' ),
    120124                                        ) );
    121125                                        break;
    122126
     
    436440                                'plugin', 'side'
    437441                        );
    438442
     443                        add_meta_box(
     444                                'plugin-support-reps',
     445                                __( 'Plugin Support Reps', 'wporg-plugins' ),
     446                                array( __NAMESPACE__ . '\Metabox\Support_Reps', 'display' ),
     447                                'plugin', 'side'
     448                        );
    439449                }
    440450
    441451                // Remove unnecessary metaboxes.
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/list-table/class-committers.php

     
    2222                parent::__construct( array(
    2323                        'singular' => 'committer',
    2424                        'plural'   => 'committers',
    25                         'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
     25                        'screen'   => isset( $args['screen'] ) ? $args['screen'] : 'plugin',
    2626                ) );
    2727        }
    2828
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/list-table/class-support-reps.php

     
     1<?php
     2namespace WordPressdotorg\Plugin_Directory\Admin\List_Table;
     3use WordPressdotorg\Plugin_Directory\Tools;
     4
     5_get_list_table( 'WP_List_Table' );
     6
     7/**
     8 * Comments list table for comments meta box.
     9 *
     10 * @package WordPressdotorg\Plugin_Directory\Admin\List_Table
     11 */
     12class Support_Reps extends \WP_List_Table {
     13
     14        /**
     15         * Constructor.
     16         *
     17         * @see WP_List_Table::__construct() for more information on default arguments.
     18         *
     19         * @param array $args An associative array of arguments.
     20         */
     21        public function __construct( $args = array() ) {
     22                parent::__construct( array(
     23                        'singular' => 'support_rep',
     24                        'plural'   => 'support_reps',
     25                        'screen'   => isset( $args['screen'] ) ? $args['screen'] : 'plugin',
     26                ) );
     27        }
     28
     29        /**
     30         * Check the current user's permissions.
     31         *
     32         * @return bool
     33         */
     34        public function ajax_user_can() {
     35                return current_user_can( 'plugin_remove_support_rep' );
     36        }
     37
     38        /**
     39         * Prepare the users list for display.
     40         *
     41         * @access public
     42         *
     43         * @global string $role
     44         * @global string $usersearch
     45         */
     46        public function prepare_items() {
     47                $plugin_slug         = get_post()->post_name;
     48                if ( ! $plugin_slug ) {
     49                        return;
     50                }
     51                $existing_support_reps = Tools::get_plugin_support_reps( $plugin_slug );
     52                $this->items         = array_map( function ( $user ) {
     53                        return new \WP_User( $user );
     54                }, $existing_support_reps );
     55        }
     56
     57        /**
     58         * Output 'no users' message.
     59         *
     60         * @access public
     61         */
     62        public function no_items() {
     63                _e( 'No support reps found.', 'wporg-plugins' );
     64        }
     65
     66        /**
     67         *
     68         * @return array
     69         */
     70        protected function get_table_classes() {
     71                $classes   = parent::get_table_classes();
     72                $classes[] = 'wp-list-table';
     73
     74                unset( $classes[ array_search( 'striped', $classes ) ] );
     75
     76                return $classes;
     77        }
     78
     79        /**
     80         *
     81         * @return array
     82         */
     83        protected function get_column_info() {
     84                return array(
     85                        array(
     86                                'avatar'   => __( 'Avatar', 'wporg-plugins' ),
     87                                'username' => __( 'Username', 'wporg-plugins' ),
     88                        ),
     89                        array(),
     90                        'username',
     91                );
     92        }
     93
     94        /**
     95         *
     96         */
     97        public function display() {
     98                ?>
     99                <table class="<?php echo implode( ' ', $this->get_table_classes() ); ?>">
     100                        <colgroup>
     101                                <col width="40px" />
     102                                <col />
     103                        </colgroup>
     104                        <tbody id="the-support-rep-list" data-wp-lists="list:support-rep">
     105                                <?php $this->display_rows_or_placeholder(); ?>
     106                        </tbody>
     107                </table>
     108        <?php
     109        }
     110
     111        /**
     112         * Generate the list table rows.
     113         *
     114         * @access public
     115         */
     116        public function display_rows() {
     117                foreach ( $this->items as $user_object ) {
     118                        echo "\n\t" . $this->single_row( $user_object );
     119                }
     120                ?>
     121                <tr id="add-support-rep" class="add-support-rep wp-hidden-children">
     122                        <td colspan="2">
     123                                <button type="button" id="add-support-rep-toggle" class="button-link"><?php _e( '+ Add New Support Rep', 'wporg-plugins' ); ?></button>
     124                                <p class="wp-hidden-child">
     125                                        <?php wp_nonce_field( 'add-support-rep', '_ajax_nonce', false ); ?>
     126                                        <span id="support-rep-error" class="notice notice-alt notice-error" style="display:none;"></span>
     127                                        <label>
     128                                                <input type="text" name="add_support_rep" class="form-required" value="" aria-required="true" placeholder="<?php esc_attr_e( 'WordPress.org username', 'wporg-plugins' ); ?>">
     129                                                <span class="screen-reader-text"><?php _e( 'Add a new support rep', 'wporg-plugins' ); ?></span>
     130                                        </label>
     131                                        <input type="button" id="add-support-rep-submit" class="button" data-wp-lists="add:the-support-rep-list:add-support-rep::post_id=<?php echo get_post()->ID; ?>" value="<?php _e( 'Add Support Rep', 'wporg-plugins' ); ?>">
     132                                </p>
     133                        </td>
     134                </tr>
     135                <?php
     136        }
     137
     138        /**
     139         * Generate HTML for a single row on the users.php admin panel.
     140         *
     141         * @access public
     142         *
     143         * @param object $user_object The current user object.
     144         * @return string Output for a single row.
     145         */
     146        public function single_row( $user_object ) {
     147                if ( ! ( $user_object instanceof \WP_User ) ) {
     148                        $user_object = get_userdata( (int) $user_object );
     149                }
     150                $user_object->filter = 'display';
     151                list( $columns, $hidden, $primary ) = $this->get_column_info();
     152
     153                // Set up the hover actions for this support rep.
     154                $actions = array();
     155
     156                // Check if the support rep for this row is removable.
     157                $post_id = get_post()->ID;
     158                if ( current_user_can( 'plugin_remove_support_rep', $post_id ) && $user_object->ID != get_current_user_id() ) {
     159                        $actions['delete'] = "<a class='submitremove' data-wp-lists='delete:the-support-rep-list:support-rep-{$user_object->ID}:faafaa:post_id={$post_id}' href='" . wp_nonce_url( 'users.php?action=remove&amp;support-rep=' . $user_object->ID, "remove-support-rep-{$user_object->ID}" ) . "'>" . __( 'Remove', 'wporg-plugins' ) . "</a>";
     160                }
     161
     162                /**
     163                 * Filter the action links displayed under each support rep in the Support Reps list table.
     164                 *
     165                 * @param array    $actions     An array of action links to be displayed.
     166                 * @param \WP_User $user_object WP_User object for the currently-listed support rep.
     167                 */
     168                $actions = apply_filters( 'support_rep_row_actions', $actions, $user_object );
     169
     170                $row = "<tr id='support-rep-$user_object->ID'>";
     171
     172                foreach ( $columns as $column_name => $column_display_name ) {
     173                        $data    = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
     174                        $classes = "$column_name column-$column_name";
     175
     176                        if ( $primary === $column_name ) {
     177                                $classes .= ' has-row-actions column-primary';
     178                        }
     179                        if ( in_array( $column_name, $hidden ) ) {
     180                                $classes .= ' hidden';
     181                        }
     182
     183                        $row .= "<td class='$classes' $data>";
     184                        switch ( $column_name ) {
     185                                case 'avatar':
     186                                        $row .= get_avatar( $user_object->ID, 32 );
     187                                        break;
     188
     189                                case 'username':
     190                                        $row .= sprintf( '<strong><a href="%s">%s</a></strong><br />&lt;%s&gt;',
     191                                                esc_url( '//profiles.wordpress.org/' . $user_object->user_nicename ),
     192                                                $user_object->user_login,
     193                                                $user_object->user_email
     194                                        );
     195                                        break;
     196
     197                                default:
     198                                        /**
     199                                         * Filter the display output of custom columns in the Users list table.
     200                                         *
     201                                         * @param string $output      Custom column output. Default empty.
     202                                         * @param string $column_name Column name.
     203                                         * @param int    $user_id     ID of the currently-listed user.
     204                                         */
     205                                        $row .= apply_filters( 'manage_support_reps_custom_column', '', $column_name, $user_object->ID );
     206                        }
     207                        if ( $primary === $column_name ) {
     208                                $row .= $this->row_actions( $actions );
     209                        }
     210                        $row .= '</td>';
     211                }
     212                $row .= '</tr>';
     213
     214                return $row;
     215        }
     216
     217        /**
     218         * Gets the name of the default primary column.
     219         *
     220         * @access protected
     221         *
     222         * @return string Name of the default primary column, in this case, 'username'.
     223         */
     224        protected function get_default_primary_column_name() {
     225                return 'username';
     226        }
     227}
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/metabox/class-support-reps.php

     
     1<?php
     2namespace WordPressdotorg\Plugin_Directory\Admin\Metabox;
     3use WordPressdotorg\Plugin_Directory\Admin\List_Table;
     4use WordPressdotorg\Plugin_Directory\Tools;
     5
     6/**
     7 * The Plugin Support Reps admin metabox.
     8 *
     9 * @package WordPressdotorg\Plugin_Directory\Admin\Metabox
     10 */
     11class Support_Reps {
     12
     13        /**
     14         * Filters the postbox classes for custom comment meta boxes.
     15         *
     16         * @param array $classes An array of postbox classes.
     17         * @return array
     18         */
     19        public static function postbox_classes( $classes ) {
     20                $classes[] = 'support-reps-meta-box';
     21
     22                return array_filter( $classes );
     23        }
     24
     25        /**
     26         * Displays a list of support reps for the current plugin.
     27         */
     28        public static function display() {
     29                $list = new List_Table\Support_Reps();
     30                $list->prepare_items();
     31                $list->display();
     32        }
     33
     34        /**
     35         * Ajax handler for adding a new support rep.
     36         */
     37        public static function add_support_rep() {
     38                $login    = isset( $_POST['add_support_rep'] ) ? sanitize_user( $_POST['add_support_rep'] ) : '';
     39                $post_id  = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
     40
     41                check_ajax_referer( 'add-support-rep' );
     42
     43                if ( ! current_user_can( 'plugin_add_support_rep', $post_id ) || 'publish' !== get_post_status( $post_id ) ) {
     44                        wp_die( -1 );
     45                }
     46
     47                global $post;
     48
     49                $response = new \WP_Ajax_Response();
     50                $post     = get_post( $post_id );
     51
     52                if ( ! $support_rep = get_user_by( 'login', $login ) ) {
     53                        $response->add( array(
     54                                'what' => 'support_rep',
     55                                'data' => new \WP_Error( 'error', sprintf( __( 'The user %s does not exist.', 'wporg-plugins' ), '<code>' . $login . '</code>' ) ),
     56                        ) );
     57                        $response->send();
     58                }
     59
     60                $result = Tools::add_plugin_support_rep( $post->post_name, $support_rep );
     61               
     62                if ( ! $result ) {
     63                        $message = __( 'An error has occurred. Please reload the page and try again.', 'wporg-plugins' );
     64
     65                        $response->add( array(
     66                                'what' => 'support_rep',
     67                                'data' => new \WP_Error( 'error', $message ),
     68                        ) );
     69                        $response->send();
     70                }
     71
     72                $wp_list_table = new List_Table\Support_Reps();
     73
     74                $response->add( array(
     75                        'what'     => 'support_rep',
     76                        'id'       => $support_rep->ID,
     77                        'data'     => $wp_list_table->single_row( $support_rep ),
     78                        'position' => -1,
     79                ) );
     80                $response->send();
     81        }
     82
     83        /**
     84         * Ajax handler for removing a support rep.
     85         */
     86        public static function remove_support_rep() {
     87                $id      = isset( $_POST['id'] )      ? (int) $_POST['id']      : 0;
     88                $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
     89
     90                check_ajax_referer( "remove-support-rep-$id" );
     91
     92                if ( ! current_user_can( 'plugin_remove_support_rep', $post_id ) || 'publish' !== get_post_status( $post_id ) ) {
     93                        wp_die( -1 );
     94                }
     95
     96                $response    = new \WP_Ajax_Response();
     97                $plugin_slug = get_post( $post_id )->post_name;
     98
     99                if ( ! $support_rep = get_user_by( 'id', $id ) ) {
     100                        $response->add( array(
     101                                'what' => 'support_rep',
     102                                'data' => new \WP_Error( 'error', __( 'The specified user does not exist.', 'wporg-plugins' ) ),
     103                        ) );
     104                        $response->send();
     105                }
     106
     107                $result = Tools::remove_plugin_support_rep( $plugin_slug, $support_rep );
     108
     109                wp_die( $result );
     110        }
     111}
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php

     
    2020                new Routes\Query_Plugins();
    2121                new Routes\SVN_Access();
    2222                new Routes\Plugin_Committers();
     23                new Routes\Plugin_Support_Reps();
    2324        }
    2425
    2526        /**
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin-support-reps.php

     
     1<?php
     2namespace WordPressdotorg\Plugin_Directory\API\Routes;
     3use WordPressdotorg\Plugin_Directory\Plugin_Directory;
     4use WordPressdotorg\Plugin_Directory\Template;
     5use WordPressdotorg\Plugin_Directory\Tools;
     6use WordPressdotorg\Plugin_Directory\API\Base;
     7use WP_REST_Server;
     8use WP_Error;
     9use WP_User;
     10
     11
     12/**
     13 * An API Endpoint to manage plugin support reps.
     14 *
     15 * @package WordPressdotorg_Plugin_Directory
     16 */
     17class Plugin_Support_Reps extends Base {
     18
     19        function __construct() {
     20                register_rest_route( 'plugins/v1', '/plugin/(?P<plugin_slug>[^/]+)/support-reps/?', array(
     21                        array(
     22                                'methods'  => WP_REST_Server::READABLE,
     23                                'callback' => array( $this, 'list_support_reps' ),
     24                                'permission_callback' => function( $request ) {
     25                                        return current_user_can(
     26                                                'plugin_admin_edit',
     27                                                Plugin_Directory::get_plugin_post( $request['plugin_slug'] )
     28                                        );
     29                                },
     30                                'args' => array(
     31                                        'plugin_slug' => array(
     32                                                'validate_callback' => array( $this, 'validate_plugin_slug_callback' ),
     33                                                'required' => true,
     34                                        ),
     35                                )
     36                        ),
     37                        array(
     38                                'methods'  => WP_REST_Server::CREATABLE,
     39                                'callback' => array( $this, 'add_support_rep' ),
     40                                'permission_callback' => function( $request ) {
     41                                        return current_user_can(
     42                                                'plugin_add_support_rep',
     43                                                Plugin_Directory::get_plugin_post( $request['plugin_slug'] )
     44                                        );
     45                                },
     46                                'args' => array(
     47                                        'plugin_slug' => array(
     48                                                'validate_callback' => array( $this, 'validate_plugin_slug_callback' ),
     49                                                'required' => true,
     50                                        ),
     51                                )
     52                        )
     53                ) );
     54
     55                register_rest_route( 'plugins/v1', '/plugin/(?P<plugin_slug>[^/]+)/support-reps/(?P<support_rep>[^/]+)/?', array(
     56                        'methods'  => WP_REST_Server::DELETABLE,
     57                        'callback' => array( $this, 'remove_support_rep' ),
     58                        'permission_callback' => function( $request ) {
     59                                return current_user_can(
     60                                        'plugin_remove_support_rep',
     61                                        Plugin_Directory::get_plugin_post( $request['plugin_slug'] )
     62                                );
     63                        },
     64                        'args' => array(
     65                                'plugin_slug' => array(
     66                                        'validate_callback' => array( $this, 'validate_plugin_slug_callback' ),
     67                                        'required' => true,
     68                                ),
     69                                'support_rep' => array(
     70                                        'validate_callback' => array( $this, 'validate_user_slug_callback' ),
     71                                        'required' => true,
     72                                )
     73                        )
     74                ) );
     75        }
     76
     77        /**
     78         *
     79         */
     80        function list_support_reps( $request ) {
     81                $plugin_slug = $request['plugin_slug'];
     82
     83                $support_reps = array();
     84                foreach ( (array) Tools::get_plugin_support_reps( $plugin_slug ) as $user_nicename ) {
     85                        $user = get_user_by( 'slug', $user_nicename );
     86                        $support_reps[] = $this->user_support_rep_details( $user );
     87                }
     88
     89                return $support_reps;
     90        }
     91
     92        function add_support_rep( $request ) {
     93                $user = new WP_User( $request['support_rep'] );
     94                if ( ! $user->exists() ) {
     95                        return new WP_Error( 'plugin_user_not_found', __( 'The provided user could not be found.', 'wporg-plugins' ) );
     96                }
     97
     98                $plugin_slug = $request['plugin_slug'];
     99
     100                if ( ! Tools::add_plugin_support_rep( $plugin_slug, $user ) ) {
     101                        return new WP_Error( 'failed', __( 'The operation failed. Please try again.', 'wporg-plugins' ) );
     102                }
     103
     104                return $this->user_support_rep_details( $user );
     105        }
     106
     107        function remove_support_rep( $request ) {
     108                $user = new WP_User( $request['support_rep'] );
     109                if ( ! $user->exists() ) {
     110                        return new WP_Error( 'plugin_user_not_found', __( 'The provided user could not be found.', 'wporg-plugins' ) );
     111                }
     112
     113                $plugin_slug = $request['plugin_slug'];
     114
     115                $result = Tools::remove_plugin_support_rep( $plugin_slug, $user );
     116                if ( ! $result ) {
     117                        return new WP_Error( 'failed', __( 'The operation failed. Please try again.', 'wporg-plugins' ) );
     118                }
     119
     120                return true;
     121        }
     122
     123        /**
     124         * Validate that a user by the given slug exists.
     125         */
     126        function validate_user_slug_callback( $value ) {
     127                return (bool) get_user_by( 'slug', $value );
     128        }
     129
     130        /**
     131         * Helper function to return a support rep object
     132         */
     133        function user_support_rep_details( $user ) {
     134                $data = array(
     135                        'nicename' => $user->user_nicename,
     136                        'profile'  => esc_url( 'https://profiles.wordpress.org/' . $user->user_nicename ),
     137                        'avatar'   => get_avatar_url( $user->ID, 32 ),
     138                        'name'     => Template::encode( $user->display_name )
     139                );
     140
     141                if ( current_user_can( 'plugin_review' ) ) {
     142                        $data['email'] = $user->user_email;
     143                }
     144
     145                return $data;
     146        }
     147
     148}
     149
     150
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/class-capabilities.php

     
    2626                        case 'plugin_admin_edit':
    2727                        case 'plugin_add_committer':
    2828                        case 'plugin_remove_committer':
     29                        case 'plugin_add_support_rep':
     30                        case 'plugin_remove_support_rep':
    2931                                $plugin_edit_cap = true;
    3032                                // Fall through
    3133
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php

     
    260260                        ),
    261261                ) );
    262262
     263                register_taxonomy( 'plugin_support_reps', array( 'plugin', 'force-count-to-include-all-post_status' ), array(
     264                        'hierarchical'      => false,
     265                        'query_var'         => 'plugin_support_rep',
     266                        'rewrite'           => false,
     267                        'labels'            => array(
     268                                'name' => __( 'Support Reps', 'wporg-plugins' ),
     269                                'singular_name' => __( 'Support Rep', 'wporg-plugins' ),
     270                        ),
     271                        'public'            => true,
     272                        'show_ui'           => true,
     273                        'show_admin_column' => true,
     274                        'capabilities'      => array(
     275                                'assign_terms' => 'do_not_allow',
     276                        ),
     277                ) );
     278
    263279                register_taxonomy( 'plugin_tags', array( 'plugin', 'force-count-to-include-all-post_status' ), array(
    264280                        'hierarchical'      => false,
    265281                        'query_var'         => 'plugin_tags',
     
    547563                register_widget( __NAMESPACE__ . '\Widgets\Support'       );
    548564                register_widget( __NAMESPACE__ . '\Widgets\Committers'    );
    549565                register_widget( __NAMESPACE__ . '\Widgets\Contributors'  );
     566                register_widget( __NAMESPACE__ . '\Widgets\Support_Reps'  );
    550567        }
    551568
    552569        /**
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/class-tools.php

     
    227227        }
    228228
    229229        /**
     230         * Retrieve a list of support reps for a specific plugin.
     231         *
     232         * @static
     233         *
     234         * @param string $plugin_slug The plugin slug.
     235         * @return array The list of user_nicename's which are support reps.
     236         */
     237        public static function get_plugin_support_reps( $plugin_slug ) {
     238                if ( ! $plugin_slug ) {
     239                        return array();
     240                }
     241
     242                if ( false === ( $support_reps = wp_cache_get( $plugin_slug, 'plugin-support-reps' ) ) ) {
     243                        $post = Plugin_Directory::get_plugin_post( $plugin_slug );
     244                        $support_reps = wp_get_object_terms( $post->ID, 'plugin_support_reps', array( 'fields' => 'names' ) );
     245
     246                        wp_cache_set( $plugin_slug, $support_reps, 'plugin-support-reps', 12 * HOUR_IN_SECONDS );
     247                }
     248
     249                return $support_reps;
     250        }
     251
     252        /**
     253         * Add a user as a support rep for a plugin.
     254         *
     255         * @static
     256         *
     257         * @param string          $plugin_slug The plugin slug.
     258         * @param string|\WP_User $user        The user to add.
     259         * @return bool
     260         */
     261        public static function add_plugin_support_rep( $plugin_slug, $user ) {
     262                if ( ! $user instanceof \WP_User ) {
     263                        $user = new \WP_User( $user );
     264                }
     265
     266                if ( ! $user->exists() || ! $plugin_slug ) {
     267                        return false;
     268                }
     269
     270                $post = Plugin_Directory::get_plugin_post( $plugin_slug );
     271
     272                if ( ! $post ) {
     273                        return false;
     274                }
     275
     276                $result = wp_add_object_terms( $post->ID, $user->user_nicename, 'plugin_support_reps' );
     277
     278                return $result;
     279        }
     280
     281        /**
     282         * Remove a user as a support rep for a plugin.
     283         *
     284         * @static
     285         *
     286         * @param string          $plugin_slug The plugin slug.
     287         * @param string|\WP_User $user        The user to remove.
     288         * @return bool
     289         */
     290        public static function remove_plugin_support_rep( $plugin_slug, $user ) {
     291                if ( ! $user instanceof \WP_User ) {
     292                        $user = new \WP_User( $user );
     293                }
     294
     295                if ( ! $user->exists() || ! $plugin_slug ) {
     296                        return false;
     297                }
     298
     299                $post = Plugin_Directory::get_plugin_post( $plugin_slug );
     300
     301                if ( ! $post ) {
     302                        return false;
     303                }
     304
     305                $result = wp_remove_object_terms( $post->ID, $user->user_nicename, 'plugin_support_reps' );
     306
     307                return $result;
     308        }
     309
     310        /**
    230311         * Subscribe/Unsubscribe a user to a plugins commits.
    231312         *
    232313         * Plugin Committers are automatically subscribed to plugin commit
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/css/edit-form.css

     
    7474
    7575#poststuff .comments-meta-box.postbox .inside,
    7676#poststuff .committers-meta-box.postbox .inside,
     77#poststuff .support-reps-meta-box.postbox .inside,
    7778.comments-meta-box .column-comment p {
    7879        margin: 0;
    7980        padding: 0;
     
    102103}
    103104
    104105.comments-meta-box .comments-box,
    105 .committers-meta-box .wp-list-table {
     106.committers-meta-box .wp-list-table,
     107.support-reps-meta-box .wp-list-table {
    106108        border: 0 none;
    107109}
    108110
     
    137139        }
    138140}
    139141
    140 /* Committers meta box */
    141 .add-committer {
     142/* Committers and Support Reps meta boxes */
     143.add-committer,
     144.add-support-rep {
    142145        padding: 0 12px 12px;
    143146}
    144147
    145 .add-committer .button-link {
     148.add-committer .button-link,
     149.add-support-rep .button-link {
    146150        font-weight: 600;
    147151        margin: 10px 0;
    148152}
    149153
    150 .add-committer input[type="text"] {
     154.add-committer input[type="text"],
     155.add-support-rep input[type="text"] {
    151156        margin: 0 0 1em;
    152157        max-width: 260px;
    153158        vertical-align: baseline;
     
    154159        width: 100%;
    155160}
    156161
    157 .add-committer .notice {
     162.add-committer .notice,
     163.add-support-rep .notice {
    158164        display: block;
    159165        padding: 0.5em 0 0.5em 1em;
    160166}
     
    264270        background-color: #fde3e3;
    265271}
    266272
    267 .plugin-committers > div {
     273.plugin-committers > div,
     274.plugin-support-reps > div {
    268275        overflow-x: hidden;
    269276        white-space: nowrap;
    270277}
    271278
    272 .plugin-committer-email {
     279.plugin-committer-email,
     280.plugin-support-rep-email {
    273281        font-size: smaller;
    274282}
    275283
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/js/edit-form.js

     
    2929                                $( 'input[name="add_committer"]', '#add-committer' ).val( '' ).focus();
    3030                        } );
    3131
     32                        $( '#add-support-rep-toggle' ).on( 'click', PluginEdit.toggleSupportRepForm );
     33
     34                        $( '#the-support-rep-list' ).wpList({
     35                                alt: false,
     36                                confirm: function( element, settings, action ) {
     37                                        if ( 'support-rep' === settings.what && 'delete' === action ) {
     38                                                return confirm( pluginDirectory.removeSupportRepAYS );
     39                                        }
     40                                        return true;
     41                                },
     42                                addAfter: PluginEdit.supportRepRequestAfter,
     43                                delAfter: PluginEdit.supportRepRequestAfter
     44                        }).on( 'wpListAddEnd', function() {
     45                                $( 'input[name="add_support_rep"]', '#add-support-rep' ).val( '' ).focus();
     46                        } );
     47
    3248                        $( '#contact-author' ).appendTo( '#plugin-review .inside' );
    3349                },
    3450
     
    108124                        } else {
    109125                                $( '#committer-error' ).empty().hide();
    110126                        }
     127                },
     128
     129                toggleSupportRepForm: function( event ) {
     130                        var $form = $( '#add-support-rep' );
     131
     132                        // Show/hide form.
     133                        $form.toggleClass( 'wp-hidden-children' );
     134
     135                        // Focus on the input field, and on enter add the support rep, don't save post.
     136                        $( 'input[name="add_support_rep"]', $form ).focus().on( 'keydown', function( event ) {
     137                                if ( 13 === event.which ) {
     138                                        event.preventDefault();
     139                                        $( '#add-support-rep-submit', $form ).click();
     140                                }
     141                        } );
     142                },
     143
     144                supportRepRequestAfter: function( response, data ) {
     145                        if ( data.parsed.errors ) {
     146                                $( '#support-rep-error' ).html( data.parsed.responses[0].errors[0].message ).show();
     147                        } else {
     148                                $( '#support-rep-error' ).empty().hide();
     149                        }
    111150                }
    112151
    113152        };
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/widgets/class-support-reps.php

     
     1<?php
     2namespace WordPressdotorg\Plugin_Directory\Widgets;
     3use WordPressdotorg\Plugin_Directory\Template;
     4use WordPressdotorg\Plugin_Directory\Tools;
     5
     6/**
     7 * A Widget to display support rep information about a plugin.
     8 *
     9 * @package WordPressdotorg\Plugin_Directory\Widgets
     10 */
     11class Support_Reps extends \WP_Widget {
     12        /**
     13         * Support Reps constructor.
     14         */
     15        public function __construct() {
     16                parent::__construct( 'plugin_support_reps', __( 'Plugin Support Reps', 'wporg-plugins' ), array(
     17                        'classname'   => 'plugin-support-reps',
     18                        'description' => __( 'Displays support rep information.', 'wporg-plugins' ),
     19                ) );
     20        }
     21
     22        /**
     23         * Outputs the content of the widget.
     24         *
     25         * @param array $args
     26         * @param array $instance
     27         */
     28        public function widget( $args, $instance ) {
     29                $post = get_post();
     30
     31                $support_reps = Tools::get_plugin_support_reps( $post->post_name );
     32                $support_reps = array_map( function ( $user_login ) {
     33                        return get_user_by( 'slug', $user_login );
     34                }, $support_reps );
     35
     36                if ( current_user_can( 'plugin_add_support_rep', $post ) || current_user_can( 'plugin_remove_support_rep', $post ) ) {
     37                        wp_enqueue_script( 'wporg-plugins-support-reps', plugins_url( 'js/support-reps.js', __FILE__ ), array( 'wp-util' ), true );
     38                        wp_localize_script( 'wporg-plugins-support-reps', 'supportRepsWidget', array(
     39                                'restUrl'             => get_rest_url(),
     40                                'restNonce'           => wp_create_nonce( 'wp_rest' ),
     41                                'pluginSlug'          => $post->post_name,
     42                                'removeSupportRepAYS' => __( 'Are you sure you want to remove this support rep?', 'wporg-plugins' ),
     43                        ) );
     44                }
     45
     46                $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Support Reps', 'wporg-plugins' ) : $instance['title'], $instance, $this->id_base );
     47
     48                echo $args['before_widget'];
     49                echo $args['before_title'] . $title . $args['after_title'];
     50                ?>
     51
     52                <ul id="support-rep-list" class="support-rep-list">
     53
     54                        <?php foreach ( $support_reps as $support_rep ) : ?>
     55                                <li data-user="<?php echo esc_attr( $support_rep->user_nicename ); ?>">
     56                                        <?php echo get_avatar( $support_rep->ID, 32 ); ?>
     57                                        <a href="<?php echo esc_url( 'https://profiles.wordpress.org/' . $support_rep->user_nicename ); ?>">
     58                                                <?php echo Template::encode( $support_rep->display_name ); ?>
     59                                        </a><br>
     60
     61                                        <?php if ( current_user_can( 'plugin_remove_support_rep', $post ) ) : ?>
     62                                        <small>
     63                                                <?php echo current_user_can( 'plugin_review' ) ? esc_html( $support_rep->user_email ) . ' ' : ''; ?>
     64                                                <button class="button-link remove"><?php _e( 'Remove', 'wporg-plugins' ); ?></button>
     65                                        </small>
     66                                        <?php endif; ?>
     67                                </li>
     68                        <?php endforeach; ?>
     69
     70                        <?php if ( current_user_can( 'plugin_add_support_rep', $post ) ) : ?>
     71                        <li class="new">
     72                                <form id="add-support-rep" action="POST">
     73                                        <input type="text" name="support_rep" placeholder="<?php esc_attr_e( 'Login, Slug, or Email.', 'wporg-plugins' ); ?>">
     74                                        <button type="submit" class="button button-secondary"><?php esc_attr_e( 'Add', 'wporg-plugins' ); ?></button>
     75                                </form>
     76
     77                                <script id="tmpl-new-support-rep" type="text/template">
     78                                        <li data-user="{{ data.nicename }}">
     79                                                <a class="profile" href="{{ data.profile }}">
     80                                                        <img src="{{ data.avatar }}" class="avatar avatar-32 photo" height="32" width="32">
     81                                                        {{ data.name }}
     82                                                </a><br>
     83                                                <small>
     84                                                        <# if ( data.email ) { #>
     85                                                                <span class="email">{{ data.email }}</span>
     86                                                        <# } #>
     87                                                        <button class="button-link remove"><?php _e( 'Remove', 'wporg-plugins' ); ?></button>
     88                                                </small>
     89                                        </li>
     90                                </script>
     91                        </li>
     92                        <?php endif; ?>
     93                </ul>
     94
     95                <?php
     96                echo $args['after_widget'];
     97        }
     98}
  • wordpress.org/public_html/wp-content/plugins/plugin-directory/widgets/js/support-reps.js

     
     1(
     2        /**
     3         * @param {Object} $
     4         * @param {Object} wp
     5         * @param {Object} pluginDir
     6         * @param {String} pluginDir.restUrl
     7         * @param {String} pluginDir.restNonce
     8         * @param {String} pluginDir.pluginSlug
     9         */
     10        function( $, wp, pluginDir ) {
     11                var logError = function( result ) {
     12                        $( '.spinner' ).removeClass( 'spinner' );
     13                        result = $.parseJSON( result.responseText );
     14                        if ( typeof result.message !== 'undefined' ) {
     15                                alert( result.message );
     16                        }
     17                };
     18
     19                $( '#support-rep-list' )
     20                        .on( 'click', '.remove', function() {
     21                                if ( ! window.confirm( pluginDir.removeSupportRepAYS ) ) {
     22                                        return;
     23                                }
     24
     25                                var $row = $( this ).addClass( 'spinner' ).parents( 'li' ),
     26                                        url = pluginDir.restUrl + 'plugins/v1/plugin/' + pluginDir.pluginSlug + '/support-reps/' + $row.data( 'user' ) + '/?_wpnonce=' + pluginDir.restNonce;
     27
     28                                $.post( {
     29                                        url: url,
     30                                        method: 'DELETE',
     31                                } ).success( function( result ) {
     32                                        if ( true === result ) {
     33                                                $row.slideUp( 500, function() {
     34                                                        $row.remove()
     35                                                } );
     36                                        }
     37                                } ).fail( logError );
     38                        } )
     39                        .on( 'submit', '#add-support-rep', function( event ) {
     40                                event.preventDefault();
     41
     42                                var $row = $( this ).parents( 'li' ),
     43                                        $newUserInput = $row.find( 'input[name="support_rep"]' ),
     44                                        $button = $row.find( '.button-small' ).addClass( 'spinner' ),
     45                                        url = pluginDir.restUrl + 'plugins/v1/plugin/' + pluginDir.pluginSlug + '/support-reps/?_wpnonce=' + pluginDir.restNonce;
     46
     47                                $.post( {
     48                                        url: url,
     49                                        dataType: 'json',
     50                                        data: {
     51                                                support_rep: $newUserInput.val()
     52                                        }
     53                                } ).done( function( result ) {
     54                                        if ( typeof result.name !== 'undefined' ) {
     55                                                $row.before( wp.template( 'new-support-rep' )( result ) );
     56                                                $newUserInput.val( '' );
     57                                                $button.removeClass( 'spinner' );
     58                                        }
     59                                } ).fail( logError );
     60                        } );
     61        } )( window.jQuery, window.wp, window.supportRepsWidget );
  • wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/client/components/widget-area/widgets/committers/style.scss

     
    1 .committer-list {
     1.committer-list,
     2.support-rep-list {
    23        font-size: ms( -2 );
    34        list-style: none;
    45        margin: 0;
  • wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-parts/plugin-sidebar-advanced.php

     
    2121// If the user is not a contributor/committer for the plugin, we'll show the Donate metabox instead of the committer metabox.
    2222if ( current_user_can( 'plugin_admin_view', $post ) ) {
    2323        the_widget( 'WordPressdotorg\Plugin_Directory\Widgets\Committers', array(), $widget_args );
     24        the_widget( 'WordPressdotorg\Plugin_Directory\Widgets\Support_Reps', array(), $widget_args );
    2425} else {
    2526        the_widget( 'WordPressdotorg\Plugin_Directory\Widgets\Donate', array(), $widget_args );
    2627}