PluginProbe
Friends / 2.7.9
Friends v2.7.9
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.9, at includes/class-admin.php

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