PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-publicize/src/class-publicize.php +178 -612 12.3.2 → 16.3 View file →
@@ -6,12 +6,13 @@
6 6 */
7 7
8 8 namespace Automattic\Jetpack\Publicize;
9 9
10 -use Automattic\Jetpack\Connection\Tokens;
11 -use Automattic\Jetpack\Redirect;
10 +use Automattic\Jetpack\Connection\Client;
12 11 use Jetpack_IXR_Client;
13 12 use Jetpack_Options;
13 +use WP_Error;
14 +use WP_Post;
14 15
15 16 /**
16 17 * Extend the base class with Jetpack-specific functionality.
17 18 */
@@ -16,9 +17,9 @@
16 17 * Extend the base class with Jetpack-specific functionality.
17 18 */
18 19 class Publicize extends Publicize_Base {
19 20
20 - const CONNECTION_REFRESH_WAIT_TRANSIENT = 'jetpack_publicize_connection_refresh_wait';
21 + const JETPACK_SOCIAL_CONNECTIONS_TRANSIENT = 'jetpack_social_connections';
21 22
22 23 /**
23 24 * Transitory storage of connection testing results.
24 25 *
@@ -26,8 +27,15 @@
26 27 */
27 28 private $test_connection_results = array();
28 29
29 30 /**
31 + * Property to store the results of fetching the connections.
32 + *
33 + * @var null|array
34 + */
35 + private $current_connections = null;
36 +
37 + /**
30 38 * Add hooks.
31 39 */
32 40 public function __construct() {
33 41 parent::__construct();
@@ -33,36 +41,13 @@
33 41 parent::__construct();
34 42
35 43 add_filter( 'jetpack_xmlrpc_unauthenticated_methods', array( $this, 'register_update_publicize_connections_xmlrpc_method' ) );
36 44
37 - add_action( 'load-settings_page_sharing', array( $this, 'admin_page_load' ), 9 );
38 -
39 - add_action( 'wp_ajax_publicize_tumblr_options_page', array( $this, 'options_page_tumblr' ) );
40 - add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
41 - add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
42 - add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
43 -
44 - add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
45 - add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
46 - add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
47 - add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
48 -
49 - add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
50 -
51 45 add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
52 46
53 47 add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 2 );
54 48
55 - add_filter( 'jetpack_twitter_cards_site_tag', array( $this, 'enhaced_twitter_cards_site_tag' ) );
56 -
57 - add_action( 'publicize_save_meta', array( $this, 'save_publicized_twitter_account' ), 10, 4 );
58 - add_action( 'publicize_save_meta', array( $this, 'save_publicized_facebook_account' ), 10, 4 );
59 -
60 49 add_action( 'connection_disconnected', array( $this, 'add_disconnect_notice' ) );
61 -
62 - add_filter( 'jetpack_sharing_twitter_via', array( $this, 'get_publicized_twitter_account' ), 10, 2 );
63 -
64 - add_action( 'updating_jetpack_version', array( $this, 'init_refresh_transient' ) );
65 50 }
66 51
67 52 /**
68 53 * Add a notice when a connection has been disconnected.
@@ -72,70 +57,51 @@
72 57 }
73 58
74 59 /**
75 60 * Force user connection before showing the Publicize UI.
61 + *
62 + * @deprecated 0.88.0 Settings > Sharing no longer hosts the Publicize UI.
63 + *
64 + * @return void
76 65 */
77 66 public function force_user_connection() {
78 - global $current_user;
79 -
80 - $user_token = ( new Tokens() )->get_access_token( $current_user->ID );
81 - $is_user_connected = $user_token && ! is_wp_error( $user_token );
82 -
83 - // If the user is already connected via Jetpack, then we're good.
84 - if ( $is_user_connected ) {
85 - return;
86 - }
87 -
88 - // If they're not connected, then remove the Publicize UI and tell them they need to connect first.
89 - global $publicize_ui;
90 - remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
91 -
92 - // Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
93 - // Jetpack::init()->admin_styles();.
94 - add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
67 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
95 68 }
96 69
97 70 /**
98 71 * Show a warning when Publicize does not have a connection.
72 + *
73 + * @deprecated 0.88.0 Settings > Sharing no longer hosts the Publicize UI.
74 + *
75 + * @return void
99 76 */
100 77 public function admin_page_warning() {
101 - $jetpack = \Jetpack::init();
102 - $blog_name = get_bloginfo( 'blogname' );
103 - if ( empty( $blog_name ) ) {
104 - $blog_name = home_url( '/' );
105 - }
78 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
79 + }
106 80
107 - ?>
108 - <div id="message" class="updated jetpack-message jp-connect">
109 - <div class="jetpack-wrap-container">
110 - <div class="jetpack-text-container">
111 - <p>
112 - <?php
113 - printf(
114 - /* translators: %s is the name of the blog */
115 - esc_html( wptexturize( __( "To use Jetpack Social, you'll need to link your %s account to your WordPress.com account using the link below.", 'jetpack-publicize-pkg' ) ) ),
116 - '<strong>' . esc_html( $blog_name ) . '</strong>'
117 - );
118 - ?>
119 - </p>
120 - <p><?php echo esc_html( wptexturize( __( "If you don't have a WordPress.com account yet, you can sign up for free in just a few seconds.", 'jetpack-publicize-pkg' ) ) ); ?></p>
121 - </div>
122 - <div class="jetpack-install-container">
123 - <p class="submit"><a
124 - href="<?php echo esc_url( $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ) ); ?>"
125 - class="button-connector"
126 - id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack-publicize-pkg' ); ?></a>
127 - </p>
128 - <p class="jetpack-install-blurb">
129 - <?php jetpack_render_tos_blurb(); ?>
130 - </p>
131 - </div>
132 - </div>
133 - </div>
134 - <?php
81 + /**
82 + * Show error on settings page if applicable.
83 + *
84 + * @deprecated 0.88.0 Settings > Sharing no longer hosts connection errors.
85 + *
86 + * @return void
87 + */
88 + public function admin_page_load() {
89 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
135 90 }
136 91
137 92 /**
93 + * Display an error message.
94 + *
95 + * @deprecated 0.88.0 Settings > Sharing no longer hosts connection errors.
96 + *
97 + * @return void
98 + */
99 + public function display_connection_error() {
100 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
101 + }
102 +
103 + /**
138 104 * Remove a Publicize Connection.
139 105 *
140 106 * @param string $service_name 'facebook', 'twitter', etc.
141 107 * @param string $connection_id Connection ID.
@@ -148,22 +114,72 @@
148 114 return Keyring_Helper::disconnect( $service_name, $connection_id, $_blog_id, $_user_id, $force_delete );
149 115 }
150 116
151 117 /**
152 - * Set updated Publicize conntections.
118 + * Set updated Publicize connections in a transient.
153 119 *
154 120 * @param mixed $publicize_connections Updated connections.
155 121 * @return true
156 122 */
157 123 public function receive_updated_publicize_connections( $publicize_connections ) {
158 - Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
159 124
125 + $publicize_connections = self::filter_usable_connections( $publicize_connections );
126 +
127 + // Populate the cache with the new data.
128 + Connections::get_all( array( 'ignore_cache' => true ) );
129 +
130 + $expiry = 3600 * 4;
131 + if ( ! set_transient( self::JETPACK_SOCIAL_CONNECTIONS_TRANSIENT, $publicize_connections, $expiry ) ) {
132 + // If the transient has beeen set in another request, the call to set_transient can fail. If so,
133 + // we can delete the transient and try again.
134 + $this->clear_connections_transient();
135 + set_transient( self::JETPACK_SOCIAL_CONNECTIONS_TRANSIENT, $publicize_connections, $expiry );
136 + }
137 + // Regardless of whether the transient is set ok, let's set and use the local property for this request.
138 + $this->current_connections = $publicize_connections;
160 139 return true;
161 140 }
162 141
163 142 /**
143 + * Drop connections we cannot attribute to a user.
144 + *
145 + * A missing user ID reads as "shared with everyone" in is_global_connection(), so such a
146 + * connection would be exposed to every user on the site. User ID 0 is a genuine shared
147 + * connection and is kept; unknown fields pass through, as WPCOM adds to this payload.
148 + *
149 + * @param mixed $publicize_connections Connections, keyed by service name.
150 + * @return array
151 + */
152 + private static function filter_usable_connections( $publicize_connections ) {
153 + // An empty payload is valid - it means the site has no connections left.
154 + if ( ! is_array( $publicize_connections ) ) {
155 + return array();
156 + }
157 +
158 + $usable_connections = array();
159 +
160 + foreach ( $publicize_connections as $service_name => $connections_for_service ) {
161 + if ( ! is_array( $connections_for_service ) ) {
162 + continue;
163 + }
164 +
165 + foreach ( $connections_for_service as $id => $connection ) {
166 + if ( ! isset( $connection['connection_data']['user_id'] ) || ! is_numeric( $connection['connection_data']['user_id'] ) ) {
167 + continue;
168 + }
169 +
170 + $usable_connections[ $service_name ][ $id ] = $connection;
171 + }
172 + }
173 +
174 + return $usable_connections;
175 + }
176 +
177 + /**
164 178 * Add method to update Publicize connections.
165 179 *
180 + * @todo Kept as a fallback for the jetpack/v4/publicize/connections/sync REST endpoint that replaced it; remove after a few releases (CONNECT-446).
181 + *
166 182 * @param array $methods Array of registered methods.
167 183 * @return array
168 184 */
169 185 public function register_update_publicize_connections_xmlrpc_method( $methods ) {
@@ -183,9 +199,15 @@
183 199 * @return array
184 200 */
185 201 public function get_all_connections() {
186 202 $this->refresh_connections();
187 - $connections = Jetpack_Options::get_option( 'publicize_connections' );
203 +
204 + $connections = $this->current_connections;
205 +
206 + if ( empty( $connections ) ) {
207 + $connections = array();
208 + }
209 +
188 210 if ( isset( $connections['google_plus'] ) ) {
189 211 unset( $connections['google_plus'] );
190 212 }
191 213 return $connections;
@@ -224,11 +246,16 @@
224 246
225 247 /**
226 248 * Get all connections for a specific user.
227 249 *
228 - * @return array|false
250 + * @param array $args Arguments to run operations such as force refresh and connection test results.
251 + * @return array
229 252 */
230 - public function get_all_connections_for_user() {
253 + public function get_all_connections_for_user( $args = array() ) {
254 + if ( ( isset( $args['clear_cache'] ) && $args['clear_cache'] )
255 + || ( isset( $args['test_connections'] ) && $args['test_connections'] ) ) {
256 + $this->clear_connections_transient();
257 + }
231 258 $connections = $this->get_all_connections();
232 259
233 260 $connections_to_return = array();
234 261 if ( ! empty( $connections ) ) {
@@ -234,22 +261,60 @@
234 261 if ( ! empty( $connections ) ) {
235 262 foreach ( (array) $connections as $service_name => $connections_for_service ) {
236 263 foreach ( $connections_for_service as $id => $connection ) {
237 264 $user_id = (int) $connection['connection_data']['user_id'];
238 - // phpcs:ignore WordPress.PHP.YodaConditions.NotYoda
239 265 if ( $user_id === 0 || $this->user_id() === $user_id ) {
240 266 $connections_to_return[ $service_name ][ $id ] = $connection;
241 267 }
242 268 }
243 269 }
270 + }
244 271
245 - return $connections_to_return;
272 + return $connections_to_return;
273 + }
274 +
275 + /**
276 + * To add the connection test results to the connections.
277 + *
278 + * @param array $connections The Jetpack Social connections.
279 +
280 + * @return array
281 + */
282 + public function add_connection_test_results( $connections ) {
283 + $path = sprintf( '/sites/%d/publicize/connection-test-results', absint( Jetpack_Options::get_option( 'id' ) ) );
284 + $response = Client::wpcom_json_api_request_as_user( $path, '2', array(), null, 'wpcom' );
285 + $connection_results = json_decode( wp_remote_retrieve_body( $response ), true );
286 + $connection_results_map = array();
287 +
288 + foreach ( $connection_results as $connection_result ) {
289 + $connection_results_map[ $connection_result['connection_id'] ] = $connection_result['test_success'] ? 'ok' : 'broken';
246 290 }
291 + foreach ( $connections as $key => $connection ) {
292 + if ( isset( $connection_results_map[ $connection['connection_id'] ] ) ) {
293 + $connections[ $key ]['status'] = $connection_results_map[ $connection['connection_id'] ];
294 + }
295 + }
247 296
248 - return false;
297 + return $connections;
249 298 }
250 299
251 300 /**
301 + * Get a connections for a user.
302 + *
303 + * @param int $connection_id The connection_id.
304 +
305 + * @return array
306 + */
307 + public function get_connection_for_user( $connection_id ) {
308 + foreach ( $this->get_all_connections_for_user() as $connection ) {
309 + if ( (int) $connection['connection_id'] === (int) $connection_id ) {
310 + return $connection;
311 + }
312 + }
313 + return array();
314 + }
315 +
316 + /**
252 317 * Get the ID of a connection.
253 318 *
254 319 * @param array $connection The connection.
255 320 * @return string
@@ -279,91 +344,8 @@
279 344 return $connection;
280 345 }
281 346
282 347 /**
283 - * Show error on settings page if applicable.
284 - */
285 - public function admin_page_load() {
286 - $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
287 -
288 - if ( 'error' === $action ) {
289 - add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 );
290 - }
291 - }
292 -
293 - /**
294 - * Display an error message.
295 - */
296 - public function display_connection_error() {
297 - $code = false;
298 - // phpcs:disable WordPress.Security.NonceVerification.Recommended
299 - $service = isset( $_GET['service'] ) ? sanitize_text_field( wp_unslash( $_GET['service'] ) ) : null;
300 - $publicize_error = isset( $_GET['publicize_error'] ) ? sanitize_text_field( wp_unslash( $_GET['publicize_error'] ) ) : null;
301 - // phpcs:enable WordPress.Security.NonceVerification.Recommended
302 -
303 - if ( $service ) {
304 - /* translators: %s is the name of the Jetpack Social service (e.g. Facebook, Twitter) */
305 - $error = sprintf( __( 'There was a problem connecting to %s to create an authorized connection. Please try again in a moment.', 'jetpack-publicize-pkg' ), self::get_service_label( $service ) );
306 - } elseif ( $publicize_error ) {
307 - $code = strtolower( $publicize_error );
308 - switch ( $code ) {
309 - case '400':
310 - $error = __( 'An invalid request was made. This normally means that something intercepted or corrupted the request from your server to the Jetpack Server. Try again and see if it works this time.', 'jetpack-publicize-pkg' );
311 - break;
312 - case 'secret_mismatch':
313 - $error = __( 'We could not verify that your server is making an authorized request. Please try again, and make sure there is nothing interfering with requests from your server to the Jetpack Server.', 'jetpack-publicize-pkg' );
314 - break;
315 - case 'empty_blog_id':
316 - $error = __( 'No blog_id was included in your request. Please try disconnecting Jetpack from WordPress.com and then reconnecting it. Once you have done that, try connecting Jetpack Social again.', 'jetpack-publicize-pkg' );
317 - break;
318 - case 'empty_state':
319 - /* translators: %s is the URL of the Jetpack admin page */
320 - $error = sprintf( __( 'No user information was included in your request. Please make sure that your user account has connected to Jetpack. Connect your user account by going to the <a href="%s">Jetpack page</a> within wp-admin.', 'jetpack-publicize-pkg' ), \Jetpack::admin_url() );
321 - break;
322 - default:
323 - $error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack-publicize-pkg' );
324 - break;
325 - }
326 - } else {
327 - $error = __( 'There was a problem connecting with Jetpack Social. Please try again in a moment.', 'jetpack-publicize-pkg' );
328 - }
329 - // Using the same formatting/style as Jetpack::admin_notices() error.
330 - ?>
331 - <div id="message" class="jetpack-message jetpack-err">
332 - <div class="squeezer">
333 - <h2>
334 - <?php
335 - echo wp_kses(
336 - $error,
337 - array(
338 - 'a' => array(
339 - 'href' => true,
340 - ),
341 - 'code' => true,
342 - 'strong' => true,
343 - 'br' => true,
344 - 'b' => true,
345 - )
346 - );
347 - ?>
348 - </h2>
349 - <?php if ( $code ) : ?>
350 - <p>
351 - <?php
352 - printf(
353 - /* translators: %s is the name of the error */
354 - esc_html__( 'Error code: %s', 'jetpack-publicize-pkg' ),
355 - esc_html( stripslashes( $code ) )
356 - );
357 - ?>
358 - </p>
359 - <?php endif; ?>
360 - </div>
361 - </div>
362 - <?php
363 - }
364 -
365 - /**
366 348 * Show a message that the connection has been removed.
367 349 */
368 350 public function display_disconnected() {
369 351 echo "<div class='updated'>\n";
@@ -416,50 +398,33 @@
416 398 }
417 399 }
418 400
419 401 /**
420 - * As Jetpack updates set the refresh transient to a random amount
421 - * in order to spread out updates to the connection data.
422 - *
423 - * @param string $version The Jetpack version being updated to.
402 + * Grabs a fresh copy of the publicize connections data, if the cache is busted.
424 403 */
425 - public function init_refresh_transient( $version ) {
426 - if ( version_compare( $version, '10.2.1', '>=' ) && ! get_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT ) ) {
427 - $this->set_refresh_wait_transient( wp_rand( 10, HOUR_IN_SECONDS * 24 ) );
428 - }
429 - }
430 -
431 - /**
432 - * Grabs a fresh copy of the publicize connections data.
433 - * Only refreshes once every 12 hours or retries after an hour with an error.
434 - */
435 404 public function refresh_connections() {
436 - if ( get_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT ) ) {
405 + if ( null !== $this->current_connections ) {
437 406 return;
438 407 }
439 - $xml = new Jetpack_IXR_Client();
440 - $xml->query( 'jetpack.fetchPublicizeConnections' );
441 - $wait_time = HOUR_IN_SECONDS * 24;
442 408
443 - if ( ! $xml->isError() ) {
444 - $response = $xml->getResponse();
445 - $this->receive_updated_publicize_connections( $response );
446 - } else {
447 - // Retry a bit quicker, but still wait.
448 - $wait_time = HOUR_IN_SECONDS;
409 + $connections = get_transient( self::JETPACK_SOCIAL_CONNECTIONS_TRANSIENT );
410 + if ( false === $connections ) {
411 + $xml = new Jetpack_IXR_Client();
412 + $xml->query( 'jetpack.fetchPublicizeConnections' );
413 + if ( ! $xml->isError() ) {
414 + $response = $xml->getResponse();
415 + $this->receive_updated_publicize_connections( $response );
416 + }
417 + return;
449 418 }
450 -
451 - $this->set_refresh_wait_transient( $wait_time );
419 + $this->current_connections = $connections;
452 420 }
453 421
454 422 /**
455 - * Sets the transient to expire at the specified time in seconds.
456 - * This prevents us from attempting to refresh the data too often.
457 - *
458 - * @param int $wait_time The number of seconds before the transient should expire.
423 + * Delete the transient.
459 424 */
460 - public function set_refresh_wait_transient( $wait_time ) {
461 - set_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT, microtime( true ), $wait_time );
425 + public function clear_connections_transient() {
426 + delete_transient( self::JETPACK_SOCIAL_CONNECTIONS_TRANSIENT );
462 427 }
463 428
464 429 /**
465 430 * Get the Publicize connect URL from Keyring.
@@ -514,8 +479,11 @@
514 479 'linkedin' => array(),
515 480 'tumblr' => array(),
516 481 'mastodon' => array(),
517 482 'instagram-business' => array(),
483 + 'nextdoor' => array(),
484 + 'threads' => array(),
485 + 'bluesky' => array(),
518 486 );
519 487
520 488 if ( 'all' === $filter ) {
521 489 return $services;
@@ -551,9 +519,9 @@
551 519 * @param string $old_status Old status of the post.
552 520 * @param WP_Post $post Post object.
553 521 */
554 522 public function flag_post_for_publicize( $new_status, $old_status, $post ) {
555 - if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
523 + if ( ! $post instanceof \WP_Post || ! $this->post_type_is_publicizeable( $post->post_type ) ) {
556 524 return;
557 525 }
558 526
559 527 $should_publicize = $this->should_submit_post_pre_checks( $post );
@@ -615,13 +583,13 @@
615 583 }
616 584
617 585 $error_data = array(
618 586 'user_can_refresh' => $user_can_refresh,
619 - 'refresh_text' => $refresh_text,
620 - 'refresh_url' => $refresh_url,
587 + 'refresh_text' => $refresh_text ?? null,
588 + 'refresh_url' => $refresh_url ?? null,
621 589 );
622 590
623 - $this->test_connection_results[ $id ] = new \WP_Error( $connection_error_code, $connection_test_message, $error_data );
591 + $this->test_connection_results[ $id ] = new WP_Error( $connection_error_code, $connection_test_message, $error_data );
624 592
625 593 return $this->test_connection_results[ $id ];
626 594 }
627 595
@@ -641,9 +609,9 @@
641 609 */
642 610 public function post_is_done_sharing( $post_id = null ) {
643 611 // Defaults to current post if $post_id is null.
644 612 $post = get_post( $post_id );
645 - if ( $post === null ) {
613 + if ( null === $post ) {
646 614 return false;
647 615 }
648 616
649 617 return 'publish' === $post->post_status || get_post_meta( $post->ID, $this->POST_DONE . 'all', true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
@@ -652,18 +620,18 @@
652 620 /**
653 621 * Save a flag locally to indicate that this post has already been Publicized via the selected
654 622 * connections.
655 623 *
656 - * @param int $post_ID Post ID.
657 - * @param \WP_Post $post Post object.
624 + * @param int $post_ID Post ID.
625 + * @param WP_Post $post Post object.
658 626 */
659 627 public function save_publicized( $post_ID, $post = null ) {
660 - if ( $post === null ) {
628 + if ( null === $post ) {
661 629 return;
662 630 }
663 631 // Only do this when a post transitions to being published.
664 632 // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
665 - if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
633 + if ( get_post_meta( $post->ID, $this->PENDING, false ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
666 634 delete_post_meta( $post->ID, $this->PENDING );
667 635 update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
668 636 }
669 637 // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
@@ -671,10 +639,10 @@
671 639
672 640 /**
673 641 * Set post flags for Publicize.
674 642 *
675 - * @param array $flags List of flags.
676 - * @param \WP_Post $post Post object.
643 + * @param array $flags List of flags.
644 + * @param WP_Post $post Post object.
677 645 * @return array
678 646 */
679 647 public function set_post_flags( $flags, $post ) {
680 648 $flags['publicize_post'] = false;
@@ -697,408 +665,6 @@
697 665
698 666 $flags['publicize_post'] = true;
699 667
700 668 return $flags;
701 - }
702 -
703 - /**
704 - * Render Facebook options.
705 - */
706 - public function options_page_facebook() {
707 - $connection_name = isset( $_REQUEST['connection'] ) ? filter_var( wp_unslash( $_REQUEST['connection'] ) ) : null;
708 -
709 - // Nonce check.
710 - check_admin_referer( 'options_page_facebook_' . $connection_name );
711 -
712 - $connected_services = $this->get_all_connections();
713 - $connection = $connected_services['facebook'][ $connection_name ];
714 - $options_to_show = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
715 -
716 - $pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
717 -
718 - $page_selected = false;
719 - if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
720 - $found = false;
721 - if ( $pages && isset( $pages->data ) && is_array( $pages->data ) ) {
722 - foreach ( $pages->data as $page ) {
723 - if ( $page->id === (int) $connection['connection_data']['meta']['facebook_page'] ) {
724 - $found = true;
725 - break;
726 - }
727 - }
728 - }
729 -
730 - if ( $found ) {
731 - $page_selected = $connection['connection_data']['meta']['facebook_page'];
732 - }
733 - }
734 -
735 - ?>
736 -
737 - <div id="thickbox-content">
738 - <?php
739 - ob_start();
740 - Publicize_UI::connected_notice( 'Facebook' );
741 - $update_notice = ob_get_clean();
742 -
743 - if ( ! empty( $update_notice ) ) {
744 - echo wp_kses_post( $update_notice );
745 - }
746 - $page_info_message = sprintf(
747 - wp_kses(
748 - /* translators: %s is the link to the support page about using Facebook with Jetpack Social */
749 - __( 'Facebook supports Jetpack Social connections to Facebook Pages, but not to Facebook Profiles. <a href="%s">Learn More about Jetpack Social for Facebook</a>', 'jetpack-publicize-pkg' ),
750 - array( 'a' => array( 'href' ) )
751 - ),
752 - esc_url( Redirect::get_url( 'jetpack-support-publicize-facebook' ) )
753 - );
754 -
755 - if ( $pages ) :
756 - ?>
757 - <p>
758 - <?php
759 - echo wp_kses(
760 - __( 'Share to my <strong>Facebook Page</strong>:', 'jetpack-publicize-pkg' ),
761 - array( 'strong' )
762 - );
763 - ?>
764 - </p>
765 - <table id="option-fb-fanpage">
766 - <tbody>
767 -
768 - <?php foreach ( $pages as $i => $page ) : ?>
769 - <?php if ( ! ( $i % 2 ) ) : ?>
770 - <tr>
771 - <?php endif; ?>
772 - <td class="radio">
773 - <input
774 - type="radio"
775 - name="option"
776 - data-type="page"
777 - id="<?php echo esc_attr( $page['id'] ); ?>"
778 - value="<?php echo esc_attr( $page['id'] ); ?>"
779 - <?php checked( $page_selected && (int) $page_selected === (int) $page['id'], true ); ?> />
780 - </td>
781 - <td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ); ?>"><img
782 - src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ); ?>"
783 - width="50" height="50"/></label></td>
784 - <td class="details">
785 - <label for="<?php echo esc_attr( $page['id'] ); ?>">
786 - <span class="name"><?php echo esc_html( $page['name'] ); ?></span><br/>
787 - <span class="category"><?php echo esc_html( $page['category'] ); ?></span>
788 - </label>
789 - </td>
790 - <?php if ( ( $i % 2 ) || ( is_countable( $pages ) && ( count( $pages ) - 1 === $i ) ) ) : ?>
791 - </tr>
792 - <?php endif; ?>
793 - <?php endforeach; ?>
794 -
795 - </tbody>
796 - </table>
797 -
798 - <?php Publicize_UI::global_checkbox( 'facebook', $connection_name ); ?>
799 - <p style="text-align: center;">
800 - <input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack-publicize-pkg' ); ?>"
801 - class="button fb-options save-options" name="save"
802 - data-connection="<?php echo esc_attr( $connection_name ); ?>"
803 - rel="<?php echo esc_attr( wp_create_nonce( 'save_fb_token_' . $connection_name ) ); ?>"/>
804 - </p><br/>
805 - <?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
806 - <p><?php echo $page_info_message; ?></p>
807 - <?php else : ?>
808 - <div>
809 - <?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
810 - <p><?php echo $page_info_message; ?></p>
811 - <p>
812 - <?php
813 - echo wp_kses(
814 - sprintf(
815 - /* translators: %1$s is the link to Facebook documentation to create a page, %2$s is the target of the link */
816 - __( '<a class="button" href="%1$s" target="%2$s">Create a Facebook page</a> to get started.', 'jetpack-publicize-pkg' ),
817 - 'https://www.facebook.com/pages/creation/',
818 - '_blank noopener noreferrer'
819 - ),
820 - array( 'a' => array( 'class', 'href', 'target' ) )
821 - );
822 - ?>
823 - </p>
824 - </div>
825 - <?php endif; ?>
826 - </div>
827 - <?php
828 - }
829 -
830 - /**
831 - * Save Facebook options.
832 - */
833 - public function options_save_facebook() {
834 - $connection_name = isset( $_REQUEST['connection'] ) ? filter_var( wp_unslash( $_REQUEST['connection'] ) ) : null;
835 -
836 - // Nonce check.
837 - check_admin_referer( 'save_fb_token_' . $connection_name );
838 -
839 - if ( ! isset( $_POST['type'] ) || 'page' !== $_POST['type'] || ! isset( $_POST['selected_id'] ) ) {
840 - return;
841 - }
842 -
843 - // Check for a numeric page ID.
844 - $page_id = $_POST['selected_id']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- Manually validated just below
845 - if ( ! ctype_digit( $page_id ) ) {
846 - die( 'Security check' );
847 - }
848 -
849 - // Publish to Page.
850 - $options = array(
851 - 'facebook_page' => $page_id,
852 - 'facebook_profile' => null,
853 - );
854 -
855 - $this->set_remote_publicize_options( $connection_name, $options );
856 - }
857 -
858 - /**
859 - * Render Tumblr options.
860 - */
861 - public function options_page_tumblr() {
862 - $connection_name = isset( $_REQUEST['connection'] ) ? filter_var( wp_unslash( $_REQUEST['connection'] ) ) : null;
863 -
864 - // Nonce check.
865 - check_admin_referer( 'options_page_tumblr_' . $connection_name );
866 -
867 - $connected_services = $this->get_all_connections();
868 - $connection = $connected_services['tumblr'][ $connection_name ];
869 - $options_to_show = $connection['connection_data']['meta']['options_responses'];
870 - $request = $options_to_show[0];
871 -
872 - $blogs = $request['response']['user']['blogs'];
873 -
874 - $blog_selected = false;
875 -
876 - if ( ! empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
877 - foreach ( $blogs as $blog ) {
878 - if ( $connection['connection_data']['meta']['tumblr_base_hostname'] === $this->get_basehostname( $blog['url'] ) ) {
879 - $blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
880 - break;
881 - }
882 - }
883 - }
884 -
885 - // Use their Primary blog if they haven't selected one yet.
886 - if ( ! $blog_selected ) {
887 - foreach ( $blogs as $blog ) {
888 - if ( $blog['primary'] ) {
889 - $blog_selected = $this->get_basehostname( $blog['url'] );
890 - }
891 - }
892 - }
893 - ?>
894 -
895 - <div id="thickbox-content">
896 -
897 - <?php
898 - ob_start();
899 - Publicize_UI::connected_notice( 'Tumblr' );
900 - $update_notice = ob_get_clean();
901 -
902 - if ( ! empty( $update_notice ) ) {
903 - echo wp_kses_post( $update_notice );
904 - }
905 - ?>
906 -
907 - <p><?php echo wp_kses( __( 'Share to my <strong>Tumblr blog</strong>:', 'jetpack-publicize-pkg' ), array( 'strong' ) ); ?></p>
908 -
909 - <ul id="option-tumblr-blog">
910 -
911 - <?php
912 - foreach ( $blogs as $blog ) {
913 - $url = $this->get_basehostname( $blog['url'] );
914 - ?>
915 - <li>
916 - <input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ); ?>"
917 - value="<?php echo esc_attr( $url ); ?>" <?php checked( $blog_selected === $url, true ); ?> />
918 - <label for="<?php echo esc_attr( $url ); ?>"><span
919 - class="name"><?php echo esc_html( $blog['title'] ); ?></span></label>
920 - </li>
921 - <?php } ?>
922 -
923 - </ul>
924 -
925 - <?php Publicize_UI::global_checkbox( 'tumblr', $connection_name ); ?>
926 -
927 - <p style="text-align: center;">
928 - <input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack-publicize-pkg' ); ?>"
929 - class="button tumblr-options save-options" name="save"
930 - data-connection="<?php echo esc_attr( $connection_name ); ?>"
931 - rel="<?php echo esc_attr( wp_create_nonce( 'save_tumblr_blog_' . $connection_name ) ); ?>"/>
932 - </p> <br/>
933 - </div>
934 -
935 - <?php
936 - }
937 -
938 - /**
939 - * Get the hostname from a URL.
940 - *
941 - * @param string $url The URL to extract the hostname from.
942 - * @return string|false|null
943 - */
944 - public function get_basehostname( $url ) {
945 - return wp_parse_url( $url, PHP_URL_HOST );
946 - }
947 -
948 - /**
949 - * Save Tumblr options.
950 - */
951 - public function options_save_tumblr() {
952 - $connection_name = isset( $_POST['connection'] ) ? filter_var( wp_unslash( $_POST['connection'] ) ) : null;
953 -
954 - // Nonce check.
955 - check_admin_referer( 'save_tumblr_blog_' . $connection_name );
956 - $options = array( 'tumblr_base_hostname' => isset( $_POST['selected_id'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_id'] ) ) : null );
957 -
958 - $this->set_remote_publicize_options( $connection_name, $options );
959 - }
960 -
961 - /**
962 - * Set remote Publicize options.
963 - *
964 - * @param int $id Connection ID.
965 - * @param array $options Options to set.
966 - */
967 - public function set_remote_publicize_options( $id, $options ) {
968 - $xml = new Jetpack_IXR_Client();
969 - $xml->query( 'jetpack.setPublicizeOptions', $id, $options );
970 -
971 - if ( ! $xml->isError() ) {
972 - $response = $xml->getResponse();
973 - Jetpack_Options::update_option( 'publicize_connections', $response );
974 - $this->globalization( $id );
975 - }
976 - }
977 -
978 - /**
979 - * Render the options page for Twitter.
980 - */
981 - public function options_page_twitter() {
982 - Publicize_UI::options_page_other( 'twitter' );
983 - }
984 -
985 - /**
986 - * Render the options page for LinkedIn.
987 - */
988 - public function options_page_linkedin() {
989 - Publicize_UI::options_page_other( 'linkedin' );
990 - }
991 -
992 - /**
993 - * Save the options page for Twitter.
994 - */
995 - public function options_save_twitter() {
996 - $this->options_save_other( 'twitter' );
997 - }
998 -
999 - /**
1000 - * Save the options page for LinkedIn.
1001 - */
1002 - public function options_save_linkedin() {
1003 - $this->options_save_other( 'linkedin' );
1004 - }
1005 -
1006 - /**
1007 - * Save the options page for a service.
1008 - *
1009 - * @param string $service_name Name of the service to save options for.
1010 - */
1011 - public function options_save_other( $service_name ) {
1012 - $connection_name = isset( $_REQUEST['connection'] ) ? filter_var( wp_unslash( $_REQUEST['connection'] ) ) : '';
1013 -
1014 - // Nonce check.
1015 - check_admin_referer( 'save_' . $service_name . '_token_' . $connection_name );
1016 -
1017 - $this->globalization( $connection_name );
1018 - }
1019 -
1020 - /**
1021 - * If there's only one shared connection to Twitter set it as twitter:site tag.
1022 - *
1023 - * @param string $tag Tag.
1024 - */
1025 - public function enhaced_twitter_cards_site_tag( $tag ) {
1026 - $custom_site_tag = get_option( 'jetpack-twitter-cards-site-tag' );
1027 - if ( ! empty( $custom_site_tag ) ) {
1028 - return $tag;
1029 - }
1030 - if ( ! $this->is_enabled( 'twitter' ) ) {
1031 - return $tag;
1032 - }
1033 - $connections = $this->get_connections( 'twitter' );
1034 - foreach ( $connections as $connection ) {
1035 - $connection_meta = $this->get_connection_meta( $connection );
1036 - if ( $this->is_global_connection( $connection_meta ) ) {
1037 - // If the connection is shared.
1038 - return $this->get_display_name( 'twitter', $connection );
1039 - }
1040 - }
1041 -
1042 - return $tag;
1043 - }
1044 -
1045 - /**
1046 - * Save the Publicized Twitter account when publishing a post.
1047 - *
1048 - * @param bool $submit_post Should the post be publicized.
1049 - * @param int $post_id Post ID.
1050 - * @param string $service_name Service name.
1051 - * @param array $connection Array of connection details.
1052 - */
1053 - public function save_publicized_twitter_account( $submit_post, $post_id, $service_name, $connection ) {
1054 - if ( 'twitter' === $service_name && $submit_post ) {
1055 - $connection_meta = $this->get_connection_meta( $connection );
1056 - $publicize_twitter_user = get_post_meta( $post_id, '_publicize_twitter_user' );
1057 - if ( empty( $publicize_twitter_user ) || ! $this->is_global_connection( $connection_meta ) ) {
1058 - update_post_meta( $post_id, '_publicize_twitter_user', $this->get_display_name( 'twitter', $connection ) );
1059 - }
1060 - }
1061 - }
1062 -
1063 - /**
1064 - * Get the Twitter username.
1065 - *
1066 - * @param string $account Twitter username.
1067 - * @param int $post_id ID of the post.
1068 - * @return string
1069 - */
1070 - public function get_publicized_twitter_account( $account, $post_id ) {
1071 - if ( ! empty( $account ) ) {
1072 - return $account;
1073 - }
1074 - $account = get_post_meta( $post_id, '_publicize_twitter_user', true );
1075 - if ( ! empty( $account ) ) {
1076 - return $account;
1077 - }
1078 -
1079 - return '';
1080 - }
1081 -
1082 - /**
1083 - * Save the Publicized Facebook account when publishing a post
1084 - * Use only Personal accounts, not Facebook Pages
1085 - *
1086 - * @param bool $submit_post Should the post be publicized.
1087 - * @param int $post_id Post ID.
1088 - * @param string $service_name Service name.
1089 - * @param array $connection Array of connection details.
1090 - */
1091 - public function save_publicized_facebook_account( $submit_post, $post_id, $service_name, $connection ) {
1092 - $connection_meta = $this->get_connection_meta( $connection );
1093 - if ( 'facebook' === $service_name && isset( $connection_meta['connection_data']['meta']['facebook_profile'] ) && $submit_post ) {
1094 - $publicize_facebook_user = get_post_meta( $post_id, '_publicize_facebook_user' );
1095 - if ( empty( $publicize_facebook_user ) || ! $this->is_global_connection( $connection_meta ) ) {
1096 - $profile_link = $this->get_profile_link( 'facebook', $connection );
1097 -
1098 - if ( false !== $profile_link ) {
1099 - update_post_meta( $post_id, '_publicize_facebook_user', $profile_link );
1100 - }
1101 - }
1102 - }
1103 669 }
1104 670 }