Completed
Pull Request — branch-4.1 (#4328)
by Jeremy
17:48 queued 08:43
created

Publicize::publicize_checkbox_default()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 4
dl 0
loc 6
rs 9.4285
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_action( 'transition_post_status', array( $this, 'save_publicized' ), 10, 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
42
	function force_user_connection() {
43
		global $current_user;
44
		$user_token = Jetpack_Data::get_access_token( $current_user->ID );
45
		$is_user_connected = $user_token && !is_wp_error( $user_token );
46
47
		// If the user is already connected via Jetpack, then we're good
48
		if ( $is_user_connected )
49
			return;
50
51
		// If they're not connected, then remove the Publicize UI and tell them they need to connect first
52
		global $publicize_ui;
53
		remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
54
55
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
56
		// Jetpack::init()->admin_styles();
57
		add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
58
	}
59
60
	function admin_page_warning() {
61
		$jetpack = Jetpack::init();
62
		$blog_name = get_bloginfo( 'blogname' );
63
		if ( empty( $blog_name ) ) {
64
			$blog_name = home_url( '/' );
65
		}
66
67
		?>
68
		<div id="message" class="updated jetpack-message jp-connect">
69
			<div class="jetpack-wrap-container">
70
				<div class="jetpack-text-container">
71
					<p><?php printf(
72
						esc_html( wptexturize( __( "To use Publicize, you'll need to link your %s account to your WordPress.com account using the link below.", 'jetpack' ) ) ),
73
						'<strong>' . esc_html( $blog_name ) . '</strong>'
74
					); ?></p>
75
					<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>
76
				</div>
77
				<div class="jetpack-install-container">
78
					<p class="submit"><a href="<?php echo $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ); ?>" class="button-connector" id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
79
				</div>
80
			</div>
81
		</div>
82
		<?php
83
	}
84
85
	/**
86
	 * Remove a Publicize connection
87
	 */
88
	function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
89
		Jetpack::load_xml_rpc_client();
90
		$xml = new Jetpack_IXR_Client();
91
		$xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
92
93
		if ( ! $xml->isError() ) {
94
			Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() );
95
		} else {
96
			return false;
97
		}
98
	}
99
100
	function receive_updated_publicize_connections( $publicize_connections ) {
101
		Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
102
		return true;
103
	}
104
105
	function register_update_publicize_connections_xmlrpc_method( $methods ) {
106
		return array_merge( $methods, array(
107
			'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
108
		) );
109
	}
110
111
	function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
112
		$connections = Jetpack_Options::get_option( 'publicize_connections' );
113
		$connections_to_return = array();
114
		if ( !empty( $connections ) && is_array( $connections ) ) {
115
			if ( !empty( $connections[$service_name] ) ) {
116
				foreach( $connections[$service_name] as $id => $connection ) {
117
					if ( 0 == $connection['connection_data']['user_id'] || $this->user_id() == $connection['connection_data']['user_id'] ) {
118
						$connections_to_return[$id] = $connection;
119
					}
120
				}
121
			}
122
			return $connections_to_return;
123
		}
124
		return false;
125
	}
126
127
	function get_connection_id( $connection ) {
128
		return $connection['connection_data']['id'];
129
	}
130
131
	function get_connection_meta( $connection ) {
132
		$connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
133
		return $connection;
134
	}
135
136
	function admin_page_load() {
137
		if ( isset( $_GET['action'] ) ) {
138
			if ( isset( $_GET['service'] ) )
139
				$service_name = $_GET['service'];
140
141
			switch ( $_GET['action'] ) {
142
			case 'error':
143
				add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 );
144
				break;
145
146
			case 'request':
147
				check_admin_referer( 'keyring-request', 'kr_nonce' );
148
				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...
149
150
				$verification = Jetpack::create_nonce( 'publicize' );
151
152
				$stats_options = get_option( 'stats_options' );
153
				$wpcom_blog_id = Jetpack_Options::get_option('id');
154
				$wpcom_blog_id = !empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
155
156
				$user = wp_get_current_user();
157
				$redirect = $this->api_url( $service_name, urlencode_deep( array(
158
					'action'       => 'request',
159
					'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
160
					'for'          => 'publicize', // required flag that says this connection is intended for publicize
161
					'siteurl'      => site_url(),
162
					'state'        => $user->ID,
163
					'blog_id'      => $wpcom_blog_id,
164
					'secret_1'	   => $verification['secret_1'],
165
					'secret_2'     => $verification['secret_2'],
166
					'eol'		   => $verification['eol'],
167
				) ) );
168
				wp_redirect( $redirect );
169
				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...
170
				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...
171
172
			case 'completed':
173
				Jetpack::load_xml_rpc_client();
174
				$xml = new Jetpack_IXR_Client();
175
				$xml->query( 'jetpack.fetchPublicizeConnections' );
176
177
				if ( ! $xml->isError() ) {
178
					$response = $xml->getResponse();
179
					Jetpack_Options::update_option( 'publicize_connections', $response );
180
				}
181
182
				break;
183
184
			case 'delete':
185
				$id = $_GET['id'];
186
187
				check_admin_referer( 'keyring-request', 'kr_nonce' );
188
				check_admin_referer( "keyring-request-$service_name", 'nonce' );
189
190
				$this->disconnect( $service_name, $id );
191
192
				add_action( 'admin_notices', array( $this, 'display_disconnected' ) );
193
				break;
194
			}
195
		}
196
197
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
198
		// Errors encountered on WordPress.com's end are passed back as a code
199
		/*
200
		if ( isset( $_GET['action'] ) && 'error' == $_GET['action'] ) {
201
			// Load Jetpack's styles to handle the box
202
			Jetpack::init()->admin_styles();
203
		}
204
		*/
205
	}
206
207
	function display_connection_error() {
208
		$code = false;
209
		if ( isset( $_GET['service'] ) ) {
210
			$service_name = $_GET['service'];
211
			$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 ) );
212
		} else {
213
			if ( isset( $_GET['publicize_error'] ) ) {
214
				$code = strtolower( $_GET['publicize_error'] );
215
				switch ( $code ) {
216
				case '400':
217
					$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' );
218
					break;
219
				case 'secret_mismatch':
220
					$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' );
221
					break;
222
				case 'empty_blog_id':
223
					$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' );
224
					break;
225
				case 'empty_state':
226
					$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() );
227
					break;
228
				default:
229
					$error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack' );
230
					break;
231
				}
232
			} else {
233
				$error = __( 'There was a problem connecting with Publicize. Please try again in a moment.', 'jetpack' );
234
			}
235
		}
236
		// Using the same formatting/style as Jetpack::admin_notices() error
237
		?>
238
		<div id="message" class="jetpack-message jetpack-err">
239
			<div class="squeezer">
240
				<h2><?php echo wp_kses( $error, array( 'a' => array( 'href' => true ), 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h2>
241
				<?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...
242
				<p><?php printf( __( 'Error code: %s', 'jetpack' ), esc_html( stripslashes( $code ) ) ); ?></p>
243
				<?php endif; ?>
244
			</div>
245
		</div>
246
		<?php
247
	}
248
249
	function display_disconnected() {
250
		echo "<div class='updated'>\n";
251
		echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "</p>\n";
252
		echo "</div>\n\n";
253
	}
254
255
	function globalization() {
256
		if ( 'on' == $_REQUEST['global'] ) {
257
			$id = $_REQUEST['connection'];
258
259
			if ( !current_user_can( $this->GLOBAL_CAP ) )
260
				return;
261
262
			Jetpack::load_xml_rpc_client();
263
			$xml = new Jetpack_IXR_Client();
264
			$xml->query( 'jetpack.globalizePublicizeConnection', $id, 'globalize' );
265
266
			if ( !$xml->isError() ) {
267
				$response = $xml->getResponse();
268
				Jetpack_Options::update_option( 'publicize_connections', $response );
269
			}
270
		}
271
	}
272
273
	/**
274
	* Gets a URL to the public-api actions. Works like WP's admin_url
275
	*
276
	* @param string $service Shortname of a specific service.
277
	* @return URL to specific public-api process
278
	*/
279
	// on WordPress.com this is/calls Keyring::admin_url
280
	function api_url( $service = false, $params = array() ) {
281
		/**
282
		 * Filters the API URL used to interact with WordPress.com.
283
		 *
284
		 * @module publicize
285
		 *
286
		 * @since 2.0.0
287
		 *
288
		 * @param string https://public-api.wordpress.com/connect/?jetpack=publicize Default Publicize API URL.
289
		 */
290
		$url = apply_filters( 'publicize_api_url', 'https://public-api.wordpress.com/connect/?jetpack=publicize' );
291
292
		if ( $service )
293
			$url = add_query_arg( array( 'service' => $service ), $url );
294
295
		if ( count ( $params ) )
296
			$url = add_query_arg( $params, $url );
297
298
		return $url;
299
	}
300
301 View Code Duplication
	function connect_url( $service_name ) {
302
		return add_query_arg( array(
303
			'action'   => 'request',
304
			'service'  =>  $service_name,
305
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
306
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
307
		), menu_page_url( 'sharing', false ) );
308
	}
309
310
	function refresh_url( $service_name ) {
311
		return add_query_arg( array(
312
			'action'   => 'request',
313
			'service'  => $service_name,
314
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
315
			'refresh'  => 1,
316
			'for'      => 'publicize',
317
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
318
		), admin_url( 'options-general.php?page=sharing' ) );
319
	}
320
321 View Code Duplication
	function disconnect_url( $service_name, $id ) {
322
		return add_query_arg( array (
323
			'action'   => 'delete',
324
			'service'  => $service_name,
325
			'id'       => $id,
326
			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
327
			'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
328
		), menu_page_url( 'sharing', false ) );
329
	}
330
331
	function get_services( $filter ) {
332
		if ( !in_array( $filter, array( 'all', 'connected' ) ) )
333
			$filter = 'all';
334
335
		$services = array(
336
				'facebook'        => array(),
337
				'twitter'         => array(),
338
				'linkedin'        => array(),
339
				'tumblr'          => array(),
340
				'path'            => array(),
341
				'google_plus'     => array(),
342
		);
343
344
		if ( 'all' == $filter ) {
345
			return $services;
346
		} else {
347
			$connected_services = array();
348
			foreach ( $services as $service => $empty ) {
349
				$connections = $this->get_connections( $service );
350
				if ( $connections )
351
					$connected_services[$service] = $connections;
352
			}
353
			return $connected_services;
354
		}
355
	}
356
357
	function get_connection( $service, $id, $_blog_id = false, $_user_id = false ) {
358
		// Stub
359
	}
360
361
	function flag_post_for_publicize( $new_status, $old_status, $post ) {
362
		// Stub only. Doesn't need to do anything on Jetpack Client
363
	}
364
365
	function test_connection( $service_name, $connection ) {
366
		$connection_test_passed = true;
367
		$connection_test_message = '';
368
		$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...
369
370
		$id = $this->get_connection_id( $connection );
371
372
		Jetpack::load_xml_rpc_client();
373
		$xml = new Jetpack_IXR_Client();
374
		$xml->query( 'jetpack.testPublicizeConnection', $id );
375
376
		if ( $xml->isError() ) {
377
			$xml_response = $xml->getResponse();
378
			$connection_test_message = $xml_response['faultString'];
379
			$connection_test_passed = false;
380
		}
381
382
		// Bail if all is well
383
		if ( $connection_test_passed ) {
384
			return true;
385
		}
386
387
		// Set up refresh if the user can
388
		$user_can_refresh = current_user_can( $this->GLOBAL_CAP );
389
		if ( $user_can_refresh ) {
390
			$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...
391
			$refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) );
392
			$refresh_url = $this->refresh_url( $service_name );
393
		}
394
395
		$error_data = array(
396
			'user_can_refresh' => $user_can_refresh,
397
			'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...
398
			'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...
399
		);
400
401
		return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data );
402
	}
403
404
	/**
405
	 * Save a flag locally to indicate that this post has already been Publicized via the selected
406
	 * connections.
407
	 */
408
	function save_publicized( $new_status, $old_status, $post ) {
409
		// Only do this when a post transitions to being published
410
		if ( 'publish' == $new_status && 'publish' != $old_status ) {
411
			update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
412
		}
413
	}
414
415
	/**
416
	* Options Code
417
	*/
418
419
	function options_page_facebook() {
420
		$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
421
		$connection = $connected_services['facebook'][$_REQUEST['connection']];
422
		$options_to_show = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
423
424
		// Nonce check
425
		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
426
427
		$me    = ( ! empty( $options_to_show[0] )         ? $options_to_show[0]         : false );
428
		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
429
430
		$profile_checked = true;
431
		$page_selected = false;
432
433
		if ( !empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
434
			$found = false;
435
			if ( is_array( $pages->data ) ) {
436
				foreach ( $pages->data as $page ) {
437
					if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
438
						$found = true;
439
						break;
440
					}
441
				}
442
			}
443
444
			if ( $found ) {
445
				$profile_checked = false;
446
				$page_selected = $connection['connection_data']['meta']['facebook_page'];
447
			}
448
		}
449
450
		?>
451
452
		<div id="thickbox-content">
453
454
			<?php
455
			ob_start();
456
			Publicize_UI::connected_notice( 'Facebook' );
457
			$update_notice = ob_get_clean();
458
459
			if ( ! empty( $update_notice ) )
460
				echo $update_notice;
461
			?>
462
463
			<?php if ( !empty( $me['name'] ) ) : ?>
464
			<p><?php printf(
465
				esc_html__( 'Publicize to my %s:', 'jetpack' ),
466
				'<strong>' . esc_html__( 'Facebook Wall', 'jetpack' ) . '</strong>'
467
			); ?></p>
468
			<table id="option-profile">
469
				<tbody>
470
					<tr>
471
						<td class="radio"><input type="radio" name="option" data-type="profile" id="<?php echo esc_attr( $me['id'] ) ?>" value="" <?php checked( $profile_checked, true ); ?> /></td>
472
						<td class="thumbnail"><label for="<?php echo esc_attr( $me['id'] ) ?>"><img src="<?php echo esc_url( $me['picture']['data']['url'] ) ?>" width="50" height="50" /></label></td>
473
						<td class="details"><label for="<?php echo esc_attr( $me['id'] ) ?>"><?php echo esc_html( $me['name'] ) ?></label></td>
474
					</tr>
475
				</tbody>
476
			</table>
477
			<?php endif; ?>
478
479
			<?php if ( $pages ) : ?>
480
481
				<p><?php printf(
482
					esc_html__( 'Publicize to my %s:', 'jetpack' ),
483
					'<strong>' . esc_html__( 'Facebook Page', 'jetpack' ) . '</strong>'
484
				); ?></p>
485
				<table id="option-fb-fanpage">
486
					<tbody>
487
488
						<?php foreach ( $pages as $i => $page ) : ?>
489
							<?php if ( ! ( $i % 2 ) ) : ?>
490
								<tr>
491
							<?php endif; ?>
492
									<td class="radio"><input type="radio" name="option" data-type="page" id="<?php echo esc_attr( $page['id'] ) ?>" value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> /></td>
493
									<td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>" width="50" height="50" /></label></td>
494
									<td class="details">
495
										<label for="<?php echo esc_attr( $page['id'] ) ?>">
496
											<span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
497
											<span class="category"><?php echo esc_html( $page['category'] ) ?></span>
498
										</label>
499
									</td>
500
							<?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
501
								</tr>
502
							<?php endif; ?>
503
						<?php endforeach; ?>
504
505
					</tbody>
506
				</table>
507
508
			<?php endif; ?>
509
510
			<?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
511
512
			<p style="text-align: center;">
513
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>" class="button fb-options save-options" name="save" data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>" rel="<?php echo wp_create_nonce('save_fb_token_' . $_REQUEST['connection'] ) ?>" />
514
			</p><br/>
515
		</div>
516
517
		<?php
518
	}
519
520
	function options_save_facebook() {
521
		// Nonce check
522
		check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
523
524
		$id = $_POST['connection'];
525
526
		// Check for a numeric page ID
527
		$page_id = $_POST['selected_id'];
528
		if ( !ctype_digit( $page_id ) )
529
			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...
530
531
		if ( isset( $_POST['selected_id'] ) && 'profile' == $_POST['type'] ) {
532
			// Publish to User Wall/Profile
533
			$options = array(
534
				'facebook_page'       => null,
535
				'facebook_profile'    => true
536
			);
537
538
		} else {
539
			if ( 'page' != $_POST['type'] || !isset( $_POST['selected_id'] ) ) {
540
				return;
541
			}
542
543
			// Publish to Page
544
			$options = array(
545
				'facebook_page'       => $page_id,
546
				'facebook_profile'    => null
547
			);
548
		}
549
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
		}
558
559
		$this->globalization();
560
	}
561
562
	function options_page_tumblr() {
563
		// Nonce check
564
		check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
565
566
		$connected_services = Jetpack_Options::get_option( 'publicize_connections' );
567
		$connection = $connected_services['tumblr'][$_POST['connection']];
568
		$options_to_show = $connection['connection_data']['meta']['options_responses'];
569
		$request = $options_to_show[0];
570
571
		$blogs = $request['response']['user']['blogs'];
572
573
		$blog_selected = false;
574
575
		if ( !empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
576
			foreach ( $blogs as $blog ) {
577
				if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
578
					$blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
579
					break;
580
				}
581
			}
582
583
		}
584
585
		// Use their Primary blog if they haven't selected one yet
586
		if ( !$blog_selected ) {
587
			foreach ( $blogs as $blog ) {
588
				if ( $blog['primary'] )
589
					$blog_selected = $this->get_basehostname( $blog['url'] );
590
			}
591
		} ?>
592
593
		<div id="thickbox-content">
594
595
			<?php
596
			ob_start();
597
			Publicize_UI::connected_notice( 'Tumblr' );
598
			$update_notice = ob_get_clean();
599
600
			if ( ! empty( $update_notice ) )
601
				echo $update_notice;
602
			?>
603
604
			<p><?php printf(
605
				esc_html__( 'Publicize to my %s:', 'jetpack' ),
606
				'<strong>' . esc_html__( 'Tumblr blog', 'jetpack' ) . '</strong>'
607
			); ?></p>
608
609
			<ul id="option-tumblr-blog">
610
611
			<?php
612
			foreach ( $blogs as $blog ) {
613
				$url = $this->get_basehostname( $blog['url'] ); ?>
614
				<li>
615
					<input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>" value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
616
					<label for="<?php echo esc_attr( $url ) ?>"><span class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
617
				</li>
618
			<?php } ?>
619
620
			</ul>
621
622
			<?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
623
624
			<p style="text-align: center;">
625
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>" class="button tumblr-options save-options" name="save" data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>" rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>" />
626
			</p> <br />
627
		</div>
628
629
		<?php
630
	}
631
632
	function get_basehostname( $url ) {
633
		return parse_url( $url, PHP_URL_HOST );
634
	}
635
636
	function options_save_tumblr() {
637
		// Nonce check
638
		check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
639
640
		$id = $_POST['connection'];
641
642
		$options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
643
644
		Jetpack::load_xml_rpc_client();
645
		$xml = new Jetpack_IXR_Client();
646
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
647
648
		if ( !$xml->isError() ) {
649
			$response = $xml->getResponse();
650
			Jetpack_Options::update_option( 'publicize_connections', $response );
651
		}
652
653
		$this->globalization();
654
	}
655
656
	function options_page_twitter() { Publicize_UI::options_page_other( 'twitter' ); }
657
	function options_page_linkedin() { Publicize_UI::options_page_other( 'linkedin' ); }
658
	function options_page_path() { Publicize_UI::options_page_other( 'path' ); }
659
	function options_page_google_plus() { Publicize_UI::options_page_other( 'google_plus' ); }
660
661
	function options_save_twitter() { $this->options_save_other( 'twitter' ); }
662
	function options_save_linkedin() { $this->options_save_other( 'linkedin' ); }
663
	function options_save_path() { $this->options_save_other( 'path' ); }
664
	function options_save_google_plus() { $this->options_save_other( 'google_plus' ); }
665
666
	function options_save_other( $service_name ) {
667
		// Nonce check
668
		check_admin_referer( 'save_' . $service_name . '_token_' . $_REQUEST['connection'] );
669
		$this->globalization();
670
	}
671
672
	/**
673
	* Already-published posts should not be Publicized by default. This filter sets checked to
674
	* false if a post has already been published.
675
	*/
676
	function publicize_checkbox_default( $checked, $post_id, $name, $connection ) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $connection is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
677
		if ( 'publish' == get_post_status( $post_id ) )
678
			return false;
679
680
		return $checked;
681
	}
682
683
	/**
684
	* If there's only one shared connection to Twitter set it as twitter:site tag.
685
	*/
686
	function enhaced_twitter_cards_site_tag( $tag ) {
687
		$custom_site_tag = get_option( 'jetpack-twitter-cards-site-tag' );
688
		if( ! empty( $custom_site_tag ) )
689
			return $tag;
690
		if ( ! $this->is_enabled('twitter') )
691
			return $tag;
692
		$connections = $this->get_connections( 'twitter' );
693
		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...
694
			$connection_meta = $this->get_connection_meta( $connection );
695
			if ( 0 == $connection_meta['connection_data']['user_id'] ) {
696
				// If the connection is shared
697
				return $this->get_display_name( 'twitter', $connection );
698
			}
699
		}
700
		return $tag;
701
	}
702
703
	function save_publicized_twitter_account( $submit_post, $post_id, $service_name, $connection ) {
704
		if ( 'twitter' == $service_name && $submit_post ) {
705
			$connection_meta = $this->get_connection_meta( $connection );
706
			$publicize_twitter_user = get_post_meta( $post_id, '_publicize_twitter_user' );
707
			if ( empty( $publicize_twitter_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
708
				update_post_meta( $post_id, '_publicize_twitter_user', $this->get_display_name( 'twitter', $connection ) );
709
			}
710
		}
711
	}
712
713
	function get_publicized_twitter_account( $account, $post_id ) {
714
		if ( ! empty( $account ) ) {
715
			return $account;
716
		}
717
		$account = get_post_meta( $post_id, '_publicize_twitter_user', true );
718
		if ( ! empty( $account ) ) {
719
			return $account;
720
		}
721
		return '';
722
	}
723
724
	/**
725
	* Save the Publicized Facebook account when publishing a post
726
	* Use only Personal accounts, not Facebook Pages
727
	*/
728
	function save_publicized_facebook_account( $submit_post, $post_id, $service_name, $connection ) {
729
		$connection_meta = $this->get_connection_meta( $connection );
730
		if ( 'facebook' == $service_name && isset( $connection_meta['connection_data']['meta']['facebook_profile'] ) && $submit_post ) {
731
			$publicize_facebook_user = get_post_meta( $post_id, '_publicize_facebook_user' );
732
			if ( empty( $publicize_facebook_user ) || 0 != $connection_meta['connection_data']['user_id'] ) {
733
				$profile_link = $this->get_profile_link( 'facebook', $connection );
734
735
				if ( false !== $profile_link ) {
736
					update_post_meta( $post_id, '_publicize_facebook_user', $profile_link );
737
				}
738
			}
739
		}
740
	}
741
}
742