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

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