Making WordPress.org


Ignore:
Timestamp:
12/04/2023 08:50:09 AM (3 years ago)
Author:
dd32
Message:

Plugin Directory: Stats: Generate a basic summary of per-reviewer stats.

See #6994.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/admin/tools/class-stats-report.php

    r12993 r13000  
    232232        }
    233233
     234        public function get_user_stats( $args = array() ) {
     235                global $wpdb;
     236
     237                $stats['as_of_date'] = gmdate( 'Y-m-d' );
     238
     239                $defaults = array(
     240                        'date'       => $stats['as_of_date'],
     241                        'num_days'   => 7,
     242                        'recentdays' => 7,
     243                );
     244
     245                foreach ( $defaults as $key => $val ) {
     246                        $args[ $key ] = empty( $args[ $key ] ) ? $val : $args[ $key ];
     247                }
     248
     249                $stats = $args;
     250                $stats['data'] = [];
     251
     252                $reviewers = get_users( [
     253                        'role__in' => [
     254                                'plugin_reviewer',
     255                                'plugin_admin',
     256                                'administrator',
     257                        ],
     258                ] );
     259
     260                $reviewer_ids            = wp_list_pluck( $reviewers, 'ID' );
     261                $reviewer_ids_list       = implode( ', ', $reviewer_ids );
     262                $reviewer_nicenames      = wp_list_pluck( $reviewers, 'user_nicename' );
     263                $reviewer_nicenames_list = $wpdb->prepare( trim( str_repeat( '%s,', count( $reviewer_nicenames ) ) , ',' ), $reviewer_nicenames );
     264
     265                $events = $wpdb->get_results( $wpdb->prepare(
     266                        "SELECT user_id,
     267                        CASE
     268                                WHEN `comment_content` LIKE concat( 'Assigned to%', comment_author, '%' ) THEN 'Assigned to self.'
     269                                WHEN `comment_content` LIKE 'Assigned to%' THEN 'Assigned to other.'
     270                                ELSE `comment_content`
     271                        END AS `_thing`,
     272                        count(*) AS `count`
     273                        FROM %i
     274                        WHERE
     275                                `comment_date_gmt` > DATE_SUB( %s, INTERVAL %d DAY )
     276                                AND `user_id` IN( {$reviewer_ids_list} )
     277                                AND `comment_agent` = ''
     278                                AND (
     279                                        `comment_content` IN( 'Plugin Approved.', 'Plugin Rejected.' )
     280                                        OR `comment_content` LIKE 'Assigned TO%'
     281                                        OR (
     282                                                `comment_content` LIKE 'Plugin closed.%'
     283                                                AND NOT `comment_content` LIKE '%Author Self-close%'
     284                                        )
     285                                )
     286                        GROUP BY `user_id`, `_thing`
     287                        ORDER BY `user_id`, `_thing`",
     288                        $wpdb->comments,
     289                        $args['date'],
     290                        $args['num_days'],
     291                ) );
     292
     293                foreach ( $events as $row ) {
     294                        $stats['data'][ $row->user_id ] ??= [];
     295                        $stats['data'][ $row->user_id ][ $row->_thing ] = $row->count;
     296                }
     297
     298                // Fetch HelpScout stats from our stats. We might be able to pull some information from HS Stats instead.
     299                $emails = $wpdb->get_results( $wpdb->prepare(
     300                        "SELECT `name`, `value`, SUM(views) AS count
     301                        FROM %i
     302                        WHERE `name` IN( 'hs-total', 'hs-replies' )
     303                                AND `value` IN( {$reviewer_nicenames_list} )
     304                                AND `date` > DATE_SUB( %s, INTERVAL %d DAY )
     305                        GROUP BY `name`, `value`",
     306                        'stats_extras',
     307                        $args['date'],
     308                        $args['num_days']
     309                ) );
     310
     311                foreach ( $emails as $row ) {
     312                        $user  = get_user_by( 'slug', $row->value );
     313                        $field = 'hs-total' === $row->name ? 'Email Actions' : 'Email Replies';
     314                        $stats['data'][ $user->ID ] ??= [];
     315                        $stats['data'][ $user->ID ][ $field ] = $row->count;
     316                }
     317
     318                uasort( $stats['data'], function( $a, $b ) {
     319                        return array_sum( $b ) <=> array_sum( $a );
     320                } );
     321
     322                return $stats;
     323        }
     324
    234325        /**
    235326         * Outputs the stats report admin page, including form to customize time range
     
    252343                $args['recentdays'] = empty( $_REQUEST['recentdays'] ) ? 7 : absint( $_REQUEST['recentdays'] );
    253344
    254                 $stats = $this->get_stats( $args );
     345                $stats      = $this->get_stats( $args );
     346                $user_stats = $this->get_user_stats( $args );
    255347
    256348                $date = gmdate( 'Y-m-d' );
     
    529621                </ul>
    530622
     623                <h3>Reviewer Stats</h3>
     624                <p><em>NOTE: These are not intended on being made public. Data displayed for the <?php echo esc_html( $user_stats['num_days'] ); ?> ending <?php echo esc_html( $user_stats['date'] ); ?></em></p>
     625
     626                <?php
     627                        $data_points = [
     628                                'Assigned to self.',
     629                                'Assigned to other.',
     630                                'Plugin approved.',
     631                                'Plugin rejected.',
     632                                'Plugin closed',
     633                                'Emails^',
     634                        ];
     635                        $close_types = [];
     636
     637                        // Determine the close reasons in this timeframe.
     638                        foreach ( $user_stats['data'] as $user => $user_stat ) {
     639                                foreach ( preg_grep( '/^Plugin closed\./', array_keys( $user_stat ) ) as $reason ) {
     640                                        $close_types[ trim( explode( ':', $reason )[1] ) ] = true;
     641                                }
     642                        }
     643                        $close_types = array_keys( $close_types );
     644
     645                        ?>
     646                        <table class="widefat">
     647                        <thead>
     648                                <tr>
     649                                        <th rowspan="2">Reviewer</th>
     650                                        <th rowspan="2" style="text-align:center">Assigned<br/>(to others)</th>
     651                                        <th colspan="2" style="text-align:center">Plugins</th>
     652                                        <th colspan="<?php echo esc_attr( count( $close_types ) ); ?>" style="text-align:center">Plugins closed</th>
     653                                        <th colspan="2" style="text-align:center">Emails^</th>
     654                                </tr>
     655                                <tr>
     656                                        <th>Approved</th>
     657                                        <th>Rejected</th>
     658                                        <?php foreach ( $close_types as $type ) : ?>
     659                                                <th><?php echo esc_html( Template::get_close_reasons()[ $type ] ); ?></th>
     660                                        <?php endforeach; ?>
     661                                        <th>Actions</th>
     662                                        <th>Replies</th>
     663                                </tr>
     664
     665                        </thead>
     666                        <?php
     667
     668                        echo '<tbody>';
     669                        foreach ( $user_stats['data'] as $user_id => $user_stat ) {
     670                                $user = get_user_by( 'id', $user_id );
     671                                echo '<tr><th>', esc_html( $user->display_name ?: $user->user_login ), '</th>';
     672
     673                                // Assigned.
     674                                echo '<td>', number_format_i18n( $user_stat[ 'Assigned to self.' ] ?? 0 );
     675                                if ( $user_stat[ 'Assigned to others.' ] ?? 0 ) {
     676                                        echo ' (', number_format_i18n( $user_stat[ 'Assigned to others.' ] ), ')';
     677                                }
     678                                echo '</td>';
     679
     680                                // Plugins Approved, Rejected.
     681                                echo '<td>', number_format_i18n( $user_stat[ 'Plugin approved.' ] ?? 0 ), '</td>';
     682                                echo '<td>', number_format_i18n( $user_stat[ 'Plugin rejected.' ] ?? 0 ), '</td>';
     683
     684                                // Plugins Closed.
     685                                foreach ( $close_types as $close_type ) {
     686                                        echo '<td>', number_format_i18n( $user_stat[ "Plugin closed. Reason: {$close_type}" ] ?? 0 ), '</td>';
     687                                }
     688
     689                                // Emails.
     690                                echo '<td>', number_format_i18n( $user_stat[ "Email Actions" ] ?? 0 ), '</td>';
     691                                echo '<td>', number_format_i18n( $user_stat[ "Email Replies" ] ?? 0 ), '</td>';
     692                                echo '</tr>';
     693                        }
     694                        echo '</tbody>';
     695                        echo '</table>';
     696
     697                        ?>
     698                        <ul style="font-style:italic;">
     699                                <li><code>^</code> : This is currently of all Helpscout mailboxes, not Plugins specific. Requires your Helpscout email to be the same as your WordPress.org email, or as one of your profiles alternate emails.</li>
     700                                <li>Email "Actions" include sending emails, replying to emails, marking as spam, moving to different inbox, etc.</li>
     701                        </ul>
     702
    531703                </div>
    532704                <?php
Note: See TracChangeset for help on using the changeset viewer.