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

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

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