Completed
Push — content-options-blog-display-7... ( 930de1 )
by
unknown
12:25
created

Publicize::save_publicized()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nc 4
nop 3
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
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( 'load-settings_page_sharing', array( $this, 'admin_page_load' ), 9 );
11
12
		add_action( 'wp_ajax_publicize_tumblr_options_page', array( $this, 'options_page_tumblr' ) );
13
		add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
14
		add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
15
		add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
16
		add_action( 'wp_ajax_publicize_path_options_page', array( $this, 'options_page_path' ) );
17
		add_action( 'wp_ajax_publicize_google_plus_options_page', array( $this, 'options_page_google_plus' ) );
18
19
		add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
20
		add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
21
		add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
22
		add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
23
		add_action( 'wp_ajax_publicize_path_options_save', array( $this, 'options_save_path' ) );
24
		add_action( 'wp_ajax_publicize_google_plus_options_save', array( $this, 'options_save_google_plus' ) );
25
26
		add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
27
28
		add_filter( 'publicize_checkbox_default', array( $this, 'publicize_checkbox_default' ), 10, 4 );
29
30
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
31
32
		add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 3 );
33
34
		add_filter( 'jetpack_twitter_cards_site_tag', array( $this, 'enhaced_twitter_cards_site_tag' ) );
35
36
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_twitter_account' ), 10, 4 );
37
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_facebook_account' ), 10, 4 );
38
39
		add_filter( 'jetpack_sharing_twitter_via', array( $this, 'get_publicized_twitter_account' ), 10, 2 );
40
41
		include_once( JETPACK__PLUGIN_DIR . 'modules/publicize/enhanced-open-graph.php' );
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
				</div>
88
			</div>
89
		</div>
90
		<?php
91
	}
92
93
	/**
94
	 * Remove a Publicize connection
95
	 */
96
	function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
97
		Jetpack::load_xml_rpc_client();
98
		$xml = new Jetpack_IXR_Client();
99
		$xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
100
101
		if ( ! $xml->isError() ) {
102
			Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() );
103
		} else {
104
			return false;
105
		}
106
	}
107
108
	function receive_updated_publicize_connections( $publicize_connections ) {
109
		Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
110
111
		return true;
112
	}
113
114
	function register_update_publicize_connections_xmlrpc_method( $methods ) {
115
		return array_merge( $methods, array(
116
			'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
117
		) );
118
	}
119
120
	function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
121
		$connections           = Jetpack_Options::get_option( 'publicize_connections' );
122
		$connections_to_return = array();
123
		if ( ! empty( $connections ) && is_array( $connections ) ) {
124
			if ( ! empty( $connections[ $service_name ] ) ) {
125
				foreach ( $connections[ $service_name ] as $id => $connection ) {
126
					if ( 0 == $connection['connection_data']['user_id'] || $this->user_id() == $connection['connection_data']['user_id'] ) {
127
						$connections_to_return[ $id ] = $connection;
128
					}
129
				}
130
			}
131
132
			return $connections_to_return;
133
		}
134
135
		return false;
136
	}
137
138
	function get_connection_id( $connection ) {
139
		return $connection['connection_data']['id'];
140
	}
141
142
	function get_connection_meta( $connection ) {
143
		$connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
144
		return $connection;
145
	}
146
147
	function admin_page_load() {
148
		if ( isset( $_GET['action'] ) ) {
149
			if ( isset( $_GET['service'] ) ) {
150
				$service_name = $_GET['service'];
151
			}
152
153
			switch ( $_GET['action'] ) {
154
				case 'error':
155
					add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 );
156
					break;
157
158
				case 'request':
159
					check_admin_referer( 'keyring-request', 'kr_nonce' );
160
					check_admin_referer( "keyring-request-$service_name", 'nonce' );
0 ignored issues
show
Bug introduced by
The variable $service_name 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...
161
162
					$verification = Jetpack::generate_secrets( 'publicize' );
163
					if ( ! $verification ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $verification of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
164
						$url = Jetpack::admin_url( 'jetpack#/settings' );
165
						wp_die( sprintf( __( "Jetpack is not connected. Please connect Jetpack by visiting <a href='%s'>Settings</a>.", 'jetpack' ), $url ) );
166
167
					}
168
					$stats_options = get_option( 'stats_options' );
169
					$wpcom_blog_id = Jetpack_Options::get_option( 'id' );
170
					$wpcom_blog_id = ! empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
171
172
					$user     = wp_get_current_user();
173
					$redirect = $this->api_url( $service_name, urlencode_deep( array(
174
						'action'       => 'request',
175
						'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
176
						'for'          => 'publicize',
177
						// required flag that says this connection is intended for publicize
178
						'siteurl'      => site_url(),
179
						'state'        => $user->ID,
180
						'blog_id'      => $wpcom_blog_id,
181
						'secret_1'     => $verification['secret_1'],
182
						'secret_2'     => $verification['secret_2'],
183
						'eol'          => $verification['exp'],
184
					) ) );
185
					wp_redirect( $redirect );
186
					exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method admin_page_load() 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...
187
					break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
188
189
				case 'completed':
190
					Jetpack::load_xml_rpc_client();
191
					$xml = new Jetpack_IXR_Client();
192
					$xml->query( 'jetpack.fetchPublicizeConnections' );
193
194
					if ( ! $xml->isError() ) {
195
						$response = $xml->getResponse();
196
						Jetpack_Options::update_option( 'publicize_connections', $response );
197
					}
198
199
					break;
200
201
				case 'delete':
202
					$id = $_GET['id'];
203
204
					check_admin_referer( 'keyring-request', 'kr_nonce' );
205
					check_admin_referer( "keyring-request-$service_name", 'nonce' );
206
207
					$this->disconnect( $service_name, $id );
208
209
					add_action( 'admin_notices', array( $this, 'display_disconnected' ) );
210
					break;
211
			}
212
		}
213
214
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
215
		// Errors encountered on WordPress.com's end are passed back as a code
216
		/*
217
		if ( isset( $_GET['action'] ) && 'error' == $_GET['action'] ) {
218
			// Load Jetpack's styles to handle the box
219
			Jetpack::init()->admin_styles();
220
		}
221
		*/
222
	}
223
224
	function display_connection_error() {
225
		$code = false;
226
		if ( isset( $_GET['service'] ) ) {
227
			$service_name = $_GET['service'];
228
			$error        = sprintf( __( 'There was a problem connecting to %s to create an authorized connection. Please try again in a moment.', 'jetpack' ), Publicize::get_service_label( $service_name ) );
229
		} else {
230
			if ( isset( $_GET['publicize_error'] ) ) {
231
				$code = strtolower( $_GET['publicize_error'] );
232
				switch ( $code ) {
233
					case '400':
234
						$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' );
235
						break;
236
					case 'secret_mismatch':
237
						$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' );
238
						break;
239
					case 'empty_blog_id':
240
						$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 Publicize again.', 'jetpack' );
241
						break;
242
					case 'empty_state':
243
						$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' ), Jetpack::admin_url() );
244
						break;
245
					default:
246
						$error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack' );
247
						break;
248
				}
249
			} else {
250
				$error = __( 'There was a problem connecting with Publicize. Please try again in a moment.', 'jetpack' );
251
			}
252
		}
253
		// Using the same formatting/style as Jetpack::admin_notices() error
254
		?>
255
		<div id="message" class="jetpack-message jetpack-err">
256
			<div class="squeezer">
257
				<h2><?php echo wp_kses( $error, array( 'a'      => array( 'href' => true ),
258
				                                       'code'   => true,
259
				                                       'strong' => true,
260
				                                       'br'     => true,
261
				                                       'b'      => true
262
					) ); ?></h2>
263
				<?php if ( $code ) : ?>
0 ignored issues
show
Bug Best Practice introduced by
The expression $code of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
264
					<p><?php printf( __( 'Error code: %s', 'jetpack' ), esc_html( stripslashes( $code ) ) ); ?></p>
265
				<?php endif; ?>
266
			</div>
267
		</div>
268
		<?php
269
	}
270
271
	function display_disconnected() {
272
		echo "<div class='updated'>\n";
273
		echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "</p>\n";
274
		echo "</div>\n\n";
275
	}
276
277
	function globalization() {
278
		if ( 'on' == $_REQUEST['global'] ) {
279
			$id = $_REQUEST['connection'];
280
281
			if ( ! current_user_can( $this->GLOBAL_CAP ) ) {
282
				return;
283
			}
284
285
			Jetpack::load_xml_rpc_client();
286
			$xml = new Jetpack_IXR_Client();
287
			$xml->query( 'jetpack.globalizePublicizeConnection', $id, 'globalize' );
288
289
			if ( ! $xml->isError() ) {
290
				$response = $xml->getResponse();
291
				Jetpack_Options::update_option( 'publicize_connections', $response );
292
			}
293
		}
294
	}
295
296
	/**
297
	 * Gets a URL to the public-api actions. Works like WP's admin_url
298
	 *
299
	 * @param string $service Shortname of a specific service.
300
	 *
301
	 * @return URL to specific public-api process
302
	 */
303
	// on WordPress.com this is/calls Keyring::admin_url
304
	function api_url( $service = false, $params = array() ) {
305
		/**
306
		 * Filters the API URL used to interact with WordPress.com.
307
		 *
308
		 * @module publicize
309
		 *
310
		 * @since 2.0.0
311
		 *
312
		 * @param string https://public-api.wordpress.com/connect/?jetpack=publicize Default Publicize API URL.
313
		 */
314
		$url = apply_filters( 'publicize_api_url', 'https://public-api.wordpress.com/connect/?jetpack=publicize' );
315
316
		if ( $service ) {
317
			$url = add_query_arg( array( 'service' => $service ), $url );
318
		}
319
320
		if ( count( $params ) ) {
321
			$url = add_query_arg( $params, $url );
322
		}
323
324
		return $url;
325
	}
326
327 View Code Duplication
	function connect_url( $service_name ) {
328
		return add_query_arg( array(
329
			'action'   => 'request',
330
			'service'  => $service_name,
331
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
332
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
333
		), menu_page_url( 'sharing', false ) );
334
	}
335
336
	function refresh_url( $service_name ) {
337
		return add_query_arg( array(
338
			'action'   => 'request',
339
			'service'  => $service_name,
340
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
341
			'refresh'  => 1,
342
			'for'      => 'publicize',
343
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
344
		), admin_url( 'options-general.php?page=sharing' ) );
345
	}
346
347 View Code Duplication
	function disconnect_url( $service_name, $id ) {
348
		return add_query_arg( array(
349
			'action'   => 'delete',
350
			'service'  => $service_name,
351
			'id'       => $id,
352
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
353
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
354
		), menu_page_url( 'sharing', false ) );
355
	}
356
357
	function get_services( $filter ) {
358
		if ( ! in_array( $filter, array( 'all', 'connected' ) ) ) {
359
			$filter = 'all';
360
		}
361
362
		$services = array(
363
			'facebook'    => array(),
364
			'twitter'     => array(),
365
			'linkedin'    => array(),
366
			'tumblr'      => array(),
367
			'path'        => array(),
368
			'google_plus' => array(),
369
		);
370
371
		if ( 'all' == $filter ) {
372
			return $services;
373
		} else {
374
			$connected_services = array();
375
			foreach ( $services as $service => $empty ) {
376
				$connections = $this->get_connections( $service );
377
				if ( $connections ) {
378
					$connected_services[ $service ] = $connections;
379
				}
380
			}
381
382
			return $connected_services;
383
		}
384
	}
385
386
	function get_connection( $service, $id, $_blog_id = false, $_user_id = false ) {
387
		// Stub
388
	}
389
390
	function flag_post_for_publicize( $new_status, $old_status, $post ) {
391
		if ( 'publish' == $new_status && 'publish' != $old_status ) {
392
			/**
393
			 * Determines whether a post being published gets publicized.
394
			 *
395
			 * Side-note: Possibly our most alliterative filter name.
396
			 *
397
			 * @module publicize
398
			 *
399
			 * @since 4.1.0
400
			 *
401
			 * @param bool $should_publicize Should the post be publicized? Default to true.
402
			 * @param WP_POST $post Current Post object.
403
			 */
404
			$should_publicize = apply_filters( 'publicize_should_publicize_published_post', true, $post );
405
406
			if ( $should_publicize ) {
407
				update_post_meta( $post->ID, $this->PENDING, true );
408
			}
409
		}
410
	}
411
412
	function test_connection( $service_name, $connection ) {
413
		$connection_test_passed  = true;
414
		$connection_test_message = '';
415
		$user_can_refresh        = false;
0 ignored issues
show
Unused Code introduced by
$user_can_refresh 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...
416
417
		$id = $this->get_connection_id( $connection );
418
419
		Jetpack::load_xml_rpc_client();
420
		$xml = new Jetpack_IXR_Client();
421
		$xml->query( 'jetpack.testPublicizeConnection', $id );
422
423
		if ( $xml->isError() ) {
424
			$xml_response            = $xml->getResponse();
425
			$connection_test_message = $xml_response['faultString'];
426
			$connection_test_passed  = false;
427
		}
428
429
		// Bail if all is well
430
		if ( $connection_test_passed ) {
431
			return true;
432
		}
433
434
		// Set up refresh if the user can
435
		$user_can_refresh = current_user_can( $this->GLOBAL_CAP );
436
		if ( $user_can_refresh ) {
437
			$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...
438
			$refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) );
439
			$refresh_url  = $this->refresh_url( $service_name );
440
		}
441
442
		$error_data = array(
443
			'user_can_refresh' => $user_can_refresh,
444
			'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...
445
			'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...
446
		);
447
448
		return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data );
449
	}
450
451
	/**
452
	 * Save a flag locally to indicate that this post has already been Publicized via the selected
453
	 * connections.
454
	 */
455
	function save_publicized( $post_ID, $post = null, $update = null ) {
456
		if ( is_null( $post ) ) {
457
			return;
458
		}
459
		// Only do this when a post transitions to being published
460
		if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
461
			$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
462
			if ( ! empty( $connected_services ) ) {
463
				/**
464
				 * Fires when a post is saved that has is marked as pending publicizing
465
				 *
466
				 * @since 4.1.0
467
				 *
468
				 * @param int The post ID
469
				 */
470
				do_action_deprecated( 'jetpack_publicize_post', $post->ID, '4.8.0', 'jetpack_published_post_flags' );
471
			}
472
			delete_post_meta( $post->ID, $this->PENDING );
473
			update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
474
		}
475
	}
476
477
	function set_post_flags( $flags, $post ) {
478
		$flags['publicize_post'] = false;
479
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
480
			return $flags;
481
		}
482
		/** This filter is already documented in modules/publicize/publicize-jetpack.php */
483
		if ( ! apply_filters( 'publicize_should_publicize_published_post', true, $post ) ) {
484
			return $flags;
485
		}
486
487
		$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
488
489
		if ( empty( $connected_services ) ) {
490
			return $flags;
491
		}
492
493
		$flags['publicize_post'] = true;
494
495
		return $flags;
496
	}
497
498
	/**
499
	 * Options Code
500
	 */
501
502
	function options_page_facebook() {
503
		$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
504
		$connection         = $connected_services['facebook'][ $_REQUEST['connection'] ];
505
		$options_to_show    = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
506
507
		// Nonce check
508
		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
509
510
		$me    = ( ! empty( $options_to_show[0] ) ? $options_to_show[0] : false );
511
		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
512
513
		$profile_checked = true;
514
		$page_selected   = false;
515
516
		if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
517
			$found = false;
518
			if ( is_array( $pages->data ) ) {
519
				foreach ( $pages->data as $page ) {
520
					if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
521
						$found = true;
522
						break;
523
					}
524
				}
525
			}
526
527
			if ( $found ) {
528
				$profile_checked = false;
529
				$page_selected   = $connection['connection_data']['meta']['facebook_page'];
530
			}
531
		}
532
533
		?>
534
535
		<div id="thickbox-content">
536
537
			<?php
538
			ob_start();
539
			Publicize_UI::connected_notice( 'Facebook' );
540
			$update_notice = ob_get_clean();
541
542
			if ( ! empty( $update_notice ) ) {
543
				echo $update_notice;
544
			}
545
			?>
546
547
			<?php if ( ! empty( $me['name'] ) ) : ?>
548
				<p><?php _e( 'Publicize to my <strong>Facebook Wall</strong>:', 'jetpack' ); ?></p>
549
				<table id="option-profile">
550
					<tbody>
551
					<tr>
552
						<td class="radio"><input type="radio" name="option" data-type="profile"
553
						                         id="<?php echo esc_attr( $me['id'] ) ?>"
554
						                         value="" <?php checked( $profile_checked, true ); ?> /></td>
555
						<td class="thumbnail"><label for="<?php echo esc_attr( $me['id'] ) ?>"><img
556
									src="<?php echo esc_url( $me['picture']['data']['url'] ) ?>" width="50"
557
									height="50"/></label></td>
558
						<td class="details"><label
559
								for="<?php echo esc_attr( $me['id'] ) ?>"><?php echo esc_html( $me['name'] ) ?></label>
560
						</td>
561
					</tr>
562
					</tbody>
563
				</table>
564
			<?php endif; ?>
565
566
			<?php if ( $pages ) : ?>
567
568
				<p><?php _e( 'Publicize to my <strong>Facebook Page</strong>:', 'jetpack' ); ?></p>
569
				<table id="option-fb-fanpage">
570
					<tbody>
571
572
					<?php foreach ( $pages as $i => $page ) : ?>
573
						<?php if ( ! ( $i % 2 ) ) : ?>
574
							<tr>
575
						<?php endif; ?>
576
						<td class="radio"><input type="radio" name="option" data-type="page"
577
						                         id="<?php echo esc_attr( $page['id'] ) ?>"
578
						                         value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> />
579
						</td>
580
						<td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img
581
									src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>"
582
									width="50" height="50"/></label></td>
583
						<td class="details">
584
							<label for="<?php echo esc_attr( $page['id'] ) ?>">
585
								<span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
586
								<span class="category"><?php echo esc_html( $page['category'] ) ?></span>
587
							</label>
588
						</td>
589
						<?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
590
							</tr>
591
						<?php endif; ?>
592
					<?php endforeach; ?>
593
594
					</tbody>
595
				</table>
596
597
			<?php endif; ?>
598
599
			<?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
600
601
			<p style="text-align: center;">
602
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
603
				       class="button fb-options save-options" name="save"
604
				       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
605
				       rel="<?php echo wp_create_nonce( 'save_fb_token_' . $_REQUEST['connection'] ) ?>"/>
606
			</p><br/>
607
		</div>
608
609
		<?php
610
	}
611
612
	function options_save_facebook() {
613
		// Nonce check
614
		check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
615
616
		$id = $_POST['connection'];
617
618
		// Check for a numeric page ID
619
		$page_id = $_POST['selected_id'];
620
		if ( ! ctype_digit( $page_id ) ) {
621
			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...
622
		}
623
624
		if ( isset( $_POST['selected_id'] ) && 'profile' == $_POST['type'] ) {
625
			// Publish to User Wall/Profile
626
			$options = array(
627
				'facebook_page'    => null,
628
				'facebook_profile' => true
629
			);
630
631
		} else {
632
			if ( 'page' != $_POST['type'] || ! isset( $_POST['selected_id'] ) ) {
633
				return;
634
			}
635
636
			// Publish to Page
637
			$options = array(
638
				'facebook_page'    => $page_id,
639
				'facebook_profile' => null
640
			);
641
		}
642
643
		Jetpack::load_xml_rpc_client();
644
		$xml = new Jetpack_IXR_Client();
645
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
646
647
		if ( ! $xml->isError() ) {
648
			$response = $xml->getResponse();
649
			Jetpack_Options::update_option( 'publicize_connections', $response );
650
		}
651
652
		$this->globalization();
653
	}
654
655
	function options_page_tumblr() {
656
		// Nonce check
657
		check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
658
659
		$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
660
		$connection         = $connected_services['tumblr'][ $_POST['connection'] ];
661
		$options_to_show    = $connection['connection_data']['meta']['options_responses'];
662
		$request            = $options_to_show[0];
663
664
		$blogs = $request['response']['user']['blogs'];
665
666
		$blog_selected = false;
667
668
		if ( ! empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
669
			foreach ( $blogs as $blog ) {
670
				if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
671
					$blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
672
					break;
673
				}
674
			}
675
676
		}
677
678
		// Use their Primary blog if they haven't selected one yet
679
		if ( ! $blog_selected ) {
680
			foreach ( $blogs as $blog ) {
681
				if ( $blog['primary'] ) {
682
					$blog_selected = $this->get_basehostname( $blog['url'] );
683
				}
684
			}
685
		} ?>
686
687
		<div id="thickbox-content">
688
689
			<?php
690
			ob_start();
691
			Publicize_UI::connected_notice( 'Tumblr' );
692
			$update_notice = ob_get_clean();
693
694
			if ( ! empty( $update_notice ) ) {
695
				echo $update_notice;
696
			}
697
			?>
698
699
			<p><?php _e( 'Publicize to my <strong>Tumblr blog</strong>:', 'jetpack' ); ?></p>
700
701
			<ul id="option-tumblr-blog">
702
703
				<?php
704
				foreach ( $blogs as $blog ) {
705
					$url = $this->get_basehostname( $blog['url'] ); ?>
706
					<li>
707
						<input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>"
708
						       value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
709
						<label for="<?php echo esc_attr( $url ) ?>"><span
710
								class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
711
					</li>
712
				<?php } ?>
713
714
			</ul>
715
716
			<?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
717
718
			<p style="text-align: center;">
719
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
720
				       class="button tumblr-options save-options" name="save"
721
				       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
722
				       rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>"/>
723
			</p> <br/>
724
		</div>
725
726
		<?php
727
	}
728
729
	function get_basehostname( $url ) {
730
		return parse_url( $url, PHP_URL_HOST );
731
	}
732
733
	function options_save_tumblr() {
734
		// Nonce check
735
		check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
736
737
		$id = $_POST['connection'];
738
739
		$options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
740
741
		Jetpack::load_xml_rpc_client();
742
		$xml = new Jetpack_IXR_Client();
743
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
744
745
		if ( ! $xml->isError() ) {
746
			$response = $xml->getResponse();
747
			Jetpack_Options::update_option( 'publicize_connections', $response );
748
		}
749
750
		$this->globalization();
751
	}
752
753
	function options_page_twitter() {
754
		Publicize_UI::options_page_other( 'twitter' );
755
	}
756
757
	function options_page_linkedin() {
758
		Publicize_UI::options_page_other( 'linkedin' );
759
	}
760
761
	function options_page_path() {
762
		Publicize_UI::options_page_other( 'path' );
763
	}
764
765
	function options_page_google_plus() {
766
		Publicize_UI::options_page_other( 'google_plus' );
767
	}
768
769
	function options_save_twitter() {
770
		$this->options_save_other( 'twitter' );
771
	}
772
773
	function options_save_linkedin() {
774
		$this->options_save_other( 'linkedin' );
775
	}
776
777
	function options_save_path() {
778
		$this->options_save_other( 'path' );
779
	}
780
781
	function options_save_google_plus() {
782
		$this->options_save_other( 'google_plus' );
783
	}
784
785
	function options_save_other( $service_name ) {
786
		// Nonce check
787
		check_admin_referer( 'save_' . $service_name . '_token_' . $_REQUEST['connection'] );
788
		$this->globalization();
789
	}
790
791
	/**
792
	 * Already-published posts should not be Publicized by default. This filter sets checked to
793
	 * false if a post has already been published.
794
	 */
795
	function publicize_checkbox_default( $checked, $post_id, $name, $connection ) {
796
		if ( 'publish' == get_post_status( $post_id ) ) {
797
			return false;
798
		}
799
800
		return $checked;
801
	}
802
803
	/**
804
	 * If there's only one shared connection to Twitter set it as twitter:site tag.
805
	 */
806
	function enhaced_twitter_cards_site_tag( $tag ) {
807
		$custom_site_tag = get_option( 'jetpack-twitter-cards-site-tag' );
808
		if ( ! empty( $custom_site_tag ) ) {
809
			return $tag;
810
		}
811
		if ( ! $this->is_enabled( 'twitter' ) ) {
812
			return $tag;
813
		}
814
		$connections = $this->get_connections( 'twitter' );
815
		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...
816
			$connection_meta = $this->get_connection_meta( $connection );
817
			if ( 0 == $connection_meta['connection_data']['user_id'] ) {
818
				// If the connection is shared
819
				return $this->get_display_name( 'twitter', $connection );
820
			}
821
		}
822
823
		return $tag;
824
	}
825
826
	function save_publicized_twitter_account( $submit_post, $post_id, $service_name, $connection ) {
827
		if ( 'twitter' == $service_name && $submit_post ) {
828
			$connection_meta        = $this->get_connection_meta( $connection );
829
			$publicize_twitter_user = get_post_meta( $post_id, '_publicize_twitter_user' );
830
			if ( empty( $publicize_twitter_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
831
				update_post_meta( $post_id, '_publicize_twitter_user', $this->get_display_name( 'twitter', $connection ) );
832
			}
833
		}
834
	}
835
836
	function get_publicized_twitter_account( $account, $post_id ) {
837
		if ( ! empty( $account ) ) {
838
			return $account;
839
		}
840
		$account = get_post_meta( $post_id, '_publicize_twitter_user', true );
841
		if ( ! empty( $account ) ) {
842
			return $account;
843
		}
844
845
		return '';
846
	}
847
848
	/**
849
	 * Save the Publicized Facebook account when publishing a post
850
	 * Use only Personal accounts, not Facebook Pages
851
	 */
852
	function save_publicized_facebook_account( $submit_post, $post_id, $service_name, $connection ) {
853
		$connection_meta = $this->get_connection_meta( $connection );
854
		if ( 'facebook' == $service_name && isset( $connection_meta['connection_data']['meta']['facebook_profile'] ) && $submit_post ) {
855
			$publicize_facebook_user = get_post_meta( $post_id, '_publicize_facebook_user' );
856
			if ( empty( $publicize_facebook_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
857
				$profile_link = $this->get_profile_link( 'facebook', $connection );
858
859
				if ( false !== $profile_link ) {
860
					update_post_meta( $post_id, '_publicize_facebook_user', $profile_link );
861
				}
862
			}
863
		}
864
	}
865
}
866