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 +670 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,670 @@
1 +<?php
2 +/**
3 + * Publicize class.
4 + *
5 + * @package automattic/jetpack-publicize
6 + */
7 +
8 +namespace Automattic\Jetpack\Publicize;
9 +
10 +use Automattic\Jetpack\Connection\Client;
11 +use Jetpack_IXR_Client;
12 +use Jetpack_Options;
13 +use WP_Error;
14 +use WP_Post;
15 +
16 +/**
17 + * Extend the base class with Jetpack-specific functionality.
18 + */
19 +class Publicize extends Publicize_Base {
20 +
21 + const JETPACK_SOCIAL_CONNECTIONS_TRANSIENT = 'jetpack_social_connections';
22 +
23 + /**
24 + * Transitory storage of connection testing results.
25 + *
26 + * @var array
27 + */
28 + private $test_connection_results = array();
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 + /**
38 + * Add hooks.
39 + */
40 + public function __construct() {
41 + parent::__construct();
42 +
43 + add_filter( 'jetpack_xmlrpc_unauthenticated_methods', array( $this, 'register_update_publicize_connections_xmlrpc_method' ) );
44 +
45 + add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
46 +
47 + add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 2 );
48 +
49 + add_action( 'connection_disconnected', array( $this, 'add_disconnect_notice' ) );
50 + }
51 +
52 + /**
53 + * Add a notice when a connection has been disconnected.
54 + */
55 + public function add_disconnect_notice() {
56 + add_action( 'admin_notices', array( $this, 'display_disconnected' ) );
57 + }
58 +
59 + /**
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
65 + */
66 + public function force_user_connection() {
67 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
68 + }
69 +
70 + /**
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
76 + */
77 + public function admin_page_warning() {
78 + _deprecated_function( __METHOD__, 'publicize-0.88.0' );
79 + }
80 +
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' );
90 + }
91 +
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 + /**
104 + * Remove a Publicize Connection.
105 + *
106 + * @param string $service_name 'facebook', 'twitter', etc.
107 + * @param string $connection_id Connection ID.
108 + * @param false|int $_blog_id The blog ID. Use false (default) for the current blog.
109 + * @param false|int $_user_id The user ID. Use false (default) for the current user.
110 + * @param bool $force_delete Whether to skip permissions checks.
111 + * @return false|void False on failure. Void on success.
112 + */
113 + public function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
114 + return Keyring_Helper::disconnect( $service_name, $connection_id, $_blog_id, $_user_id, $force_delete );
115 + }
116 +
117 + /**
118 + * Set updated Publicize connections in a transient.
119 + *
120 + * @param mixed $publicize_connections Updated connections.
121 + * @return true
122 + */
123 + public function receive_updated_publicize_connections( $publicize_connections ) {
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;
139 + return true;
140 + }
141 +
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 + /**
178 + * Add method to update Publicize connections.
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 + *
182 + * @param array $methods Array of registered methods.
183 + * @return array
184 + */
185 + public function register_update_publicize_connections_xmlrpc_method( $methods ) {
186 + return array_merge(
187 + $methods,
188 + array(
189 + 'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
190 + )
191 + );
192 + }
193 +
194 + /**
195 + * Get a list of all connections.
196 + *
197 + * Google Plus is no longer a functional service, so we remove it from the list.
198 + *
199 + * @return array
200 + */
201 + public function get_all_connections() {
202 + $this->refresh_connections();
203 +
204 + $connections = $this->current_connections;
205 +
206 + if ( empty( $connections ) ) {
207 + $connections = array();
208 + }
209 +
210 + if ( isset( $connections['google_plus'] ) ) {
211 + unset( $connections['google_plus'] );
212 + }
213 + return $connections;
214 + }
215 +
216 + /**
217 + * Get connections for a specific service.
218 + *
219 + * @param string $service_name 'facebook', 'twitter', etc.
220 + * @param false|int $_blog_id The blog ID. Use false (default) for the current blog.
221 + * @param false|int $_user_id The user ID. Use false (default) for the current user.
222 + * @return false|object[]|array[]
223 + */
224 + public function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
225 + if ( false === $_user_id ) {
226 + $_user_id = $this->user_id();
227 + }
228 +
229 + $connections = $this->get_all_connections();
230 + $connections_to_return = array();
231 +
232 + if ( ! empty( $connections ) && is_array( $connections ) ) {
233 + if ( ! empty( $connections[ $service_name ] ) ) {
234 + foreach ( $connections[ $service_name ] as $id => $connection ) {
235 + if ( $this->is_global_connection( $connection ) || $_user_id === (int) $connection['connection_data']['user_id'] ) {
236 + $connections_to_return[ $id ] = $connection;
237 + }
238 + }
239 + }
240 +
241 + return $connections_to_return;
242 + }
243 +
244 + return false;
245 + }
246 +
247 + /**
248 + * Get all connections for a specific user.
249 + *
250 + * @param array $args Arguments to run operations such as force refresh and connection test results.
251 + * @return array
252 + */
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 + }
258 + $connections = $this->get_all_connections();
259 +
260 + $connections_to_return = array();
261 + if ( ! empty( $connections ) ) {
262 + foreach ( (array) $connections as $service_name => $connections_for_service ) {
263 + foreach ( $connections_for_service as $id => $connection ) {
264 + $user_id = (int) $connection['connection_data']['user_id'];
265 + if ( $user_id === 0 || $this->user_id() === $user_id ) {
266 + $connections_to_return[ $service_name ][ $id ] = $connection;
267 + }
268 + }
269 + }
270 + }
271 +
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';
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 + }
296 +
297 + return $connections;
298 + }
299 +
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 + /**
317 + * Get the ID of a connection.
318 + *
319 + * @param array $connection The connection.
320 + * @return string
321 + */
322 + public function get_connection_id( $connection ) {
323 + return $connection['connection_data']['id'];
324 + }
325 +
326 + /**
327 + * Get the unique ID of a connection.
328 + *
329 + * @param array $connection The connection.
330 + * @return string
331 + */
332 + public function get_connection_unique_id( $connection ) {
333 + return $connection['connection_data']['token_id'];
334 + }
335 +
336 + /**
337 + * Get the meta of a connection.
338 + *
339 + * @param array $connection The connection.
340 + * @return array
341 + */
342 + public function get_connection_meta( $connection ) {
343 + $connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections.
344 + return $connection;
345 + }
346 +
347 + /**
348 + * Show a message that the connection has been removed.
349 + */
350 + public function display_disconnected() {
351 + echo "<div class='updated'>\n";
352 + echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack-publicize-pkg' ) ) . "</p>\n";
353 + echo "</div>\n\n";
354 + }
355 +
356 + /**
357 + * If applicable, globalize a connection.
358 + *
359 + * @param string $connection_id Connection ID.
360 + */
361 + public function globalization( $connection_id ) {
362 + if ( isset( $_REQUEST['global'] ) && 'on' === $_REQUEST['global'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce check happens earlier in the process before we get here
363 + if ( ! current_user_can( $this->GLOBAL_CAP ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
364 + return;
365 + }
366 +
367 + $this->globalize_connection( $connection_id );
368 + }
369 + }
370 +
371 + /**
372 + * Globalize a connection.
373 + *
374 + * @param string $connection_id Connection ID.
375 + */
376 + public function globalize_connection( $connection_id ) {
377 + $xml = new Jetpack_IXR_Client();
378 + $xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'globalize' );
379 +
380 + if ( ! $xml->isError() ) {
381 + $response = $xml->getResponse();
382 + $this->receive_updated_publicize_connections( $response );
383 + }
384 + }
385 +
386 + /**
387 + * Unglobalize a connection.
388 + *
389 + * @param string $connection_id Connection ID.
390 + */
391 + public function unglobalize_connection( $connection_id ) {
392 + $xml = new Jetpack_IXR_Client();
393 + $xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'unglobalize' );
394 +
395 + if ( ! $xml->isError() ) {
396 + $response = $xml->getResponse();
397 + $this->receive_updated_publicize_connections( $response );
398 + }
399 + }
400 +
401 + /**
402 + * Grabs a fresh copy of the publicize connections data, if the cache is busted.
403 + */
404 + public function refresh_connections() {
405 + if ( null !== $this->current_connections ) {
406 + return;
407 + }
408 +
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;
418 + }
419 + $this->current_connections = $connections;
420 + }
421 +
422 + /**
423 + * Delete the transient.
424 + */
425 + public function clear_connections_transient() {
426 + delete_transient( self::JETPACK_SOCIAL_CONNECTIONS_TRANSIENT );
427 + }
428 +
429 + /**
430 + * Get the Publicize connect URL from Keyring.
431 + *
432 + * @param string $service_name Name of the service to get connect URL for.
433 + * @param string $for What the URL is for. Default 'publicize'.
434 + * @return string
435 + */
436 + public function connect_url( $service_name, $for = 'publicize' ) {
437 + return Keyring_Helper::connect_url( $service_name, $for );
438 + }
439 +
440 + /**
441 + * Get the Publicize refresh URL from Keyring.
442 + *
443 + * @param string $service_name Name of the service to get refresh URL for.
444 + * @param string $for What the URL is for. Default 'publicize'.
445 + * @return string
446 + */
447 + public function refresh_url( $service_name, $for = 'publicize' ) {
448 + return Keyring_Helper::refresh_url( $service_name, $for );
449 + }
450 +
451 + /**
452 + * Get the Publicize disconnect URL from Keyring.
453 + *
454 + * @param string $service_name Name of the service to get disconnect URL for.
455 + * @param mixed $id ID of the conenction to disconnect.
456 + * @return string
457 + */
458 + public function disconnect_url( $service_name, $id ) {
459 + return Keyring_Helper::disconnect_url( $service_name, $id );
460 + }
461 +
462 + /**
463 + * Get social networks, either all available or only those that the site is connected to.
464 + *
465 + * @since 0.1.0
466 + * @since-jetpack 2.0.0
467 + *
468 + * @since-jetpack 6.6.0 Removed Path. Service closed October 2018.
469 + *
470 + * @param string $filter Select the list of services that will be returned. Defaults to 'all', accepts 'connected'.
471 + * @param false|int $_blog_id Get services for a specific blog by ID, or set to false for current blog. Default false.
472 + * @param false|int $_user_id Get services for a specific user by ID, or set to false for current user. Default false.
473 + * @return array List of social networks.
474 + */
475 + public function get_services( $filter = 'all', $_blog_id = false, $_user_id = false ) {
476 + $services = array(
477 + 'facebook' => array(),
478 + 'twitter' => array(),
479 + 'linkedin' => array(),
480 + 'tumblr' => array(),
481 + 'mastodon' => array(),
482 + 'instagram-business' => array(),
483 + 'nextdoor' => array(),
484 + 'threads' => array(),
485 + 'bluesky' => array(),
486 + );
487 +
488 + if ( 'all' === $filter ) {
489 + return $services;
490 + }
491 +
492 + $connected_services = array();
493 + foreach ( $services as $service_name => $empty ) {
494 + $connections = $this->get_connections( $service_name, $_blog_id, $_user_id );
495 + if ( $connections ) {
496 + $connected_services[ $service_name ] = $connections;
497 + }
498 + }
499 + return $connected_services;
500 + }
501 +
502 + /**
503 + * Get a specific connection. Stub.
504 + *
505 + * @param string $service_name 'facebook', 'twitter', etc.
506 + * @param string $connection_id Connection ID.
507 + * @param false|int $_blog_id The blog ID. Use false (default) for the current blog.
508 + * @param false|int $_user_id The user ID. Use false (default) for the current user.
509 + * @return void
510 + */
511 + public function get_connection( $service_name, $connection_id, $_blog_id = false, $_user_id = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
512 + // Stub.
513 + }
514 +
515 + /**
516 + * Flag a post for Publicize after publishing.
517 + *
518 + * @param string $new_status New status of the post.
519 + * @param string $old_status Old status of the post.
520 + * @param WP_Post $post Post object.
521 + */
522 + public function flag_post_for_publicize( $new_status, $old_status, $post ) {
523 + if ( ! $post instanceof \WP_Post || ! $this->post_type_is_publicizeable( $post->post_type ) ) {
524 + return;
525 + }
526 +
527 + $should_publicize = $this->should_submit_post_pre_checks( $post );
528 +
529 + if ( 'publish' === $new_status && 'publish' !== $old_status ) {
530 + /**
531 + * Determines whether a post being published gets publicized.
532 + *
533 + * Side-note: Possibly our most alliterative filter name.
534 + *
535 + * @since 0.1.0 No longer defaults to true. Adds checks to not publicize based on different contexts.
536 + * @since-jetpack 4.1.0
537 + *
538 + * @param bool $should_publicize Should the post be publicized? Default to true.
539 + * @param WP_POST $post Current Post object.
540 + */
541 + $should_publicize = apply_filters( 'publicize_should_publicize_published_post', $should_publicize, $post );
542 +
543 + if ( $should_publicize ) {
544 + update_post_meta( $post->ID, $this->PENDING, true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
545 + }
546 + }
547 + }
548 +
549 + /**
550 + * Test a connection.
551 + *
552 + * @param string $service_name Name of the service.
553 + * @param array $connection Connection to be tested.
554 + */
555 + public function test_connection( $service_name, $connection ) {
556 + $id = $this->get_connection_id( $connection );
557 +
558 + if ( array_key_exists( $id, $this->test_connection_results ) ) {
559 + return $this->test_connection_results[ $id ];
560 + }
561 +
562 + $xml = new Jetpack_IXR_Client();
563 + $xml->query( 'jetpack.testPublicizeConnection', $id );
564 +
565 + // Bail if all is well.
566 + if ( ! $xml->isError() ) {
567 + $this->test_connection_results[ $id ] = true;
568 + return true;
569 + }
570 +
571 + $xml_response = $xml->getResponse();
572 + $connection_test_message = $xml_response['faultString'];
573 + $connection_error_code = ( empty( $xml_response['faultCode'] ) || ! is_int( $xml_response['faultCode'] ) )
574 + ? -1
575 + : $xml_response['faultCode'];
576 +
577 + // Set up refresh if the user can.
578 + $user_can_refresh = current_user_can( $this->GLOBAL_CAP ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
579 + if ( $user_can_refresh ) {
580 + /* translators: %s is the name of a social media service */
581 + $refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack-publicize-pkg' ), $this->get_service_label( $service_name ) );
582 + $refresh_url = $this->refresh_url( $service_name );
583 + }
584 +
585 + $error_data = array(
586 + 'user_can_refresh' => $user_can_refresh,
587 + 'refresh_text' => $refresh_text ?? null,
588 + 'refresh_url' => $refresh_url ?? null,
589 + );
590 +
591 + $this->test_connection_results[ $id ] = new WP_Error( $connection_error_code, $connection_test_message, $error_data );
592 +
593 + return $this->test_connection_results[ $id ];
594 + }
595 +
596 + /**
597 + * Checks if post has already been shared by Publicize in the past.
598 + *
599 + * Jetpack uses two methods:
600 + * 1. A POST_DONE . 'all' postmeta flag, or
601 + * 2. if the post has already been published.
602 + *
603 + * @since 0.1.0
604 + * @since-jetpack 6.7.0
605 + *
606 + * @param integer $post_id Optional. Post ID to query connection status for: will use current post if missing.
607 + *
608 + * @return bool True if post has already been shared by Publicize, false otherwise.
609 + */
610 + public function post_is_done_sharing( $post_id = null ) {
611 + // Defaults to current post if $post_id is null.
612 + $post = get_post( $post_id );
613 + if ( null === $post ) {
614 + return false;
615 + }
616 +
617 + return 'publish' === $post->post_status || get_post_meta( $post->ID, $this->POST_DONE . 'all', true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
618 + }
619 +
620 + /**
621 + * Save a flag locally to indicate that this post has already been Publicized via the selected
622 + * connections.
623 + *
624 + * @param int $post_ID Post ID.
625 + * @param WP_Post $post Post object.
626 + */
627 + public function save_publicized( $post_ID, $post = null ) {
628 + if ( null === $post ) {
629 + return;
630 + }
631 + // Only do this when a post transitions to being published.
632 + // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
633 + if ( get_post_meta( $post->ID, $this->PENDING, false ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
634 + delete_post_meta( $post->ID, $this->PENDING );
635 + update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
636 + }
637 + // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
638 + }
639 +
640 + /**
641 + * Set post flags for Publicize.
642 + *
643 + * @param array $flags List of flags.
644 + * @param WP_Post $post Post object.
645 + * @return array
646 + */
647 + public function set_post_flags( $flags, $post ) {
648 + $flags['publicize_post'] = false;
649 + if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
650 + return $flags;
651 + }
652 +
653 + $should_publicize = $this->should_submit_post_pre_checks( $post );
654 +
655 + /** This filter is already documented in modules/publicize/publicize-jetpack.php */
656 + if ( ! apply_filters( 'publicize_should_publicize_published_post', $should_publicize, $post ) ) {
657 + return $flags;
658 + }
659 +
660 + $connected_services = $this->get_all_connections();
661 +
662 + if ( empty( $connected_services ) ) {
663 + return $flags;
664 + }
665 +
666 + $flags['publicize_post'] = true;
667 +
668 + return $flags;
669 + }
670 +}