Completed
Push — try/seperate-publicize-handlin... ( 849cf0 )
by
unknown
31:45 queued 22:53
created

Publicize::display_connection_error()   B

Complexity

Conditions 8
Paths 14

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 14
nop 0
dl 0
loc 46
rs 7.9337
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A Publicize::get_connection() 0 3 1
A Publicize::flag_post_for_publicize() 0 25 5
1
<?php
2
3
require_once dirname( __FILE__ ) . '/../keyring/keyring-jetpack.php';
4
5
class Publicize extends Publicize_Base {
6
7
	function __construct() {
8
		parent::__construct();
9
10
		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'register_update_publicize_connections_xmlrpc_method' ) );
11
12
		// moved to Keyring module
13
		//add_action( 'load-settings_page_sharing', array( $this, 'admin_page_load' ), 9 );
14
15
		add_action( 'wp_ajax_publicize_tumblr_options_page', array( $this, 'options_page_tumblr' ) );
16
		add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
17
		add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
18
		add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
19
		add_action( 'wp_ajax_publicize_path_options_page', array( $this, 'options_page_path' ) );
20
		add_action( 'wp_ajax_publicize_google_plus_options_page', array( $this, 'options_page_google_plus' ) );
21
22
		add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
23
		add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
24
		add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
25
		add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
26
		add_action( 'wp_ajax_publicize_path_options_save', array( $this, 'options_save_path' ) );
27
		add_action( 'wp_ajax_publicize_google_plus_options_save', array( $this, 'options_save_google_plus' ) );
28
29
		add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
30
31
		add_filter( 'publicize_checkbox_default', array( $this, 'publicize_checkbox_default' ), 10, 4 );
32
33
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
34
35
		add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 3 );
36
37
		add_filter( 'jetpack_twitter_cards_site_tag', array( $this, 'enhaced_twitter_cards_site_tag' ) );
38
39
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_twitter_account' ), 10, 4 );
40
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_facebook_account' ), 10, 4 );
41
42
		add_filter( 'jetpack_sharing_twitter_via', array( $this, 'get_publicized_twitter_account' ), 10, 2 );
43
44
		include_once( JETPACK__PLUGIN_DIR . 'modules/publicize/enhanced-open-graph.php' );
45
	}
46
47
	function force_user_connection() {
48
		global $current_user;
49
		$user_token        = Jetpack_Data::get_access_token( $current_user->ID );
50
		$is_user_connected = $user_token && ! is_wp_error( $user_token );
51
52
		// If the user is already connected via Jetpack, then we're good
53
		if ( $is_user_connected ) {
54
			return;
55
		}
56
57
		// If they're not connected, then remove the Publicize UI and tell them they need to connect first
58
		global $publicize_ui;
59
		remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
60
61
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
62
		// Jetpack::init()->admin_styles();
63
		add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
64
	}
65
66
	function admin_page_warning() {
67
		$jetpack   = Jetpack::init();
68
		$blog_name = get_bloginfo( 'blogname' );
69
		if ( empty( $blog_name ) ) {
70
			$blog_name = home_url( '/' );
71
		}
72
73
		?>
74
		<div id="message" class="updated jetpack-message jp-connect">
75
			<div class="jetpack-wrap-container">
76
				<div class="jetpack-text-container">
77
					<p><?php printf(
78
							/* translators: %s is the name of the blog */
79
							esc_html( wptexturize( __( "To use Publicize, you'll need to link your %s account to your WordPress.com account using the link below.", 'jetpack' ) ) ),
80
							'<strong>' . esc_html( $blog_name ) . '</strong>'
81
						); ?></p>
82
					<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' ) ) ); ?></p>
83
				</div>
84
				<div class="jetpack-install-container">
85
					<p class="submit"><a
86
							href="<?php echo $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ); ?>"
87
							class="button-connector"
88
							id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a>
89
					</p>
90
					<p class="jetpack-install-blurb">
91
						<?php jetpack_render_tos_blurb(); ?>
92
					</p>
93
				</div>
94
			</div>
95
		</div>
96
		<?php
97
	}
98
99
	/**
100
	 * Remove a Publicize connection
101
	 */
102 View Code Duplication
	function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
103
		Jetpack::load_xml_rpc_client();
104
		$xml = new Jetpack_IXR_Client();
105
		$xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
106
107
		if ( ! $xml->isError() ) {
108
			Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() );
109
		} else {
110
			return false;
111
		}
112
	}
113
114
	function receive_updated_publicize_connections( $publicize_connections ) {
115
		Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
116
117
		return true;
118
	}
119
120
	function register_update_publicize_connections_xmlrpc_method( $methods ) {
121
		return array_merge( $methods, array(
122
			'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
123
		) );
124
	}
125
126
	function get_all_connections() {
127
		return Jetpack_Options::get_option( 'publicize_connections' );
128
	}
129
130
	function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
131
		$connections           = $this->get_all_connections();
132
		$connections_to_return = array();
133
		if ( ! empty( $connections ) && is_array( $connections ) ) {
134
			if ( ! empty( $connections[ $service_name ] ) ) {
135
				foreach ( $connections[ $service_name ] as $id => $connection ) {
136
					if ( 0 == $connection['connection_data']['user_id'] || $this->user_id() == $connection['connection_data']['user_id'] ) {
137
						$connections_to_return[ $id ] = $connection;
138
					}
139
				}
140
			}
141
142
			return $connections_to_return;
143
		}
144
145
		return false;
146
	}
147
148
	function get_all_connections_for_user() {
149
		$connections = $this->get_all_connections();
150
151
		$connections_to_return = array();
152
		if ( ! empty( $connections ) ) {
153
			foreach ( (array) $connections as $service_name => $connections_for_service ) {
154
				foreach ( $connections_for_service as $id => $connection ) {
155
					$user_id = intval( $connection['connection_data']['user_id'] );
156
					// phpcs:ignore WordPress.PHP.YodaConditions.NotYoda
157
					if ( $user_id === 0 || $this->user_id() === $user_id ) {
158
						$connections_to_return[ $service_name ][ $id ] = $connection;
159
					}
160
				}
161
			}
162
163
			return $connections_to_return;
164
		}
165
166
		return false;
167
	}
168
169
	function get_connection_id( $connection ) {
170
		return $connection['connection_data']['id'];
171
	}
172
173
	function get_connection_meta( $connection ) {
174
		$connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
175
		return $connection;
176
	}
177
178
	// moved to Keyring module
179
	// function admin_age_load() {
180
181
	// moved to Keyring module
182
	// function display_connection_error() {
183
184
185
	function display_disconnected() {
186
		echo "<div class='updated'>\n";
187
		echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "</p>\n";
188
		echo "</div>\n\n";
189
	}
190
191
	function globalization() {
192
		if ( 'on' == $_REQUEST['global'] ) {
193
			$id = $_REQUEST['connection'];
194
195
			if ( ! current_user_can( $this->GLOBAL_CAP ) ) {
196
				return;
197
			}
198
199
			Jetpack::load_xml_rpc_client();
200
			$xml = new Jetpack_IXR_Client();
201
			$xml->query( 'jetpack.globalizePublicizeConnection', $id, 'globalize' );
202
203
			if ( ! $xml->isError() ) {
204
				$response = $xml->getResponse();
205
				Jetpack_Options::update_option( 'publicize_connections', $response );
206
			}
207
		}
208
	}
209
210
211
	// moved to Keyring module
212
	//function api_url( $service = false, $params = array() ) {
213
214
	function connect_url( $service_name ) {
215
		return Keyring::connect_url( $service_name );
216
	}
217
218
	function refresh_url( $service_name ) {
219
		return Keyring::refresh_url( $service_name );
220
	}
221
222
	function disconnect_url( $service_name, $id ) {
223
		return Keyring::disconnect_url( $service_name, $id );
224
	}
225
226
	/**
227
	 * Get social networks, either all available or only those that the site is connected to.
228
	 *
229
	 * @since 2.0
230
	 *
231
	 * @param string $filter Select the list of services that will be returned. Defaults to 'all', accepts 'connected'.
232
	 *
233
	 * @return array List of social networks.
234
	 */
235
	function get_services( $filter = 'all' ) {
236
		$services = array(
237
			'facebook'    => array(),
238
			'twitter'     => array(),
239
			'linkedin'    => array(),
240
			'tumblr'      => array(),
241
			'path'        => array(),
242
			'google_plus' => array(),
243
		);
244
245
		if ( 'all' == $filter ) {
246
			return $services;
247
		} else {
248
			$connected_services = array();
249
			foreach ( $services as $service => $empty ) {
250
				$connections = $this->get_connections( $service );
251
				if ( $connections ) {
252
					$connected_services[ $service ] = $connections;
253
				}
254
			}
255
			return $connected_services;
256
		}
257
	}
258
259
	function get_connection( $service, $id, $_blog_id = false, $_user_id = false ) {
260
		// Stub
261
	}
262
263
	function flag_post_for_publicize( $new_status, $old_status, $post ) {
264
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
265
			return;
266
		}
267
268
		if ( 'publish' == $new_status && 'publish' != $old_status ) {
269
			/**
270
			 * Determines whether a post being published gets publicized.
271
			 *
272
			 * Side-note: Possibly our most alliterative filter name.
273
			 *
274
			 * @module publicize
275
			 *
276
			 * @since 4.1.0
277
			 *
278
			 * @param bool $should_publicize Should the post be publicized? Default to true.
279
			 * @param WP_POST $post Current Post object.
280
			 */
281
			$should_publicize = apply_filters( 'publicize_should_publicize_published_post', true, $post );
282
283
			if ( $should_publicize ) {
284
				update_post_meta( $post->ID, $this->PENDING, true );
285
			}
286
		}
287
	}
288
289
	function test_connection( $service_name, $connection ) {
290
291
		$id = $this->get_connection_id( $connection );
292
293
		Jetpack::load_xml_rpc_client();
294
		$xml = new Jetpack_IXR_Client();
295
		$xml->query( 'jetpack.testPublicizeConnection', $id );
296
297
		// Bail if all is well
298
		if ( ! $xml->isError() ) {
299
			return true;
300
		}
301
302
		$xml_response            = $xml->getResponse();
303
		$connection_test_message = $xml_response['faultString'];
304
305
		// Set up refresh if the user can
306
		$user_can_refresh = current_user_can( $this->GLOBAL_CAP );
307
		if ( $user_can_refresh ) {
308
			$nonce        = wp_create_nonce( "keyring-request-" . $service_name );
0 ignored issues
show
Unused Code introduced by
$nonce is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
309
			$refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) );
310
			$refresh_url  = $this->refresh_url( $service_name );
311
		}
312
313
		$error_data = array(
314
			'user_can_refresh' => $user_can_refresh,
315
			'refresh_text'     => $refresh_text,
0 ignored issues
show
Bug introduced by
The variable $refresh_text does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
316
			'refresh_url'      => $refresh_url
0 ignored issues
show
Bug introduced by
The variable $refresh_url does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
317
		);
318
319
		return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data );
320
	}
321
322
	/**
323
	 * Save a flag locally to indicate that this post has already been Publicized via the selected
324
	 * connections.
325
	 */
326
	function save_publicized( $post_ID, $post = null, $update = null ) {
327
		if ( is_null( $post ) ) {
328
			return;
329
		}
330
		// Only do this when a post transitions to being published
331
		if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
332
			$connected_services = $this->get_all_connections();
333
			if ( ! empty( $connected_services ) ) {
334
				/**
335
				 * Fires when a post is saved that has is marked as pending publicizing
336
				 *
337
				 * @since 4.1.0
338
				 *
339
				 * @param int The post ID
340
				 */
341
				do_action_deprecated( 'jetpack_publicize_post', $post->ID, '4.8.0', 'jetpack_published_post_flags' );
342
			}
343
			delete_post_meta( $post->ID, $this->PENDING );
344
			update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
345
		}
346
	}
347
348
	function set_post_flags( $flags, $post ) {
349
		$flags['publicize_post'] = false;
350
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
351
			return $flags;
352
		}
353
		/** This filter is already documented in modules/publicize/publicize-jetpack.php */
354
		if ( ! apply_filters( 'publicize_should_publicize_published_post', true, $post ) ) {
355
			return $flags;
356
		}
357
358
		$connected_services = $this->get_all_connections();
359
360
		if ( empty( $connected_services ) ) {
361
			return $flags;
362
		}
363
364
		$flags['publicize_post'] = true;
365
366
		return $flags;
367
	}
368
369
	/**
370
	 * Options Code
371
	 */
372
373
	function options_page_facebook() {
374
		$connected_services = $this->get_all_connections();
375
		$connection         = $connected_services['facebook'][ $_REQUEST['connection'] ];
376
		$options_to_show    = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
377
378
		// Nonce check
379
		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
380
381
		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
382
383
		$page_selected   = false;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
384
		if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
385
			$found = false;
386
			if ( $pages && isset( $pages->data ) && is_array( $pages->data )  ) {
387
				foreach ( $pages->data as $page ) {
388
					if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
389
						$found = true;
390
						break;
391
					}
392
				}
393
			}
394
395
			if ( $found ) {
396
				$page_selected   = $connection['connection_data']['meta']['facebook_page'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 3 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
397
			}
398
		}
399
400
		?>
401
402
		<div id="thickbox-content">
403
404
			<?php
405
			ob_start();
406
			Publicize_UI::connected_notice( 'Facebook' );
407
			$update_notice = ob_get_clean();
408
409
			if ( ! empty( $update_notice ) ) {
410
				echo $update_notice;
411
			}
412
			$page_info_message = sprintf(
413
				__( 'Facebook supports Publicize connections to Facebook Pages, but not to Facebook Profiles. <a href="%s">Learn More about Publicize for Facebook</a>', 'jetpack' ),
414
				'https://jetpack.com/support/publicize/facebook'
415
			);
416
417
			if ( $pages ) : ?>
418
				<p><?php _e( 'Publicize to my <strong>Facebook Page</strong>:', 'jetpack' ); ?></p>
419
				<table id="option-fb-fanpage">
420
					<tbody>
421
422
					<?php foreach ( $pages as $i => $page ) : ?>
423
						<?php if ( ! ( $i % 2 ) ) : ?>
424
							<tr>
425
						<?php endif; ?>
426
						<td class="radio"><input type="radio" name="option" data-type="page"
427
						                         id="<?php echo esc_attr( $page['id'] ) ?>"
428
						                         value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> />
429
						</td>
430
						<td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img
431
									src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>"
432
									width="50" height="50"/></label></td>
433
						<td class="details">
434
							<label for="<?php echo esc_attr( $page['id'] ) ?>">
435
								<span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
436
								<span class="category"><?php echo esc_html( $page['category'] ) ?></span>
437
							</label>
438
						</td>
439
						<?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
440
							</tr>
441
						<?php endif; ?>
442
					<?php endforeach; ?>
443
444
					</tbody>
445
				</table>
446
447
				<?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
448
				<p style="text-align: center;">
449
					<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
450
					       class="button fb-options save-options" name="save"
451
					       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
452
					       rel="<?php echo wp_create_nonce( 'save_fb_token_' . $_REQUEST['connection'] ) ?>"/>
453
				</p><br/>
454
				<p><?php echo $page_info_message; ?></p>
455
			<?php else: ?>
456
				<div>
457
					<p><?php echo $page_info_message; ?></p>
458
					<p><?php printf( __( '<a class="button" href="%s" target="%s">Create a Facebook page</a> to get started.', 'jetpack' ), 'https://www.facebook.com/pages/creation/', '_blank noopener noreferrer' ); ?></p>
459
				</div>
460
			<?php endif; ?>
461
		</div>
462
		<?php
463
	}
464
465
	function options_save_facebook() {
466
		// Nonce check
467
		check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
468
469
		// Check for a numeric page ID
470
		$page_id = $_POST['selected_id'];
471
		if ( ! ctype_digit( $page_id ) ) {
472
			die( 'Security check' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method options_save_facebook() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
473
		}
474
475
		if ( 'page' != $_POST['type'] || ! isset( $_POST['selected_id'] ) ) {
476
			return;
477
		}
478
479
		// Publish to Page
480
		$options = array(
481
			'facebook_page'    => $page_id,
482
			'facebook_profile' => null
483
		);
484
485
		$this->set_remote_publicize_options( $_POST['connection'], $options );
486
	}
487
488
	function options_page_tumblr() {
489
		// Nonce check
490
		check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
491
492
		$connected_services = $this->get_all_connections();
493
		$connection         = $connected_services['tumblr'][ $_POST['connection'] ];
494
		$options_to_show    = $connection['connection_data']['meta']['options_responses'];
495
		$request            = $options_to_show[0];
496
497
		$blogs = $request['response']['user']['blogs'];
498
499
		$blog_selected = false;
500
501
		if ( ! empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
502
			foreach ( $blogs as $blog ) {
503
				if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
504
					$blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
505
					break;
506
				}
507
			}
508
509
		}
510
511
		// Use their Primary blog if they haven't selected one yet
512
		if ( ! $blog_selected ) {
513
			foreach ( $blogs as $blog ) {
514
				if ( $blog['primary'] ) {
515
					$blog_selected = $this->get_basehostname( $blog['url'] );
516
				}
517
			}
518
		} ?>
519
520
		<div id="thickbox-content">
521
522
			<?php
523
			ob_start();
524
			Publicize_UI::connected_notice( 'Tumblr' );
525
			$update_notice = ob_get_clean();
526
527
			if ( ! empty( $update_notice ) ) {
528
				echo $update_notice;
529
			}
530
			?>
531
532
			<p><?php _e( 'Publicize to my <strong>Tumblr blog</strong>:', 'jetpack' ); ?></p>
533
534
			<ul id="option-tumblr-blog">
535
536
				<?php
537
				foreach ( $blogs as $blog ) {
538
					$url = $this->get_basehostname( $blog['url'] ); ?>
539
					<li>
540
						<input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>"
541
						       value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
542
						<label for="<?php echo esc_attr( $url ) ?>"><span
543
								class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
544
					</li>
545
				<?php } ?>
546
547
			</ul>
548
549
			<?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
550
551
			<p style="text-align: center;">
552
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
553
				       class="button tumblr-options save-options" name="save"
554
				       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
555
				       rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>"/>
556
			</p> <br/>
557
		</div>
558
559
		<?php
560
	}
561
562
	function get_basehostname( $url ) {
563
		return parse_url( $url, PHP_URL_HOST );
564
	}
565
566
	function options_save_tumblr() {
567
		// Nonce check
568
		check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
569
		$options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
570
571
		$this->set_remote_publicize_options( $_POST['connection'], $options );
572
573
	}
574
575
	function set_remote_publicize_options( $id, $options ) {
576
		Jetpack::load_xml_rpc_client();
577
		$xml = new Jetpack_IXR_Client();
578
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
579
580
		if ( ! $xml->isError() ) {
581
			$response = $xml->getResponse();
582
			Jetpack_Options::update_option( 'publicize_connections', $response );
583
			$this->globalization();
584
		}
585
	}
586
587
	function options_page_twitter() {
588
		Publicize_UI::options_page_other( 'twitter' );
589
	}
590
591
	function options_page_linkedin() {
592
		Publicize_UI::options_page_other( 'linkedin' );
593
	}
594
595
	function options_page_path() {
596
		Publicize_UI::options_page_other( 'path' );
597
	}
598
599
	function options_page_google_plus() {
600
		Publicize_UI::options_page_other( 'google_plus' );
601
	}
602
603
	function options_save_twitter() {
604
		$this->options_save_other( 'twitter' );
605
	}
606
607
	function options_save_linkedin() {
608
		$this->options_save_other( 'linkedin' );
609
	}
610
611
	function options_save_path() {
612
		$this->options_save_other( 'path' );
613
	}
614
615
	function options_save_google_plus() {
616
		$this->options_save_other( 'google_plus' );
617
	}
618
619
	function options_save_other( $service_name ) {
620
		// Nonce check
621
		check_admin_referer( 'save_' . $service_name . '_token_' . $_REQUEST['connection'] );
622
		$this->globalization();
623
	}
624
625
	/**
626
	 * Already-published posts should not be Publicized by default. This filter sets checked to
627
	 * false if a post has already been published.
628
	 */
629
	function publicize_checkbox_default( $checked, $post_id, $name, $connection ) {
630
		if ( 'publish' == get_post_status( $post_id ) ) {
631
			return false;
632
		}
633
634
		return $checked;
635
	}
636
637
	/**
638
	 * If there's only one shared connection to Twitter set it as twitter:site tag.
639
	 */
640
	function enhaced_twitter_cards_site_tag( $tag ) {
641
		$custom_site_tag = get_option( 'jetpack-twitter-cards-site-tag' );
642
		if ( ! empty( $custom_site_tag ) ) {
643
			return $tag;
644
		}
645
		if ( ! $this->is_enabled( 'twitter' ) ) {
646
			return $tag;
647
		}
648
		$connections = $this->get_connections( 'twitter' );
649
		foreach ( $connections as $connection ) {
0 ignored issues
show
Bug introduced by
The expression $connections of type array|false is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
650
			$connection_meta = $this->get_connection_meta( $connection );
651
			if ( 0 == $connection_meta['connection_data']['user_id'] ) {
652
				// If the connection is shared
653
				return $this->get_display_name( 'twitter', $connection );
654
			}
655
		}
656
657
		return $tag;
658
	}
659
660
	function save_publicized_twitter_account( $submit_post, $post_id, $service_name, $connection ) {
661
		if ( 'twitter' == $service_name && $submit_post ) {
662
			$connection_meta        = $this->get_connection_meta( $connection );
663
			$publicize_twitter_user = get_post_meta( $post_id, '_publicize_twitter_user' );
664
			if ( empty( $publicize_twitter_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
665
				update_post_meta( $post_id, '_publicize_twitter_user', $this->get_display_name( 'twitter', $connection ) );
666
			}
667
		}
668
	}
669
670
	function get_publicized_twitter_account( $account, $post_id ) {
671
		if ( ! empty( $account ) ) {
672
			return $account;
673
		}
674
		$account = get_post_meta( $post_id, '_publicize_twitter_user', true );
675
		if ( ! empty( $account ) ) {
676
			return $account;
677
		}
678
679
		return '';
680
	}
681
682
	/**
683
	 * Save the Publicized Facebook account when publishing a post
684
	 * Use only Personal accounts, not Facebook Pages
685
	 */
686
	function save_publicized_facebook_account( $submit_post, $post_id, $service_name, $connection ) {
687
		$connection_meta = $this->get_connection_meta( $connection );
688
		if ( 'facebook' == $service_name && isset( $connection_meta['connection_data']['meta']['facebook_profile'] ) && $submit_post ) {
689
			$publicize_facebook_user = get_post_meta( $post_id, '_publicize_facebook_user' );
690
			if ( empty( $publicize_facebook_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
691
				$profile_link = $this->get_profile_link( 'facebook', $connection );
692
693
				if ( false !== $profile_link ) {
694
					update_post_meta( $post_id, '_publicize_facebook_user', $profile_link );
695
				}
696
			}
697
		}
698
	}
699
}
700