Making WordPress.org

Changeset 13000


Ignore:
Timestamp:
12/04/2023 08:50:09 AM (10 months 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.