Completed
Push — try/seperate-publicize-handlin... ( 02fa99...a92583 )
by
unknown
26:53 queued 16:38
created

Publicize::connect_url()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
nc 1
nop 1
1
<?php
2
3
class Publicize extends Publicize_Base {
4
5
	function __construct() {
6
		parent::__construct();
7
8
		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'register_update_publicize_connections_xmlrpc_method' ) );
9
10
		add_action( 'wp_ajax_publicize_tumblr_options_page', array( $this, 'options_page_tumblr' ) );
11
		add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
12
		add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
13
		add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
14
		add_action( 'wp_ajax_publicize_path_options_page', array( $this, 'options_page_path' ) );
15
		add_action( 'wp_ajax_publicize_google_plus_options_page', array( $this, 'options_page_google_plus' ) );
16
17
		add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
18
		add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
19
		add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
20
		add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
21
		add_action( 'wp_ajax_publicize_path_options_save', array( $this, 'options_save_path' ) );
22
		add_action( 'wp_ajax_publicize_google_plus_options_save', array( $this, 'options_save_google_plus' ) );
23
24
		add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
25
26
		add_filter( 'publicize_checkbox_default', array( $this, 'publicize_checkbox_default' ), 10, 4 );
27
28
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
29
30
		add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 3 );
31
32
		add_filter( 'jetpack_twitter_cards_site_tag', array( $this, 'enhaced_twitter_cards_site_tag' ) );
33
34
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_twitter_account' ), 10, 4 );
35
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_facebook_account' ), 10, 4 );
36
37
		add_filter( 'jetpack_sharing_twitter_via', array( $this, 'get_publicized_twitter_account' ), 10, 2 );
38
39
		include_once( JETPACK__PLUGIN_DIR . 'modules/publicize/enhanced-open-graph.php' );
40
41
		jetpack_require_lib( 'class.jetpack-service-helper' );
42
	}
43
44
	function force_user_connection() {
45
		global $current_user;
46
		$user_token        = Jetpack_Data::get_access_token( $current_user->ID );
47
		$is_user_connected = $user_token && ! is_wp_error( $user_token );
48
49
		// If the user is already connected via Jetpack, then we're good
50
		if ( $is_user_connected ) {
51
			return;
52
		}
53
54
		// If they're not connected, then remove the Publicize UI and tell them they need to connect first
55
		global $publicize_ui;
56
		remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
57
58
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
59
		// Jetpack::init()->admin_styles();
60
		add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
61
	}
62
63
	function admin_page_warning() {
64
		$jetpack   = Jetpack::init();
65
		$blog_name = get_bloginfo( 'blogname' );
66
		if ( empty( $blog_name ) ) {
67
			$blog_name = home_url( '/' );
68
		}
69
70
		?>
71
		<div id="message" class="updated jetpack-message jp-connect">
72
			<div class="jetpack-wrap-container">
73
				<div class="jetpack-text-container">
74
					<p><?php printf(
75
							/* translators: %s is the name of the blog */
76
							esc_html( wptexturize( __( "To use Publicize, you'll need to link your %s account to your WordPress.com account using the link below.", 'jetpack' ) ) ),
77
							'<strong>' . esc_html( $blog_name ) . '</strong>'
78
						); ?></p>
79
					<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>
80
				</div>
81
				<div class="jetpack-install-container">
82
					<p class="submit"><a
83
							href="<?php echo $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ); ?>"
84
							class="button-connector"
85
							id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a>
86
					</p>
87
					<p class="jetpack-install-blurb">
88
						<?php jetpack_render_tos_blurb(); ?>
89
					</p>
90
				</div>
91
			</div>
92
		</div>
93
		<?php
94
	}
95
96
	/**
97
	 * Remove a Publicize connection
98
	 */
99
	function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
100
		return Jetpack_Service_Helper::disconnect( $serivce_name, $connection_id, $_blog_id, $_user_id, $force_delete );
0 ignored issues
show
Bug introduced by
The variable $serivce_name does not exist. Did you mean $service_name?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
101
	}
102
103
	function receive_updated_publicize_connections( $publicize_connections ) {
104
		Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
105
106
		return true;
107
	}
108
109
	function register_update_publicize_connections_xmlrpc_method( $methods ) {
110
		return array_merge( $methods, array(
111
			'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
112
		) );
113
	}
114
115
	function get_all_connections() {
116
		return Jetpack_Options::get_option( 'publicize_connections' );
117
	}
118
119
	function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
120
		$connections           = $this->get_all_connections();
121
		$connections_to_return = array();
122
		if ( ! empty( $connections ) && is_array( $connections ) ) {
123
			if ( ! empty( $connections[ $service_name ] ) ) {
124
				foreach ( $connections[ $service_name ] as $id => $connection ) {
125
					if ( 0 == $connection['connection_data']['user_id'] || $this->user_id() == $connection['connection_data']['user_id'] ) {
126
						$connections_to_return[ $id ] = $connection;
127
					}
128
				}
129
			}
130
131
			return $connections_to_return;
132
		}
133
134
		return false;
135
	}
136
137
	function get_all_connections_for_user() {
138
		$connections = $this->get_all_connections();
139
140
		$connections_to_return = array();
141
		if ( ! empty( $connections ) ) {
142
			foreach ( (array) $connections as $service_name => $connections_for_service ) {
143
				foreach ( $connections_for_service as $id => $connection ) {
144
					$user_id = intval( $connection['connection_data']['user_id'] );
145
					// phpcs:ignore WordPress.PHP.YodaConditions.NotYoda
146
					if ( $user_id === 0 || $this->user_id() === $user_id ) {
147
						$connections_to_return[ $service_name ][ $id ] = $connection;
148
					}
149
				}
150
			}
151
152
			return $connections_to_return;
153
		}
154
155
		return false;
156
	}
157
158
	function get_connection_id( $connection ) {
159
		return $connection['connection_data']['id'];
160
	}
161
162
	function get_connection_meta( $connection ) {
163
		$connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
164
		return $connection;
165
	}
166
167
168
169
	function globalization() {
170
		if ( 'on' == $_REQUEST['global'] ) {
171
			$id = $_REQUEST['connection'];
172
173
			if ( ! current_user_can( $this->GLOBAL_CAP ) ) {
174
				return;
175
			}
176
177
			Jetpack::load_xml_rpc_client();
178
			$xml = new Jetpack_IXR_Client();
179
			$xml->query( 'jetpack.globalizePublicizeConnection', $id, 'globalize' );
180
181
			if ( ! $xml->isError() ) {
182
				$response = $xml->getResponse();
183
				Jetpack_Options::update_option( 'publicize_connections', $response );
184
			}
185
		}
186
	}
187
188
	function connect_url( $service_name ) {
189
		return Jetpack_Service_Helper::connect_url( $service_name );
190
	}
191
192
	function refresh_url( $service_name ) {
193
		return Jetpack_Service_Helper::refresh_url( $service_name );
194
	}
195
196
	function disconnect_url( $service_name, $id ) {
197
		return Jetpack_Service_Helper::disconnect_url( $service_name, $id );
198
	}
199
200
	/**
201
	 * Get social networks, either all available or only those that the site is connected to.
202
	 *
203
	 * @since 2.0
204
	 *
205
	 * @param string $filter Select the list of services that will be returned. Defaults to 'all', accepts 'connected'.
206
	 *
207
	 * @return array List of social networks.
208
	 */
209
	function get_services( $filter = 'all' ) {
210
		$services = array(
211
			'facebook'    => array(),
212
			'twitter'     => array(),
213
			'linkedin'    => array(),
214
			'tumblr'      => array(),
215
			'path'        => array(),
216
			'google_plus' => array(),
217
		);
218
219
		if ( 'all' == $filter ) {
220
			return $services;
221
		} else {
222
			$connected_services = array();
223
			foreach ( $services as $service => $empty ) {
224
				$connections = $this->get_connections( $service );
225
				if ( $connections ) {
226
					$connected_services[ $service ] = $connections;
227
				}
228
			}
229
			return $connected_services;
230
		}
231
	}
232
233
	function get_connection( $service, $id, $_blog_id = false, $_user_id = false ) {
234
		// Stub
235
	}
236
237
	function flag_post_for_publicize( $new_status, $old_status, $post ) {
238
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
239
			return;
240
		}
241
242
		if ( 'publish' == $new_status && 'publish' != $old_status ) {
243
			/**
244
			 * Determines whether a post being published gets publicized.
245
			 *
246
			 * Side-note: Possibly our most alliterative filter name.
247
			 *
248
			 * @module publicize
249
			 *
250
			 * @since 4.1.0
251
			 *
252
			 * @param bool $should_publicize Should the post be publicized? Default to true.
253
			 * @param WP_POST $post Current Post object.
254
			 */
255
			$should_publicize = apply_filters( 'publicize_should_publicize_published_post', true, $post );
256
257
			if ( $should_publicize ) {
258
				update_post_meta( $post->ID, $this->PENDING, true );
259
			}
260
		}
261
	}
262
263
	function test_connection( $service_name, $connection ) {
264
265
		$id = $this->get_connection_id( $connection );
266
267
		Jetpack::load_xml_rpc_client();
268
		$xml = new Jetpack_IXR_Client();
269
		$xml->query( 'jetpack.testPublicizeConnection', $id );
270
271
		// Bail if all is well
272
		if ( ! $xml->isError() ) {
273
			return true;
274
		}
275
276
		$xml_response            = $xml->getResponse();
277
		$connection_test_message = $xml_response['faultString'];
278
279
		// Set up refresh if the user can
280
		$user_can_refresh = current_user_can( $this->GLOBAL_CAP );
281
		if ( $user_can_refresh ) {
282
			$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...
283
			$refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) );
284
			$refresh_url  = $this->refresh_url( $service_name );
285
		}
286
287
		$error_data = array(
288
			'user_can_refresh' => $user_can_refresh,
289
			'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...
290
			'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...
291
		);
292
293
		return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data );
294
	}
295
296
	/**
297
	 * Save a flag locally to indicate that this post has already been Publicized via the selected
298
	 * connections.
299
	 */
300
	function save_publicized( $post_ID, $post = null, $update = null ) {
301
		if ( is_null( $post ) ) {
302
			return;
303
		}
304
		// Only do this when a post transitions to being published
305
		if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
306
			$connected_services = $this->get_all_connections();
307
			if ( ! empty( $connected_services ) ) {
308
				/**
309
				 * Fires when a post is saved that has is marked as pending publicizing
310
				 *
311
				 * @since 4.1.0
312
				 *
313
				 * @param int The post ID
314
				 */
315
				do_action_deprecated( 'jetpack_publicize_post', $post->ID, '4.8.0', 'jetpack_published_post_flags' );
316
			}
317
			delete_post_meta( $post->ID, $this->PENDING );
318
			update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
319
		}
320
	}
321
322
	function set_post_flags( $flags, $post ) {
323
		$flags['publicize_post'] = false;
324
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
325
			return $flags;
326
		}
327
		/** This filter is already documented in modules/publicize/publicize-jetpack.php */
328
		if ( ! apply_filters( 'publicize_should_publicize_published_post', true, $post ) ) {
329
			return $flags;
330
		}
331
332
		$connected_services = $this->get_all_connections();
333
334
		if ( empty( $connected_services ) ) {
335
			return $flags;
336
		}
337
338
		$flags['publicize_post'] = true;
339
340
		return $flags;
341
	}
342
343
	/**
344
	 * Options Code
345
	 */
346
347
	function options_page_facebook() {
348
		$connected_services = $this->get_all_connections();
349
		$connection         = $connected_services['facebook'][ $_REQUEST['connection'] ];
350
		$options_to_show    = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
351
352
		// Nonce check
353
		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
354
355
		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
356
357
		$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...
358
		if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
359
			$found = false;
360
			if ( $pages && isset( $pages->data ) && is_array( $pages->data )  ) {
361
				foreach ( $pages->data as $page ) {
362
					if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
363
						$found = true;
364
						break;
365
					}
366
				}
367
			}
368
369
			if ( $found ) {
370
				$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...
371
			}
372
		}
373
374
		?>
375
376
		<div id="thickbox-content">
377
378
			<?php
379
			ob_start();
380
			Publicize_UI::connected_notice( 'Facebook' );
381
			$update_notice = ob_get_clean();
382
383
			if ( ! empty( $update_notice ) ) {
384
				echo $update_notice;
385
			}
386
			$page_info_message = sprintf(
387
				__( 'Facebook supports Publicize connections to Facebook Pages, but not to Facebook Profiles. <a href="%s">Learn More about Publicize for Facebook</a>', 'jetpack' ),
388
				'https://jetpack.com/support/publicize/facebook'
389
			);
390
391
			if ( $pages ) : ?>
392
				<p><?php _e( 'Publicize to my <strong>Facebook Page</strong>:', 'jetpack' ); ?></p>
393
				<table id="option-fb-fanpage">
394
					<tbody>
395
396
					<?php foreach ( $pages as $i => $page ) : ?>
397
						<?php if ( ! ( $i % 2 ) ) : ?>
398
							<tr>
399
						<?php endif; ?>
400
						<td class="radio"><input type="radio" name="option" data-type="page"
401
						                         id="<?php echo esc_attr( $page['id'] ) ?>"
402
						                         value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> />
403
						</td>
404
						<td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img
405
									src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>"
406
									width="50" height="50"/></label></td>
407
						<td class="details">
408
							<label for="<?php echo esc_attr( $page['id'] ) ?>">
409
								<span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
410
								<span class="category"><?php echo esc_html( $page['category'] ) ?></span>
411
							</label>
412
						</td>
413
						<?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
414
							</tr>
415
						<?php endif; ?>
416
					<?php endforeach; ?>
417
418
					</tbody>
419
				</table>
420
421
				<?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
422
				<p style="text-align: center;">
423
					<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
424
					       class="button fb-options save-options" name="save"
425
					       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
426
					       rel="<?php echo wp_create_nonce( 'save_fb_token_' . $_REQUEST['connection'] ) ?>"/>
427
				</p><br/>
428
				<p><?php echo $page_info_message; ?></p>
429
			<?php else: ?>
430
				<div>
431
					<p><?php echo $page_info_message; ?></p>
432
					<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>
433
				</div>
434
			<?php endif; ?>
435
		</div>
436
		<?php
437
	}
438
439
	function options_save_facebook() {
440
		// Nonce check
441
		check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
442
443
		// Check for a numeric page ID
444
		$page_id = $_POST['selected_id'];
445
		if ( ! ctype_digit( $page_id ) ) {
446
			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...
447
		}
448
449
		if ( 'page' != $_POST['type'] || ! isset( $_POST['selected_id'] ) ) {
450
			return;
451
		}
452
453
		// Publish to Page
454
		$options = array(
455
			'facebook_page'    => $page_id,
456
			'facebook_profile' => null
457
		);
458
459
		$this->set_remote_publicize_options( $_POST['connection'], $options );
460
	}
461
462
	function options_page_tumblr() {
463
		// Nonce check
464
		check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
465
466
		$connected_services = $this->get_all_connections();
467
		$connection         = $connected_services['tumblr'][ $_POST['connection'] ];
468
		$options_to_show    = $connection['connection_data']['meta']['options_responses'];
469
		$request            = $options_to_show[0];
470
471
		$blogs = $request['response']['user']['blogs'];
472
473
		$blog_selected = false;
474
475
		if ( ! empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
476
			foreach ( $blogs as $blog ) {
477
				if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
478
					$blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
479
					break;
480
				}
481
			}
482
483
		}
484
485
		// Use their Primary blog if they haven't selected one yet
486
		if ( ! $blog_selected ) {
487
			foreach ( $blogs as $blog ) {
488
				if ( $blog['primary'] ) {
489
					$blog_selected = $this->get_basehostname( $blog['url'] );
490
				}
491
			}
492
		} ?>
493
494
		<div id="thickbox-content">
495
496
			<?php
497
			ob_start();
498
			Publicize_UI::connected_notice( 'Tumblr' );
499
			$update_notice = ob_get_clean();
500
501
			if ( ! empty( $update_notice ) ) {
502
				echo $update_notice;
503
			}
504
			?>
505
506
			<p><?php _e( 'Publicize to my <strong>Tumblr blog</strong>:', 'jetpack' ); ?></p>
507
508
			<ul id="option-tumblr-blog">
509
510
				<?php
511
				foreach ( $blogs as $blog ) {
512
					$url = $this->get_basehostname( $blog['url'] ); ?>
513
					<li>
514
						<input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>"
515
						       value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
516
						<label for="<?php echo esc_attr( $url ) ?>"><span
517
								class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
518
					</li>
519
				<?php } ?>
520
521
			</ul>
522
523
			<?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
524
525
			<p style="text-align: center;">
526
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
527
				       class="button tumblr-options save-options" name="save"
528
				       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
529
				       rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>"/>
530
			</p> <br/>
531
		</div>
532
533
		<?php
534
	}
535
536
	function get_basehostname( $url ) {
537
		return parse_url( $url, PHP_URL_HOST );
538
	}
539
540
	function options_save_tumblr() {
541
		// Nonce check
542
		check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
543
		$options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
544
545
		$this->set_remote_publicize_options( $_POST['connection'], $options );
546
547
	}
548
549
	function set_remote_publicize_options( $id, $options ) {
550
		Jetpack::load_xml_rpc_client();
551
		$xml = new Jetpack_IXR_Client();
552
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
553
554
		if ( ! $xml->isError() ) {
555
			$response = $xml->getResponse();
556
			Jetpack_Options::update_option( 'publicize_connections', $response );
557
			$this->globalization();
558
		}
559
	}
560
561
	function options_page_twitter() {
562
		Publicize_UI::options_page_other( 'twitter' );
563
	}
564
565
	function options_page_linkedin() {
566
		Publicize_UI::options_page_other( 'linkedin' );
567
	}
568
569
	function options_page_path() {
570
		Publicize_UI::options_page_other( 'path' );
571
	}
572
573
	function options_page_google_plus() {
574
		Publicize_UI::options_page_other( 'google_plus' );
575
	}
576
577
	function options_save_twitter() {
578
		$this->options_save_other( 'twitter' );
579
	}
580
581
	function options_save_linkedin() {
582
		$this->options_save_other( 'linkedin' );
583
	}
584
585
	function options_save_path() {
586
		$this->options_save_other( 'path' );
587
	}
588
589
	function options_save_google_plus() {
590
		$this->options_save_other( 'google_plus' );
591
	}
592
593
	function options_save_other( $service_name ) {
594
		// Nonce check
595
		check_admin_referer( 'save_' . $service_name . '_token_' . $_REQUEST['connection'] );
596
		$this->globalization();
597
	}
598
599
	/**
600
	 * Already-published posts should not be Publicized by default. This filter sets checked to
601
	 * false if a post has already been published.
602
	 */
603
	function publicize_checkbox_default( $checked, $post_id, $name, $connection ) {
604
		if ( 'publish' == get_post_status( $post_id ) ) {
605
			return false;
606
		}
607
608
		return $checked;
609
	}
610
611
	/**
612
	 * If there's only one shared connection to Twitter set it as twitter:site tag.
613
	 */
614
	function enhaced_twitter_cards_site_tag( $tag ) {
615
		$custom_site_tag = get_option( 'jetpack-twitter-cards-site-tag' );
616
		if ( ! empty( $custom_site_tag ) ) {
617
			return $tag;
618
		}
619
		if ( ! $this->is_enabled( 'twitter' ) ) {
620
			return $tag;
621
		}
622
		$connections = $this->get_connections( 'twitter' );
623
		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...
624
			$connection_meta = $this->get_connection_meta( $connection );
625
			if ( 0 == $connection_meta['connection_data']['user_id'] ) {
626
				// If the connection is shared
627
				return $this->get_display_name( 'twitter', $connection );
628
			}
629
		}
630
631
		return $tag;
632
	}
633
634
	function save_publicized_twitter_account( $submit_post, $post_id, $service_name, $connection ) {
635
		if ( 'twitter' == $service_name && $submit_post ) {
636
			$connection_meta        = $this->get_connection_meta( $connection );
637
			$publicize_twitter_user = get_post_meta( $post_id, '_publicize_twitter_user' );
638
			if ( empty( $publicize_twitter_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
639
				update_post_meta( $post_id, '_publicize_twitter_user', $this->get_display_name( 'twitter', $connection ) );
640
			}
641
		}
642
	}
643
644
	function get_publicized_twitter_account( $account, $post_id ) {
645
		if ( ! empty( $account ) ) {
646
			return $account;
647
		}
648
		$account = get_post_meta( $post_id, '_publicize_twitter_user', true );
649
		if ( ! empty( $account ) ) {
650
			return $account;
651
		}
652
653
		return '';
654
	}
655
656
	/**
657
	 * Save the Publicized Facebook account when publishing a post
658
	 * Use only Personal accounts, not Facebook Pages
659
	 */
660
	function save_publicized_facebook_account( $submit_post, $post_id, $service_name, $connection ) {
661
		$connection_meta = $this->get_connection_meta( $connection );
662
		if ( 'facebook' == $service_name && isset( $connection_meta['connection_data']['meta']['facebook_profile'] ) && $submit_post ) {
663
			$publicize_facebook_user = get_post_meta( $post_id, '_publicize_facebook_user' );
664
			if ( empty( $publicize_facebook_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
665
				$profile_link = $this->get_profile_link( 'facebook', $connection );
666
667
				if ( false !== $profile_link ) {
668
					update_post_meta( $post_id, '_publicize_facebook_user', $profile_link );
669
				}
670
			}
671
		}
672
	}
673
}
674