Making WordPress.org


Ignore:
Timestamp:
12/13/2016 08:45:19 PM (10 years ago)
Author:
coreymckrill
Message:

Mentor Dashboard: Use dotorg usernames to id mentors instead of email

  • Adds the Mentor WordPress.org User Name field to wcpt.
  • Introduces "protected" fields in wcpt, which will be marked as readonly unless current user has specific caps. Used to make all mentor fields in the wcpt edit screen readonly unless current user can manage the network.
  • Adds a dropdown pick list of current mentors next to Mentor WordPress.org User Name that will fill in username, name, and email when a mentor is chosen. This only appears if current user has the right caps.
  • Adds a field in the Mentor Dashboard for managing the list of current mentors based on their dotorg usernames.
  • Uses dotorg username to determine which camps a mentor currently has, with their dotorg account email address as a backup.
  • All camps that don't have a value for Mentor WordPress.org User Name or whose value doesn't match a current mentor will appear in the "Active Camps that don't have a mentor" list.
  • Enqueues existing admin.js script for wcpt instead of printing it in the footer.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wcpt/mentors/dashboard.php

    r3727 r4525  
    33namespace WordCamp\Mentors_Dashboard;
    44defined( 'WPINC' ) or die();
     5
     6const USERNAMES_KEY     = 'wcpt-mentors-usernames';
     7const MENTORS_CACHE_KEY = 'wcpt-mentors-data';
     8
     9const STATUS_UPDATED       = 'Mentor usernames updated.';
     10const STATUS_INVALID_NONCE = 'Invalid nonce. Mentor usernames were not updated.';
     11const STATUS_NO_USERNAME   = 'No username data was submitted.';
     12const STATUS_UPDATE_FAILED = 'Mentor usernames could not be updated.';
     13
     14
     15add_action( 'admin_init', __NAMESPACE__ . '\admin_init' );
     16
     17/**
     18 * Initialize admin functionality
     19 */
     20function admin_init() {
     21        if ( isset( $_GET['wcpt-status'] ) ) {
     22                add_action( 'admin_notices', __NAMESPACE__ . '\status_admin_notice' );
     23        }
     24}
    525
    626add_action( 'admin_menu', __NAMESPACE__ . '\add_admin_pages' );
     
    2646        $mentors          = get_mentors();
    2747        $unmentored_camps = get_unmentored_camps();
     48        $usernames        = get_usernames();
    2849
    2950        require_once( dirname( __DIR__ ) . '/views/mentors/dashboard.php' );
     
    3657 */
    3758function get_mentors() {
    38         $mentors = array();
    39 
    40         $mentored_camps = get_posts( array(
    41                 'post_type'      => WCPT_POST_TYPE_ID,
    42                 'post_status'    => \WordCamp_Loader::get_mentored_post_statuses(),
    43                 'posts_per_page' => 10000,
    44                 'meta_query'     => array(
    45                         array(
    46                                 'key'     => 'Mentor E-mail Address',
    47                                 'value'   => '',
    48                                 'compare' => '!='
    49                         ),
    50                 ),
    51         ) );
    52 
    53         foreach ( $mentored_camps as $camp ) {
    54                 $email = get_post_meta( $camp->ID, 'Mentor E-mail Address', true );
    55 
    56                 /*
    57                  * Closed camps were included in the query above, in order to get all mentors, even if they're not
    58                  * currently mentoring any active camps. Closed camps shouldn't be included in the list of camps being
    59                  * actively mentored, though.
    60                  */
    61                 $count_camp = 'wcpt-closed' !== $camp->post_status;
    62 
    63                 if ( array_key_exists( $email, $mentors ) ) {
    64                         if ( $count_camp ) {
    65                                 $mentors[ $email ]['camps_mentoring'][] = $camp->post_title;
    66                         }
    67                 } else {
    68                         $mentor_name = get_post_meta( $camp->ID, 'Mentor Name', true );
    69 
    70                         $mentors[ $email ] = array(
    71                                 'name'            => $mentor_name,
    72                                 'camps_mentoring' => $count_camp ? array( $camp->post_title ) : array(),
    73                         );
    74                 }
    75         }
    76 
    77         return $mentors;
    78 }
    79 
    80 /**
    81  * Count the total number of camps being mentored
    82  *
    83  * @param array $mentors
    84  *
    85  * @return int
    86  */
    87 function count_camps_being_mentored( $mentors ) {
    88         $camps_being_mentored = 0;
    89 
    90         foreach ( $mentors as $mentor ) {
    91                 $camps_being_mentored += count( $mentor['camps_mentoring'] );
    92         }
    93 
    94         return $camps_being_mentored;
    95 }
    96 
    97 /**
    98  * Get active camps that haven't been assigned a mentor
    99  *
    100  * @return array
    101  */
    102 function get_unmentored_camps() {
    103         $unmentored_camps = array();
     59        $mentors = get_all_mentor_data();
     60
     61        if ( empty( $mentors ) ) {
     62                return array();
     63        }
     64
     65        $mentor_email = wp_list_pluck( $mentors, 'email' );
    10466
    10567        $post_statuses = array_diff(
     
    10870        );
    10971
     72        $mentored_camps = get_posts( array(
     73                'post_type'      => WCPT_POST_TYPE_ID,
     74                'post_status'    => $post_statuses,
     75                'posts_per_page' => 10000,
     76                'order'          => 'ASC',
     77                'orderby'        => 'name',
     78                'meta_query'     => array(
     79                        'relation' => 'OR',
     80                        array(
     81                                'key'     => 'Mentor WordPress.org User Name',
     82                                'value'   => get_usernames(),
     83                                'compare' => 'IN',
     84                        ),
     85                        array(
     86                                'key'     => 'Mentor E-mail Address',
     87                                'value'   => $mentor_email,
     88                                'compare' => 'IN',
     89                        ),
     90                ),
     91        ) );
     92
     93        $mentors = array_map( function( $value ) {
     94                $value['camps_mentoring'] = array();
     95                return $value;
     96        }, $mentors );
     97
     98        foreach ( $mentored_camps as $camp ) {
     99                $username = get_post_meta( $camp->ID, 'Mentor WordPress.org User Name', true );
     100                $email    = get_post_meta( $camp->ID, 'Mentor E-mail Address', true );
     101
     102                // Camp has username
     103                if ( false !== $username && isset( $mentors[ $username ] ) ) {
     104                        $mentors[ $username ]['camps_mentoring'][ $camp->ID ] = $camp->post_title;
     105                }
     106                // Camp doesn't have username, but has email
     107                else if ( false !== $email && false !== $key = array_search( $email, $mentor_email ) ) {
     108                        // Add asterisk to show camp has mentor email but not username
     109                        $mentors[ $key ]['camps_mentoring'][ $camp->ID ] = $camp->post_title . ' *';
     110                }
     111        }
     112
     113        return $mentors;
     114}
     115
     116/**
     117 * Count the total number of camps being mentored
     118 *
     119 * @param array $mentors
     120 *
     121 * @return int
     122 */
     123function count_camps_being_mentored( $mentors ) {
     124        $camps_being_mentored = 0;
     125
     126        foreach ( $mentors as $mentor ) {
     127                $camps_being_mentored += count( $mentor['camps_mentoring'] );
     128        }
     129
     130        return $camps_being_mentored;
     131}
     132
     133/**
     134 * Get active camps that haven't been assigned a mentor
     135 *
     136 * @return array
     137 */
     138function get_unmentored_camps() {
     139        $unmentored_camps = array();
     140
     141        $post_statuses = array_diff(
     142                \WordCamp_Loader::get_mentored_post_statuses(),
     143                array( 'wcpt-closed' )
     144        );
     145
    110146        $posts = get_posts( array(
    111147                'post_type'      => WCPT_POST_TYPE_ID,
    112148                'post_status'    => $post_statuses,
    113149                'posts_per_page' => 10000,
     150                'order'          => 'ASC',
     151                'orderby'        => 'name',
    114152                'meta_query'     => array(
     153                        'relation' => 'OR',
    115154                        array(
    116                                 'key'     => 'Mentor E-mail Address',
    117                                 'value'   => '',
    118                                 'compare' => '='
     155                                'key'     => 'Mentor WordPress.org User Name',
     156                                'value'   => get_usernames(),
     157                                'compare' => 'NOT IN'
     158                        ),
     159                        array(
     160                                'key'     => 'Mentor WordPress.org User Name',
     161                                'compare' => 'NOT EXISTS'
    119162                        ),
    120163                ),
     
    122165
    123166        foreach ( $posts as $post ) {
    124                 $unmentored_camps[ $post->ID ] = $post->post_title;
     167                $email = get_post_meta( $post->ID, 'Mentor E-mail Address', true );
     168                $camp_name = $post->post_title;
     169
     170                if ( $email ) {
     171                        $camp_name .= ' *';
     172                }
     173
     174                $unmentored_camps[ $post->ID ] = $camp_name;
    125175        }
    126176
    127177        return $unmentored_camps;
    128178}
     179
     180/**
     181 * Get the stored array of mentor usernames and sanitize before returning.
     182 *
     183 * @return array
     184 */
     185function get_usernames() {
     186        $raw_usernames = get_site_option( USERNAMES_KEY, array() );
     187
     188        return sanitize_usernames( $raw_usernames );
     189}
     190
     191/**
     192 * Sanitize a list of usernames and store in the database.
     193 *
     194 * @param string|array $usernames
     195 *
     196 * @return bool
     197 */
     198function set_usernames( $usernames ) {
     199        $sanitized_usernames = sanitize_usernames( $usernames );
     200
     201        return update_site_option( USERNAMES_KEY, $sanitized_usernames );
     202}
     203
     204/**
     205 * Sanitize an array of usernames. Convert to an array first if a string is provided.
     206 *
     207 * @param string|array $usernames
     208 *
     209 * @return array
     210 */
     211function sanitize_usernames( $usernames ) {
     212        if ( ! is_array( $usernames ) ) {
     213                $usernames = explode( ',', $usernames );
     214        }
     215
     216        $usernames = array_map( 'trim', $usernames );
     217
     218        $usernames = array_map( 'sanitize_user', $usernames );
     219
     220        // Remove empty array items
     221        return array_filter( $usernames );
     222}
     223
     224/**
     225 * @todo
     226 *
     227 * @param array $sanitized_usernames
     228 */
     229function validate_usernames( array $sanitized_usernames ) {
     230        // todo
     231}
     232
     233add_action( 'admin_post_wcpt-mentors-update-usernames', __NAMESPACE__ . '\update_usernames' );
     234
     235/**
     236 * Admin Post callback to receive a list of usernames from a form and store it in the database.
     237 */
     238function update_usernames() {
     239        // Base redirect URL
     240        $redirect_url = add_query_arg( array(
     241                'post_type' => 'wordcamp',
     242                'page'      => 'mentors',
     243        ), admin_url( 'edit.php' ) );
     244
     245        // Invalid nonce
     246        if ( ! isset( $_POST['wcpt-mentors-nonce'] ) ||
     247                 ! wp_verify_nonce( $_POST['wcpt-mentors-nonce'], 'wcpt-mentors-update-usernames' ) ) {
     248                $status_code = 'invalid-nonce';
     249        }
     250        // No usernames field
     251        else if ( ! isset( $_POST['wcpt-mentors-usernames'] ) ) {
     252                $status_code = 'no-username';
     253        }
     254        //
     255        else {
     256                $raw_usernames = $_POST['wcpt-mentors-usernames'];
     257
     258                $success = set_usernames( $raw_usernames );
     259
     260                if ( $success ) {
     261                        $status_code = 'updated';
     262
     263                        // Bust cache
     264                        delete_site_transient( MENTORS_CACHE_KEY );
     265                } else {
     266                        $status_code = 'update-failed';
     267                }
     268        }
     269
     270        $redirect_url = add_query_arg( 'wcpt-status', $status_code, $redirect_url );
     271
     272        wp_safe_redirect( esc_url_raw( $redirect_url ) );
     273}
     274
     275/**
     276 * Display the result of `update_usernames`
     277 */
     278function status_admin_notice() {
     279        if ( ! isset( $_GET['wcpt-status'] ) ) {
     280                return;
     281        }
     282
     283        $status = 'STATUS_' . strtoupper( str_replace( '-', '_', $_GET['wcpt-status'] ) );
     284
     285        if ( ! defined( __NAMESPACE__ . '\\' . $status ) ) {
     286                return;
     287        }
     288
     289        $type = 'success';
     290        if ( 'STATUS_UPDATED' !== $status ) {
     291                $type = 'error';
     292        }
     293
     294        $message = constant( __NAMESPACE__ . '\\' . $status );
     295
     296        ?>
     297        <div class="notice notice-<?php echo esc_attr( $type ); ?> is-dismissible">
     298                <?php echo wpautop( esc_html( $message ) ); ?>
     299        </div>
     300<?php
     301}
     302
     303/**
     304 * Retrieve name and email for a particular mentor username.
     305 *
     306 * @param string $username
     307 *
     308 * @return array
     309 */
     310function get_mentor_data( $username ) {
     311        $usernames = get_usernames();
     312        $data = array();
     313
     314        // Data for specific mentor
     315        if ( in_array( $username, $usernames ) ) {
     316                $user = \get_user_by( 'login', $username );
     317
     318                if ( $user instanceof \WP_User ) {
     319                        $data[ $username ] = array(
     320                                'name'  => $user->display_name,
     321                                'email' => $user->user_email,
     322                        );
     323                }
     324        }
     325
     326        return $data;
     327}
     328
     329/**
     330 * Retrieve data for all the mentor usernames in the list.
     331 *
     332 * @return array
     333 */
     334function get_all_mentor_data() {
     335        if ( false !== $data = \get_site_transient( MENTORS_CACHE_KEY ) ) {
     336                return $data;
     337        }
     338
     339        $usernames = get_usernames();
     340        $data = array();
     341
     342        foreach ( $usernames as $username ) {
     343                $data = array_merge( $data, get_mentor_data( $username ) );
     344        }
     345
     346        ksort( $data );
     347
     348        \set_site_transient( MENTORS_CACHE_KEY, $data, WEEK_IN_SECONDS );
     349
     350        return $data;
     351}
Note: See TracChangeset for help on using the changeset viewer.