Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 189 additions & 43 deletions includes/class-blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,20 +363,101 @@ public function render_followers_block() {
return '<section class="followers"><p>' . esc_html__( 'The follower list is currently dependent on the ActivityPub plugin.', 'friends' ) . '</p></section>';
}

$user_id = isset( $friends_args['user_id'] ) ? $friends_args['user_id'] : get_current_user_id();
$only_mutual = isset( $friends_args['only_mutual'] ) ? $friends_args['only_mutual'] : false;
$user_id = isset( $friends_args['user_id'] ) ? $friends_args['user_id'] : get_current_user_id();
$blog_followers = class_exists( '\ActivityPub\Collection\Actors' ) && \ActivityPub\Collection\Actors::BLOG_USER_ID === $user_id;

$filter = isset( $_GET['filter'] ) ? sanitize_key( $_GET['filter'] ) : 'all'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $filter, array( 'all', 'following', 'not-following' ), true ) ) {
$filter = 'all';
}
// Backwards compatibility with ?mutual.
if ( isset( $_GET['mutual'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$filter = 'following';
}

$sort = isset( $_GET['sort'] ) ? sanitize_key( $_GET['sort'] ) : 'newest'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $sort, array( 'newest', 'oldest', 'name' ), true ) ) {
$sort = 'newest';
}

$followers_list_page = 'users.php?page=activitypub-followers-list';
if ( $blog_followers ) {
$followers_list_page = 'options-general.php?page=activitypub&tab=followers';
}

$follower_data = \ActivityPub\Collection\Followers::get_followers_with_count( $user_id );
$total = $follower_data['total'];
$already_following = 0;
$follower_data = \ActivityPub\Collection\Followers::query( $user_id );
$total = $follower_data['total'];
// Classify followers only when a filter is active.
if ( 'all' !== $filter ) {
$following_ids = array();
$not_following_ids = array();
foreach ( $follower_data['followers'] as $follower ) {
$url = $follower->guid;
$is_following = false;
if ( $url ) {
$is_following = User_Feed::get_by_url( $url );
if ( ! $is_following || is_wp_error( $is_following ) ) {
$is_following = User_Feed::get_by_url( str_replace( '@', 'users/', $url ) );
}
}
if ( $is_following && ! is_wp_error( $is_following ) ) {
$following_ids[] = $follower->ID;
} else {
$not_following_ids[] = $follower->ID;
}
}

if ( 'following' === $filter ) {
$filtered_followers = array_filter(
$follower_data['followers'],
function ( $f ) use ( $following_ids ) {
return in_array( $f->ID, $following_ids, true );
}
);
} else {
$filtered_followers = array_filter(
$follower_data['followers'],
function ( $f ) use ( $not_following_ids ) {
return in_array( $f->ID, $not_following_ids, true );
}
);
}
} else {
$filtered_followers = $follower_data['followers'];
}

// Sort.
$filtered_followers = array_values( $filtered_followers );
if ( 'oldest' === $sort ) {
usort(
$filtered_followers,
function ( $a, $b ) {
return $a->ID - $b->ID;
}
);
} elseif ( 'name' === $sort ) {
usort(
$filtered_followers,
function ( $a, $b ) {
return strnatcasecmp( $a->post_title, $b->post_title );
}
);
}

// Paginate.
$filtered_total = count( $filtered_followers );
$followers_per_page = 20;
$current_page = isset( $_GET['fpage'] ) ? max( 1, absint( $_GET['fpage'] ) ) : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$page_followers = array_slice( $filtered_followers, ( $current_page - 1 ) * $followers_per_page, $followers_per_page );
$display_followers = array();

foreach ( $follower_data['followers'] as $k => $follower ) {
foreach ( $page_followers as $follower ) {
if ( $follower instanceof \WP_Post ) {
$follower = \Activitypub\Collection\Remote_Actors::get_actor( $follower );
if ( is_wp_error( $follower ) ) {
continue;
}
}
$data = $follower->to_array();
$data['url'] = \ActivityPub\object_to_uri( $data['url'] );
$data['server'] = wp_parse_url( $data['url'], PHP_URL_HOST );
Expand All @@ -388,28 +469,33 @@ public function render_followers_block() {
}

if ( $following && ! is_wp_error( $following ) ) {
++$already_following;
$data['friend_user'] = $following->get_friend_user();
$data['action_url'] = $following->get_friend_user()->get_local_friends_page_url();
$data['url'] = $following->get_friend_user()->get_local_friends_page_url();
if ( ! $only_mutual ) {
if ( 'all' === $filter ) {
$data['css_class'] = ' already-following';
}
} else {
$data['friend_user'] = false;
$data['action_url'] = add_query_arg( 'url', $data['url'], admin_url( 'admin.php?page=add-friend' ) );
}
$data['remove_action_url'] = add_query_arg( 's', $data['url'], admin_url( $followers_list_page ) );
$follower_data['followers'][ $k ] = $data;
$data['remove_action_url'] = add_query_arg( 's', $data['url'], admin_url( $followers_list_page ) );
$display_followers[] = $data;
}

$base_url = strtok( $_SERVER['REQUEST_URI'], '?' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$link_args = array();
if ( 'all' !== $filter ) {
$link_args['filter'] = $filter;
}
if ( 'newest' !== $sort ) {
$link_args['sort'] = $sort;
}

ob_start();
?>
<section class="followers">
<p>
<?php if ( $only_mutual ) : ?>
<a href="?">
<?php endif; ?>
<?php
if ( $blog_followers ) {
echo esc_html(
Expand All @@ -428,32 +514,8 @@ public function render_followers_block() {
)
);
}

?>
<?php if ( $only_mutual ) : ?>
</a>
<?php
$not_yet_following = $total - $already_following;
echo esc_html(
sprintf(
// translators: %s is the number of followers not yet followed back.
_n( "You're not yet following %s of them.", "You're not yet following %s of them.", $not_yet_following, 'friends' ),
$not_yet_following
)
);
?>
<?php else : ?>
<a href="?mutual">
<?php
echo esc_html(
sprintf(
// translators: %s is the number of followers you follow back.
_n( "You're following %s of them.", "You're following %s of them.", $already_following, 'friends' ),
$already_following
)
);
?>
</a>
<?php endif; ?>
<a href="<?php echo esc_url( admin_url( $followers_list_page ) ); ?>">
<?php
if ( $blog_followers ) {
Expand All @@ -464,16 +526,83 @@ public function render_followers_block() {
?>
</a>
</p>
<p>
<?php esc_html_e( 'Filter:', 'friends' ); ?>
<?php
$filters = array(
'all' => __( 'All', 'friends' ),
'following' => __( 'Following', 'friends' ),
'not-following' => __( 'Not Following', 'friends' ),
);
$filter_links = array();
foreach ( $filters as $filter_key => $filter_label ) {
$url = $base_url;
$f_args = $link_args;
if ( 'all' !== $filter_key ) {
$f_args['filter'] = $filter_key;
} else {
unset( $f_args['filter'] );
}
if ( $f_args ) {
$url = add_query_arg( $f_args, $url );
}
if ( $filter === $filter_key ) {
$filter_links[] = '<strong>' . esc_html( $filter_label ) . '</strong>';
} else {
$filter_links[] = '<a href="' . esc_url( $url ) . '">' . esc_html( $filter_label ) . '</a>';
}
}
echo wp_kses(
implode( ' | ', $filter_links ),
array(
'strong' => array(),
'a' => array( 'href' => array() ),
)
);
?>

&nbsp;&nbsp;
<?php esc_html_e( 'Sort:', 'friends' ); ?>
<?php
$sorts = array(
'newest' => __( 'Newest', 'friends' ),
'oldest' => __( 'Oldest', 'friends' ),
'name' => __( 'Name', 'friends' ),
);
$sort_links = array();
foreach ( $sorts as $sort_key => $sort_label ) {
$url = $base_url;
$s_args = $link_args;
if ( 'newest' !== $sort_key ) {
$s_args['sort'] = $sort_key;
} else {
unset( $s_args['sort'] );
}
if ( $s_args ) {
$url = add_query_arg( $s_args, $url );
}
if ( $sort === $sort_key ) {
$sort_links[] = '<strong>' . esc_html( $sort_label ) . '</strong>';
} else {
$sort_links[] = '<a href="' . esc_url( $url ) . '">' . esc_html( $sort_label ) . '</a>';
}
}
echo wp_kses(
implode( ' | ', $sort_links ),
array(
'strong' => array(),
'a' => array( 'href' => array() ),
)
);
?>
</p>
<ul>
<?php foreach ( $follower_data['followers'] as $follower ) : ?>
<?php if ( $only_mutual && ! $follower['friend_user'] ) : ?>
<?php continue; ?>
<?php endif; ?>
<?php foreach ( $display_followers as $follower ) : ?>
<li>
<details data-nonce="<?php echo esc_attr( wp_create_nonce( 'friends-preview' ) ); ?>" data-following="<?php echo esc_attr( $follower['following'] ); ?>" data-followers="<?php echo esc_attr( $follower['followers'] ); ?>" data-id="<?php echo esc_attr( $follower['id'] ); ?>">
<summary>
<a href="<?php echo esc_url( $follower['url'] ); ?>" class="follower<?php echo esc_attr( $follower['css_class'] ); ?>">
<img width="40" height="40" src="<?php echo esc_attr( $follower['icon']['url'] ); ?>" class="avatar activitypub-avatar" />
<img width="40" height="40" src="<?php echo esc_attr( $follower['icon']['url'] ); ?>" loading="lazy" class="avatar activitypub-avatar" />
<span class="activitypub-actor">
<strong class="activitypub-name"><?php echo esc_html( $follower['name'] ); ?></strong>
(<span class="activitypub-handle">@<?php echo esc_html( $follower['preferredUsername'] . '@' . $follower['server'] ); ?></span>)
Expand Down Expand Up @@ -514,6 +643,23 @@ public function render_followers_block() {
</li>
<?php endforeach; ?>
</ul>
<?php
$total_pages = ceil( $filtered_total / $followers_per_page );
if ( $total_pages > 1 ) {
$pagination_args = array(
'base' => add_query_arg( 'fpage', '%#%' ),
'format' => '',
'current' => $current_page,
'total' => $total_pages,
);
if ( $link_args ) {
$pagination_args['add_args'] = $link_args;
}
echo '<nav class="pagination">';
echo wp_kses_post( paginate_links( $pagination_args ) );
echo '</nav>';
}
?>
</section>
<?php
return ob_get_clean();
Expand Down
Loading
Loading