Skip to content

Commit

Permalink
feat: user discrepancies display (#100)
Browse files Browse the repository at this point in the history
Co-authored-by: Derrick Koo <[email protected]>
  • Loading branch information
adekbadek and dkoo authored Jul 2, 2024
1 parent eace5d2 commit a054967
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 46 deletions.
67 changes: 39 additions & 28 deletions includes/class-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Users {
*/
public static function init() {
add_filter( 'manage_users_columns', [ __CLASS__, 'manage_users_columns' ] );
add_filter( 'manage_users_custom_column', [ __CLASS__, 'manage_users_custom_column' ], 10, 3 );
add_filter( 'manage_users_custom_column', [ __CLASS__, 'manage_users_custom_column' ], 99, 3 ); // priority must be higher than Jetpack's jetpack_show_connection_status (10).
add_filter( 'users_list_table_query_args', [ __CLASS__, 'users_list_table_query_args' ] );
}

Expand All @@ -30,9 +30,7 @@ public static function init() {
* @return array
*/
public static function manage_users_columns( $columns ) {
if ( Site_Role::is_hub() ) {
$columns['newspack_network_activity'] = __( 'Newspack Network Activity', 'newspack-network' );
}
$columns['newspack_network_activity'] = __( 'Newspack Network Activity', 'newspack-network' );
if ( \Newspack_Network\Admin::use_experimental_auditing_features() ) {
$columns['newspack_network_user'] = __( 'Network Original User', 'newspack-network' );
}
Expand Down Expand Up @@ -60,36 +58,45 @@ public static function manage_users_custom_column( $value, $column_name, $user_i
);
}
}
if ( 'newspack_network_activity' === $column_name && Site_Role::is_hub() ) {
if ( 'newspack_network_activity' === $column_name ) {
$user = get_user_by( 'id', $user_id );
if ( ! $user ) {
return $value;
}
if ( Site_Role::is_hub() ) {
$last_activity = \Newspack_Network\Hub\Stores\Event_Log::get( [ 'email' => $user->user_email ], 1 );
if ( empty( $last_activity ) ) {
return '-';
}

$last_activity = \Newspack_Network\Hub\Stores\Event_Log::get( [ 'email' => $user->user_email ], 1 );

if ( empty( $last_activity ) ) {
return '-';
$event_log_url = add_query_arg(
[
'page' => EVENT_LOG_PAGE_SLUG,
'email' => urlencode( $user->user_email ),
],
admin_url( 'admin.php' )
);
return sprintf(
'%s: <code>%s</code><br><a href="%s">%s</a>',
__( 'Last Activity', 'newspack-network' ),
$last_activity[0]->get_summary(),
$event_log_url,
__( 'View all', 'newspack-network' )
);
} else {
$event_log_url = add_query_arg(
[
'page' => EVENT_LOG_PAGE_SLUG,
'email' => urlencode( $user->user_email ),
],
untrailingslashit( Node\Settings::get_hub_url() ) . '/wp-admin/admin.php'
);
return sprintf(
'<a href="%s">%s</a>',
$event_log_url,
__( 'View activity', 'newspack-network' )
);
}

$last_activity = $last_activity[0];

$summary = $last_activity->get_summary();
$event_log_url = add_query_arg(
[
'page' => EVENT_LOG_PAGE_SLUG,
'email' => $user->user_email,
],
admin_url( 'admin.php' )
);
return sprintf(
'%s: <code>%s</code><br><a href="%s">%s</a>',
__( 'Last Activity', 'newspack-network' ),
$summary,
$event_log_url,
__( 'View all', 'newspack-network' )
);

}
return $value;
}
Expand All @@ -106,6 +113,10 @@ public static function users_list_table_query_args( $args ) {
$args['role__in'] = explode( ',', sanitize_text_field( $_REQUEST['role__in'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
unset( $args['role'] );
}
if ( isset( $_REQUEST['role__not_in'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['role__not_in'] = explode( ',', sanitize_text_field( $_REQUEST['role__not_in'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
unset( $args['role'] );
}
return $args;
}
}
79 changes: 76 additions & 3 deletions includes/hub/admin/class-nodes-list.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ public static function init() {
add_action( 'admin_bar_menu', [ __CLASS__, 'admin_bar_menu' ], 100 );
}

/**
* Cache for site info responses.
*
* @var array
*/
private static $node_site_info_cache = [];

/**
* Cache for Hub site info.
*
* @var array
*/
private static $hub_site_info = false;

/**
* Modify columns on post type table
*
Expand All @@ -37,16 +51,32 @@ public static function posts_columns( $columns ) {
unset( $columns['date'] );
unset( $columns['stats'] );
if ( \Newspack_Network\Admin::use_experimental_auditing_features() ) {
$sync_users_count = \Newspack_Network\Utils\Users::get_synchronized_users_count();
$sync_users_info = sprintf(
' <span class="dashicons dashicons-info-outline" title="%s"></span>',
sprintf(
/* translators: list of user roles which will entail synchronization */
esc_attr__( 'Users with the following roles: %1$s (%2$d on the Hub)', 'newspack-network' ),
implode( ', ', \Newspack_Network\Utils\Users::get_synced_user_roles() ),
\Newspack_Network\Utils\Users::get_synchronized_users_count()
$sync_users_count
)
);
/* translators: %d is the synchronizable users count. */
$columns['sync_users'] = sprintf( __( 'Synchronizable Users (%d)', 'newspack-network' ), $sync_users_count ) . $sync_users_info;
if ( isset( $_GET['_newspack_user_discrepancies'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$columns['user_discrepancies'] = __( 'Discrepancies in Sync. Users', 'newspack-network' );
}

$not_sync_users_info = sprintf(
' <span class="dashicons dashicons-info-outline" title="%s"></span>',
sprintf(
/* translators: list of user roles which will entail synchronization */
esc_attr__( 'Users with roles different than the following roles: %1$s (%2$d on the Hub)', 'newspack-network' ),
implode( ', ', \Newspack_Network\Utils\Users::get_synced_user_roles() ),
\Newspack_Network\Utils\Users::get_not_synchronized_users_count()
)
);
$columns['sync_users'] = __( 'Synchronizable Users', 'newspack-network' ) . $sync_users_info;
$columns['not_sync_users'] = __( 'Non-synchronizable Users', 'newspack-network' ) . $not_sync_users_info;
}
$columns['links'] = __( 'Links', 'newspack-network' );
return $columns;
Expand Down Expand Up @@ -80,6 +110,38 @@ function ( $bookmark ) {
</p>
<?php
}
if ( ! isset( self::$node_site_info_cache[ $post_id ] ) ) {
self::$node_site_info_cache[ $post_id ] = $node->get_site_info();
}
$node_site_info = self::$node_site_info_cache[ $post_id ];

if ( isset( $_GET['_newspack_user_discrepancies'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! self::$hub_site_info ) {
self::$hub_site_info = [
'sync_user_emails' => \Newspack_Network\Utils\Users::get_synchronized_users_emails(),
];
}

// Display user discrepancies.
$node_users_emails = $node_site_info->sync_users_emails ?? [];
// Users who are on the Hub but not on the Node.
$not_on_node = array_diff( self::$hub_site_info['sync_user_emails'], $node_users_emails );
// Users who are not on the Node but are on the Hub.
$not_on_hub = array_diff( $node_users_emails, self::$hub_site_info['sync_user_emails'] );
if ( 'user_discrepancies' === $column ) {
?>
<span>
<?php
echo esc_html(
/* translators: %d - users on the Hub only, %d on the Node only */
sprintf( __( '%1$d on the Hub only, %2$d on the Node only', 'newspack-network' ), count( $not_on_node ), count( $not_on_hub ) )
);
?>
</span>
<?php
}
}

if ( 'sync_users' === $column ) {
$users_link = add_query_arg(
[
Expand All @@ -88,7 +150,18 @@ function ( $bookmark ) {
trailingslashit( $node->get_url() ) . 'wp-admin/users.php'
);
?>
<a href="<?php echo esc_url( $users_link ); ?>"><?php echo esc_html( $node->get_sync_users_count() ); ?></a>
<a href="<?php echo esc_url( $users_link ); ?>"><?php echo esc_html( $node_site_info->sync_users_count ?? 0 ); ?></a>
<?php
}
if ( 'not_sync_users' === $column ) {
$users_link = add_query_arg(
[
'role__not_in' => implode( ',', \Newspack_Network\Utils\Users::get_synced_user_roles() ),
],
trailingslashit( $node->get_url() ) . 'wp-admin/users.php'
);
?>
<a href="<?php echo esc_url( $users_link ); ?>"><?php echo esc_html( $node_site_info->not_sync_users_count ?? 0 ); ?></a>
<?php
}
}
Expand Down
10 changes: 1 addition & 9 deletions includes/hub/class-node.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function get_bookmarks() {
/**
* Get site info.
*/
private function get_site_info() {
public function get_site_info() {
$response = wp_remote_get( // phpcs:ignore
$this->get_url() . '/wp-json/newspack-network/v1/info',
[
Expand All @@ -183,12 +183,4 @@ private function get_site_info() {
);
return json_decode( wp_remote_retrieve_body( $response ) );
}

/**
* Get synchronized users count.
*/
public function get_sync_users_count() {
$site_info = $this->get_site_info();
return $site_info->sync_users_count ?? 0;
}
}
6 changes: 5 additions & 1 deletion includes/node/class-info-endpoints.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ public static function register_routes() {
public static function handle_info_request() {
return rest_ensure_response(
[
'sync_users_count' => \Newspack_Network\Utils\Users::get_synchronized_users_count(),
'sync_users_count' => \Newspack_Network\Utils\Users::get_synchronized_users_count(),
'sync_users_emails' => \Newspack_Network\Utils\Users::get_synchronized_users_emails(),
'not_sync_users_count' => \Newspack_Network\Utils\Users::get_not_synchronized_users_count(),
'not_sync_users_emails' => \Newspack_Network\Utils\Users::get_not_synchronized_users_emails(),
'no_role_users_emails' => \Newspack_Network\Utils\Users::get_no_role_users_emails(),
]
);
}
Expand Down
61 changes: 58 additions & 3 deletions includes/utils/class-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,68 @@ public static function get_synced_user_roles() {
* Get synchronized users count.
*/
public static function get_synchronized_users_count() {
$users = get_users(
return count( self::get_synchronized_users( [ 'id' ] ) );
}

/**
* Get synchronized users emails.
*/
public static function get_synchronized_users_emails() {
return array_map( 'strtolower', array_column( self::get_synchronized_users( [ 'user_email' ] ), 'user_email' ) );
}

/**
* Get no-role users emails.
*/
public static function get_no_role_users_emails() {
global $wpdb;
$no_role_users_emails = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
"SELECT user_email FROM wp_users WHERE ID IN (SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_capabilities' AND (meta_value = 'a:0:{}' OR meta_value = '')) OR ID NOT IN (SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_capabilities')"
);
return array_map( 'strtolower', array_column( $no_role_users_emails, 'user_email' ) );
}

/**
* Get synchronized users.
*
* @param array $fields Fields to return.
*/
public static function get_synchronized_users( $fields = [] ) {
return get_users(
[
'role__in' => self::get_synced_user_roles(),
'fields' => [ 'id' ],
'fields' => $fields,
'number' => -1,
]
);
return count( $users );
}

/**
* Get not synchronized users count.
*
* @param array $fields Fields to return.
*/
public static function get_not_synchronized_users( $fields = [] ) {
return get_users(
[
'role__not_in' => self::get_synced_user_roles(),
'fields' => $fields,
'number' => -1,
]
);
}

/**
* Get synchronized users emails.
*/
public static function get_not_synchronized_users_emails() {
return array_map( 'strtolower', array_column( self::get_not_synchronized_users( [ 'user_email' ] ), 'user_email' ) );
}

/**
* Get not synchronized users count.
*/
public static function get_not_synchronized_users_count() {
return count( self::get_not_synchronized_users( [ 'id' ] ) );
}
}
8 changes: 6 additions & 2 deletions includes/woocommerce-memberships/class-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,18 @@ public static function init() {
/**
* Get active members' emails.
*
* @param \WC_Memberships_Membership_Plan $plan the membership plan.
* @param \WC_Memberships_Membership_Plan $plan The membership plan.
*/
public static function get_active_members_emails( $plan ) {
$active_memberships = $plan->get_memberships( [ 'post_status' => 'wcm-active' ] );
return array_map(
function ( $membership ) {
$user = get_user_by( 'id', $membership->get_user_id() );
return $user->user_email;
if ( $user ) {
return strtolower( $user->user_email );
} else {
return '';
}
},
$active_memberships
);
Expand Down

0 comments on commit a054967

Please sign in to comment.