PluginProbe
Friends / 2.8.5
Friends v2.8.5
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.5, at includes/class-admin.php

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