PluginProbe
Friends / 2.7.5
Friends v2.7.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.7.5, at includes/class-admin.php

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