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

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

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