PluginProbe
Friends / 2.8.6
Friends v2.8.6
4.3.2 4.3.1 4.3.0 4.2.2 4.2.1 4.2.0 4.1.0 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.0 2.9.1 All 88 releases
friends / includes / class-admin.php

class-admin.php in Friends 2.8.6, at includes/class-admin.php

3,026 lines 105.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Friends Admin
4 *
5 * This contains the functions for the admin section.
6 *
7 * @package Friends
8 */
9
10 namespace Friends;
11
12 /**
13 * This is the class for the Friends Plugin Admin section.
14 *
15 * @since 0.6
16 *
17 * @package Friends
18 * @author Alex Kirk
19 */
20 class Admin {
21 /**
22 * Contains a reference to the Friends class.
23 *
24 * @var Friends
25 */
26 private $friends;
27
28 /**
29 * Constructor
30 *
31 * @param Friends $friends A reference to the Friends object.
32 */
33 public function __construct( Friends $friends ) {
34 $this->friends = $friends;
35 $this->register_hooks();
36 }
37
38 /**
39 * Register the WordPress hooks
40 */
41 private function register_hooks() {
42 add_action( 'admin_menu', array( $this, 'admin_menu' ) );
43 add_action( 'friends_own_site_menu_top', array( $this, 'friends_add_menu_open_friend_request' ), 10, 2 );
44 add_filter( 'users_list_table_query_args', array( $this, 'allow_role_multi_select' ) );
45 add_filter( 'user_row_actions', array( get_called_class(), 'user_row_actions' ), 10, 2 );
46 add_filter( 'handle_bulk_actions-users', array( $this, 'handle_bulk_friend_request_approval' ), 10, 3 );
47 add_filter( 'bulk_actions-users', array( $this, 'add_user_bulk_options' ) );
48 add_filter( 'manage_users_columns', array( $this, 'user_list_columns' ) );
49 add_filter( 'manage_users_custom_column', array( get_called_class(), 'user_list_custom_column' ), 10, 3 );
50 add_filter( 'the_title', array( $this, 'override_post_format_title' ), 10, 2 );
51 add_filter( 'get_edit_user_link', array( $this, 'admin_edit_user_link' ), 10, 2 );
52 add_action( 'admin_bar_menu', array( $this, 'admin_bar_friends_menu' ), 39 );
53 add_action( 'admin_bar_menu', array( $this, 'admin_bar_new_content' ), 71 );
54 add_action( 'wp_head', array( $this, 'admin_bar_mobile' ) );
55 add_action( 'current_screen', array( $this, 'register_help' ) );
56 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 39 );
57 add_action( 'gettext_with_context', array( $this->friends, 'translate_user_role' ), 10, 4 );
58 add_action( 'wp_ajax_friends_preview_rules', array( $this, 'ajax_preview_friend_rules' ) );
59 add_action( 'wp_ajax_friends_refresh_link_token', array( $this, 'ajax_refresh_link_token' ) );
60 add_action( 'wp_ajax_friends_fetch_feeds', array( $this, 'ajax_fetch_feeds' ) );
61 add_action( 'wp_ajax_friends_set_avatar', array( $this, 'ajax_set_avatar' ) );
62 add_action( 'delete_user_form', array( $this, 'delete_user_form' ), 10, 2 );
63 add_action( 'delete_user', array( $this, 'delete_user' ) );
64 add_action( 'remove_user_from_blog', array( $this, 'delete_user' ) );
65 add_action( 'tool_box', array( $this, 'toolbox_bookmarklets' ) );
66 add_action( 'dashboard_glance_items', array( $this, 'dashboard_glance_items' ) );
67 add_filter( 'site_status_tests', array( $this, 'site_status_tests' ) );
68 add_filter( 'site_status_test_php_modules', array( $this, 'site_status_test_php_modules' ) );
69 add_filter( 'debug_information', array( $this, 'site_health_debug' ) );
70 add_filter( 'friends_create_and_follow', array( $this, 'create_and_follow' ), 10, 4 );
71
72 if ( ! get_option( 'permalink_structure' ) ) {
73 add_action( 'admin_notices', array( $this, 'admin_notice_unsupported_permalink_structure' ) );
74 }
75 add_filter( 'friends_unread_count', array( $this, 'friends_unread_friend_request_count' ) );
76 }
77
78 /**
79 * Display admin notice about an unsupported permalink structure
80 */
81 public function admin_notice_unsupported_permalink_structure() {
82 $screen = get_current_screen();
83
84 if ( 'plugins' !== $screen->id ) {
85 return;
86 }
87
88 ?>
89 <div class="friends-notice notice notice-error">
90 <p style="max-width:800px;"><b><?php esc_html_e( 'Friends', 'friends' ); ?></b><?php esc_html_e( '&#151; You are running an unsupported permalink structure.', 'friends' ); ?></p>
91 <p style="max-width:800px;">
92 <?php
93 echo wp_kses_post(
94 sprintf(
95 // translators: 1: URL to permalink settings, 2: the name of the Permalink Settings page.
96 __( 'In order to be able to view the Friends page, you need to enable a custom permalink structure. Please go to <a href="%1$s">%2$s</a> and enable an option other than Plain.', 'friends' ),
97 admin_url( 'options-permalink.php' ),
98 __( 'Permalink Settings' ) // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
99 )
100 );
101 ?>
102 </p>
103 </div>
104 <?php
105 }
106
107 /**
108 * Registers the admin menus
109 */
110 public function admin_menu() {
111 if ( isset( $_REQUEST['rerun-activate'] ) && isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'friends-settings' ) ) {
112 Friends::activate_plugin();
113 wp_safe_redirect( add_query_arg( array( 'reran-activation' => 'friends' ), wp_get_referer() ) );
114 exit;
115 }
116 $required_role = Friends::required_menu_role();
117 $unread_badge = $this->get_unread_badge();
118
119 $menu_title = __( 'Friends', 'friends' ) . $unread_badge;
120 $page_type = sanitize_title( $menu_title );
121 add_menu_page( 'friends', $menu_title, $required_role, 'friends', null, 'dashicons-groups', 3 );
122 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
123 add_submenu_page( 'friends', __( 'Home' ), __( 'Home' ), $required_role, 'friends', array( $this, 'render_admin_home' ) );
124 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
125 add_submenu_page( 'friends', __( 'Settings' ), __( 'Settings' ), $required_role, 'friends-settings', array( $this, 'render_admin_settings' ) );
126 add_action( 'load-' . $page_type . '_page_friends-page', array( $this, 'redirect_to_friends_page' ) );
127 add_submenu_page( 'friends', __( 'Notification Manager', 'friends' ), __( 'Notification Manager', 'friends' ), $required_role, 'friends-notification-manager', array( $this, 'render_admin_notification_manager' ) );
128 add_action( 'load-' . $page_type . '_page_friends-notification-manager', array( $this, 'process_admin_notification_manager' ) );
129 add_submenu_page( 'friends', __( 'Add New Friend', 'friends' ), __( 'Add New Friend', 'friends' ), $required_role, 'add-friend', array( $this, 'render_admin_add_friend' ) );
130 add_action( 'load-' . $page_type . '_page_friends-settings', array( $this, 'process_admin_settings' ) );
131
132 add_submenu_page( 'friends', __( 'Friends &amp; Requests', 'friends' ), __( 'Friends &amp; Requests', 'friends' ), $required_role, 'friends-list', array( $this, 'render_friends_list' ) );
133
134 if ( $this->friends_unread_friend_request_count( 0 ) > 0 ) {
135 add_submenu_page( 'friends', __( 'Friend Requests', 'friends' ), __( 'Friend Requests', 'friends' ) . $unread_badge, $required_role, 'friends-list-requests', array( $this, 'render_friends_list' ) );
136 } elseif ( isset( $_GET['page'] ) && 'friends-list-requests' === $_GET['page'] ) {
137 // Don't show a no permission page but redirect to the friends list.
138 add_submenu_page( 'friends', __( 'Friend Requests', 'friends' ), __( 'Friend Requests', 'friends' ) . $unread_badge, $required_role, 'friends-list-requests', array( $this, 'render_friends_list' ) );
139 }
140
141 if ( isset( $_GET['page'] ) && 'friends-refresh' === $_GET['page'] ) {
142 add_submenu_page( 'friends', __( 'Refresh', 'friends' ), __( 'Refresh', 'friends' ), $required_role, 'friends-refresh', array( $this, 'admin_refresh_friend_posts' ) );
143 }
144
145 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
146 add_submenu_page( 'friends', __( 'Plugins' ), __( 'Plugins' ), $required_role, 'friends-plugins', array( $this, 'admin_plugin_installer' ) );
147
148 if ( isset( $_GET['page'] ) && 0 === strpos( $_GET['page'], 'edit-friend' ) ) {
149 add_submenu_page( 'friends', __( 'Edit User', 'friends' ), __( 'Edit User', 'friends' ), $required_role, 'edit-friend' . ( 'edit-friend' !== $_GET['page'] && isset( $_GET['user'] ) ? '&user=' . $_GET['user'] : '' ), array( $this, 'render_admin_edit_friend' ) );
150 add_submenu_page( 'friends', __( 'Edit Feeds', 'friends' ), __( 'Edit Feeds', 'friends' ), $required_role, 'edit-friend-feeds' . ( 'edit-friend-feeds' !== $_GET['page'] && isset( $_GET['user'] ) ? '&user=' . $_GET['user'] : '' ), array( $this, 'render_admin_edit_friend_feeds' ) );
151 add_submenu_page( 'friends', __( 'Edit Notifications', 'friends' ), __( 'Edit Notifications', 'friends' ), $required_role, 'edit-friend-notifications' . ( 'edit-friend-notifications' !== $_GET['page'] && isset( $_GET['user'] ) ? '&user=' . $_GET['user'] : '' ), array( $this, 'render_admin_edit_friend_notifications' ) );
152 add_submenu_page( 'friends', __( 'Edit Rules', 'friends' ), __( 'Edit Rules', 'friends' ), $required_role, 'edit-friend-rules' . ( 'edit-friend-rules' !== $_GET['page'] && isset( $_GET['user'] ) ? '&user=' . $_GET['user'] : '' ), array( $this, 'render_admin_edit_friend_rules' ) );
153 add_action( 'load-' . $page_type . '_page_edit-friend', array( $this, 'process_admin_edit_friend' ) );
154 add_action( 'load-' . $page_type . '_page_edit-friend-feeds', array( $this, 'process_admin_edit_friend_feeds' ) );
155 add_action( 'load-' . $page_type . '_page_edit-friend-notifications', array( $this, 'process_admin_edit_friend_notifications' ) );
156 add_action( 'load-' . $page_type . '_page_edit-friend-rules', array( $this, 'process_admin_edit_friend_rules' ) );
157 }
158
159 if ( isset( $_GET['page'] ) && 'unfriend' === $_GET['page'] ) {
160 $user = new User( $_GET['user'] );
161 if ( $user ) {
162 $title = /* translators: %s is a username. */ sprintf( __( 'Unfriend %s', 'friends' ), $user->user_login );
163 add_submenu_page( 'friends', $title, $title, $required_role, 'unfriend', array( $this, 'render_admin_unfriend' ) );
164 add_action( 'load-' . $page_type . '_page_unfriend', array( $this, 'process_admin_unfriend' ) );
165 }
166 }
167 }
168
169 /**
170 * Allow making use of the role__in query.
171 *
172 * @param array $args The arguments.
173 *
174 * @return array The modified array.
175 */
176 public function allow_role_multi_select( $args ) {
177 if ( isset( $args['role'] ) && ! isset( $args['role__in'] ) ) {
178 if ( false !== strpos( $args['role'], ',' ) ) {
179 $args['role__in'] = explode( ',', $args['role'] );
180 unset( $args['role'] );
181 }
182
183 $roles = self::get_associated_roles();
184 if (
185 ( isset( $args['role__in'] ) && array_intersect( $args['role__in'], array_keys( $roles ) ) )
186 || ( isset( $args['role'] ) && isset( $roles[ $args['role'] ] ) )
187 ) {
188 add_action( 'admin_head-users.php', array( $this, 'keep_friends_open_on_users_screen' ) );
189 }
190 }
191 return $args;
192 }
193
194 /**
195 * Use JavaScript to keep the Friends menu open when responding to a Friend Request.
196 */
197 public function keep_friends_open_on_users_screen() {
198 ?>
199 <script type="text/javascript">
200 jQuery( document ).ready( function ( $ ) {
201 $( '#toplevel_page_friends-settings, #toplevel_page_friends-settings > a' ).addClass( 'wp-has-current-submenu wp-menu-open' ).removeClass( 'wp-not-current-submenu' );
202 $( '#menu-users > a' ).removeClass( 'wp-has-current-submenu wp-menu-open' );
203 $( "#toplevel_page_friends-settings ul li a[href='<?php echo esc_html( self::get_users_url() ); ?>']" ).closest( 'li' ).addClass( 'current' );
204 } );
205 </script>
206 <?php
207 }
208
209 /**
210 * Add our help information
211 *
212 * @param \WP_Screen $screen The current wp-admin screen.
213 */
214 public function register_help( $screen ) {
215 if ( ! ( $screen instanceof \WP_Screen ) ) {
216 return;
217 }
218
219 switch ( $screen->id ) {
220 case 'toplevel_page_friends-settings':
221 $screen->add_help_tab(
222 array(
223 'id' => 'overview',
224 'title' => __( 'Overview', 'friends' ),
225 'content' =>
226 '<p>' .
227 __( 'Welcome to the Friends Settings! You can configure the Friends plugin here to your liking.', 'friends' ) .
228 '</p>' .
229 '<p>' .
230 sprintf(
231 // translators: %1$s is a URL, %2$s is the name of a wp-admin screen.
232 __( 'There are more settings available for each friend or subscription individually. To get there, click on the user on the <a href=%1$s>%2$s</a> screen.', 'friends' ),
233 '"' . esc_attr( self_admin_url( self::get_users_url() ) ) . '"',
234 __( 'Friends &amp; Requests', 'friends' )
235 ) .
236 '</p>',
237 )
238 );
239 break;
240 case 'users':
241 $screen->add_help_tab(
242 array(
243 'id' => 'friends',
244 'title' => __( 'Friends', 'friends' ),
245 'content' => '<p>' . __( 'Here you can find your friends and subscriptions.', 'friends' ) . '</p><p>' . __( 'If you no longer want to be friends with someone or stop a subscription, you can simply delete that user.', 'friends' ) . '</p>',
246 )
247 );
248 break;
249 }
250 }
251
252 /**
253 * Reference our script for the /friends page
254 */
255 public function admin_enqueue_scripts() {
256 $handle = 'friends-admin';
257 $file = 'friends-admin.js';
258 $version = Friends::VERSION;
259 wp_enqueue_script( $handle, plugins_url( $file, FRIENDS_PLUGIN_FILE ), array( 'jquery' ), apply_filters( 'friends_debug_enqueue', $version, $handle, dirname( FRIENDS_PLUGIN_FILE ) . '/' . $file ) );
260
261 $variables = array(
262 'ajax_url' => admin_url( 'admin-ajax.php' ),
263 'add_friend_url' => self_admin_url( 'admin.php?page=add-friend' ),
264 'add_friend_text' => __( 'Add a Friend', 'friends' ),
265 'delete_feed_question' => __( 'Delete the feed? You need to click "Save Changes" to really delete it.', 'friends' ),
266 'role_friend' => __( 'Friend', 'friends' ),
267 'role_acquaintance' => __( 'Acquaintance', 'friends' ),
268 'role_friend_request' => __( 'Friend Request', 'friends' ),
269 'role_pending_friend_request' => __( 'Pending Friend Request', 'friends' ),
270 'role_subscription' => __( 'Following', 'friends' ),
271 'role_connection' => __( 'Connection', 'friends' ),
272 'role_contact' => __( 'Contact', 'friends' ),
273 'role_connection_request' => __( 'Connection Request', 'friends' ),
274 'role_pending_connection_request' => __( 'Pending Connection Request', 'friends' ),
275 'role_following' => __( 'Following', 'friends' ),
276 );
277 wp_localize_script( 'friends-admin', 'friends', $variables );
278
279 $handle = 'friends-admin';
280 $file = 'friends-admin.css';
281 $version = Friends::VERSION;
282 wp_enqueue_style( $handle, plugins_url( $file, FRIENDS_PLUGIN_FILE ), array(), apply_filters( 'friends_debug_enqueue', $version, $handle, dirname( FRIENDS_PLUGIN_FILE ) . '/' . $file ) );
283 }
284
285 /**
286 * Admin menu to refresh the friend posts.
287 */
288 public function admin_refresh_friend_posts() {
289 ?>
290 <h1><?php esc_html_e( "Refreshing Your Friends' Posts", 'friends' ); ?></h1>
291 <?php
292
293 add_filter( 'notify_about_new_friend_post', '__return_false', 999 );
294
295 add_filter(
296 'friends_friend_private_feed_url',
297 function ( $feed_url, $friend_user ) {
298 // translators: %1s is the name of the friend, %2$s is the feed URL.
299 printf( __( 'Refreshing %1$s at %2$s', 'friends' ) . '<br/>', '<a href="' . esc_url( $friend_user->get_local_friends_page_url() ) . '">' . esc_html( $friend_user->user_login ) . '</a>', '<a href="' . esc_url( $feed_url ) . '">' . esc_html( $feed_url ) . '</a>' );
300 return $feed_url;
301 },
302 10,
303 2
304 );
305
306 add_action(
307 'friends_retrieved_new_posts',
308 function ( $user_feed, $new_posts, $modified_posts ) {
309 // translators: %s is the number of new posts found.
310 echo esc_html( sprintf( _n( 'Found %d new post.', 'Found %d new posts.', count( $new_posts ), 'friends' ), count( $new_posts ) ) );
311 ?>
312 <br />
313 <?php
314 // translators: %s is the number of modified posts.
315 echo esc_html( sprintf( _n( '%d post was modified.', '%d posts were modified.', count( $modified_posts ), 'friends' ), count( $modified_posts ) ) );
316 ?>
317 <br />
318 <?php
319 },
320 10,
321 3
322 );
323
324 add_action(
325 'friends_incoming_feed_items',
326 function ( $items ) {
327 // translators: %s is the number of posts found.
328 echo esc_html( sprintf( _n( 'Found %d item in the feed.', 'Found %d items in the feed.', count( $items ), 'friends' ) . ' ', count( $items ) ) );
329 }
330 );
331
332 add_action(
333 'friends_retrieve_friends_error',
334 function ( $user_feed, $error ) {
335 esc_html_e( 'An error occurred while retrieving the posts.', 'friends' );
336 echo esc_html( $error->get_error_message() ), '<br/>';
337 },
338 10,
339 2
340 );
341
342 if ( isset( $_GET['user'] ) ) {
343 $friend_user = User::get_by_username( $_GET['user'] );
344 if ( ! $friend_user || is_wp_error( $friend_user ) || ! $friend_user->can_refresh_feeds() ) {
345 wp_die( esc_html__( 'Invalid user ID.' ) ); // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
346 }
347 $friend_user->retrieve_posts_from_active_feeds();
348 } else {
349 $this->friends->feed->retrieve_friend_posts();
350 }
351 }
352
353 /**
354 * Admin page for installing plugins.
355 */
356 public function admin_plugin_installer() {
357 Friends::template_loader()->get_template_part( 'admin/plugin-installer-header' );
358 Plugin_Installer::init();
359 Friends::template_loader()->get_template_part( 'admin/plugin-installer-footer' );
360 }
361
362 /**
363 * Send a friend request to another WordPress with the Friends plugin
364 *
365 * @param string $rest_url The site URL of the friend's
366 * WordPress.
367 * @param string $user_login The user login.
368 * @param string $user_url The user url.
369 * @param string $display_name The display name.
370 * @param string $codeword A codeword to send along.
371 * @param string $message A message to send along.
372 *
373 * @return \WP_User|\WP_error $user The new associated user or an error object.
374 */
375 public function send_friend_request( $rest_url, $user_login, $user_url, $display_name, $codeword = 'friends', $message = '' ) {
376 if ( ! is_string( $rest_url ) || ! Friends::check_url( $rest_url ) ) {
377 return new \WP_Error( 'invalid-url', __( 'You entered an invalid URL.', 'friends' ) );
378 }
379
380 $future_in_token = wp_generate_password( 128, false );
381
382 $current_user = wp_get_current_user();
383 $response = wp_safe_remote_post(
384 $rest_url . '/friend-request',
385 array(
386 'body' => array(
387 'version' => 2,
388 'codeword' => $codeword,
389 'name' => $current_user->display_name,
390 'url' => home_url(),
391 'icon_url' => get_avatar_url( $current_user->ID ),
392 'message' => mb_substr( trim( $message ), 0, 2000 ),
393 'key' => $future_in_token,
394 ),
395 'timeout' => 20,
396 'redirection' => 5,
397 )
398 );
399 if ( is_wp_error( $response ) ) {
400 return $response;
401 }
402
403 $json = json_decode( wp_remote_retrieve_body( $response ) );
404 if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
405 if ( $json && isset( $json->code ) && isset( $json->message ) ) {
406 // translators: %s is the message from the other server.
407 return new \WP_Error( $json->code, sprintf( __( 'The other side responded: %s', 'friends' ), $json->message ), $json->data );
408 }
409 }
410
411 if ( ! $json || ! is_object( $json ) ) {
412 return new \WP_Error( 'unexpected-rest-response', 'Unexpected remote response: ' . substr( wp_remote_retrieve_body( $response ), 0, 30 ), $response );
413 }
414
415 $friend_user = User::create( $user_login, 'pending_friend_request', $user_url, $display_name );
416 if ( is_wp_error( $friend_user ) ) {
417 return $friend_user;
418 }
419 $friend_user->update_user_option( 'friends_rest_url', $rest_url );
420
421 if ( isset( $json->request ) ) {
422 update_option( 'friends_request_' . sha1( $json->request ), $friend_user->ID );
423 $friend_user->update_user_option( 'friends_future_in_token_' . sha1( $json->request ), $future_in_token );
424 $friend_user->set_role( 'pending_friend_request' );
425 }
426
427 return $friend_user;
428 }
429
430 /**
431 * Don't show the edit link for friend posts
432 *
433 * @param string $link The edit link.
434 * @param int|User $user The user.
435 * @return string|bool The edit link or false.
436 */
437 public static function admin_edit_user_link( $link, $user ) {
438 if ( ! $user instanceof \WP_User ) {
439 if ( is_string( $user ) ) {
440 $user = User::get_by_username( $user );
441 } else {
442 $user = new \WP_User( $user );
443 }
444 }
445
446 if ( is_multisite() && is_super_admin( $user->ID ) ) {
447 return $link;
448 }
449 if ( ! $user->has_cap( 'friends_plugin' ) ) {
450 return $link;
451 }
452
453 return self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login );
454 }
455
456 public static function get_edit_friend_link( $user ) {
457 if ( ! $user instanceof \WP_User ) {
458 $user = new \WP_User( $user );
459 }
460 return apply_filters( 'get_edit_user_link', $user->user_url, $user->user_login );
461 }
462
463 public static function get_unfriend_link( $user ) {
464 if ( ! $user->has_cap( 'friends_plugin' ) ) {
465 return '';
466 }
467
468 return wp_nonce_url( self_admin_url( 'admin.php?page=unfriend&user=' . $user->user_login ), 'unfriend_' . $user->user_login );
469 }
470
471 /**
472 * Redirect to the Friends page
473 */
474 public function redirect_to_friends_page() {
475 wp_safe_redirect( home_url( '/friends/' ) );
476 exit;
477 }
478
479 /**
480 * Check access for the Friends Admin settings page
481 */
482 public function check_admin_settings() {
483 if ( ! Friends::has_required_privileges() ) {
484 wp_die( esc_html__( 'Sorry, you are not allowed to change the settings.', 'friends' ) );
485 }
486 }
487
488 /**
489 * Process the Friends Admin settings page
490 */
491 public function process_admin_settings() {
492 if ( empty( $_REQUEST ) || ! isset( $_REQUEST['_wpnonce'] ) ) {
493 return;
494 }
495
496 if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'friends-settings' ) ) {
497 return;
498 }
499
500 $this->check_admin_settings();
501 foreach ( array( 'ignore_incoming_friend_requests' ) as $checkbox ) {
502 if ( isset( $_POST[ $checkbox ] ) && $_POST[ $checkbox ] ) {
503 update_option( 'friends_' . $checkbox, true );
504 } else {
505 delete_option( 'friends_' . $checkbox );
506 }
507 }
508
509 foreach ( array( 'friend_request_notification' ) as $negative_user_checkbox ) {
510 if ( isset( $_POST[ $negative_user_checkbox ] ) && $_POST[ $negative_user_checkbox ] ) {
511 delete_user_option( get_current_user_id(), 'friends_no_' . $negative_user_checkbox );
512 } else {
513 update_user_option( get_current_user_id(), 'friends_no_' . $negative_user_checkbox, 1 );
514 }
515 }
516
517 if ( current_user_can( 'manage_options' ) ) {
518 foreach ( array( 'force_enable_post_formats', 'expose_post_format_feeds' ) as $checkbox ) {
519 if ( isset( $_POST[ $checkbox ] ) && $_POST[ $checkbox ] ) {
520 update_option( 'friends_' . $checkbox, true );
521 } else {
522 delete_option( 'friends_' . $checkbox );
523 }
524 }
525
526 if ( isset( $_POST['limit_homepage_post_format'] ) && $_POST['limit_homepage_post_format'] && in_array( $_POST['limit_homepage_post_format'], get_post_format_slugs() ) ) {
527 update_option( 'friends_limit_homepage_post_format', $_POST['limit_homepage_post_format'] );
528 } else {
529 delete_option( 'friends_limit_homepage_post_format' );
530 }
531
532 if ( isset( $_POST['main_user_id'] ) && is_numeric( $_POST['main_user_id'] ) ) {
533 update_option( 'friends_main_user_id', intval( $_POST['main_user_id'] ) );
534 } else {
535 $main_user_id = Friends::get_main_friend_user_id();
536 $main_user_id_exists = false;
537 $users = User_Query::all_admin_users();
538 foreach ( $users->get_results() as $user ) {
539 if ( $user->ID === $main_user_id ) {
540 $main_user_id_exists = true;
541 break;
542 }
543 }
544 if ( ! $main_user_id_exists ) {
545 // Reset the main user id.
546 delete_option( 'friends_main_user_id' );
547 Friends::get_main_friend_user_id();
548 }
549 }
550
551 if ( isset( $_POST['comment_registration'] ) && $_POST['comment_registration'] ) {
552 update_option( 'comment_registration', true );
553 } else {
554 delete_option( 'comment_registration' );
555 }
556
557 if ( isset( $_POST['blocks_everywhere'] ) && $_POST['blocks_everywhere'] ) {
558 update_user_option( get_current_user_id(), 'friends_blocks_everywhere', 1 );
559 } else {
560 delete_user_option( get_current_user_id(), 'friends_blocks_everywhere' );
561 }
562
563 if ( isset( $_POST['comment_registration_message'] ) && $_POST['comment_registration_message'] ) {
564 update_option( 'friends_comment_registration_message', $_POST['comment_registration_message'] );
565 } else {
566 delete_option( 'friends_comment_registration_message' );
567 }
568 }
569
570 if ( isset( $_POST['require_codeword'] ) && $_POST['require_codeword'] ) {
571 update_option( 'friends_require_codeword', true );
572 } else {
573 delete_option( 'friends_require_codeword' );
574 }
575
576 if ( isset( $_POST['codeword'] ) && $_POST['codeword'] ) {
577 update_option( 'friends_codeword', $_POST['codeword'] );
578 } else {
579 delete_option( 'friends_codeword' );
580 }
581
582 if ( isset( $_POST['wrong_codeword_message'] ) && $_POST['wrong_codeword_message'] ) {
583 update_option( 'friends_wrong_codeword_message', $_POST['wrong_codeword_message'] );
584 } else {
585 delete_option( 'friends_wrong_codeword_message' );
586 }
587
588 if ( isset( $_POST['available_emojis'] ) && $_POST['available_emojis'] ) {
589 $available_emojis = array();
590 foreach ( $_POST['available_emojis'] as $id ) {
591 $data = Reactions::get_emoji_data( $id );
592 if ( $data ) {
593 $available_emojis[ $id ] = $data;
594 }
595 }
596 update_option( 'friends_selected_emojis', $available_emojis );
597 } else {
598 delete_option( 'friends_selected_emojis' );
599 }
600
601 if ( isset( $_POST['notification_keywords'] ) && $_POST['notification_keywords'] ) {
602 $keywords = array();
603 foreach ( $_POST['notification_keywords'] as $i => $keyword ) {
604 if ( trim( $keyword ) ) {
605 $keywords[] = array(
606 'enabled' => isset( $_POST['notification_keywords_enabled'][ $i ] ) && $_POST['notification_keywords_enabled'][ $i ],
607 'keyword' => $keyword,
608 );
609 }
610 }
611 update_option( 'friends_notification_keywords', $keywords );
612 }
613
614 if ( isset( $_POST['default_role'] ) && in_array( $_POST['default_role'], array( 'friend', 'acquaintance' ), true ) ) {
615 update_option( 'friends_default_friend_role', $_POST['default_role'] );
616 }
617
618 if ( isset( $_POST['new_post_notification'] ) && $_POST['new_post_notification'] ) {
619 delete_user_option( get_current_user_id(), 'friends_no_new_post_notification' );
620 } else {
621 update_user_option( get_current_user_id(), 'friends_no_new_post_notification', 1 );
622 }
623
624 // Global retention.
625 $retention_number_enabled = boolval( isset( $_POST['friends_enable_retention_number'] ) && $_POST['friends_enable_retention_number'] );
626 update_option( 'friends_enable_retention_number', $retention_number_enabled );
627 if ( $retention_number_enabled ) {
628 update_option( 'friends_retention_number', max( 1, intval( $_POST['friends_retention_number'] ) ) );
629 }
630 $retention_days_enabled = boolval( isset( $_POST['friends_enable_retention_days'] ) && $_POST['friends_enable_retention_days'] );
631 update_option( 'friends_enable_retention_days', $retention_days_enabled );
632 if ( $retention_days_enabled ) {
633 update_option( 'friends_retention_days', max( 1, intval( $_POST['friends_retention_days'] ) ) );
634 }
635
636 if ( isset( $_POST['frontend_default_view'] ) && in_array(
637 $_POST['frontend_default_view'],
638 array(
639 'collapsed',
640 )
641 ) ) {
642 update_option( 'friends_frontend_default_view', $_POST['frontend_default_view'] );
643 } else {
644 delete_option( 'friends_frontend_default_view' );
645 }
646
647 if ( isset( $_GET['_wp_http_referer'] ) ) {
648 wp_safe_redirect( wp_get_referer() );
649 } else {
650 wp_safe_redirect( add_query_arg( 'updated', '1', remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
651 }
652 exit;
653 }
654
655 /**
656 * Gets the frontend locale.
657 *
658 * @return string The frontend locale.
659 */
660 public function get_frontend_locale() {
661 $locale = get_option( 'WPLANG' );
662 return empty( $locale ) ? 'en_US' : $locale;
663 }
664
665 /**
666 * Render the Friends Admin home page
667 */
668 public function render_admin_home() {
669 $friends_subscriptions = User_Query::all_associated_users();
670 $has_friend_users = $friends_subscriptions->get_total() > 0;
671 wp_enqueue_script( 'plugin-install' );
672 add_thickbox();
673 wp_enqueue_script( 'updates' );
674
675 Friends::template_loader()->get_template_part(
676 'admin/settings-header',
677 null,
678 array(
679 'active' => 'friends',
680 'title' => __( 'Friends', 'friends' ),
681 )
682 );
683
684 Friends::template_loader()->get_template_part( 'admin/welcome', null, array( 'installed_plugins' => get_plugins() ) );
685
686 Friends::template_loader()->get_template_part( 'admin/settings-footer' );
687 }
688
689 /**
690 * Render the Friends Admin settings page
691 */
692 public function render_admin_settings() {
693 Friends::template_loader()->get_template_part(
694 'admin/settings-header',
695 null,
696 array(
697 'active' => 'friends-settings',
698 'title' => __( 'Friends', 'friends' ),
699 )
700 );
701 $this->check_admin_settings();
702
703 if ( isset( $_GET['updated'] ) ) {
704 ?>
705 <div id="message" class="updated notice is-dismissible"><p>
706 <?php
707 esc_html_e( 'Your settings were updated.', 'friends' );
708 ?>
709 </p></div>
710 <?php
711 }
712
713 // In order to switch to the frontend locale, we need to first pretend that nothing was loaded yet.
714 global $l10n;
715 $l10n = array();
716
717 switch_to_locale( $this->get_frontend_locale() );
718 // Now while loading the next translations we need to ensure that determine_locale() doesn't return the admin language but the frontend language.
719 add_filter( 'pre_determine_locale', array( $this, 'get_frontend_locale' ) );
720
721 $wrong_codeword_message = __( 'An invalid codeword was provided.', 'friends' );
722 $comment_registration_message = __( 'Only people in my network can comment.', 'friends' );
723 $my_network = __( 'my network', 'friends' );
724 $comment_registration_default = strip_tags(
725 /* translators: %s: Login URL. */
726 __( 'You must be <a href="%s">logged in</a> to post a comment.' ) // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
727 );
728 // Now let's switch back to the admin language.
729 remove_filter( 'pre_determine_locale', array( $this, 'get_frontend_locale' ) );
730 restore_previous_locale();
731 $post_stats = Friends::get_post_stats();
732
733 Friends::template_loader()->get_template_part(
734 'admin/settings',
735 null,
736 array_merge(
737 Friends::get_post_stats(),
738 array(
739 'potential_main_users' => User_Query::all_admin_users(),
740 'main_user_id' => Friends::get_main_friend_user_id(),
741 'friend_roles' => $this->get_friend_roles(),
742 'default_role' => get_option( 'friends_default_friend_role', 'friend' ),
743 'force_enable_post_formats' => get_option( 'friends_force_enable_post_formats' ),
744 'post_format_strings' => get_post_format_strings(),
745 'limit_homepage_post_format' => get_option( 'friends_limit_homepage_post_format', false ),
746 'expose_post_format_feeds' => get_option( 'friends_expose_post_format_feeds' ),
747 'private_rss_key' => get_option( 'friends_private_rss_key' ),
748 'comment_registration' => get_option( 'comment_registration' ), // WordPress option.
749 'comment_registration_message' => get_option( 'friends_comment_registration_message', $comment_registration_message ),
750 'comment_registration_default' => $comment_registration_default,
751 'my_network' => $my_network,
752 'public_profile_link' => home_url( '/friends/' ),
753 'codeword' => get_option( 'friends_codeword', 'friends' ),
754 'require_codeword' => get_option( 'friends_require_codeword' ),
755 'wrong_codeword_message' => get_option( 'friends_wrong_codeword_message', $wrong_codeword_message ),
756 'no_friend_request_notification' => get_user_option( 'friends_no_friend_request_notification' ),
757 'no_new_post_notification' => get_user_option( 'friends_no_new_post_notification' ),
758 'notification_keywords' => Feed::get_all_notification_keywords(),
759 'retention_days' => Friends::get_retention_days(),
760 'retention_number' => Friends::get_retention_number(),
761 'retention_days_enabled' => get_option( 'friends_enable_retention_days' ),
762 'retention_number_enabled' => get_option( 'friends_enable_retention_number' ),
763 'frontend_default_view' => get_option( 'friends_frontend_default_view', 'expanded' ),
764 'blocks_everywhere' => get_user_option( 'friends_blocks_everywhere' ),
765 )
766 )
767 );
768
769 Friends::template_loader()->get_template_part( 'admin/settings-footer' );
770 }
771
772 /**
773 * Process access for the Friends Edit Rules page
774 */
775 private function check_admin_edit_friend_rules() {
776 if ( ! Friends::is_main_user() ) {
777 wp_die( esc_html__( 'Sorry, you are not allowed to edit the rules.', 'friends' ) );
778 }
779
780 if ( ! isset( $_GET['user'] ) ) {
781 wp_die( esc_html__( 'Invalid user.', 'friends' ) );
782 }
783
784 $friend = User::get_by_username( $_GET['user'] );
785 if ( ! $friend || is_wp_error( $friend ) ) {
786 wp_die( esc_html__( 'Invalid username.', 'friends' ) );
787 }
788
789 if (
790 ! $friend->has_cap( 'friend_request' ) &&
791 ! $friend->has_cap( 'pending_friend_request' ) &&
792 ! $friend->has_cap( 'friend' ) &&
793 ! $friend->has_cap( 'subscription' )
794 ) {
795 wp_die( esc_html__( 'This is not a user related to this plugin.', 'friends' ) );
796 }
797
798 return $friend;
799 }
800
801 /**
802 * Process the Friends Edit Rules page
803 */
804 public function process_admin_edit_friend_rules() {
805 $friend = $this->check_admin_edit_friend_rules();
806 $arg = 'updated';
807 $arg_value = 1;
808 if ( isset( $_POST['friend-rules-raw'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'friend-rules-raw-' . $friend->user_login ) ) {
809 $rules = $this->friends->feed->validate_feed_rules( json_decode( stripslashes( $_POST['rules'] ), true ) );
810 if ( false === $rules ) {
811 $arg = 'error';
812 } else {
813 $friend->update_user_option( 'friends_feed_rules', $rules );
814 }
815 } elseif ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'edit-friend-rules-' . $friend->user_login ) ) {
816 $friend->update_user_option( 'friends_feed_catch_all', $this->friends->feed->validate_feed_catch_all( $_POST['catch_all'] ) );
817 $friend->update_user_option( 'friends_feed_rules', $this->friends->feed->validate_feed_rules( $_POST['rules'] ) );
818 } else {
819 return;
820 }
821
822 if ( isset( $_GET['_wp_http_referer'] ) ) {
823 wp_safe_redirect( wp_get_referer() );
824 } else {
825 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
826 }
827 exit;
828 }
829
830 /**
831 * Render the Friends Edit Rules page
832 */
833 public function render_admin_edit_friend_rules() {
834 $friend = $this->check_admin_edit_friend_rules();
835 $catch_all = $friend->get_feed_catch_all();
836 $rules = $friend->get_feed_rules();
837
838 $this->header_edit_friend( $friend, 'edit-friend-rules' );
839
840 if ( isset( $_GET['updated'] ) ) {
841 ?>
842 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Rules were updated.', 'friends' ); ?></p></div>
843 <?php
844 } elseif ( isset( $_GET['error'] ) ) {
845 ?>
846 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
847 <?php
848 }
849
850 $rules = array_values( $rules );
851 $rules[] = array(
852 'field' => 'title',
853 'regex' => '',
854 'action' => in_array( $catch_all, array( 'trash', 'delete' ), true ) ? 'accept' : 'trash',
855 'replace' => '',
856 );
857
858 if ( isset( $_GET['post'] ) && intval( $_GET['post'] ) ) {
859 $post = get_post( intval( $_GET['post'] ) );
860 } else {
861 $post = null;
862 }
863
864 $args = array(
865 'rules' => $rules,
866 'friend' => $friend,
867 'catch_all' => $catch_all,
868 'post' => $post,
869 );
870 Friends::template_loader()->get_template_part( 'admin/edit-rules', null, $args );
871
872 echo '<div id="preview-rules">';
873 $this->render_preview_friend_rules( $rules, $catch_all, $post );
874 echo '</div>';
875
876 array_pop( $args['rules'] );
877 Friends::template_loader()->get_template_part( 'admin/edit-raw-rules', null, $args );
878 }
879
880 /**
881 * Respond to the Ajax request to the Friend rules preview
882 */
883 public function ajax_preview_friend_rules() {
884 if ( ! Friends::has_required_privileges() ) {
885 wp_die( -1 );
886 }
887
888 if ( isset( $_GET['post'] ) && intval( $_GET['post'] ) ) {
889 $post = get_post( intval( $_GET['post'] ) );
890 } else {
891 $post = null;
892 }
893
894 $this->render_preview_friend_rules( $_POST['rules'], $_POST['catch_all'], $post );
895 wp_die( 1 );
896 }
897
898 /**
899 * Respond to the Ajax request to fetch feeds
900 */
901 public function ajax_fetch_feeds() {
902 if ( ! isset( $_POST['friend'] ) ) {
903 wp_send_json_error( 'missing-parameters' );
904 }
905 check_ajax_referer( 'fetch-feeds-' . $_POST['friend'] );
906
907 $friend_user = User::get_by_username( $_POST['friend'] );
908 if ( ! $friend_user ) {
909 wp_send_json_error( 'unknown-user' );
910 }
911
912 $friend_user->retrieve_posts_from_active_feeds();
913
914 wp_send_json_success();
915 }
916
917
918 /**
919 * Respond to the Ajax request to refresh the link token
920 */
921 public function ajax_refresh_link_token() {
922 if ( ! isset( $_POST['url'] ) || ! isset( $_POST['friend'] ) ) {
923 wp_send_json_error( 'missing-parameters' );
924 }
925 $url = $_POST['url'];
926 check_ajax_referer( 'auth-link-' . $url );
927
928 if ( ! friends::has_required_privileges() ) {
929 wp_send_json_error( 'missing-priviledges' );
930 }
931
932 $friend_user = User::get_user( $_POST['friend'] );
933 if ( ! $friend_user ) {
934 wp_send_json_error( 'unknown-user' );
935 }
936
937 wp_send_json_success(
938 array(
939 'success' => true,
940 'data' => array(
941 'token' => $friend_user->get_friend_auth(),
942 ),
943 )
944 );
945 }
946
947 public function render_friends_list() {
948 Friends::template_loader()->get_template_part(
949 'admin/settings-header',
950 null,
951 array(
952 'menu' => array(
953 __( 'Your Friends & Subscriptions', 'friends' ) => 'friends-list',
954 __( 'Your Friend Requests', 'friends' ) => 'friends-list-requests',
955 ),
956 'active' => $_GET['page'],
957 'title' => __( 'Friends', 'friends' ),
958 )
959 );
960
961 if ( isset( $_GET['page'] ) && 'friends-list-requests' === $_GET['page'] ) {
962 echo '<p>';
963 echo wp_kses(
964 sprintf(
965 // translators: %1$s is a URL, %2$s is the translated text "Your Friends & Subscriptions".
966 __( 'These are your current friend requests. To see all your friends and subscriptions, go to <a href="%1$s">%2$s</a>.', 'friends' ),
967 self_admin_url( 'admin.php?page=friends-list' ),
968 __( 'Your Friends & Subscriptions', 'friends' )
969 ),
970 array(
971 'a' => array(
972 'href' => array(),
973 ),
974 )
975 );
976 echo '</p>';
977 $query = User_Query::all_friend_requests();
978 } else {
979 $query = User_Query::all_associated_users();
980 }
981
982 if ( isset( $_GET['deleted'] ) ) {
983 ?>
984 <div id="message" class="updated notice is-dismissible"><p>
985 <?php
986 echo esc_html(
987 sprintf(
988 // translators: % s is a username.
989 __( '%s was deleted.', 'friends' ),
990 $_GET['deleted']
991 )
992 );
993 ?>
994 </p></div>
995 <?php
996 } elseif ( isset( $_GET['error'] ) ) {
997 ?>
998 <div id="message" class="updated error is-dismissible"><p>
999 <?php
1000 esc_html_e( 'An error occurred.', 'friends' );
1001 echo ' ';
1002 echo esc_html( $_GET['error'] );
1003 ?>
1004 </p></div>
1005 <?php
1006 }
1007
1008 Friends::template_loader()->get_template_part(
1009 'admin/friends-list',
1010 null,
1011 array(
1012 'friends' => $query->get_results(),
1013 )
1014 );
1015
1016 Friends::template_loader()->get_template_part( 'admin/settings-footer' );
1017 }
1018
1019 /**
1020 * Render the Friend rules preview
1021 *
1022 * @param array $rules The rules to apply.
1023 * @param string $catch_all The catch all behavior.
1024 * @param \WP_Post $post The post.
1025 */
1026 public function render_preview_friend_rules( $rules, $catch_all, \WP_Post $post = null ) {
1027 $friend = $this->check_admin_edit_friend_rules();
1028 $friend_posts = new \WP_Query();
1029
1030 $friend_posts->set( 'post_type', Friends::CPT );
1031 $friend_posts->set( 'post_status', array( 'publish', 'private', 'trash' ) );
1032 $friend_posts->set( 'posts_per_page', 25 );
1033 $friend_posts = $friend->modify_query_by_author( $friend_posts );
1034
1035 $args = array(
1036 'friend' => $friend,
1037 'friend_posts' => $friend_posts,
1038 'feed' => $this->friends->feed,
1039 'post' => $post,
1040 );
1041
1042 $friend->set_feed_rules( $rules );
1043 $friend->set_feed_catch_all( $catch_all );
1044
1045 Friends::template_loader()->get_template_part( 'admin/preview-rules', null, $args );
1046 }
1047
1048 /**
1049 * Process access for the Friends Edit User page
1050 */
1051 private function check_admin_edit_friend() {
1052 if ( ! friends::has_required_privileges() ) {
1053 wp_die( esc_html__( 'Sorry, you are not allowed to edit this user.' ) ); // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1054 }
1055
1056 if ( ! isset( $_GET['user'] ) ) {
1057 wp_die( esc_html__( 'Invalid user.', 'friends' ) );
1058 }
1059
1060 $friend = User::get_by_username( $_GET['user'] );
1061 if ( ! $friend || is_wp_error( $friend ) ) {
1062 wp_die( esc_html__( 'Invalid username.', 'friends' ) );
1063 }
1064
1065 if ( ! $friend->has_cap( 'friends_plugin' ) ) {
1066 wp_die( esc_html__( 'This is not a user related to this plugin.', 'friends' ) );
1067 }
1068
1069 return $friend;
1070 }
1071
1072 /**
1073 * Process the Friends Edit User page
1074 */
1075 public function process_admin_edit_friend() {
1076 $friend = $this->check_admin_edit_friend();
1077 $arg = 'updated';
1078 $arg_value = 1;
1079
1080 if ( isset( $_GET['convert-to-user'] ) && wp_verify_nonce( $_GET['convert-to-user'], 'convert-to-user-' . $friend->user_login ) ) {
1081 if ( $friend instanceof Subscription ) {
1082 Subscription::convert_to_user( $friend );
1083 }
1084 } elseif ( isset( $_GET['convert-from-user'] ) && wp_verify_nonce( $_GET['convert-from-user'], 'convert-from-user-' . $friend->user_login ) ) {
1085 if ( $friend instanceof User && ! $friend instanceof Subscription ) {
1086 if ( $friend->has_cap( 'friends_plugin' ) && ! $friend->has_cap( 'friend' ) && ! $friend->has_cap( 'pending_friend_request' ) && ! $friend->has_cap( 'friend_request' ) ) {
1087 Subscription::convert_from_user( $friend );
1088 } else {
1089 $arg = 'error';
1090 $arg_value = __( 'A friend cannot be converted to a virtual user.', 'friends' );
1091 }
1092 }
1093 } elseif ( isset( $_GET['accept-friend-request'] ) && wp_verify_nonce( $_GET['accept-friend-request'], 'accept-friend-request-' . $friend->user_login ) ) {
1094 if ( $friend->has_cap( 'friend_request' ) ) {
1095 $friend->set_role( get_option( 'friends_default_friend_role', 'friend' ) );
1096 $arg = 'friend';
1097 }
1098 } elseif ( isset( $_GET['add-friend'] ) && wp_verify_nonce( $_GET['add-friend'], 'add-friend-' . $friend->user_login ) ) {
1099 if ( $friend->has_cap( 'pending_friend_request' ) || $friend->has_cap( 'subscription' ) ) {
1100 $rest_url = $this->friends->rest->discover_rest_url( $friend->user_url );
1101 if ( ! is_wp_error( $rest_url ) ) {
1102 $response = $this->send_friend_request( $rest_url, $friend->user_login, $friend->user_url, $friend->display_name );
1103 } else {
1104 $response = $rest_url;
1105 }
1106
1107 if ( is_wp_error( $response ) ) {
1108 $arg = 'error';
1109 } elseif ( $response instanceof User ) {
1110 if ( $response->has_cap( 'pending_friend_request' ) ) {
1111 $arg = 'sent-request';
1112 // translators: %s is a Site URL.
1113 $arg_value = wp_kses( sprintf( __( 'Friendship requested for site %s.', 'friends' ), $response->get_local_friends_page_url() ), array( 'a' => array( 'href' => array() ) ) );
1114 } elseif ( $response->has_cap( 'friend' ) ) {
1115 $arg = 'friend';
1116 $arg_value = 1;
1117 } elseif ( $response->has_cap( 'subscription' ) ) {
1118 $arg = 'subscribed';
1119 $arg_value = 1;
1120 }
1121 }
1122 }
1123 } elseif ( isset( $_GET['change-to-restricted-friend'] ) && wp_verify_nonce( $_GET['change-to-restricted-friend'], 'change-to-restricted-friend-' . $friend->user_login ) ) {
1124 if ( $friend->has_cap( 'friend' ) ) {
1125 $friend->set_role( 'acquaintance' );
1126 }
1127 } elseif ( isset( $_GET['change-to-friend'] ) && wp_verify_nonce( $_GET['change-to-friend'], 'change-to-friend-' . $friend->user_login ) ) {
1128 if ( $friend->has_cap( 'acquaintance' ) ) {
1129 $friend->set_role( 'friend' );
1130 }
1131 } elseif ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'edit-friend-' . $friend->user_login ) ) {
1132 if ( trim( $_POST['friends_display_name'] ) ) {
1133 $friend->first_name = trim( $_POST['friends_display_name'] );
1134 $friend->display_name = trim( $_POST['friends_display_name'] );
1135 }
1136
1137 $friend->description = trim( $_POST['friends_description'] );
1138 if ( trim( $_POST['user_url'] ) && filter_var( $_POST['user_url'], FILTER_VALIDATE_URL ) ) {
1139 $friend->user_url = $_POST['user_url'];
1140 }
1141 $friend->save();
1142
1143 $hide_from_friends_page = get_user_option( 'friends_hide_from_friends_page' );
1144 if ( ! $hide_from_friends_page ) {
1145 $hide_from_friends_page = array();
1146 }
1147 if ( ! isset( $_POST['show_on_friends_page'] ) || ! $_POST['show_on_friends_page'] ) {
1148 if ( ! in_array( $friend->user_login, $hide_from_friends_page ) ) {
1149 $hide_from_friends_page[] = $friend->user_login;
1150 update_user_option( get_current_user_id(), 'friends_hide_from_friends_page', $hide_from_friends_page );
1151 }
1152 } else {
1153 if ( in_array( $friend->user_login, $hide_from_friends_page ) ) {
1154 $hide_from_friends_page = array_values( array_diff( $hide_from_friends_page, array( $friend->user_login ) ) );
1155 update_user_option( get_current_user_id(), 'friends_hide_from_friends_page', $hide_from_friends_page );
1156 }
1157 }
1158 } else {
1159 return;
1160 }
1161
1162 do_action( 'friends_edit_friend_after_form_submit', $friend );
1163
1164 if ( isset( $_GET['_wp_http_referer'] ) ) {
1165 wp_safe_redirect( add_query_arg( $arg, $arg_value, wp_get_referer() ) );
1166 } else {
1167 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
1168 }
1169 exit;
1170 }
1171
1172 /**
1173 * The Friends Edit User header
1174 *
1175 * @param User $friend The friend.
1176 * @param string $active The active menu entry.
1177 */
1178 public function header_edit_friend( User $friend, $active ) {
1179 $append = '&user=' . $friend->user_login;
1180 Friends::template_loader()->get_template_part(
1181 'admin/settings-header',
1182 null,
1183 array(
1184 'active' => $active . $append,
1185 'title' => $friend->user_login,
1186 'menu' => array(
1187 __( 'Settings' ) => 'edit-friend' . $append, // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1188 __( 'Feeds', 'friends' ) => 'edit-friend-feeds' . $append,
1189 __( 'Notifications', 'friends' ) => 'edit-friend-notifications' . $append,
1190 __( 'Rules', 'friends' ) => 'edit-friend-rules' . $append,
1191 ),
1192 )
1193 );
1194 }
1195
1196 /**
1197 * Render the Friends Edit User page
1198 */
1199 public function render_admin_edit_friend() {
1200 $friend = $this->check_admin_edit_friend();
1201
1202 $args = array_merge(
1203 $friend->get_post_stats(),
1204 array(
1205 'friend' => $friend,
1206 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
1207 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1208 'hide_from_friends_page' => get_user_option( 'friends_hide_from_friends_page' ),
1209 )
1210 );
1211 if ( ! $args['hide_from_friends_page'] ) {
1212 $args['hide_from_friends_page'] = array();
1213 }
1214
1215 $this->header_edit_friend( $friend, 'edit-friend' );
1216
1217 if ( isset( $_GET['updated'] ) ) {
1218 ?>
1219 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'User was updated.', 'friends' ); ?></p></div>
1220 <?php
1221 } elseif ( isset( $_GET['friend'] ) ) {
1222 ?>
1223 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'You are now friends.', 'friends' ); ?></p></div>
1224 <?php
1225 } elseif ( isset( $_GET['error'] ) ) {
1226 ?>
1227 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
1228 <?php
1229 } elseif ( isset( $_GET['sent-request'] ) ) {
1230 ?>
1231 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Your request was sent.', 'friends' ); ?></p></div>
1232 <?php
1233 } elseif ( isset( $_GET['subscribed'] ) ) {
1234 ?>
1235 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Subscription activated.', 'friends' ); ?></p></div>
1236 <?php
1237 }
1238
1239 Friends::template_loader()->get_template_part( 'admin/edit-friend', null, $args );
1240 }
1241
1242 public function ajax_set_avatar() {
1243 $user_id = isset( $_POST['user'] ) ? $_POST['user'] : 0;
1244
1245 check_ajax_referer( "set-avatar-$user_id" );
1246
1247 if ( ! current_user_can( Friends::REQUIRED_ROLE ) ) {
1248 wp_send_json_error();
1249 exit;
1250 }
1251
1252 if ( empty( $_POST['avatar'] ) || ! Friends::check_url( $_POST['avatar'] ) ) {
1253 wp_send_json_error();
1254 exit;
1255 }
1256
1257 $friend = User::get_user_by_id( $user_id );
1258
1259 // Use WordPress functions to check the image dimensions.
1260 $size = \wp_getimagesize( $_POST['avatar'] );
1261 if ( ! $size ) {
1262 wp_send_json_error( __( 'Image is in an unknown format.', 'friends' ) );
1263 exit;
1264 }
1265 // Needs to be square and not larger than 512x512.
1266 if ( $size[0] !== $size[1] || $size[0] > 512 ) {
1267 wp_send_json_error( __( 'Image must be square and not larger than 512x512.', 'friends' ) );
1268 exit;
1269 }
1270
1271 $url = $friend->update_user_icon_url( $_POST['avatar'] );
1272
1273 if ( ! $url || is_wp_error( $url ) ) {
1274 wp_send_json_error( $url );
1275 exit;
1276 }
1277
1278 wp_send_json_success(
1279 array(
1280 'url' => $url,
1281 )
1282 );
1283 }
1284
1285 /**
1286 * Process the Friends Edit Notifications page
1287 */
1288 public function process_admin_edit_friend_notifications() {
1289 $friend = $this->check_admin_edit_friend();
1290 $arg = 'updated';
1291 $arg_value = 1;
1292
1293 if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'edit-friend-notifications-' . $friend->user_login ) ) {
1294 if ( ! get_user_option( 'friends_no_new_post_notification' ) ) {
1295 if ( isset( $_POST['friends_new_post_notification'] ) && $_POST['friends_new_post_notification'] ) {
1296 delete_user_option( get_current_user_id(), 'friends_no_new_post_notification_' . $friend->user_login );
1297 } else {
1298 update_user_option( get_current_user_id(), 'friends_no_new_post_notification_' . $friend->user_login, 1 );
1299 }
1300 }
1301
1302 if ( ! get_user_option( 'friends_no_keyword_notification' ) ) {
1303 if ( isset( $_POST['friends_keyword_notification'] ) && $_POST['friends_keyword_notification'] ) {
1304 delete_user_option( get_current_user_id(), 'friends_no_keyword_notification_' . $friend->user_login );
1305 } else {
1306 update_user_option( get_current_user_id(), 'friends_no_keyword_notification_' . $friend->user_login, 1 );
1307 }
1308 }
1309
1310 do_action( 'friends_edit_friend_notifications_after_form_submit', $friend );
1311 } else {
1312 return;
1313 }
1314
1315 if ( isset( $_GET['_wp_http_referer'] ) ) {
1316 wp_safe_redirect( wp_get_referer() );
1317 } else {
1318 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
1319 }
1320 exit;
1321 }
1322
1323 /**
1324 * Render the Friends Edit Notifications page
1325 */
1326 public function render_admin_edit_friend_notifications() {
1327 $friend = $this->check_admin_edit_friend();
1328 $post_stats = $friend->get_post_stats();
1329
1330 $this->header_edit_friend( $friend, 'edit-friend-notifications' );
1331
1332 if ( isset( $_GET['updated'] ) ) {
1333 ?>
1334 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Notification Settings were updated.', 'friends' ); ?></p></div>
1335 <?php
1336 } elseif ( isset( $_GET['error'] ) ) {
1337 ?>
1338 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
1339 <?php
1340 }
1341
1342 Friends::template_loader()->get_template_part(
1343 'admin/edit-notifications',
1344 null,
1345 array(
1346 'friend' => $friend,
1347 )
1348 );
1349 }
1350
1351 /**
1352 * Process the Friends Edit Feeds page
1353 */
1354 public function process_admin_edit_friend_feeds() {
1355 $friend = $this->check_admin_edit_friend();
1356 $arg = 'updated';
1357 $arg_value = 1;
1358
1359 if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'edit-friend-feeds-' . $friend->user_login ) ) {
1360 $hide_from_friends_page = get_user_option( 'friends_hide_from_friends_page' );
1361 if ( ! $hide_from_friends_page ) {
1362 $hide_from_friends_page = array();
1363 }
1364 if ( ! isset( $_POST['show_on_friends_page'] ) || ! $_POST['show_on_friends_page'] ) {
1365 if ( ! in_array( $friend->user_login, $hide_from_friends_page ) ) {
1366 $hide_from_friends_page[] = $friend->user_login;
1367 update_user_option( get_current_user_id(), 'friends_hide_from_friends_page', $hide_from_friends_page );
1368 }
1369 } else {
1370 if ( in_array( $friend->user_login, $hide_from_friends_page ) ) {
1371 $hide_from_friends_page = array_values( array_diff( $hide_from_friends_page, array( $friend->user_login ) ) );
1372 update_user_option( get_current_user_id(), 'friends_hide_from_friends_page', $hide_from_friends_page );
1373 }
1374 }
1375
1376 if ( $friend->set_retention_number_enabled( isset( $_POST['friends_enable_retention_number'] ) && $_POST['friends_enable_retention_number'] ) ) {
1377 $friend->set_retention_number( $_POST['friends_retention_number'] );
1378 }
1379 if ( $friend->set_retention_days_enabled( isset( $_POST['friends_enable_retention_days'] ) && $_POST['friends_enable_retention_days'] ) ) {
1380 $friend->set_retention_days( $_POST['friends_retention_days'] );
1381 }
1382
1383 $hide_from_friends_page = get_user_option( 'friends_hide_from_friends_page' );
1384 if ( ! $hide_from_friends_page ) {
1385 $hide_from_friends_page = array();
1386 }
1387
1388 if ( isset( $_POST['feeds'] ) ) {
1389 $existing_feeds = $friend->get_feeds();
1390 if ( '' === trim( $_POST['feeds']['new']['url'] ) ) {
1391 unset( $_POST['feeds']['new'] );
1392 } else {
1393 foreach ( $existing_feeds as $term_id => $user_feed ) {
1394 if ( $user_feed->get_url() === trim( $_POST['feeds']['new']['url'] ) ) {
1395 if ( isset( $_POST['feeds'][ $term_id ] ) ) {
1396 // Let a newly entered feed overrule an existing one.
1397 $_POST['feeds'][ $term_id ] = array_merge( $_POST['feeds'][ $term_id ], $_POST['feeds']['new'] );
1398 $_POST['feeds'][ $term_id ]['active'] = 1;
1399 }
1400 unset( $_POST['feeds']['new'] );
1401 break;
1402 }
1403 }
1404 }
1405 foreach ( $_POST['feeds'] as $term_id => $feed ) {
1406 if ( 'new' === $term_id ) {
1407 if ( '' === trim( $feed['url'] ) ) {
1408 continue;
1409 }
1410
1411 $feed['active'] = true;
1412 $protocol = wp_parse_url( $feed['url'], PHP_URL_SCHEME );
1413 if ( ! $protocol ) {
1414 $feed['url'] = apply_filters( 'friends_rewrite_incoming_url', 'https://' . $feed['url'], $feed['url'] );
1415 }
1416 $new_feed = $friend->subscribe( $feed['url'], $feed );
1417 if ( is_wp_error( $new_feed ) ) {
1418 do_action( 'friends_process_feed_item_submit_error', $new_feed, $feed );
1419 continue;
1420 }
1421
1422 do_action( 'friends_user_feed_activated', $new_feed );
1423 do_action( 'friends_process_feed_item_submit', $new_feed, $feed );
1424 continue;
1425 }
1426
1427 if ( ! isset( $existing_feeds[ $term_id ] ) ) {
1428 continue;
1429 }
1430 $user_feed = $existing_feeds[ $term_id ];
1431 unset( $existing_feeds[ $term_id ] );
1432
1433 $protocol = wp_parse_url( $feed['url'], PHP_URL_SCHEME );
1434 if ( ! $protocol ) {
1435 $feed['url'] = apply_filters( 'friends_rewrite_incoming_url', 'https://' . $feed['url'], $feed['url'] );
1436 }
1437
1438 if ( $user_feed->get_url() !== $feed['url'] ) {
1439 do_action( 'friends_user_feed_deactivated', $user_feed );
1440
1441 if ( ! isset( $feed['mime-type'] ) ) {
1442 $feed['mime-type'] = $user_feed->get_mime_type();
1443 }
1444
1445 if ( $feed['active'] ) {
1446 $new_feed = $friend->subscribe( $feed['url'], $feed );
1447 if ( ! is_wp_error( $new_feed ) ) {
1448 do_action( 'friends_user_feed_activated', $new_feed );
1449 }
1450 } else {
1451 $new_feed = $friend->save_feed( $feed['url'], $feed );
1452 }
1453
1454 // Since the URL has changed, the above will create a new feed, therefore we need to delete the old one.
1455 $user_feed->delete();
1456
1457 if ( is_wp_error( $new_feed ) ) {
1458 do_action( 'friends_process_feed_item_submit_error', $new_feed, $feed );
1459 continue;
1460 }
1461
1462 do_action( 'friends_process_feed_item_submit', $new_feed, $feed );
1463 continue;
1464 }
1465
1466 if ( $user_feed->get_title() !== $feed['title'] ) {
1467 $user_feed->update_metadata( 'title', $feed['title'] );
1468 }
1469
1470 if ( $user_feed->get_parser() !== $feed['parser'] ) {
1471 $user_feed->update_metadata( 'parser', $feed['parser'] );
1472 }
1473
1474 if ( $user_feed->get_post_format() !== $feed['post-format'] ) {
1475 $user_feed->update_metadata( 'post-format', $feed['post-format'] );
1476 }
1477
1478 if ( isset( $feed['mime-type'] ) && $user_feed->get_mime_type() !== $feed['mime-type'] ) {
1479 $user_feed->update_metadata( 'mime-type', $feed['mime-type'] );
1480 }
1481
1482 $was_active = $user_feed->is_active();
1483 $is_active = isset( $feed['active'] ) && $feed['active'];
1484 $user_feed->update_metadata( 'active', $is_active );
1485 if ( $was_active !== $is_active ) {
1486 if ( $is_active ) {
1487 do_action( 'friends_user_feed_activated', $user_feed );
1488 } else {
1489 do_action( 'friends_user_feed_deactivated', $user_feed );
1490 }
1491 }
1492
1493 do_action( 'friends_process_feed_item_submit', $user_feed, $feed );
1494 }
1495
1496 // Delete remaining existing feeds since they were not submitted.
1497 foreach ( $existing_feeds as $term_id => $user_feed ) {
1498 do_action( 'friends_user_feed_deactivated', $user_feed );
1499 $user_feed->delete();
1500 }
1501 }
1502 do_action( 'friends_edit_feeds_after_form_submit', $friend );
1503 } else {
1504 return;
1505 }
1506
1507 if ( isset( $_GET['_wp_http_referer'] ) ) {
1508 wp_safe_redirect( wp_get_referer() );
1509 } else {
1510 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
1511 }
1512 exit;
1513 }
1514
1515 /**
1516 * Render the Friends Edit Feeds page
1517 */
1518 public function render_admin_edit_friend_feeds() {
1519 $friend = $this->check_admin_edit_friend();
1520
1521 $args = array_merge(
1522 $friend->get_post_stats(),
1523 array(
1524 'friend' => $friend,
1525 'rules' => $friend->get_feed_rules(),
1526 'hide_from_friends_page' => get_user_option( 'friends_hide_from_friends_page' ),
1527 'post_formats' => array_merge( array( 'autodetect' => __( 'Autodetect Post Format', 'friends' ) ), get_post_format_strings() ),
1528 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
1529 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1530 'global_retention_days' => Friends::get_retention_days(),
1531 'global_retention_number' => Friends::get_retention_number(),
1532 'global_retention_days_enabled' => get_option( 'friends_enable_retention_days' ),
1533 'global_retention_number_enabled' => get_option( 'friends_enable_retention_number' ),
1534 )
1535 );
1536 if ( ! $args['hide_from_friends_page'] ) {
1537 $args['hide_from_friends_page'] = array();
1538 }
1539 $this->header_edit_friend( $friend, 'edit-friend-feeds' );
1540
1541 if ( isset( $_GET['updated'] ) ) {
1542 ?>
1543 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Feeds were updated.', 'friends' ); ?></p></div>
1544 <?php
1545 } elseif ( isset( $_GET['error'] ) ) {
1546 ?>
1547 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
1548 <?php
1549 }
1550
1551 Friends::template_loader()->get_template_part( 'admin/edit-feeds', null, $args );
1552 }
1553
1554 /**
1555 * Process the Unfriend page
1556 */
1557 public function process_admin_unfriend() {
1558 $friend = $this->check_admin_edit_friend();
1559 $arg = 'deleted';
1560 $arg_value = $friend->user_login;
1561
1562 if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'unfriend-' . $friend->user_login ) ) {
1563 $friend->delete();
1564 } else {
1565 return;
1566 }
1567
1568 if ( isset( $_GET['_wp_http_referer'] ) ) {
1569 wp_safe_redirect( wp_get_referer() );
1570 } else {
1571 wp_safe_redirect( add_query_arg( $arg, $arg_value, self_admin_url( 'admin.php?page=friends-list' ) ) );
1572 }
1573 exit;
1574 }
1575
1576 /**
1577 * Render the Unfriend page
1578 */
1579 public function render_admin_unfriend() {
1580 $friend = $this->check_admin_edit_friend();
1581 $post_stats = $friend->get_post_stats();
1582
1583 $args = array(
1584 'friend' => $friend,
1585 'friend_posts' => $post_stats['post_count'],
1586 'total_size' => $post_stats['total_size'],
1587 );
1588
1589 Friends::template_loader()->get_template_part( 'admin/unfriend', null, $args );
1590 }
1591
1592 /**
1593 * Display error messages.
1594 *
1595 * @param object $errors The errors.
1596 */
1597 private function display_errors( $errors ) {
1598 if ( ! is_wp_error( $errors ) ) {
1599 return;
1600 }
1601
1602 ?>
1603 <div id="message" class="updated error is-dismissible"><p><?php echo esc_html( $errors->get_error_message() ); ?></p>
1604 <?php
1605 $error_data = $errors->get_error_data();
1606 if ( isset( $error_data->error ) ) {
1607 $error = unserialize( $error_data->error );
1608 if ( is_wp_error( $error ) ) {
1609 ?>
1610 <pre>
1611 <?php
1612 print_r( $error );
1613 ?>
1614 </pre>
1615 <?php
1616 } elseif ( is_array( $error ) && isset( $error['body'] ) ) {
1617 ?>
1618 <textarea>
1619 <?php
1620 echo esc_html( $error['body'] );
1621 ?>
1622 </textarea>
1623 <?php
1624 }
1625 }
1626 ?>
1627 </div>
1628 <?php
1629 }
1630
1631 public function create_and_follow( $user_id, $url, $type, $vars = array() ) {
1632 $vars['friend_url'] = $url;
1633
1634 $vars['user_login'] = apply_filters( 'friends_suggest_user_login', User::get_user_login_for_url( $url ), $url );
1635 if ( empty( $vars['display_name'] ) ) {
1636 $vars['display_name'] = apply_filters( 'friends_suggest_display_name', User::get_display_name_for_url( $url ), $url );
1637 }
1638
1639 $vars['step2'] = true;
1640
1641 $vars['subscribe'] = array( $url );
1642 $vars['feeds'] = $this->friends->feed->discover_available_feeds( $url );
1643
1644 ob_start();
1645 $ret = $this->process_admin_add_friend( $vars );
1646 ob_end_clean();
1647
1648 if ( is_wp_error( $ret ) ) {
1649 return $ret;
1650 }
1651
1652 $friend_user = User::get_by_username( $vars['user_login'] );
1653 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1654 return new \WP_Error( 'friend_not_created', __( 'Friend could not be created.', 'friends' ) );
1655 }
1656
1657 return $friend_user->ID;
1658 }
1659
1660 /**
1661 * Previous process the Add Friend form. Todo: re-integrate.
1662 *
1663 * @param User $friend_user The Friend user.
1664 * @param array $vars The variables from the admin
1665 * submission.
1666 *
1667 * @return boolean true when there was no error.
1668 */
1669 public function process_admin_add_friend_response( $friend_user, $vars ) {
1670 if ( is_wp_error( $friend_user ) ) {
1671 $this->display_errors( $friend_user );
1672 return false;
1673 }
1674
1675 if ( ! $friend_user instanceof User ) {
1676 ?>
1677 <div id="message" class="updated notice is-dismissible"><p>
1678 <?php
1679 // translators: %s is a username.
1680 esc_html_e( 'Unknown error', 'friends' );
1681 ?>
1682 </p></div>
1683 <?php
1684 return false;
1685 }
1686
1687 $feed_options = array();
1688 if ( ! isset( $vars['feeds'] ) ) {
1689 $vars['feeds'] = array();
1690 }
1691 foreach ( $vars['feeds'] as $feed ) {
1692 if ( isset( $feed['type'] ) ) {
1693 $feed['mime-type'] = $feed['type'];
1694 unset( $feed['type'] );
1695 }
1696 $feed_options[ $feed['url'] ] = $feed;
1697 }
1698
1699 // Save the all feeds for possible later activation.
1700 $friend_user->save_feeds( $feed_options );
1701
1702 if ( ! isset( $vars['subscribe'] ) ) {
1703 $vars['subscribe'] = array();
1704 }
1705
1706 $count = 0;
1707 foreach ( $vars['subscribe'] as $feed_url ) {
1708 if ( ! isset( $feed_options[ $feed_url ] ) ) {
1709 continue;
1710 }
1711 $new_feed = $friend_user->subscribe( $feed_url, $feed_options[ $feed_url ] );
1712 if ( ! is_wp_error( $new_feed ) ) {
1713 do_action( 'friends_user_feed_activated', $new_feed );
1714 $count += 1;
1715 }
1716 }
1717
1718 add_filter( 'notify_about_new_friend_post', '__return_false', 999 );
1719
1720 wp_schedule_single_event( time(), 'friends_retrieve_user_feeds', array( $friend_user->ID ) );
1721
1722 if ( isset( $vars['errors'] ) ) {
1723 $this->display_errors( $vars['errors'] );
1724 }
1725
1726 $friend_link = '<a href="' . esc_url( $this->admin_edit_user_link( $friend_user->get_local_friends_page_url(), $friend_user ) ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $friend_user->display_name ) . '</a>';
1727 $message = false;
1728
1729 if ( $friend_user->has_cap( 'pending_friend_request' ) ) {
1730 // translators: %s is a Site URL.
1731 $message = sprintf( __( 'Friendship requested for site %s.', 'friends' ), $friend_link );
1732 $message .= ' ' . sprintf( __( 'Until they respond, we have already subscribed you to their updates.', 'friends' ), $friend_link );
1733 } elseif ( $friend_user->has_cap( 'friend' ) ) {
1734 // translators: %s is a Site URL.
1735 $message = sprintf( __( "You're now a friend of site %s.", 'friends' ), $friend_link );
1736 // translators: %s is the friends page URL.
1737 } elseif ( $friend_user->has_cap( 'subscription' ) ) {
1738 if ( isset( $vars['friendship'] ) ) {
1739 // translators: %s is a Site URL.
1740 $message = sprintf( __( 'No friends plugin installed at %s.', 'friends' ), $friend_link );
1741 $message .= ' ' . esc_html__( 'We subscribed you to their updates.', 'friends' );
1742 } else {
1743 // translators: %s is a Site URL.
1744 $message = sprintf( __( "You're now subscribed to %s.", 'friends' ), $friend_link );
1745 }
1746 }
1747
1748 if ( $message ) {
1749 ?>
1750 <div id="message" class="updated notice is-dismissible"><p>
1751 <?php
1752 echo wp_kses( $message, array( 'a' => array( 'href' => array() ) ) );
1753 // translators: %s is the friends page URL.
1754 echo ' ', wp_kses( sprintf( __( 'Go to your <a href=%s>friends page</a> to view their posts.', 'friends' ), '"' . esc_url( $friend_user->get_local_friends_page_url() ) . '"' ), array( 'a' => array( 'href' => array() ) ) );
1755 echo ' <span id="fetch-feeds" data-nonce="', esc_attr( wp_create_nonce( 'fetch-feeds-' . $friend_user->user_login ) ), '" data-friend=', esc_attr( $friend_user->user_login ), '>', __( 'Fetching feeds...', 'friends' ), '</span>';
1756 ?>
1757 </p></div>
1758 <?php
1759 return true;
1760 }
1761
1762 ?>
1763 <div id="message" class="updated notice is-dismissible"><p>
1764 <?php
1765 // translators: %s is a username.
1766 echo esc_html( sprintf( __( 'User %s could not be assigned the appropriate role.', 'friends' ), $friend_user->display_name ) );
1767 ?>
1768 </p></div>
1769 <?php
1770 return false;
1771 }
1772
1773 /**
1774 * Process the Add Friend form.
1775 *
1776 * @param array $vars The POST or GET variables.
1777 *
1778 * @return boolean A \WP_Error or void.
1779 */
1780 public function process_admin_add_friend( $vars ) {
1781 $errors = new \WP_Error();
1782 $args = array();
1783
1784 $friend_url = isset( $vars['friend_url'] ) ? trim( $vars['friend_url'] ) : '';
1785 $codeword = isset( $vars['codeword'] ) ? trim( $vars['codeword'] ) : '';
1786 $message = isset( $vars['message'] ) ? trim( $vars['message'] ) : '';
1787
1788 $friends_plugin = false;
1789 $friend_user = false;
1790
1791 $protocol = wp_parse_url( $friend_url, PHP_URL_SCHEME );
1792 if ( ! $protocol ) {
1793 // Allow adding a friend by username.
1794 if ( is_multisite() ) {
1795 $friend_user = get_user_by( 'login', $friend_url );
1796 if ( $friend_user ) {
1797 $site = get_active_blog_for_user( $friend_user->ID );
1798 // Ensure we're using the same URL protocol.
1799 $friend_url = set_url_scheme( $site->siteurl );
1800 }
1801 }
1802
1803 // If unsuccessful, then the protocol was forgotten.
1804 if ( ! $friend_user ) {
1805 $friend_url = apply_filters( 'friends_rewrite_incoming_url', 'https://' . $friend_url, $friend_url );
1806 }
1807 }
1808 $friend_user_login = apply_filters( 'friends_suggest_user_login', User::get_user_login_for_url( $friend_url ), $friend_url );
1809 $friend_display_name = apply_filters( 'friends_suggest_display_name', User::get_display_name_for_url( $friend_url ), $friend_url );
1810
1811 $friend_user = get_user_by( 'login', $friend_user_login );
1812
1813 if ( $friend_user ) {
1814 $args['friends_multisite_user_login'] = $friend_user_login;
1815 $args['friends_multisite_display_name'] = $friend_display_name;
1816 }
1817 $rest_url = false;
1818
1819 if ( ( isset( $vars['step2'] ) && isset( $vars['feeds'] ) && is_array( $vars['feeds'] ) ) || isset( $vars['step3'] ) ) {
1820 $friend_user_login = str_replace( ' ', '-', sanitize_user( $vars['user_login'] ) );
1821 $friend_display_name = sanitize_text_field( $vars['display_name'] );
1822 if ( ! $friend_user_login ) {
1823 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1824 $errors->add( 'user_login', __( '<strong>Error</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
1825 } elseif ( ! is_multisite() && username_exists( $friend_user_login ) ) {
1826 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1827 $errors->add( 'user_login', __( '<strong>Error</strong>: This username is already registered. Please choose another one.' ) );
1828 }
1829
1830 $feeds = $vars['feeds'];
1831 if ( ! $errors->has_errors() ) {
1832 $friend_user = false;
1833 if ( isset( $vars['friendship'] ) ) {
1834 $friend_user = $this->send_friend_request( $vars['friendship'], $friend_user_login, $friend_url, $friend_display_name, $codeword, $message );
1835 if ( $friend_user->has_errors() ) {
1836 $vars['errors'] = $friend_user;
1837 }
1838 }
1839
1840 $avatar = null;
1841 $description = null;
1842 foreach ( $feeds as $feed_details ) {
1843 if ( ! $avatar && ! empty( $feed_details['avatar'] ) ) {
1844 $avatar = $feed_details['avatar'];
1845 }
1846 if ( ! $description && ! empty( $feed_details['description'] ) ) {
1847 $description = $feed_details['description'];
1848 }
1849 }
1850
1851 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1852 $friend_user = User::create( $friend_user_login, 'subscription', $friend_url, $friend_display_name, $avatar, $description );
1853 }
1854
1855 return $this->process_admin_add_friend_response( $friend_user, $vars );
1856 }
1857
1858 if ( isset( $vars['friendship'] ) ) {
1859 $rest_url = $vars['friendship'];
1860 } else {
1861 $rest_url = $this->friends->rest->get_friends_rest_url( $feeds );
1862 }
1863 } else {
1864 if ( home_url() === trailingslashit( $friend_url ) ) {
1865 return new \WP_Error( 'friend-yourself', __( 'It seems like you sent a friend request to yourself.', 'friends' ) );
1866 }
1867
1868 if ( ! Friends::check_url( $friend_url ) ) {
1869 return new \WP_Error( 'invalid-url', __( 'You entered an invalid URL.', 'friends' ) );
1870 }
1871
1872 $friend_user = User::get_user( $friend_user_login );
1873 if ( $friend_user && ! is_wp_error( $friend_user ) ) {
1874 if ( $friend_user->is_valid_friend() ) {
1875 return new \WP_Error( 'already-friend', __( 'You are already friends with this site.', 'friends' ) );
1876 }
1877
1878 // translators: %s is the name of a friend / site.
1879 return new \WP_Error( 'already-subscribed', sprintf( __( 'You are already subscribed to this site: %s', 'friends' ), '<a href="' . esc_url( $this->admin_edit_user_link( $friend_user->get_local_friends_page_url(), $friend_user ) ) . '">' . esc_html( $friend_user->display_name ) . '</a>' ) );
1880 }
1881
1882 $feeds = $this->friends->feed->discover_available_feeds( $friend_url );
1883 if ( is_wp_error( $feeds ) ) {
1884 return $feeds;
1885 }
1886 if ( ! $feeds ) {
1887 return new \WP_Error( 'no-feed-found', __( 'No suitable feed was found at the provided address.', 'friends' ) );
1888 }
1889
1890 $better_display_name = User::get_display_name_from_feeds( $feeds );
1891 if ( $better_display_name ) {
1892 $friend_display_name = $better_display_name;
1893 }
1894
1895 $rest_url = $this->friends->rest->get_friends_rest_url( $feeds );
1896 }
1897
1898 if ( $rest_url ) {
1899 $friends_plugin = $rest_url;
1900 unset( $feeds[ $rest_url ] );
1901 }
1902
1903 if ( isset( $vars['quick-subscribe'] ) ) {
1904 $vars['feeds'] = $feeds;
1905 $vars['subscribe'] = array();
1906 foreach ( $feeds as $feed_url => $details ) {
1907 if ( isset( $details['autoselect'] ) && $details['autoselect'] ) {
1908 $vars['subscribe'][] = $feed_url;
1909 }
1910 }
1911
1912 $friend_user = false;
1913 if ( isset( $rest_url ) ) {
1914 $friend_user = $this->send_friend_request( $rest_url, $friend_user_login, $friend_url, $friend_display_name, $codeword, $message );
1915 }
1916
1917 $avatar = null;
1918 $description = null;
1919 foreach ( $feeds as $feed_details ) {
1920 if ( ! $avatar && ! empty( $feed_details['avatar'] ) ) {
1921 $avatar = $feed_details['avatar'];
1922 }
1923 if ( ! $description && ! empty( $feed_details['description'] ) ) {
1924 $description = $feed_details['description'];
1925 }
1926 }
1927
1928 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1929 $friend_user = User::create( $friend_user_login, 'subscription', $friend_url, $friend_display_name, $avatar, $description );
1930 }
1931
1932 return $this->process_admin_add_friend_response( $friend_user, $vars );
1933 }
1934
1935 Friends::template_loader()->get_template_part(
1936 'admin/settings-header',
1937 null,
1938 array(
1939 'active' => 'add-friend-confirm',
1940 'title' => __( 'Add New Friend', 'friends' ),
1941 'menu' => array(
1942 '1. ' . __( 'Enter Details', 'friends' ) => 'add-friend' . ( isset( $friend_url ) ? '&url=' . urlencode( $friend_url ) : '' ),
1943 '2. ' . __( 'Confirm', 'friends' ) => 'add-friend-confirm',
1944 ),
1945 )
1946 );
1947
1948 if ( $errors->has_errors() ) {
1949 ?>
1950 <div id="message" class="updated notice is-dismissible"><p><?php echo wp_kses( $errors->get_error_message(), array( 'strong' => array() ) ); ?></p>
1951 </div>
1952 <?php
1953 }
1954
1955 Friends::template_loader()->get_template_part(
1956 'admin/select-feeds',
1957 null,
1958 array_merge(
1959 $args,
1960 array(
1961 'friends_plugin' => $friends_plugin,
1962 'friend_url' => $friend_url,
1963 'friend_user_login' => $friend_user_login,
1964 'friend_display_name' => $friend_display_name,
1965 'friend_roles' => $this->get_friend_roles(),
1966 'default_role' => get_option( 'friends_default_friend_role', 'friend' ),
1967 'codeword' => $codeword,
1968 'message' => $message,
1969 'post_formats' => array_merge( array( 'autodetect' => __( 'Autodetect Post Format', 'friends' ) ), get_post_format_strings() ),
1970 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1971 'feeds' => $feeds,
1972 )
1973 )
1974 );
1975 }
1976
1977 /**
1978 * Render the admin form for sending a friend request.
1979 */
1980 public function render_admin_add_friend() {
1981 if ( ! friends::has_required_privileges() ) {
1982 wp_die( esc_html__( 'Sorry, you are not allowed to add friends.', 'friends' ) );
1983 }
1984
1985 if ( ! empty( $_GET['preview'] ) ) {
1986 $url = $_GET['preview'];
1987
1988 ?>
1989 <h1>
1990 <?php
1991 // translators: %s is a URL.
1992 echo esc_html( sprintf( __( 'Preview for %s', 'friends' ), $url ) );
1993 ?>
1994 </h1>
1995 <?php
1996
1997 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'preview-feed' ) ) {
1998 ?>
1999 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'For security reasons, this preview is not available.', 'friends' ); ?></p>
2000 </div>
2001 <?php
2002 exit;
2003 }
2004
2005 $parser_name = $this->friends->feed->get_registered_parser( $_GET['parser'] );
2006 if ( ! $parser_name ) {
2007 ?>
2008 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'An unknown parser name was supplied.', 'friends' ); ?></p>
2009 </div>
2010 <?php
2011 exit;
2012 }
2013 ?>
2014 <h3><?php esc_html_e( 'Parser Details', 'friends' ); ?></h3>
2015 <ul id="parser">
2016 <li>
2017 <?php
2018 echo wp_kses(
2019 // translators: %s is the name of a parser, e.g. simplepie.
2020 sprintf( __( 'Parser: %s', 'friends' ), $parser_name ),
2021 array(
2022 'a' => array(
2023 'href' => array(),
2024 'rel' => array(),
2025 'target' => array(),
2026 ),
2027 )
2028 );
2029 ?>
2030 </li>
2031 </ul>
2032 <h3><?php esc_html_e( 'Items in the Feed', 'friends' ); ?></h3>
2033
2034 <?php
2035
2036 $items = $this->friends->feed->preview( $_GET['parser'], $url, isset( $_GET['feed'] ) ? intval( $_GET['feed'] ) : null );
2037 if ( is_wp_error( $items ) ) {
2038 ?>
2039 <div id="message" class="updated notice is-dismissible"><p><?php echo esc_html( $items->get_error_message() ); ?></p>
2040 </div>
2041 <?php
2042 exit;
2043 }
2044 ?>
2045
2046 <ul>
2047 <?php
2048 foreach ( $items as $item ) {
2049 $title = $item->title;
2050 if ( 'status' === $item->post_format ) {
2051 $title = strip_tags( $item->content );
2052 }
2053 ?>
2054 <li><a href="<?php echo esc_url( $item->permalink ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $item->date ); ?></a> (author: <?php echo esc_html( $item->author ); ?>, type: <?php echo esc_html( $item->post_format ); ?>):
2055 <?php if ( $title ) : ?>
2056 <a href="<?php echo esc_url( $item->permalink ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $title ); ?></a> <?php echo esc_html( str_word_count( wp_strip_all_tags( $item->content ) ) ); ?> words
2057 <?php else : ?>
2058 <p>
2059 <?php
2060 echo wp_kses(
2061 wp_trim_excerpt( $item->content ),
2062 array(
2063 'a' => array( 'href' => array() ),
2064 'img' => array( 'src' => array() ),
2065 )
2066 );
2067 ?>
2068 </p>
2069 <?php endif; ?>
2070 </li>
2071 <?php
2072 }
2073 ?>
2074 </ul>
2075 <?php
2076 return;
2077 }
2078
2079 if ( apply_filters( 'friends_debug', false ) && isset( $_GET['next'] ) ) {
2080 $_POST = $_REQUEST;
2081 $_POST['_wpnonce'] = wp_create_nonce( 'add-friend' );
2082 if ( ! empty( $_POST['url'] ) && ! isset( $_POST['friend_url'] ) ) {
2083 $_POST['friend_url'] = $_POST['url'];
2084 $parsed_url = parse_url( $_POST['friend_url'] );
2085 if ( isset( $parsed_url['host'] ) ) {
2086 if ( ! isset( $parsed_url['scheme'] ) ) {
2087 $_POST['friend_url'] = 'https://' . ltrim( $_POST['friend_url'], '/' );
2088 }
2089 }
2090 }
2091 }
2092
2093 $response = null;
2094 $postdata = apply_filters( 'friends_add_friend_postdata', $_POST );
2095 if ( ! empty( $postdata ) ) {
2096 if ( ! wp_verify_nonce( $postdata['_wpnonce'], 'add-friend' ) ) {
2097 $response = new \WP_Error( 'invalid-nonce', __( 'For security reasons, please verify the URL and click next if you want to proceed.', 'friends' ) );
2098 } else {
2099 $response = $this->process_admin_add_friend( $postdata );
2100 }
2101 if ( is_wp_error( $response ) ) {
2102 ?>
2103 <div id="message" class="updated notice is-dismissible"><p>
2104 <?php
2105 $message = $response->get_error_message();
2106 if ( $response->get_error_data() ) {
2107 $message .= ' (' . $response->get_error_data() . ')';
2108 }
2109 echo wp_kses(
2110 $message,
2111 array(
2112 'strong' => array(),
2113 'a' => array(
2114 'href' => array(),
2115 'rel' => array(),
2116 'target' => array(),
2117 ),
2118 )
2119 );
2120 ?>
2121 </p>
2122 </div>
2123 <?php
2124 }
2125 if ( is_null( $response ) ) {
2126 return;
2127 }
2128 }
2129
2130 $args = array(
2131 'friend_url' => '',
2132 'add-friends-placeholder' => apply_filters( 'friends_add_friends_input_placeholder', __( 'Enter URL', 'friends' ) ),
2133 );
2134
2135 if ( ! empty( $_GET['url'] ) || ! empty( $_POST['url'] ) ) {
2136 $friend_url = isset( $_GET['url'] ) ? $_GET['url'] : $_POST['url'];
2137 $parsed_url = parse_url( $friend_url );
2138 if ( isset( $parsed_url['host'] ) ) {
2139 if ( ! isset( $parsed_url['scheme'] ) ) {
2140 $args['friend_url'] = apply_filters( 'friends_rewrite_incoming_url', 'https://' . ltrim( $friend_url, '/' ), $friend_url, $parsed_url );
2141 } else {
2142 $args['friend_url'] = $friend_url;
2143 }
2144 } elseif ( preg_match( '/^@?' . Feed_Parser_ActivityPub::ACTIVITYPUB_USERNAME_REGEXP . '$/i', $friend_url ) ) {
2145 $args['friend_url'] = $friend_url;
2146 }
2147 }
2148
2149 Friends::template_loader()->get_template_part(
2150 'admin/settings-header',
2151 null,
2152 array(
2153 'active' => 'add-friend',
2154 'title' => __( 'Add New Friend', 'friends' ),
2155 'menu' => array(
2156 '1. ' . __( 'Enter Details', 'friends' ) => 'add-friend' . ( isset( $friend_url ) ? '&url=' . urlencode( $friend_url ) : '' ),
2157 '2. ' . __( 'Confirm', 'friends' ) => false,
2158 ),
2159 )
2160 );
2161
2162 Friends::template_loader()->get_template_part( 'admin/add-friend', null, $args );
2163
2164 Friends::template_loader()->get_template_part(
2165 'admin/latest-friends',
2166 null,
2167 array(
2168 'friend_requests' => User_Query::recent_friends_subscriptions( 25 )->get_results(),
2169 )
2170 );
2171 Friends::template_loader()->get_template_part( 'admin/settings-footer', null, $args );
2172 }
2173
2174 /**
2175 * Process the admin notification manager form submission.
2176 */
2177 public function process_admin_notification_manager() {
2178
2179 if ( empty( $_POST ) || empty( $_POST['friend_listed'] ) ) {
2180 return;
2181 }
2182
2183 if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'notification-manager' ) ) {
2184 return;
2185 }
2186
2187 $this->check_admin_settings();
2188 $friend_ids = $_POST['friend_listed'];
2189 $current_user_id = get_current_user_id();
2190 $hide_from_friends_page = array();
2191
2192 foreach ( $friend_ids as $friend_id ) {
2193 if ( ! isset( $_POST['show_on_friends_page'][ $friend_id ] ) ) {
2194 $hide_from_friends_page[] = $friend_id;
2195 }
2196
2197 $no_new_post_notification = ! isset( $_POST['new_post_notification'][ $friend_id ] );
2198 if ( get_user_option( 'friends_no_new_post_notification_' . $friend_id ) !== $no_new_post_notification ) {
2199 update_user_option( $current_user_id, 'friends_no_new_post_notification_' . $friend_id, $no_new_post_notification );
2200 }
2201
2202 $no_keyword_notification = ! isset( $_POST['keyword_notification'][ $friend_id ] );
2203 if ( get_user_option( 'friends_no_keyword_notification_' . $friend_id ) !== $no_keyword_notification ) {
2204 update_user_option( $current_user_id, 'friends_no_keyword_notification_' . $friend_id, $no_keyword_notification );
2205 }
2206 }
2207
2208 update_user_option( $current_user_id, 'friends_hide_from_friends_page', $hide_from_friends_page );
2209
2210 do_action( 'friends_notification_manager_after_form_submit', $friend_ids );
2211
2212 if ( isset( $_GET['_wp_http_referer'] ) ) {
2213 wp_safe_redirect( wp_get_referer() );
2214 } else {
2215 wp_safe_redirect( add_query_arg( 'updated', '1', remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
2216 }
2217 exit;
2218 }
2219
2220 /**
2221 * Render the admin notification manager.
2222 */
2223 public function render_admin_notification_manager() {
2224 Friends::template_loader()->get_template_part(
2225 'admin/settings-header',
2226 null,
2227 array(
2228 'active' => 'friends-notification-manager',
2229 'title' => __( 'Friends', 'friends' ),
2230 )
2231 );
2232 $this->check_admin_settings();
2233
2234 ?>
2235 <h1><?php esc_html_e( 'Notification Manager', 'friends' ); ?></h1>
2236 <?php
2237
2238 $friend_users = new User_Query(
2239 array(
2240 'role__in' => array( 'friend', 'acquaintance', 'pending_friend_request', 'friend_request', 'subscription' ),
2241 'orderby' => 'display_name',
2242 'order' => 'ASC',
2243 )
2244 );
2245
2246 $hide_from_friends_page = get_user_option( 'friends_hide_from_friends_page' );
2247 if ( ! $hide_from_friends_page ) {
2248 $hide_from_friends_page = array();
2249 }
2250
2251 Friends::template_loader()->get_template_part(
2252 'admin/notification-manager',
2253 null,
2254 array(
2255 'friend_users' => $friend_users->get_results(),
2256 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
2257 'hide_from_friends_page' => $hide_from_friends_page,
2258 'no_new_post_notification' => get_user_option( 'friends_no_new_post_notification' ),
2259 'no_keyword_notification' => get_user_option( 'friends_no_keyword_notification' ),
2260 'active_keywords' => Feed::get_active_notification_keywords(),
2261 )
2262 );
2263
2264 Friends::template_loader()->get_template_part( 'admin/settings-footer' );
2265 }
2266
2267 /**
2268 * Gets the friend roles.
2269 *
2270 * @return array The friend roles.
2271 */
2272 public function get_friend_roles() {
2273 $roles = new \WP_Roles();
2274 $friend_roles = array();
2275 foreach ( $roles->roles as $role => $data ) {
2276 if ( isset( $data['capabilities']['friend'] ) ) {
2277 $friend_roles[ $role ] = $data['name'];
2278 }
2279 }
2280 return $friend_roles;
2281 }
2282
2283 /**
2284 * Gets the roles associated with the Friends plugin.
2285 *
2286 * @return array The associated roles.
2287 */
2288 public static function get_associated_roles() {
2289 $roles = new \WP_Roles();
2290 $friend_roles = array();
2291 foreach ( $roles->roles as $role => $data ) {
2292 if ( isset( $data['capabilities']['friends_plugin'] ) ) {
2293 $friend_roles[ $role ] = $data['name'];
2294 }
2295 }
2296 return $friend_roles;
2297 }
2298
2299 public static function get_users_url() {
2300 return 'admin.php?page=friends-list';
2301 }
2302
2303 /**
2304 * Add actions to the user rows
2305 *
2306 * @param array $actions The existing actions.
2307 * @param \WP_User $user The user in question.
2308 * @return array The extended actions.
2309 */
2310 public static function user_row_actions( array $actions, \WP_User $user ) {
2311 if (
2312 ! Friends::has_required_privileges() ||
2313 (
2314 ! $user->has_cap( 'friend_request' ) &&
2315 ! $user->has_cap( 'pending_friend_request' ) &&
2316 ! $user->has_cap( 'friend' ) &&
2317 ! $user->has_cap( 'subscription' )
2318 )
2319 ) {
2320 return $actions;
2321 }
2322
2323 if ( is_multisite() ) {
2324 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2325 $actions = array_merge( array( 'edit' => '<a href="' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login ) ) . '">' . __( 'Edit' ) . '</a>' ), $actions );
2326 }
2327
2328 // Ensuire we have a friends user here.
2329 $user = new User( $user );
2330
2331 $actions['view'] = Frontend::get_link(
2332 $user->user_url,
2333 sprintf(
2334 // translators: %s: Author’s display name.
2335 __( 'Visit %s&#8217;s website' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2336 $user->display_name
2337 ),
2338 array(),
2339 $user
2340 );
2341 unset( $actions['resetpassword'] );
2342
2343 if ( $user->has_cap( 'friend_request' ) ) {
2344 $link = self_admin_url( wp_nonce_url( 'users.php?action=accept_friend_request&users[]=' . $user->ID ) );
2345
2346 $actions['user_accept_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Accept Friend Request', 'friends' ) . '</a>';
2347 $message = get_user_option( 'friends_request_message', $user->ID );
2348 $actions['friends friends_request_date'] = '<br/><span class="nonessential">' . esc_html(
2349 sprintf(
2350 // translators: %s is a date.
2351 __( 'Requested on %s', 'friends' ),
2352 date_i18n( __( 'F j, Y g:i a' ), strtotime( $user->user_registered ) ) // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2353 )
2354 ) . '</span>';
2355 if ( $message ) {
2356 // translators: %s is a message text.
2357 $actions['friends friend_request_message'] = '<br/><span class="nonessential">' . esc_html( sprintf( __( 'Message: %s', 'friends' ), $message ) ) . '</span>';
2358 }
2359 }
2360
2361 if ( $user->has_cap( 'pending_friend_request' ) || $user->has_cap( 'subscription' ) ) {
2362 $link = wp_nonce_url( add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login ) ), 'add-friend-' . $user->user_login, 'add-friend' );
2363 if ( $user->has_cap( 'pending_friend_request' ) ) {
2364 $actions['user_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Resend Friend Request', 'friends' ) . '</a>';
2365 } elseif ( $user->has_cap( 'subscription' ) ) {
2366 $actions['user_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Send Friend Request', 'friends' ) . '</a>';
2367 }
2368 }
2369
2370 return $actions;
2371 }
2372
2373 /**
2374 * Handle bulk friend request approvals on the user page
2375 *
2376 * @param string $sendback The URL to send the user back to.
2377 * @param string $action The requested action.
2378 * @param array $users The selected users.
2379 */
2380 public function handle_bulk_friend_request_approval( $sendback, $action, $users ) {
2381 if ( 'accept_friend_request' !== $action ) {
2382 return $sendback;
2383 }
2384
2385 $accepted = 0;
2386 foreach ( $users as $user_id ) {
2387 $user = new User( $user_id );
2388 if ( ! $user || is_wp_error( $user ) ) {
2389 continue;
2390 }
2391
2392 if ( ! $user->has_cap( 'friend_request' ) ) {
2393 continue;
2394 }
2395
2396 if ( $user->has_cap( 'friend' ) ) {
2397 continue;
2398 }
2399
2400 $user->set_role( get_option( 'friends_default_friend_role', 'friend' ) );
2401 ++$accepted;
2402 }
2403
2404 if ( ! $sendback ) {
2405 return array(
2406 'accepted' => $accepted,
2407 );
2408 }
2409
2410 $sendback = add_query_arg( 'accepted', $accepted, $sendback );
2411 $sendback = remove_query_arg( 'role', $sendback );
2412 wp_safe_redirect( $sendback );
2413 }
2414
2415 /**
2416 * Add options to the Bulk dropdown on the users page
2417 *
2418 * @param array $actions The existing bulk options.
2419 * @return array The extended bulk options.
2420 */
2421 public function add_user_bulk_options( $actions ) {
2422 $friends = User_Query::all_friend_requests();
2423 $friends->get_results();
2424
2425 if ( ! empty( $friends ) ) {
2426 $actions['accept_friend_request'] = __( 'Accept Friend Request', 'friends' );
2427 }
2428
2429 $friends = User_Query::all_subscriptions();
2430 $friends->get_results();
2431
2432 if ( ! empty( $friends ) ) {
2433 $actions['friend_request'] = __( 'Send Friend Request', 'friends' );
2434 }
2435
2436 return $actions;
2437 }
2438
2439 /**
2440 * Add a column "Posts" (that emcompasses both user and friend posts.)
2441 *
2442 * @param array $columns The columns.
2443 *
2444 * @return array The columns extended by the friends_posts.
2445 */
2446 public function user_list_columns( $columns ) {
2447 $columns['friends_posts'] = __( 'Friend Posts', 'friends' );
2448 unset( $columns['email'] );
2449 return $columns;
2450 }
2451
2452 /**
2453 * Return the results for the friends_posts column.
2454 *
2455 * @param string $output Custom column output. Default empty.
2456 * @param string $column_name Column name.
2457 * @param int $user_id ID of the currently-listed user.
2458 *
2459 * @return string The column contents.
2460 */
2461 public static function user_list_custom_column( $output, $column_name, $user_id ) {
2462 if ( 'friends_posts' !== $column_name ) {
2463 return $output;
2464 }
2465 $numposts = count_user_posts( $user_id, apply_filters( 'friends_frontend_post_types', array( 'post' ) ) );
2466 $user = User::get_user_by_id( $user_id );
2467 return sprintf(
2468 '<a href="%s" class="edit"><span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
2469 $user ? $user->get_local_friends_page_url() : "edit.php?author={$user_id}",
2470 $numposts,
2471 sprintf(
2472 /* translators: %s: Number of posts. */
2473 _n( '%s post', '%s posts', $numposts ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2474 number_format_i18n( $numposts )
2475 )
2476 );
2477 }
2478
2479 /**
2480 * Override the post title for specific post formats.
2481 *
2482 * @param string $title The title.
2483 * @param int $post_id The post id.
2484 *
2485 * @return string The potentially overriden title.
2486 */
2487 public function override_post_format_title( $title, $post_id = null ) {
2488 if ( $post_id && empty( $title ) && is_admin() && function_exists( 'get_current_screen' ) ) {
2489 $screen = get_current_screen();
2490 if ( $screen && 'edit-post' === $screen->id ) {
2491 if ( 'status' === get_post_format() ) {
2492 $post = get_post( $post_id );
2493 return wp_trim_words( wp_strip_all_tags( $post->post_content ) );
2494 }
2495 }
2496 }
2497 return $title;
2498 }
2499
2500 /**
2501 * Adds the friend requests to the unread count.
2502 *
2503 * @param int $unread The unread count.
2504 *
2505 * @return int Unread count + friend requests.
2506 */
2507 public function friends_unread_friend_request_count( $unread ) {
2508 $friend_requests = User_Query::all_friend_requests();
2509 return $unread + $friend_requests->get_total();
2510 }
2511
2512 /**
2513 * Add open friend requests to the menu.
2514 *
2515 * @param \WP_Menu $wp_menu The wp menu.
2516 * @param string $my_url My url.
2517 */
2518 public function friends_add_menu_open_friend_request( $wp_menu, $my_url ) {
2519 $friend_request_count = $this->friends_unread_friend_request_count( 0 );
2520 if ( $friend_request_count > 0 ) {
2521 $wp_menu->add_menu(
2522 array(
2523 'id' => 'open-friend-requests',
2524 'parent' => 'friends-menu',
2525 // translators: %s is the number of open friend requests.
2526 'title' => esc_html( sprintf( _n( 'Review %s Friend Request', 'Review %s Friends Request', $friend_request_count, 'friends' ), $friend_request_count ) ),
2527 'href' => $my_url . '/wp-admin/admin.php?page=friends-list-requests',
2528 )
2529 );
2530 }
2531 }
2532
2533 /**
2534 * Get the unread badge HTML
2535 *
2536 * @return string The unread badge HTML.
2537 */
2538 public function get_unread_badge() {
2539 $unread_count = apply_filters( 'friends_unread_count', 0 );
2540 if ( 0 === intval( $unread_count ) ) {
2541 return '';
2542 }
2543
2544 if ( get_user_option( 'friends_unobtrusive_badge' ) ) {
2545 return ' (' . $unread_count . ')';
2546 }
2547 $unread_badge = ' <div class="wp-core-ui wp-ui-notification friends-open-requests" style="display: inline; font-size: 11px; padding: .1em .5em .1em .4em; border-radius: 9px; background-color: #d63638; color: #fff; text-align: center; height: 18px"><span aria-hidden="true">' . $unread_count . '</span><span class="screen-reader-text">';
2548 // translators: %s is the number of unread items.
2549 $unread_badge .= sprintf( _n( '%s unread item', '%s unread items', $unread_count, 'friends' ), $unread_count );
2550 $unread_badge .= '</span></div>';
2551 return $unread_badge;
2552 }
2553
2554 /**
2555 * Add a Friends menu to the admin bar
2556 *
2557 * @param \WP_Admin_Bar $wp_menu The admin bar to modify.
2558 */
2559 public function admin_bar_friends_menu( \WP_Admin_Bar $wp_menu ) {
2560 $my_url = false;
2561 $my_own_site = false;
2562 $on_my_own_site = false;
2563 $we_requested_friendship = false;
2564 $they_requested_friendship = false;
2565
2566 if ( current_user_can( 'friend' ) ) {
2567 $current_user = wp_get_current_user();
2568 if ( ! $current_user->user_url ) {
2569 return;
2570 }
2571
2572 $my_url = $current_user->user_url;
2573 } elseif ( is_multisite() ) {
2574 $site = get_active_blog_for_user( get_current_user_id() );
2575 if ( ! $site ) {
2576 // If we cannot find a site, we shouldn't show the admin bar entry.
2577 return;
2578 }
2579
2580 $my_url = set_url_scheme( $site->siteurl );
2581 $my_own_site = $site;
2582 $on_my_own_site = get_current_blog_id() === intval( $site->blog_id );
2583 if ( is_user_member_of_blog( get_current_user_id(), get_current_blog_id() ) ) {
2584 if ( current_user_can( 'pending_friend_request' ) ) {
2585 $they_requested_friendship = true;
2586 } elseif ( current_user_can( 'friend_request' ) ) {
2587 $we_requested_friendship = true;
2588 }
2589 }
2590 } elseif ( Friends::has_required_privileges() ) {
2591 $my_url = home_url();
2592 $on_my_own_site = true;
2593 }
2594
2595 if ( ! $on_my_own_site && $my_own_site ) {
2596 switch_to_blog( $my_own_site->blog_id );
2597 }
2598
2599 $unread = '';
2600 if ( $on_my_own_site ) {
2601 $unread = $this->get_unread_badge();
2602 }
2603 $wp_menu->add_node(
2604 array(
2605 'id' => 'friends-menu',
2606 'parent' => '',
2607 'title' => '<span class="ab-icon dashicons dashicons-groups"></span> <span class="ab-label">' . esc_html( __( 'Friends', 'friends' ) ) . $unread . '</span>',
2608 'href' => $my_url . '/friends/',
2609 )
2610 );
2611
2612 if ( $on_my_own_site ) {
2613 do_action( 'friends_own_site_menu_top', $wp_menu, $my_url );
2614 }
2615
2616 if ( ! $on_my_own_site && $my_own_site ) {
2617 restore_current_blog();
2618 }
2619
2620 do_action( 'friends_current_site_menu_top', $wp_menu, $my_url );
2621
2622 $wp_menu->add_menu(
2623 array(
2624 'id' => 'your-feed',
2625 'parent' => 'friends-menu',
2626 'title' => esc_html__( 'My Friends Feed', 'friends' ),
2627 'href' => $my_url . '/friends/',
2628 )
2629 );
2630
2631 if ( $they_requested_friendship ) {
2632 $wp_menu->add_menu(
2633 array(
2634 'id' => 'add-friend',
2635 'parent' => 'friends-menu',
2636 'title' => '<span style="border-left: 2px solid #d63638; padding-left: .5em">' . esc_html(
2637 sprintf(
2638 // translators: %s is a site title.
2639 __( "Respond to %s's friend request", 'friends' ),
2640 get_bloginfo( 'name' )
2641 ) . '</span>'
2642 ),
2643 'href' => $my_url . '/wp-admin/admin.php?page=friends-list-requests',
2644 )
2645 );
2646 }
2647
2648 if ( $on_my_own_site ) {
2649 $wp_menu->add_menu(
2650 array(
2651 'id' => 'your-profile',
2652 'parent' => 'friends-menu',
2653 'title' => esc_html__( 'My Public Friends Profile', 'friends' ),
2654 'href' => $my_url . '/friends/?public',
2655 )
2656 );
2657 $wp_menu->add_menu(
2658 array(
2659 'id' => 'friends-requests',
2660 'parent' => 'friends-menu',
2661 'title' => esc_html__( 'My Friends & Requests', 'friends' ),
2662 'href' => $my_url . '/wp-admin/admin.php?page=friends-list',
2663 )
2664 );
2665 $wp_menu->add_menu(
2666 array(
2667 'id' => 'friends',
2668 'parent' => 'friends-menu',
2669 'title' => esc_html__( 'Settings' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2670 'href' => $my_url . '/wp-admin/admin.php?page=friends-settings',
2671 )
2672 );
2673 } else {
2674 if ( ! current_user_can( 'friend' ) ) {
2675 if ( $we_requested_friendship ) {
2676 $wp_menu->add_menu(
2677 array(
2678 'id' => 'add-friend',
2679 'parent' => 'friends-menu',
2680 'title' => esc_html__( 'Friendship Already Requested', 'friends' ),
2681 'href' => $my_url . '/wp-admin/' . self::get_users_url(),
2682 )
2683 );
2684 } elseif ( ! $they_requested_friendship ) {
2685 $wp_menu->add_menu(
2686 array(
2687 'id' => 'add-friend',
2688 'parent' => 'friends-menu',
2689 'title' => esc_html(
2690 sprintf(
2691 // translators: %s is a site title.
2692 __( 'Add %s as a friend', 'friends' ),
2693 get_bloginfo( 'name' )
2694 )
2695 ),
2696 'href' => $my_url . '/?add-friend=' . urlencode( home_url() ),
2697 )
2698 );
2699 }
2700 }
2701
2702 $wp_menu->add_menu(
2703 array(
2704 'id' => 'profile',
2705 'parent' => 'friends-menu',
2706 'title' => esc_html(
2707 sprintf(
2708 // translators: %s is a site title.
2709 __( "%s's Profile", 'friends' ),
2710 get_bloginfo( 'name' )
2711 )
2712 ),
2713 'href' => home_url( '/friends/' ),
2714 )
2715 );
2716 }
2717 }
2718
2719 /**
2720 * Add Friend entries to the New Content admin section
2721 *
2722 * @param \WP_Admin_Bar $wp_menu The admin bar to modify.
2723 */
2724 public function admin_bar_new_content( \WP_Admin_Bar $wp_menu ) {
2725 if ( Friends::has_required_privileges() ) {
2726 $wp_menu->add_menu(
2727 array(
2728 'id' => 'new-friend-request',
2729 'parent' => 'new-content',
2730 'title' => esc_html__( 'Friend', 'friends' ),
2731 'href' => self_admin_url( 'admin.php?page=add-friend' ),
2732 )
2733 );
2734 $wp_menu->add_menu(
2735 array(
2736 'id' => 'new-subscription',
2737 'parent' => 'new-content',
2738 'title' => esc_html__( 'Subscription', 'friends' ),
2739 'href' => self_admin_url( 'admin.php?page=add-friend' ),
2740 )
2741 );
2742 }
2743 }
2744
2745 /**
2746 * Show friends admin bar item on mobile.
2747 */
2748 public function admin_bar_mobile() {
2749 if ( ! is_user_logged_in() ) {
2750 return;
2751 }
2752 ?>
2753 <style type="text/css" media="screen">
2754 @media screen and (max-width: 782px) {
2755 #wpadminbar #wp-admin-bar-friends, #wpadminbar #wp-admin-bar-friends .ab-icon {
2756 display: block !important;
2757 }
2758 #wpadminbar #wp-admin-bar-friends .ab-label {
2759 display: none !important;
2760 }
2761 }
2762 </style>
2763 <?php
2764 }
2765
2766
2767 /**
2768 * Fires at the end of the delete users form prior to the confirm button.
2769 *
2770 * @param \WP_User $current_user \WP_User object for the current user.
2771 * @param array $userids Array of IDs for users being deleted.
2772 */
2773 public function delete_user_form( $current_user, $userids ) {
2774 $only_friends_affiliated = true;
2775 foreach ( $userids as $user_id ) {
2776 $user = new \WP_User( $user_id );
2777 if (
2778 ! $user->has_cap( 'friend_request' ) &&
2779 ! $user->has_cap( 'pending_friend_request' ) &&
2780 ! $user->has_cap( 'friend' ) &&
2781 ! $user->has_cap( 'subscription' )
2782 ) {
2783 $only_friends_affiliated = false;
2784 break;
2785 }
2786 }
2787
2788 if ( $only_friends_affiliated ) {
2789 ?>
2790 <script type="text/javascript">
2791 jQuery( function () {
2792 jQuery( '#delete_option1' ).closest( 'li' ).hide();
2793 } );
2794 </script>
2795 <?php
2796 }
2797 }
2798
2799 /**
2800 * Actions when a (friend) user is deleted.
2801 *
2802 * @param integer $user_id The user identifier.
2803 */
2804 public function delete_user( $user_id ) {
2805 $friend_user = User::get_user_by_id( $user_id );
2806 if ( ! $friend_user ) {
2807 return; // user was already deleted?
2808 }
2809 // Allow unsubscribing to all these feeds.
2810 foreach ( $friend_user->get_active_feeds() as $feed ) {
2811 do_action( 'friends_user_feed_deactivated', $feed );
2812 $feed->delete();
2813 }
2814
2815 // Delete the rest.
2816 foreach ( $friend_user->get_feeds() as $feed ) {
2817 $feed->delete();
2818 }
2819
2820 foreach ( $friend_user->get_all_post_ids() as $post_id ) {
2821 wp_delete_post( $post_id );
2822 }
2823 }
2824
2825 /**
2826 * Display the Bookmarklets at the Tools section of wp-admin
2827 */
2828 public function toolbox_bookmarklets() {
2829 ?>
2830 <div class="card">
2831 <h2 class="title"><?php esc_html_e( 'Friends', 'friends' ); ?></h2>
2832 <h3><?php esc_html_e( 'Bookmarklets', 'friends' ); ?></h3>
2833
2834 <p><?php esc_html_e( "Drag one of these bookmarklets to your bookmarks bar and click it when you're on a site around the web for the appropriate action.", 'friends' ); ?></p>
2835 <p>
2836 <a href="javascript:void(location.href='<?php echo esc_attr( self_admin_url( 'admin.php?page=add-friend&url=' ) ); ?>'+encodeURIComponent(location.href))" style="display: inline-block; padding: .5em; border: 1px solid #999; border-radius: 4px; background-color: #ddd;text-decoration: none; margin-right: 3em"><?php echo esc_html_e( 'Add friend', 'friends' ); ?></a>
2837 <a href="javascript:void(location.href='<?php echo esc_attr( self_admin_url( 'admin.php?page=add-friend&url=' ) ); ?>'+encodeURIComponent(location.href))" style="display: inline-block; padding: .5em; border: 1px solid #999; border-radius: 4px; background-color: #ddd; text-decoration: none; margin-right: 3em"><?php echo esc_html_e( 'Subscribe', 'friends' ); ?></a>
2838 </p>
2839 <h3><?php esc_html_e( 'Browser Extension', 'friends' ); ?></h3>
2840
2841 <p><?php esc_html_e( 'There is also the option to use a browser extension.', 'friends' ); ?></p>
2842 <p>
2843 <a href="https://addons.mozilla.org/en-US/firefox/addon/wpfriends/"><?php echo esc_html_e( 'Firefox Extension', 'friends' ); ?></a>
2844 </p>
2845 </div>
2846 <?php
2847 }
2848
2849 /**
2850 * Add more "at a glance" items
2851
2852 * @param array $items Items inserted by another plugin.
2853 * @return array Items + our items.
2854 */
2855 public function dashboard_glance_items( $items ) {
2856 $count_users = count_users();
2857 $count = array_merge(
2858 array(
2859 'friend' => 0,
2860 'acquaintance' => 0,
2861 'friend_request' => 0,
2862 'subscription' => 0,
2863 ),
2864 $count_users['avail_roles']
2865 );
2866 $friend_count = $count['friend'] + $count['acquaintance'];
2867 $friend_request_count = $count['friend_request'];
2868 $subscription_count = $count['subscription'];
2869 $friend_post_count = wp_count_posts( Friends::CPT );
2870 $friend_post_count = $friend_post_count->publish + $friend_post_count->private;
2871
2872 $items[] = '<a class="friends" href="' . self_admin_url( 'users.php?role=friend' ) . '">' . sprintf(
2873 // translators: %s is the number of your friends.
2874 _n( '%s Friend', '%s Friends', $friend_count, 'friends' ),
2875 $friend_count
2876 ) . '</a>';
2877 if ( $friend_request_count ) {
2878 // translators: %s is the number of friend requests.
2879 $items[] = '<a class="friend-requests" href="' . self_admin_url( 'users.php?role=friend_request' ) . '">' . sprintf( _n( '%s Friend Request', '%s Friend Requests', $friend_request_count, 'friends' ), $friend_request_count ) . '</a>';
2880 }
2881 if ( $subscription_count ) {
2882 // translators: %s is the number of subscriptions.
2883 $items[] = '<a class="subscriptions" href="' . self_admin_url( 'users.php?role=subscription' ) . '">' . sprintf( _n( '%s Subscription', '%s Subscriptions', $subscription_count, 'friends' ), $subscription_count ) . '</a>';
2884 }
2885
2886 if ( $friend_post_count ) {
2887 // translators: %s is the number of friend posts.
2888 $items[] = '<a class="friend-posts" href="' . home_url( '/friends/' ) . '">' . sprintf( _n( '%s Post by Friends', '%s Posts by Friends', $friend_post_count, 'friends' ), $friend_post_count ) . '</a>';
2889 }
2890 return $items;
2891 }
2892
2893 public function site_status_tests( $tests ) {
2894 $tests['direct']['friends-roles'] = array(
2895 'label' => __( 'Friend roles were created', 'friends' ),
2896 'test' => array( $this, 'friend_roles_test' ),
2897 );
2898 return $tests;
2899 }
2900
2901 public function get_missing_friends_plugin_roles() {
2902 $missing = Friends::get_friends_plugin_roles();
2903 $roles = new \WP_Roles();
2904 foreach ( $roles->roles as $role => $data ) {
2905 if ( isset( $data['capabilities']['friends_plugin'] ) ) {
2906 foreach ( $missing as $k => $cap ) {
2907 if ( isset( $data['capabilities'][ $cap ] ) ) {
2908 unset( $missing[ $k ] );
2909 break;
2910 }
2911 }
2912 }
2913 }
2914
2915 return array_values( $missing );
2916 }
2917
2918 public function friend_roles_test() {
2919 $result = array(
2920 'label' => __( 'The friend roles have been installed', 'friends' ),
2921 'status' => 'good',
2922 'badge' => array(
2923 'label' => __( 'Friends', 'friends' ),
2924 'color' => 'green',
2925 ),
2926 'description' =>
2927 '<p>' .
2928 __( 'The Friends Plugin uses users and user roles to determine friendship status between sites.', 'friends' ) .
2929 '</p>' .
2930 '<p>' .
2931 sprintf(
2932 // translators: %s is a list of roles.
2933 __( 'These are the roles required for the friends plugin: %s', 'friends' ),
2934 implode( ', ', Friends::get_friends_plugin_roles() )
2935 ) .
2936 '</p>',
2937 'test' => 'friends-roles',
2938 );
2939
2940 $missing_friend_roles = $this->get_missing_friends_plugin_roles();
2941 if ( ! empty( $missing_friend_roles ) ) {
2942
2943 $result['label'] = sprintf(
2944 // translators: %s is a list of missing roles.
2945 __( 'Not all friend roles have been installed. Missing: %s', 'friends' ),
2946 implode( ', ', $missing_friend_roles )
2947 );
2948 $result['badge']['color'] = 'red';
2949 $result['status'] = 'critical';
2950 $result['description'] .= '<p>';
2951 $result['description'] .= wp_kses_post(
2952 sprintf(
2953 // translators: %s is a URL.
2954 __( '<strong>To fix this:</strong> <a href="%s">Re-run activation of the Friends plugin</a>.', 'friends' ),
2955 esc_url( wp_nonce_url( add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings&rerun-activate' ) ), 'friends-settings' ) )
2956 )
2957 );
2958 $result['description'] .= '</p>';
2959 }
2960
2961 return $result;
2962 }
2963
2964 public function site_status_test_php_modules( $modules ) {
2965 $modules['mbstring']['required'] = true;
2966 return $modules;
2967 }
2968
2969 public function site_health_debug( $debug_info ) {
2970 $missing_friend_roles = $this->get_missing_friends_plugin_roles();
2971 $debug_info['friends'] = array(
2972 'label' => __( 'Friends', 'friends' ),
2973 'fields' => array(
2974 'version' => array(
2975 'label' => __( 'Friends Version', 'friends' ),
2976 'value' => Friends::VERSION,
2977 ),
2978 'mbstring' => array(
2979 'label' => __( 'mbstring is available', 'friends' ),
2980 'value' => function_exists( 'mb_check_encoding' ) ? __( 'Yes' ) : __( 'No' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2981 ),
2982 'roles' => array(
2983 'label' => __( 'Friend roles missing', 'friends' ),
2984 'value' => empty( $missing_friend_roles ) ? sprintf(
2985 // translators: %s is a list of roles.
2986 __( 'All roles found: %s', 'friends' ),
2987 implode( ', ', Friends::get_friends_plugin_roles() )
2988 ) : implode( ', ', $missing_friend_roles ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2989 ),
2990 'main_user' => array(
2991 'label' => __( 'Main Friend User', 'friends' ),
2992 'value' => self::human_readable_main_user(),
2993 ),
2994 'parsers' => array(
2995 'label' => __( 'Registered Parsers', 'friends' ),
2996 'value' => strip_tags( implode( ', ', $this->friends->feed->get_registered_parsers() ) ),
2997 ),
2998 ),
2999 );
3000
3001 return $debug_info;
3002 }
3003
3004 /**
3005 * Returns a human readable string for which user is the main user.
3006 *
3007 * @return string
3008 */
3009 private static function human_readable_main_user() {
3010 $main_user = Friends::get_main_friend_user_id();
3011
3012 if ( ! $main_user ) {
3013 // translators: %d is the number of users.
3014 return esc_html( sprintf( __( 'No main user set. Admin users: %d', 'friends' ), User_Query::all_admin_users()->get_total() ) );
3015 }
3016
3017 $user = new \WP_User( $main_user );
3018
3019 if ( ! $user ) {
3020 return sprintf( '#%1$d %2$s', $main_user, '???' );
3021 }
3022
3023 return sprintf( '#%1$d %2$s', $user->ID, $user->user_login );
3024 }
3025 }
3026