PluginProbe
Friends / 2.8.4
Friends v2.8.4
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.4, at includes/class-admin.php

3,023 lines 105.1 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 if ( isset( $_GET['_wp_http_referer'] ) ) {
1163 wp_safe_redirect( add_query_arg( $arg, $arg_value, wp_get_referer() ) );
1164 } else {
1165 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
1166 }
1167 exit;
1168 }
1169
1170 /**
1171 * The Friends Edit User header
1172 *
1173 * @param User $friend The friend.
1174 * @param string $active The active menu entry.
1175 */
1176 public function header_edit_friend( User $friend, $active ) {
1177 $append = '&user=' . $friend->user_login;
1178 Friends::template_loader()->get_template_part(
1179 'admin/settings-header',
1180 null,
1181 array(
1182 'active' => $active . $append,
1183 'title' => $friend->user_login,
1184 'menu' => array(
1185 __( 'Settings' ) => 'edit-friend' . $append, // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1186 __( 'Feeds', 'friends' ) => 'edit-friend-feeds' . $append,
1187 __( 'Notifications', 'friends' ) => 'edit-friend-notifications' . $append,
1188 __( 'Rules', 'friends' ) => 'edit-friend-rules' . $append,
1189 ),
1190 )
1191 );
1192 }
1193
1194 /**
1195 * Render the Friends Edit User page
1196 */
1197 public function render_admin_edit_friend() {
1198 $friend = $this->check_admin_edit_friend();
1199
1200 $args = array_merge(
1201 $friend->get_post_stats(),
1202 array(
1203 'friend' => $friend,
1204 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
1205 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1206 'hide_from_friends_page' => get_user_option( 'friends_hide_from_friends_page' ),
1207 )
1208 );
1209 if ( ! $args['hide_from_friends_page'] ) {
1210 $args['hide_from_friends_page'] = array();
1211 }
1212
1213 $this->header_edit_friend( $friend, 'edit-friend' );
1214
1215 if ( isset( $_GET['updated'] ) ) {
1216 ?>
1217 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'User was updated.', 'friends' ); ?></p></div>
1218 <?php
1219 } elseif ( isset( $_GET['friend'] ) ) {
1220 ?>
1221 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'You are now friends.', 'friends' ); ?></p></div>
1222 <?php
1223 } elseif ( isset( $_GET['error'] ) ) {
1224 ?>
1225 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
1226 <?php
1227 } elseif ( isset( $_GET['sent-request'] ) ) {
1228 ?>
1229 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Your request was sent.', 'friends' ); ?></p></div>
1230 <?php
1231 } elseif ( isset( $_GET['subscribed'] ) ) {
1232 ?>
1233 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Subscription activated.', 'friends' ); ?></p></div>
1234 <?php
1235 }
1236
1237 Friends::template_loader()->get_template_part( 'admin/edit-friend', null, $args );
1238 }
1239
1240 public function ajax_set_avatar() {
1241 $user_id = isset( $_POST['user'] ) ? $_POST['user'] : 0;
1242
1243 check_ajax_referer( "set-avatar-$user_id" );
1244
1245 if ( ! current_user_can( Friends::REQUIRED_ROLE ) ) {
1246 wp_send_json_error();
1247 exit;
1248 }
1249
1250 if ( empty( $_POST['avatar'] ) || ! Friends::check_url( $_POST['avatar'] ) ) {
1251 wp_send_json_error();
1252 exit;
1253 }
1254
1255 $friend = User::get_user_by_id( $user_id );
1256
1257 $image = file_get_contents( $_POST['avatar'] );
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_friend_after_form_submit', $friend );
1503 }
1504 } else {
1505 return;
1506 }
1507
1508 if ( isset( $_GET['_wp_http_referer'] ) ) {
1509 wp_safe_redirect( wp_get_referer() );
1510 } else {
1511 wp_safe_redirect( add_query_arg( $arg, $arg_value, remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
1512 }
1513 exit;
1514 }
1515
1516 /**
1517 * Render the Friends Edit Feeds page
1518 */
1519 public function render_admin_edit_friend_feeds() {
1520 $friend = $this->check_admin_edit_friend();
1521
1522 $args = array_merge(
1523 $friend->get_post_stats(),
1524 array(
1525 'friend' => $friend,
1526 'rules' => $friend->get_feed_rules(),
1527 'hide_from_friends_page' => get_user_option( 'friends_hide_from_friends_page' ),
1528 'post_formats' => array_merge( array( 'autodetect' => __( 'Autodetect Post Format', 'friends' ) ), get_post_format_strings() ),
1529 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
1530 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1531 'global_retention_days' => Friends::get_retention_days(),
1532 'global_retention_number' => Friends::get_retention_number(),
1533 'global_retention_days_enabled' => get_option( 'friends_enable_retention_days' ),
1534 'global_retention_number_enabled' => get_option( 'friends_enable_retention_number' ),
1535 )
1536 );
1537 if ( ! $args['hide_from_friends_page'] ) {
1538 $args['hide_from_friends_page'] = array();
1539 }
1540 $this->header_edit_friend( $friend, 'edit-friend-feeds' );
1541
1542 if ( isset( $_GET['updated'] ) ) {
1543 ?>
1544 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'Feeds were updated.', 'friends' ); ?></p></div>
1545 <?php
1546 } elseif ( isset( $_GET['error'] ) ) {
1547 ?>
1548 <div id="message" class="updated error is-dismissible"><p><?php esc_html_e( 'An error occurred.', 'friends' ); ?></p></div>
1549 <?php
1550 }
1551
1552 Friends::template_loader()->get_template_part( 'admin/edit-feeds', null, $args );
1553 }
1554
1555 /**
1556 * Process the Unfriend page
1557 */
1558 public function process_admin_unfriend() {
1559 $friend = $this->check_admin_edit_friend();
1560 $arg = 'deleted';
1561 $arg_value = $friend->user_login;
1562
1563 if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'unfriend-' . $friend->user_login ) ) {
1564 $friend->delete();
1565 } else {
1566 return;
1567 }
1568
1569 if ( isset( $_GET['_wp_http_referer'] ) ) {
1570 wp_safe_redirect( wp_get_referer() );
1571 } else {
1572 wp_safe_redirect( add_query_arg( $arg, $arg_value, self_admin_url( 'admin.php?page=friends-list' ) ) );
1573 }
1574 exit;
1575 }
1576
1577 /**
1578 * Render the Unfriend page
1579 */
1580 public function render_admin_unfriend() {
1581 $friend = $this->check_admin_edit_friend();
1582 $post_stats = $friend->get_post_stats();
1583
1584 $args = array(
1585 'friend' => $friend,
1586 'friend_posts' => $post_stats['post_count'],
1587 'total_size' => $post_stats['total_size'],
1588 );
1589
1590 Friends::template_loader()->get_template_part( 'admin/unfriend', null, $args );
1591 }
1592
1593 /**
1594 * Display error messages.
1595 *
1596 * @param object $errors The errors.
1597 */
1598 private function display_errors( $errors ) {
1599 if ( ! is_wp_error( $errors ) ) {
1600 return;
1601 }
1602
1603 ?>
1604 <div id="message" class="updated error is-dismissible"><p><?php echo esc_html( $errors->get_error_message() ); ?></p>
1605 <?php
1606 $error_data = $errors->get_error_data();
1607 if ( isset( $error_data->error ) ) {
1608 $error = unserialize( $error_data->error );
1609 if ( is_wp_error( $error ) ) {
1610 ?>
1611 <pre>
1612 <?php
1613 print_r( $error );
1614 ?>
1615 </pre>
1616 <?php
1617 } elseif ( is_array( $error ) && isset( $error['body'] ) ) {
1618 ?>
1619 <textarea>
1620 <?php
1621 echo esc_html( $error['body'] );
1622 ?>
1623 </textarea>
1624 <?php
1625 }
1626 }
1627 ?>
1628 </div>
1629 <?php
1630 }
1631
1632 public function create_and_follow( $user_id, $url, $type, $vars = array() ) {
1633 $vars['friend_url'] = $url;
1634
1635 $vars['user_login'] = apply_filters( 'friends_suggest_user_login', User::get_user_login_for_url( $url ), $url );
1636 if ( empty( $vars['display_name'] ) ) {
1637 $vars['display_name'] = apply_filters( 'friends_suggest_display_name', User::get_display_name_for_url( $url ), $url );
1638 }
1639
1640 $vars['step2'] = true;
1641
1642 $vars['subscribe'] = array( $url );
1643 $vars['feeds'] = $this->friends->feed->discover_available_feeds( $url );
1644
1645 ob_start();
1646 $ret = $this->process_admin_add_friend( $vars );
1647 ob_end_clean();
1648
1649 if ( is_wp_error( $ret ) ) {
1650 return $ret;
1651 }
1652
1653 $friend_user = User::get_by_username( $vars['user_login'] );
1654 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1655 return new \WP_Error( 'friend_not_created', __( 'Friend could not be created.', 'friends' ) );
1656 }
1657
1658 return $friend_user->ID;
1659 }
1660
1661 /**
1662 * Previous process the Add Friend form. Todo: re-integrate.
1663 *
1664 * @param User $friend_user The Friend user.
1665 * @param array $vars The variables from the admin
1666 * submission.
1667 *
1668 * @return boolean true when there was no error.
1669 */
1670 public function process_admin_add_friend_response( $friend_user, $vars ) {
1671 if ( is_wp_error( $friend_user ) ) {
1672 $this->display_errors( $friend_user );
1673 return false;
1674 }
1675
1676 if ( ! $friend_user instanceof User ) {
1677 ?>
1678 <div id="message" class="updated notice is-dismissible"><p>
1679 <?php
1680 // translators: %s is a username.
1681 esc_html_e( 'Unknown error', 'friends' );
1682 ?>
1683 </p></div>
1684 <?php
1685 return false;
1686 }
1687
1688 $feed_options = array();
1689 if ( ! isset( $vars['feeds'] ) ) {
1690 $vars['feeds'] = array();
1691 }
1692 foreach ( $vars['feeds'] as $feed ) {
1693 if ( isset( $feed['type'] ) ) {
1694 $feed['mime-type'] = $feed['type'];
1695 unset( $feed['type'] );
1696 }
1697 $feed_options[ $feed['url'] ] = $feed;
1698 }
1699
1700 // Save the all feeds for possible later activation.
1701 $friend_user->save_feeds( $feed_options );
1702
1703 if ( ! isset( $vars['subscribe'] ) ) {
1704 $vars['subscribe'] = array();
1705 }
1706
1707 $count = 0;
1708 foreach ( $vars['subscribe'] as $feed_url ) {
1709 if ( ! isset( $feed_options[ $feed_url ] ) ) {
1710 continue;
1711 }
1712 $new_feed = $friend_user->subscribe( $feed_url, $feed_options[ $feed_url ] );
1713 if ( ! is_wp_error( $new_feed ) ) {
1714 do_action( 'friends_user_feed_activated', $new_feed );
1715 $count += 1;
1716 }
1717 }
1718
1719 add_filter( 'notify_about_new_friend_post', '__return_false', 999 );
1720
1721 wp_schedule_single_event( time(), 'friends_retrieve_user_feeds', array( $friend_user->ID ) );
1722
1723 if ( isset( $vars['errors'] ) ) {
1724 $this->display_errors( $vars['errors'] );
1725 }
1726
1727 $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>';
1728 $message = false;
1729
1730 if ( $friend_user->has_cap( 'pending_friend_request' ) ) {
1731 // translators: %s is a Site URL.
1732 $message = sprintf( __( 'Friendship requested for site %s.', 'friends' ), $friend_link );
1733 $message .= ' ' . sprintf( __( 'Until they respond, we have already subscribed you to their updates.', 'friends' ), $friend_link );
1734 } elseif ( $friend_user->has_cap( 'friend' ) ) {
1735 // translators: %s is a Site URL.
1736 $message = sprintf( __( "You're now a friend of site %s.", 'friends' ), $friend_link );
1737 // translators: %s is the friends page URL.
1738 } elseif ( $friend_user->has_cap( 'subscription' ) ) {
1739 if ( isset( $vars['friendship'] ) ) {
1740 // translators: %s is a Site URL.
1741 $message = sprintf( __( 'No friends plugin installed at %s.', 'friends' ), $friend_link );
1742 $message .= ' ' . esc_html__( 'We subscribed you to their updates.', 'friends' );
1743 } else {
1744 // translators: %s is a Site URL.
1745 $message = sprintf( __( "You're now subscribed to %s.", 'friends' ), $friend_link );
1746 }
1747 }
1748
1749 if ( $message ) {
1750 ?>
1751 <div id="message" class="updated notice is-dismissible"><p>
1752 <?php
1753 echo wp_kses( $message, array( 'a' => array( 'href' => array() ) ) );
1754 // translators: %s is the friends page URL.
1755 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() ) ) );
1756 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>';
1757 ?>
1758 </p></div>
1759 <?php
1760 return true;
1761 }
1762
1763 ?>
1764 <div id="message" class="updated notice is-dismissible"><p>
1765 <?php
1766 // translators: %s is a username.
1767 echo esc_html( sprintf( __( 'User %s could not be assigned the appropriate role.', 'friends' ), $friend_user->display_name ) );
1768 ?>
1769 </p></div>
1770 <?php
1771 return false;
1772 }
1773
1774 /**
1775 * Process the Add Friend form.
1776 *
1777 * @param array $vars The POST or GET variables.
1778 *
1779 * @return boolean A \WP_Error or void.
1780 */
1781 public function process_admin_add_friend( $vars ) {
1782 $errors = new \WP_Error();
1783 $args = array();
1784
1785 $friend_url = isset( $vars['friend_url'] ) ? trim( $vars['friend_url'] ) : '';
1786 $codeword = isset( $vars['codeword'] ) ? trim( $vars['codeword'] ) : '';
1787 $message = isset( $vars['message'] ) ? trim( $vars['message'] ) : '';
1788
1789 $friends_plugin = false;
1790 $friend_user = false;
1791
1792 $protocol = wp_parse_url( $friend_url, PHP_URL_SCHEME );
1793 if ( ! $protocol ) {
1794 // Allow adding a friend by username.
1795 if ( is_multisite() ) {
1796 $friend_user = get_user_by( 'login', $friend_url );
1797 if ( $friend_user ) {
1798 $site = get_active_blog_for_user( $friend_user->ID );
1799 // Ensure we're using the same URL protocol.
1800 $friend_url = set_url_scheme( $site->siteurl );
1801 }
1802 }
1803
1804 // If unsuccessful, then the protocol was forgotten.
1805 if ( ! $friend_user ) {
1806 $friend_url = apply_filters( 'friends_rewrite_incoming_url', 'https://' . $friend_url, $friend_url );
1807 }
1808 }
1809 $friend_user_login = apply_filters( 'friends_suggest_user_login', User::get_user_login_for_url( $friend_url ), $friend_url );
1810 $friend_display_name = apply_filters( 'friends_suggest_display_name', User::get_display_name_for_url( $friend_url ), $friend_url );
1811
1812 $friend_user = get_user_by( 'login', $friend_user_login );
1813
1814 if ( $friend_user ) {
1815 $args['friends_multisite_user_login'] = $friend_user_login;
1816 $args['friends_multisite_display_name'] = $friend_display_name;
1817 }
1818 $rest_url = false;
1819
1820 if ( ( isset( $vars['step2'] ) && isset( $vars['feeds'] ) && is_array( $vars['feeds'] ) ) || isset( $vars['step3'] ) ) {
1821 $friend_user_login = str_replace( ' ', '-', sanitize_user( $vars['user_login'] ) );
1822 $friend_display_name = sanitize_text_field( $vars['display_name'] );
1823 if ( ! $friend_user_login ) {
1824 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1825 $errors->add( 'user_login', __( '<strong>Error</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
1826 } elseif ( ! is_multisite() && username_exists( $friend_user_login ) ) {
1827 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
1828 $errors->add( 'user_login', __( '<strong>Error</strong>: This username is already registered. Please choose another one.' ) );
1829 }
1830
1831 $feeds = $vars['feeds'];
1832 if ( ! $errors->has_errors() ) {
1833 $friend_user = false;
1834 if ( isset( $vars['friendship'] ) ) {
1835 $friend_user = $this->send_friend_request( $vars['friendship'], $friend_user_login, $friend_url, $friend_display_name, $codeword, $message );
1836 if ( $friend_user->has_errors() ) {
1837 $vars['errors'] = $friend_user;
1838 }
1839 }
1840
1841 $avatar = null;
1842 $description = null;
1843 foreach ( $feeds as $feed_details ) {
1844 if ( ! $avatar && ! empty( $feed_details['avatar'] ) ) {
1845 $avatar = $feed_details['avatar'];
1846 }
1847 if ( ! $description && ! empty( $feed_details['description'] ) ) {
1848 $description = $feed_details['description'];
1849 }
1850 }
1851
1852 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1853 $friend_user = User::create( $friend_user_login, 'subscription', $friend_url, $friend_display_name, $avatar, $description );
1854 }
1855
1856 return $this->process_admin_add_friend_response( $friend_user, $vars );
1857 }
1858
1859 if ( isset( $vars['friendship'] ) ) {
1860 $rest_url = $vars['friendship'];
1861 } else {
1862 $rest_url = $this->friends->rest->get_friends_rest_url( $feeds );
1863 }
1864 } else {
1865 if ( home_url() === trailingslashit( $friend_url ) ) {
1866 return new \WP_Error( 'friend-yourself', __( 'It seems like you sent a friend request to yourself.', 'friends' ) );
1867 }
1868
1869 $friend_user = User::get_user( $friend_user_login );
1870 if ( $friend_user && ! is_wp_error( $friend_user ) ) {
1871 if ( $friend_user->is_valid_friend() ) {
1872 return new \WP_Error( 'already-friend', __( 'You are already friends with this site.', 'friends' ) );
1873 }
1874
1875 // translators: %s is the name of a friend / site.
1876 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>' ) );
1877 }
1878
1879 $feeds = $this->friends->feed->discover_available_feeds( $friend_url );
1880 if ( is_wp_error( $feeds ) ) {
1881 return $feeds;
1882 }
1883 if ( ! $feeds ) {
1884 return new \WP_Error( 'no-feed-found', __( 'No suitable feed was found at the provided address.', 'friends' ) );
1885 }
1886
1887 $better_display_name = User::get_display_name_from_feeds( $feeds );
1888 if ( $better_display_name ) {
1889 $friend_display_name = $better_display_name;
1890 }
1891
1892 $rest_url = $this->friends->rest->get_friends_rest_url( $feeds );
1893 }
1894
1895 if ( $rest_url ) {
1896 $friends_plugin = $rest_url;
1897 unset( $feeds[ $rest_url ] );
1898 }
1899
1900 if ( isset( $vars['quick-subscribe'] ) ) {
1901 $vars['feeds'] = $feeds;
1902 $vars['subscribe'] = array();
1903 foreach ( $feeds as $feed_url => $details ) {
1904 if ( isset( $details['autoselect'] ) && $details['autoselect'] ) {
1905 $vars['subscribe'][] = $feed_url;
1906 }
1907 }
1908
1909 $friend_user = false;
1910 if ( isset( $rest_url ) ) {
1911 $friend_user = $this->send_friend_request( $rest_url, $friend_user_login, $friend_url, $friend_display_name, $codeword, $message );
1912 }
1913
1914 $avatar = null;
1915 $description = null;
1916 foreach ( $feeds as $feed_details ) {
1917 if ( ! $avatar && ! empty( $feed_details['avatar'] ) ) {
1918 $avatar = $feed_details['avatar'];
1919 }
1920 if ( ! $description && ! empty( $feed_details['description'] ) ) {
1921 $description = $feed_details['description'];
1922 }
1923 }
1924
1925 if ( ! $friend_user || is_wp_error( $friend_user ) ) {
1926 $friend_user = User::create( $friend_user_login, 'subscription', $friend_url, $friend_display_name, $avatar, $description );
1927 }
1928
1929 return $this->process_admin_add_friend_response( $friend_user, $vars );
1930 }
1931
1932 Friends::template_loader()->get_template_part(
1933 'admin/settings-header',
1934 null,
1935 array(
1936 'active' => 'add-friend-confirm',
1937 'title' => __( 'Add New Friend', 'friends' ),
1938 'menu' => array(
1939 '1. ' . __( 'Enter Details', 'friends' ) => 'add-friend' . ( isset( $friend_url ) ? '&url=' . urlencode( $friend_url ) : '' ),
1940 '2. ' . __( 'Confirm', 'friends' ) => 'add-friend-confirm',
1941 ),
1942 )
1943 );
1944
1945 if ( $errors->has_errors() ) {
1946 ?>
1947 <div id="message" class="updated notice is-dismissible"><p><?php echo wp_kses( $errors->get_error_message(), array( 'strong' => array() ) ); ?></p>
1948 </div>
1949 <?php
1950 }
1951
1952 Friends::template_loader()->get_template_part(
1953 'admin/select-feeds',
1954 null,
1955 array_merge(
1956 $args,
1957 array(
1958 'friends_plugin' => $friends_plugin,
1959 'friend_url' => $friend_url,
1960 'friend_user_login' => $friend_user_login,
1961 'friend_display_name' => $friend_display_name,
1962 'friend_roles' => $this->get_friend_roles(),
1963 'default_role' => get_option( 'friends_default_friend_role', 'friend' ),
1964 'codeword' => $codeword,
1965 'message' => $message,
1966 'post_formats' => array_merge( array( 'autodetect' => __( 'Autodetect Post Format', 'friends' ) ), get_post_format_strings() ),
1967 'registered_parsers' => $this->friends->feed->get_registered_parsers(),
1968 'feeds' => $feeds,
1969 )
1970 )
1971 );
1972 }
1973
1974 /**
1975 * Render the admin form for sending a friend request.
1976 */
1977 public function render_admin_add_friend() {
1978 if ( ! friends::has_required_privileges() ) {
1979 wp_die( esc_html__( 'Sorry, you are not allowed to add friends.', 'friends' ) );
1980 }
1981
1982 if ( ! empty( $_GET['preview'] ) ) {
1983 $url = $_GET['preview'];
1984
1985 ?>
1986 <h1>
1987 <?php
1988 // translators: %s is a URL.
1989 echo esc_html( sprintf( __( 'Preview for %s', 'friends' ), $url ) );
1990 ?>
1991 </h1>
1992 <?php
1993
1994 if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'preview-feed' ) ) {
1995 ?>
1996 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'For security reasons, this preview is not available.', 'friends' ); ?></p>
1997 </div>
1998 <?php
1999 exit;
2000 }
2001
2002 $parser_name = $this->friends->feed->get_registered_parser( $_GET['parser'] );
2003 if ( ! $parser_name ) {
2004 ?>
2005 <div id="message" class="updated notice is-dismissible"><p><?php esc_html_e( 'An unknown parser name was supplied.', 'friends' ); ?></p>
2006 </div>
2007 <?php
2008 exit;
2009 }
2010 ?>
2011 <h3><?php esc_html_e( 'Parser Details', 'friends' ); ?></h3>
2012 <ul id="parser">
2013 <li>
2014 <?php
2015 echo wp_kses(
2016 // translators: %s is the name of a parser, e.g. simplepie.
2017 sprintf( __( 'Parser: %s', 'friends' ), $parser_name ),
2018 array(
2019 'a' => array(
2020 'href' => array(),
2021 'rel' => array(),
2022 'target' => array(),
2023 ),
2024 )
2025 );
2026 ?>
2027 </li>
2028 </ul>
2029 <h3><?php esc_html_e( 'Items in the Feed', 'friends' ); ?></h3>
2030
2031 <?php
2032
2033 $items = $this->friends->feed->preview( $_GET['parser'], $url, isset( $_GET['feed'] ) ? intval( $_GET['feed'] ) : null );
2034 if ( is_wp_error( $items ) ) {
2035 ?>
2036 <div id="message" class="updated notice is-dismissible"><p><?php echo esc_html( $items->get_error_message() ); ?></p>
2037 </div>
2038 <?php
2039 exit;
2040 }
2041 ?>
2042
2043 <ul>
2044 <?php
2045 foreach ( $items as $item ) {
2046 $title = $item->title;
2047 if ( 'status' === $item->post_format ) {
2048 $title = strip_tags( $item->content );
2049 }
2050 ?>
2051 <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 ); ?>):
2052 <?php if ( $title ) : ?>
2053 <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
2054 <?php else : ?>
2055 <p>
2056 <?php
2057 echo wp_kses(
2058 wp_trim_excerpt( $item->content ),
2059 array(
2060 'a' => array( 'href' => array() ),
2061 'img' => array( 'src' => array() ),
2062 )
2063 );
2064 ?>
2065 </p>
2066 <?php endif; ?>
2067 </li>
2068 <?php
2069 }
2070 ?>
2071 </ul>
2072 <?php
2073 return;
2074 }
2075
2076 if ( apply_filters( 'friends_debug', false ) && isset( $_GET['next'] ) ) {
2077 $_POST = $_REQUEST;
2078 $_POST['_wpnonce'] = wp_create_nonce( 'add-friend' );
2079 if ( ! empty( $_POST['url'] ) && ! isset( $_POST['friend_url'] ) ) {
2080 $_POST['friend_url'] = $_POST['url'];
2081 $parsed_url = parse_url( $_POST['friend_url'] );
2082 if ( isset( $parsed_url['host'] ) ) {
2083 if ( ! isset( $parsed_url['scheme'] ) ) {
2084 $_POST['friend_url'] = 'https://' . ltrim( $_POST['friend_url'], '/' );
2085 }
2086 }
2087 }
2088 }
2089
2090 $response = null;
2091 $postdata = apply_filters( 'friends_add_friend_postdata', $_POST );
2092 if ( ! empty( $postdata ) ) {
2093 if ( ! wp_verify_nonce( $postdata['_wpnonce'], 'add-friend' ) ) {
2094 $response = new \WP_Error( 'invalid-nonce', __( 'For security reasons, please verify the URL and click next if you want to proceed.', 'friends' ) );
2095 } else {
2096 $response = $this->process_admin_add_friend( $postdata );
2097 }
2098 if ( is_wp_error( $response ) ) {
2099 ?>
2100 <div id="message" class="updated notice is-dismissible"><p>
2101 <?php
2102 $message = $response->get_error_message();
2103 if ( $response->get_error_data() ) {
2104 $message .= ' (' . $response->get_error_data() . ')';
2105 }
2106 echo wp_kses(
2107 $message,
2108 array(
2109 'strong' => array(),
2110 'a' => array(
2111 'href' => array(),
2112 'rel' => array(),
2113 'target' => array(),
2114 ),
2115 )
2116 );
2117 ?>
2118 </p>
2119 </div>
2120 <?php
2121 }
2122 if ( is_null( $response ) ) {
2123 return;
2124 }
2125 }
2126
2127 $args = array(
2128 'friend_url' => '',
2129 'add-friends-placeholder' => apply_filters( 'friends_add_friends_input_placeholder', __( 'Enter URL', 'friends' ) ),
2130 );
2131
2132 if ( ! empty( $_GET['url'] ) || ! empty( $_POST['url'] ) ) {
2133 $friend_url = isset( $_GET['url'] ) ? $_GET['url'] : $_POST['url'];
2134 $parsed_url = parse_url( $friend_url );
2135 if ( isset( $parsed_url['host'] ) ) {
2136 if ( ! isset( $parsed_url['scheme'] ) ) {
2137 $args['friend_url'] = apply_filters( 'friends_rewrite_incoming_url', 'https://' . ltrim( $friend_url, '/' ), $friend_url, $parsed_url );
2138 } else {
2139 $args['friend_url'] = $friend_url;
2140 }
2141 } elseif ( preg_match( '/^@?' . Feed_Parser_ActivityPub::ACTIVITYPUB_USERNAME_REGEXP . '$/i', $friend_url ) ) {
2142 $args['friend_url'] = $friend_url;
2143 }
2144 }
2145
2146 Friends::template_loader()->get_template_part(
2147 'admin/settings-header',
2148 null,
2149 array(
2150 'active' => 'add-friend',
2151 'title' => __( 'Add New Friend', 'friends' ),
2152 'menu' => array(
2153 '1. ' . __( 'Enter Details', 'friends' ) => 'add-friend' . ( isset( $friend_url ) ? '&url=' . urlencode( $friend_url ) : '' ),
2154 '2. ' . __( 'Confirm', 'friends' ) => false,
2155 ),
2156 )
2157 );
2158
2159 Friends::template_loader()->get_template_part( 'admin/add-friend', null, $args );
2160
2161 Friends::template_loader()->get_template_part(
2162 'admin/latest-friends',
2163 null,
2164 array(
2165 'friend_requests' => User_Query::recent_friends_subscriptions( 25 )->get_results(),
2166 )
2167 );
2168 Friends::template_loader()->get_template_part( 'admin/settings-footer', null, $args );
2169 }
2170
2171 /**
2172 * Process the admin notification manager form submission.
2173 */
2174 public function process_admin_notification_manager() {
2175
2176 if ( empty( $_POST ) || empty( $_POST['friend_listed'] ) ) {
2177 return;
2178 }
2179
2180 if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'notification-manager' ) ) {
2181 return;
2182 }
2183
2184 $this->check_admin_settings();
2185 $friend_ids = $_POST['friend_listed'];
2186 $current_user_id = get_current_user_id();
2187 $hide_from_friends_page = array();
2188
2189 foreach ( $friend_ids as $friend_id ) {
2190 if ( ! isset( $_POST['show_on_friends_page'][ $friend_id ] ) ) {
2191 $hide_from_friends_page[] = $friend_id;
2192 }
2193
2194 $no_new_post_notification = ! isset( $_POST['new_post_notification'][ $friend_id ] );
2195 if ( get_user_option( 'friends_no_new_post_notification_' . $friend_id ) !== $no_new_post_notification ) {
2196 update_user_option( $current_user_id, 'friends_no_new_post_notification_' . $friend_id, $no_new_post_notification );
2197 }
2198
2199 $no_keyword_notification = ! isset( $_POST['keyword_notification'][ $friend_id ] );
2200 if ( get_user_option( 'friends_no_keyword_notification_' . $friend_id ) !== $no_keyword_notification ) {
2201 update_user_option( $current_user_id, 'friends_no_keyword_notification_' . $friend_id, $no_keyword_notification );
2202 }
2203 }
2204
2205 update_user_option( $current_user_id, 'friends_hide_from_friends_page', $hide_from_friends_page );
2206
2207 do_action( 'friends_notification_manager_after_form_submit', $friend_ids );
2208
2209 if ( isset( $_GET['_wp_http_referer'] ) ) {
2210 wp_safe_redirect( wp_get_referer() );
2211 } else {
2212 wp_safe_redirect( add_query_arg( 'updated', '1', remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
2213 }
2214 exit;
2215 }
2216
2217 /**
2218 * Render the admin notification manager.
2219 */
2220 public function render_admin_notification_manager() {
2221 Friends::template_loader()->get_template_part(
2222 'admin/settings-header',
2223 null,
2224 array(
2225 'active' => 'friends-notification-manager',
2226 'title' => __( 'Friends', 'friends' ),
2227 )
2228 );
2229 $this->check_admin_settings();
2230
2231 ?>
2232 <h1><?php esc_html_e( 'Notification Manager', 'friends' ); ?></h1>
2233 <?php
2234
2235 $friend_users = new User_Query(
2236 array(
2237 'role__in' => array( 'friend', 'acquaintance', 'pending_friend_request', 'friend_request', 'subscription' ),
2238 'orderby' => 'display_name',
2239 'order' => 'ASC',
2240 )
2241 );
2242
2243 $hide_from_friends_page = get_user_option( 'friends_hide_from_friends_page' );
2244 if ( ! $hide_from_friends_page ) {
2245 $hide_from_friends_page = array();
2246 }
2247
2248 Friends::template_loader()->get_template_part(
2249 'admin/notification-manager',
2250 null,
2251 array(
2252 'friend_users' => $friend_users->get_results(),
2253 'friends_settings_url' => add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), self_admin_url( 'admin.php?page=friends-settings' ) ),
2254 'hide_from_friends_page' => $hide_from_friends_page,
2255 'no_new_post_notification' => get_user_option( 'friends_no_new_post_notification' ),
2256 'no_keyword_notification' => get_user_option( 'friends_no_keyword_notification' ),
2257 'active_keywords' => Feed::get_active_notification_keywords(),
2258 )
2259 );
2260
2261 Friends::template_loader()->get_template_part( 'admin/settings-footer' );
2262 }
2263
2264 /**
2265 * Gets the friend roles.
2266 *
2267 * @return array The friend roles.
2268 */
2269 public function get_friend_roles() {
2270 $roles = new \WP_Roles();
2271 $friend_roles = array();
2272 foreach ( $roles->roles as $role => $data ) {
2273 if ( isset( $data['capabilities']['friend'] ) ) {
2274 $friend_roles[ $role ] = $data['name'];
2275 }
2276 }
2277 return $friend_roles;
2278 }
2279
2280 /**
2281 * Gets the roles associated with the Friends plugin.
2282 *
2283 * @return array The associated roles.
2284 */
2285 public static function get_associated_roles() {
2286 $roles = new \WP_Roles();
2287 $friend_roles = array();
2288 foreach ( $roles->roles as $role => $data ) {
2289 if ( isset( $data['capabilities']['friends_plugin'] ) ) {
2290 $friend_roles[ $role ] = $data['name'];
2291 }
2292 }
2293 return $friend_roles;
2294 }
2295
2296 public static function get_users_url() {
2297 return 'admin.php?page=friends-list';
2298 }
2299
2300 /**
2301 * Add actions to the user rows
2302 *
2303 * @param array $actions The existing actions.
2304 * @param \WP_User $user The user in question.
2305 * @return array The extended actions.
2306 */
2307 public static function user_row_actions( array $actions, \WP_User $user ) {
2308 if (
2309 ! Friends::has_required_privileges() ||
2310 (
2311 ! $user->has_cap( 'friend_request' ) &&
2312 ! $user->has_cap( 'pending_friend_request' ) &&
2313 ! $user->has_cap( 'friend' ) &&
2314 ! $user->has_cap( 'subscription' )
2315 )
2316 ) {
2317 return $actions;
2318 }
2319
2320 if ( is_multisite() ) {
2321 // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2322 $actions = array_merge( array( 'edit' => '<a href="' . esc_url( self_admin_url( 'admin.php?page=edit-friend&user=' . $user->user_login ) ) . '">' . __( 'Edit' ) . '</a>' ), $actions );
2323 }
2324
2325 // Ensuire we have a friends user here.
2326 $user = new User( $user );
2327
2328 $actions['view'] = Frontend::get_link(
2329 $user->user_url,
2330 sprintf(
2331 // translators: %s: Author’s display name.
2332 __( 'Visit %s&#8217;s website' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2333 $user->display_name
2334 ),
2335 array(),
2336 $user
2337 );
2338 unset( $actions['resetpassword'] );
2339
2340 if ( $user->has_cap( 'friend_request' ) ) {
2341 $link = self_admin_url( wp_nonce_url( 'users.php?action=accept_friend_request&users[]=' . $user->ID ) );
2342
2343 $actions['user_accept_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Accept Friend Request', 'friends' ) . '</a>';
2344 $message = get_user_option( 'friends_request_message', $user->ID );
2345 $actions['friends friends_request_date'] = '<br/><span class="nonessential">' . esc_html(
2346 sprintf(
2347 // translators: %s is a date.
2348 __( 'Requested on %s', 'friends' ),
2349 date_i18n( __( 'F j, Y g:i a' ), strtotime( $user->user_registered ) ) // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2350 )
2351 ) . '</span>';
2352 if ( $message ) {
2353 // translators: %s is a message text.
2354 $actions['friends friend_request_message'] = '<br/><span class="nonessential">' . esc_html( sprintf( __( 'Message: %s', 'friends' ), $message ) ) . '</span>';
2355 }
2356 }
2357
2358 if ( $user->has_cap( 'pending_friend_request' ) || $user->has_cap( 'subscription' ) ) {
2359 $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' );
2360 if ( $user->has_cap( 'pending_friend_request' ) ) {
2361 $actions['user_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Resend Friend Request', 'friends' ) . '</a>';
2362 } elseif ( $user->has_cap( 'subscription' ) ) {
2363 $actions['user_friend_request'] = '<a href="' . esc_url( $link ) . '">' . __( 'Send Friend Request', 'friends' ) . '</a>';
2364 }
2365 }
2366
2367 return $actions;
2368 }
2369
2370 /**
2371 * Handle bulk friend request approvals on the user page
2372 *
2373 * @param string $sendback The URL to send the user back to.
2374 * @param string $action The requested action.
2375 * @param array $users The selected users.
2376 */
2377 public function handle_bulk_friend_request_approval( $sendback, $action, $users ) {
2378 if ( 'accept_friend_request' !== $action ) {
2379 return $sendback;
2380 }
2381
2382 $accepted = 0;
2383 foreach ( $users as $user_id ) {
2384 $user = new User( $user_id );
2385 if ( ! $user || is_wp_error( $user ) ) {
2386 continue;
2387 }
2388
2389 if ( ! $user->has_cap( 'friend_request' ) ) {
2390 continue;
2391 }
2392
2393 if ( $user->has_cap( 'friend' ) ) {
2394 continue;
2395 }
2396
2397 $user->set_role( get_option( 'friends_default_friend_role', 'friend' ) );
2398 ++$accepted;
2399 }
2400
2401 if ( ! $sendback ) {
2402 return array(
2403 'accepted' => $accepted,
2404 );
2405 }
2406
2407 $sendback = add_query_arg( 'accepted', $accepted, $sendback );
2408 $sendback = remove_query_arg( 'role', $sendback );
2409 wp_safe_redirect( $sendback );
2410 }
2411
2412 /**
2413 * Add options to the Bulk dropdown on the users page
2414 *
2415 * @param array $actions The existing bulk options.
2416 * @return array The extended bulk options.
2417 */
2418 public function add_user_bulk_options( $actions ) {
2419 $friends = User_Query::all_friend_requests();
2420 $friends->get_results();
2421
2422 if ( ! empty( $friends ) ) {
2423 $actions['accept_friend_request'] = __( 'Accept Friend Request', 'friends' );
2424 }
2425
2426 $friends = User_Query::all_subscriptions();
2427 $friends->get_results();
2428
2429 if ( ! empty( $friends ) ) {
2430 $actions['friend_request'] = __( 'Send Friend Request', 'friends' );
2431 }
2432
2433 return $actions;
2434 }
2435
2436 /**
2437 * Add a column "Posts" (that emcompasses both user and friend posts.)
2438 *
2439 * @param array $columns The columns.
2440 *
2441 * @return array The columns extended by the friends_posts.
2442 */
2443 public function user_list_columns( $columns ) {
2444 $columns['friends_posts'] = __( 'Friend Posts', 'friends' );
2445 unset( $columns['email'] );
2446 return $columns;
2447 }
2448
2449 /**
2450 * Return the results for the friends_posts column.
2451 *
2452 * @param string $output Custom column output. Default empty.
2453 * @param string $column_name Column name.
2454 * @param int $user_id ID of the currently-listed user.
2455 *
2456 * @return string The column contents.
2457 */
2458 public static function user_list_custom_column( $output, $column_name, $user_id ) {
2459 if ( 'friends_posts' !== $column_name ) {
2460 return $output;
2461 }
2462 $numposts = count_user_posts( $user_id, apply_filters( 'friends_frontend_post_types', array( 'post' ) ) );
2463 $user = User::get_user_by_id( $user_id );
2464 return sprintf(
2465 '<a href="%s" class="edit"><span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
2466 $user ? $user->get_local_friends_page_url() : "edit.php?author={$user_id}",
2467 $numposts,
2468 sprintf(
2469 /* translators: %s: Number of posts. */
2470 _n( '%s post', '%s posts', $numposts ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2471 number_format_i18n( $numposts )
2472 )
2473 );
2474 }
2475
2476 /**
2477 * Override the post title for specific post formats.
2478 *
2479 * @param string $title The title.
2480 * @param int $post_id The post id.
2481 *
2482 * @return string The potentially overriden title.
2483 */
2484 public function override_post_format_title( $title, $post_id = null ) {
2485 if ( $post_id && empty( $title ) && is_admin() && function_exists( 'get_current_screen' ) ) {
2486 $screen = get_current_screen();
2487 if ( $screen && 'edit-post' === $screen->id ) {
2488 if ( 'status' === get_post_format() ) {
2489 $post = get_post( $post_id );
2490 return wp_trim_words( wp_strip_all_tags( $post->post_content ) );
2491 }
2492 }
2493 }
2494 return $title;
2495 }
2496
2497 /**
2498 * Adds the friend requests to the unread count.
2499 *
2500 * @param int $unread The unread count.
2501 *
2502 * @return int Unread count + friend requests.
2503 */
2504 public function friends_unread_friend_request_count( $unread ) {
2505 $friend_requests = User_Query::all_friend_requests();
2506 return $unread + $friend_requests->get_total();
2507 }
2508
2509 /**
2510 * Add open friend requests to the menu.
2511 *
2512 * @param \WP_Menu $wp_menu The wp menu.
2513 * @param string $my_url My url.
2514 */
2515 public function friends_add_menu_open_friend_request( $wp_menu, $my_url ) {
2516 $friend_request_count = $this->friends_unread_friend_request_count( 0 );
2517 if ( $friend_request_count > 0 ) {
2518 $wp_menu->add_menu(
2519 array(
2520 'id' => 'open-friend-requests',
2521 'parent' => 'friends-menu',
2522 // translators: %s is the number of open friend requests.
2523 'title' => esc_html( sprintf( _n( 'Review %s Friend Request', 'Review %s Friends Request', $friend_request_count, 'friends' ), $friend_request_count ) ),
2524 'href' => $my_url . '/wp-admin/admin.php?page=friends-list-requests',
2525 )
2526 );
2527 }
2528 }
2529
2530 /**
2531 * Get the unread badge HTML
2532 *
2533 * @return string The unread badge HTML.
2534 */
2535 public function get_unread_badge() {
2536 $unread_count = apply_filters( 'friends_unread_count', 0 );
2537 if ( 0 === intval( $unread_count ) ) {
2538 return '';
2539 }
2540
2541 if ( get_user_option( 'friends_unobtrusive_badge' ) ) {
2542 return ' (' . $unread_count . ')';
2543 }
2544 $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">';
2545 // translators: %s is the number of unread items.
2546 $unread_badge .= sprintf( _n( '%s unread item', '%s unread items', $unread_count, 'friends' ), $unread_count );
2547 $unread_badge .= '</span></div>';
2548 return $unread_badge;
2549 }
2550
2551 /**
2552 * Add a Friends menu to the admin bar
2553 *
2554 * @param \WP_Admin_Bar $wp_menu The admin bar to modify.
2555 */
2556 public function admin_bar_friends_menu( \WP_Admin_Bar $wp_menu ) {
2557 $my_url = false;
2558 $my_own_site = false;
2559 $on_my_own_site = false;
2560 $we_requested_friendship = false;
2561 $they_requested_friendship = false;
2562
2563 if ( current_user_can( 'friend' ) ) {
2564 $current_user = wp_get_current_user();
2565 if ( ! $current_user->user_url ) {
2566 return;
2567 }
2568
2569 $my_url = $current_user->user_url;
2570 } elseif ( is_multisite() ) {
2571 $site = get_active_blog_for_user( get_current_user_id() );
2572 if ( ! $site ) {
2573 // If we cannot find a site, we shouldn't show the admin bar entry.
2574 return;
2575 }
2576
2577 $my_url = set_url_scheme( $site->siteurl );
2578 $my_own_site = $site;
2579 $on_my_own_site = get_current_blog_id() === intval( $site->blog_id );
2580 if ( is_user_member_of_blog( get_current_user_id(), get_current_blog_id() ) ) {
2581 if ( current_user_can( 'pending_friend_request' ) ) {
2582 $they_requested_friendship = true;
2583 } elseif ( current_user_can( 'friend_request' ) ) {
2584 $we_requested_friendship = true;
2585 }
2586 }
2587 } elseif ( Friends::has_required_privileges() ) {
2588 $my_url = home_url();
2589 $on_my_own_site = true;
2590 }
2591
2592 if ( ! $on_my_own_site && $my_own_site ) {
2593 switch_to_blog( $my_own_site->blog_id );
2594 }
2595
2596 $unread = '';
2597 if ( $on_my_own_site ) {
2598 $unread = $this->get_unread_badge();
2599 }
2600 $wp_menu->add_node(
2601 array(
2602 'id' => 'friends-menu',
2603 'parent' => '',
2604 'title' => '<span class="ab-icon dashicons dashicons-groups"></span> <span class="ab-label">' . esc_html( __( 'Friends', 'friends' ) ) . $unread . '</span>',
2605 'href' => $my_url . '/friends/',
2606 )
2607 );
2608
2609 if ( $on_my_own_site ) {
2610 do_action( 'friends_own_site_menu_top', $wp_menu, $my_url );
2611 }
2612
2613 if ( ! $on_my_own_site && $my_own_site ) {
2614 restore_current_blog();
2615 }
2616
2617 do_action( 'friends_current_site_menu_top', $wp_menu, $my_url );
2618
2619 $wp_menu->add_menu(
2620 array(
2621 'id' => 'your-feed',
2622 'parent' => 'friends-menu',
2623 'title' => esc_html__( 'My Friends Feed', 'friends' ),
2624 'href' => $my_url . '/friends/',
2625 )
2626 );
2627
2628 if ( $they_requested_friendship ) {
2629 $wp_menu->add_menu(
2630 array(
2631 'id' => 'add-friend',
2632 'parent' => 'friends-menu',
2633 'title' => '<span style="border-left: 2px solid #d63638; padding-left: .5em">' . esc_html(
2634 sprintf(
2635 // translators: %s is a site title.
2636 __( "Respond to %s's friend request", 'friends' ),
2637 get_bloginfo( 'name' )
2638 ) . '</span>'
2639 ),
2640 'href' => $my_url . '/wp-admin/admin.php?page=friends-list-requests',
2641 )
2642 );
2643 }
2644
2645 if ( $on_my_own_site ) {
2646 $wp_menu->add_menu(
2647 array(
2648 'id' => 'your-profile',
2649 'parent' => 'friends-menu',
2650 'title' => esc_html__( 'My Public Friends Profile', 'friends' ),
2651 'href' => $my_url . '/friends/?public',
2652 )
2653 );
2654 $wp_menu->add_menu(
2655 array(
2656 'id' => 'friends-requests',
2657 'parent' => 'friends-menu',
2658 'title' => esc_html__( 'My Friends & Requests', 'friends' ),
2659 'href' => $my_url . '/wp-admin/admin.php?page=friends-list',
2660 )
2661 );
2662 $wp_menu->add_menu(
2663 array(
2664 'id' => 'friends',
2665 'parent' => 'friends-menu',
2666 'title' => esc_html__( 'Settings' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2667 'href' => $my_url . '/wp-admin/admin.php?page=friends-settings',
2668 )
2669 );
2670 } else {
2671 if ( ! current_user_can( 'friend' ) ) {
2672 if ( $we_requested_friendship ) {
2673 $wp_menu->add_menu(
2674 array(
2675 'id' => 'add-friend',
2676 'parent' => 'friends-menu',
2677 'title' => esc_html__( 'Friendship Already Requested', 'friends' ),
2678 'href' => $my_url . '/wp-admin/' . self::get_users_url(),
2679 )
2680 );
2681 } elseif ( ! $they_requested_friendship ) {
2682 $wp_menu->add_menu(
2683 array(
2684 'id' => 'add-friend',
2685 'parent' => 'friends-menu',
2686 'title' => esc_html(
2687 sprintf(
2688 // translators: %s is a site title.
2689 __( 'Add %s as a friend', 'friends' ),
2690 get_bloginfo( 'name' )
2691 )
2692 ),
2693 'href' => $my_url . '/?add-friend=' . urlencode( home_url() ),
2694 )
2695 );
2696 }
2697 }
2698
2699 $wp_menu->add_menu(
2700 array(
2701 'id' => 'profile',
2702 'parent' => 'friends-menu',
2703 'title' => esc_html(
2704 sprintf(
2705 // translators: %s is a site title.
2706 __( "%s's Profile", 'friends' ),
2707 get_bloginfo( 'name' )
2708 )
2709 ),
2710 'href' => home_url( '/friends/' ),
2711 )
2712 );
2713 }
2714 }
2715
2716 /**
2717 * Add Friend entries to the New Content admin section
2718 *
2719 * @param \WP_Admin_Bar $wp_menu The admin bar to modify.
2720 */
2721 public function admin_bar_new_content( \WP_Admin_Bar $wp_menu ) {
2722 if ( Friends::has_required_privileges() ) {
2723 $wp_menu->add_menu(
2724 array(
2725 'id' => 'new-friend-request',
2726 'parent' => 'new-content',
2727 'title' => esc_html__( 'Friend', 'friends' ),
2728 'href' => self_admin_url( 'admin.php?page=add-friend' ),
2729 )
2730 );
2731 $wp_menu->add_menu(
2732 array(
2733 'id' => 'new-subscription',
2734 'parent' => 'new-content',
2735 'title' => esc_html__( 'Subscription', 'friends' ),
2736 'href' => self_admin_url( 'admin.php?page=add-friend' ),
2737 )
2738 );
2739 }
2740 }
2741
2742 /**
2743 * Show friends admin bar item on mobile.
2744 */
2745 public function admin_bar_mobile() {
2746 if ( ! is_user_logged_in() ) {
2747 return;
2748 }
2749 ?>
2750 <style type="text/css" media="screen">
2751 @media screen and (max-width: 782px) {
2752 #wpadminbar #wp-admin-bar-friends, #wpadminbar #wp-admin-bar-friends .ab-icon {
2753 display: block !important;
2754 }
2755 #wpadminbar #wp-admin-bar-friends .ab-label {
2756 display: none !important;
2757 }
2758 }
2759 </style>
2760 <?php
2761 }
2762
2763
2764 /**
2765 * Fires at the end of the delete users form prior to the confirm button.
2766 *
2767 * @param \WP_User $current_user \WP_User object for the current user.
2768 * @param array $userids Array of IDs for users being deleted.
2769 */
2770 public function delete_user_form( $current_user, $userids ) {
2771 $only_friends_affiliated = true;
2772 foreach ( $userids as $user_id ) {
2773 $user = new \WP_User( $user_id );
2774 if (
2775 ! $user->has_cap( 'friend_request' ) &&
2776 ! $user->has_cap( 'pending_friend_request' ) &&
2777 ! $user->has_cap( 'friend' ) &&
2778 ! $user->has_cap( 'subscription' )
2779 ) {
2780 $only_friends_affiliated = false;
2781 break;
2782 }
2783 }
2784
2785 if ( $only_friends_affiliated ) {
2786 ?>
2787 <script type="text/javascript">
2788 jQuery( function () {
2789 jQuery( '#delete_option1' ).closest( 'li' ).hide();
2790 } );
2791 </script>
2792 <?php
2793 }
2794 }
2795
2796 /**
2797 * Actions when a (friend) user is deleted.
2798 *
2799 * @param integer $user_id The user identifier.
2800 */
2801 public function delete_user( $user_id ) {
2802 $friend_user = User::get_user_by_id( $user_id );
2803 if ( ! $friend_user ) {
2804 return; // user was already deleted?
2805 }
2806 // Allow unsubscribing to all these feeds.
2807 foreach ( $friend_user->get_active_feeds() as $feed ) {
2808 do_action( 'friends_user_feed_deactivated', $feed );
2809 $feed->delete();
2810 }
2811
2812 // Delete the rest.
2813 foreach ( $friend_user->get_feeds() as $feed ) {
2814 $feed->delete();
2815 }
2816
2817 foreach ( $friend_user->get_all_post_ids() as $post_id ) {
2818 wp_delete_post( $post_id );
2819 }
2820 }
2821
2822 /**
2823 * Display the Bookmarklets at the Tools section of wp-admin
2824 */
2825 public function toolbox_bookmarklets() {
2826 ?>
2827 <div class="card">
2828 <h2 class="title"><?php esc_html_e( 'Friends', 'friends' ); ?></h2>
2829 <h3><?php esc_html_e( 'Bookmarklets', 'friends' ); ?></h3>
2830
2831 <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>
2832 <p>
2833 <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>
2834 <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>
2835 </p>
2836 <h3><?php esc_html_e( 'Browser Extension', 'friends' ); ?></h3>
2837
2838 <p><?php esc_html_e( 'There is also the option to use a browser extension.', 'friends' ); ?></p>
2839 <p>
2840 <a href="https://addons.mozilla.org/en-US/firefox/addon/wpfriends/"><?php echo esc_html_e( 'Firefox Extension', 'friends' ); ?></a>
2841 </p>
2842 </div>
2843 <?php
2844 }
2845
2846 /**
2847 * Add more "at a glance" items
2848
2849 * @param array $items Items inserted by another plugin.
2850 * @return array Items + our items.
2851 */
2852 public function dashboard_glance_items( $items ) {
2853 $count_users = count_users();
2854 $count = array_merge(
2855 array(
2856 'friend' => 0,
2857 'acquaintance' => 0,
2858 'friend_request' => 0,
2859 'subscription' => 0,
2860 ),
2861 $count_users['avail_roles']
2862 );
2863 $friend_count = $count['friend'] + $count['acquaintance'];
2864 $friend_request_count = $count['friend_request'];
2865 $subscription_count = $count['subscription'];
2866 $friend_post_count = wp_count_posts( Friends::CPT );
2867 $friend_post_count = $friend_post_count->publish + $friend_post_count->private;
2868
2869 $items[] = '<a class="friends" href="' . self_admin_url( 'users.php?role=friend' ) . '">' . sprintf(
2870 // translators: %s is the number of your friends.
2871 _n( '%s Friend', '%s Friends', $friend_count, 'friends' ),
2872 $friend_count
2873 ) . '</a>';
2874 if ( $friend_request_count ) {
2875 // translators: %s is the number of friend requests.
2876 $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>';
2877 }
2878 if ( $subscription_count ) {
2879 // translators: %s is the number of subscriptions.
2880 $items[] = '<a class="subscriptions" href="' . self_admin_url( 'users.php?role=subscription' ) . '">' . sprintf( _n( '%s Subscription', '%s Subscriptions', $subscription_count, 'friends' ), $subscription_count ) . '</a>';
2881 }
2882
2883 if ( $friend_post_count ) {
2884 // translators: %s is the number of friend posts.
2885 $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>';
2886 }
2887 return $items;
2888 }
2889
2890 public function site_status_tests( $tests ) {
2891 $tests['direct']['friends-roles'] = array(
2892 'label' => __( 'Friend roles were created', 'friends' ),
2893 'test' => array( $this, 'friend_roles_test' ),
2894 );
2895 return $tests;
2896 }
2897
2898 public function get_missing_friends_plugin_roles() {
2899 $missing = Friends::get_friends_plugin_roles();
2900 $roles = new \WP_Roles();
2901 foreach ( $roles->roles as $role => $data ) {
2902 if ( isset( $data['capabilities']['friends_plugin'] ) ) {
2903 foreach ( $missing as $k => $cap ) {
2904 if ( isset( $data['capabilities'][ $cap ] ) ) {
2905 unset( $missing[ $k ] );
2906 break;
2907 }
2908 }
2909 }
2910 }
2911
2912 return array_values( $missing );
2913 }
2914
2915 public function friend_roles_test() {
2916 $result = array(
2917 'label' => __( 'The friend roles have been installed', 'friends' ),
2918 'status' => 'good',
2919 'badge' => array(
2920 'label' => __( 'Friends', 'friends' ),
2921 'color' => 'green',
2922 ),
2923 'description' =>
2924 '<p>' .
2925 __( 'The Friends Plugin uses users and user roles to determine friendship status between sites.', 'friends' ) .
2926 '</p>' .
2927 '<p>' .
2928 sprintf(
2929 // translators: %s is a list of roles.
2930 __( 'These are the roles required for the friends plugin: %s', 'friends' ),
2931 implode( ', ', Friends::get_friends_plugin_roles() )
2932 ) .
2933 '</p>',
2934 'test' => 'friends-roles',
2935 );
2936
2937 $missing_friend_roles = $this->get_missing_friends_plugin_roles();
2938 if ( ! empty( $missing_friend_roles ) ) {
2939
2940 $result['label'] = sprintf(
2941 // translators: %s is a list of missing roles.
2942 __( 'Not all friend roles have been installed. Missing: %s', 'friends' ),
2943 implode( ', ', $missing_friend_roles )
2944 );
2945 $result['badge']['color'] = 'red';
2946 $result['status'] = 'critical';
2947 $result['description'] .= '<p>';
2948 $result['description'] .= wp_kses_post(
2949 sprintf(
2950 // translators: %s is a URL.
2951 __( '<strong>To fix this:</strong> <a href="%s">Re-run activation of the Friends plugin</a>.', 'friends' ),
2952 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' ) )
2953 )
2954 );
2955 $result['description'] .= '</p>';
2956 }
2957
2958 return $result;
2959 }
2960
2961 public function site_status_test_php_modules( $modules ) {
2962 $modules['mbstring']['required'] = true;
2963 return $modules;
2964 }
2965
2966 public function site_health_debug( $debug_info ) {
2967 $missing_friend_roles = $this->get_missing_friends_plugin_roles();
2968 $debug_info['friends'] = array(
2969 'label' => __( 'Friends', 'friends' ),
2970 'fields' => array(
2971 'version' => array(
2972 'label' => __( 'Friends Version', 'friends' ),
2973 'value' => Friends::VERSION,
2974 ),
2975 'mbstring' => array(
2976 'label' => __( 'mbstring is available', 'friends' ),
2977 'value' => function_exists( 'mb_check_encoding' ) ? __( 'Yes' ) : __( 'No' ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2978 ),
2979 'roles' => array(
2980 'label' => __( 'Friend roles missing', 'friends' ),
2981 'value' => empty( $missing_friend_roles ) ? sprintf(
2982 // translators: %s is a list of roles.
2983 __( 'All roles found: %s', 'friends' ),
2984 implode( ', ', Friends::get_friends_plugin_roles() )
2985 ) : implode( ', ', $missing_friend_roles ), // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
2986 ),
2987 'main_user' => array(
2988 'label' => __( 'Main Friend User', 'friends' ),
2989 'value' => self::human_readable_main_user(),
2990 ),
2991 'parsers' => array(
2992 'label' => __( 'Registered Parsers', 'friends' ),
2993 'value' => strip_tags( implode( ', ', $this->friends->feed->get_registered_parsers() ) ),
2994 ),
2995 ),
2996 );
2997
2998 return $debug_info;
2999 }
3000
3001 /**
3002 * Returns a human readable string for which user is the main user.
3003 *
3004 * @return string
3005 */
3006 private static function human_readable_main_user() {
3007 $main_user = Friends::get_main_friend_user_id();
3008
3009 if ( ! $main_user ) {
3010 // translators: %d is the number of users.
3011 return esc_html( sprintf( __( 'No main user set. Admin users: %d', 'friends' ), User_Query::all_admin_users()->get_total() ) );
3012 }
3013
3014 $user = new \WP_User( $main_user );
3015
3016 if ( ! $user ) {
3017 return sprintf( '#%1$d %2$s', $main_user, '???' );
3018 }
3019
3020 return sprintf( '#%1$d %2$s', $user->ID, $user->user_login );
3021 }
3022 }
3023