Completed
Push — renovate/enzyme-adapter-react-... ( 953931...f74946 )
by
unknown
25:48 queued 19:05
created

Publicize::get_connection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 4
dl 0
loc 3
rs 10
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
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
22
		add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
23
24
		add_filter( 'jetpack_published_post_flags', array( $this, 'set_post_flags' ), 10, 2 );
25
26
		add_action( 'wp_insert_post', array( $this, 'save_publicized' ), 11, 3 );
27
28
		add_filter( 'jetpack_twitter_cards_site_tag', array( $this, 'enhaced_twitter_cards_site_tag' ) );
29
30
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_twitter_account' ), 10, 4 );
31
		add_action( 'publicize_save_meta', array( $this, 'save_publicized_facebook_account' ), 10, 4 );
32
33
		add_action( 'connection_disconnected', array( $this, 'add_disconnect_notice' ) );
34
35
		add_filter( 'jetpack_sharing_twitter_via', array( $this, 'get_publicized_twitter_account' ), 10, 2 );
36
37
		include_once( JETPACK__PLUGIN_DIR . 'modules/publicize/enhanced-open-graph.php' );
38
39
		jetpack_require_lib( 'class.jetpack-keyring-service-helper' );
40
	}
41
42
	function add_disconnect_notice() {
43
		add_action( 'admin_notices', array( $this, 'display_disconnected' ) );
44
	}
45
46
	function force_user_connection() {
47
		global $current_user;
48
		$user_token        = Jetpack_Data::get_access_token( $current_user->ID );
49
		$is_user_connected = $user_token && ! is_wp_error( $user_token );
50
51
		// If the user is already connected via Jetpack, then we're good
52
		if ( $is_user_connected ) {
53
			return;
54
		}
55
56
		// If they're not connected, then remove the Publicize UI and tell them they need to connect first
57
		global $publicize_ui;
58
		remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
59
60
		// Do we really need `admin_styles`? With the new admin UI, it's breaking some bits.
61
		// Jetpack::init()->admin_styles();
62
		add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
63
	}
64
65
	function admin_page_warning() {
66
		$jetpack   = Jetpack::init();
67
		$blog_name = get_bloginfo( 'blogname' );
68
		if ( empty( $blog_name ) ) {
69
			$blog_name = home_url( '/' );
70
		}
71
72
		?>
73
		<div id="message" class="updated jetpack-message jp-connect">
74
			<div class="jetpack-wrap-container">
75
				<div class="jetpack-text-container">
76
					<p><?php printf(
77
							/* translators: %s is the name of the blog */
78
							esc_html( wptexturize( __( "To use Publicize, you'll need to link your %s account to your WordPress.com account using the link below.", 'jetpack' ) ) ),
79
							'<strong>' . esc_html( $blog_name ) . '</strong>'
80
						); ?></p>
81
					<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>
82
				</div>
83
				<div class="jetpack-install-container">
84
					<p class="submit"><a
85
							href="<?php echo $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ); ?>"
86
							class="button-connector"
87
							id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a>
88
					</p>
89
					<p class="jetpack-install-blurb">
90
						<?php jetpack_render_tos_blurb(); ?>
91
					</p>
92
				</div>
93
			</div>
94
		</div>
95
		<?php
96
	}
97
98
	/**
99
	 * Remove a Publicize connection
100
	 */
101
	function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
102
		return Jetpack_Keyring_Service_Helper::disconnect( $service_name, $connection_id, $_blog_id, $_user_id, $force_delete );
103
	}
104
105
	function receive_updated_publicize_connections( $publicize_connections ) {
106
		Jetpack_Options::update_option( 'publicize_connections', $publicize_connections );
107
108
		return true;
109
	}
110
111
	function register_update_publicize_connections_xmlrpc_method( $methods ) {
112
		return array_merge( $methods, array(
113
			'jetpack.updatePublicizeConnections' => array( $this, 'receive_updated_publicize_connections' ),
114
		) );
115
	}
116
117
	function get_all_connections() {
118
		$connections = Jetpack_Options::get_option( 'publicize_connections' );
119
		if ( isset( $connections['google_plus'] ) ) {
120
			unset( $connections['google_plus'] );
121
		}
122
		return $connections;
123
	}
124
125
	function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
126
		if ( false === $_user_id ) {
127
			$_user_id = $this->user_id();
128
		}
129
130
		$connections           = $this->get_all_connections();
131
		$connections_to_return = array();
132
133
		if ( ! empty( $connections ) && is_array( $connections ) ) {
134
			if ( ! empty( $connections[ $service_name ] ) ) {
135
				foreach ( $connections[ $service_name ] as $id => $connection ) {
136
					if ( 0 == $connection['connection_data']['user_id'] || $_user_id == $connection['connection_data']['user_id'] ) {
137
						$connections_to_return[ $id ] = $connection;
138
					}
139
				}
140
			}
141
142
			return $connections_to_return;
143
		}
144
145
		return false;
146
	}
147
148
	function get_all_connections_for_user() {
149
		$connections = $this->get_all_connections();
150
151
		$connections_to_return = array();
152
		if ( ! empty( $connections ) ) {
153
			foreach ( (array) $connections as $service_name => $connections_for_service ) {
154
				foreach ( $connections_for_service as $id => $connection ) {
155
					$user_id = intval( $connection['connection_data']['user_id'] );
156
					// phpcs:ignore WordPress.PHP.YodaConditions.NotYoda
157
					if ( $user_id === 0 || $this->user_id() === $user_id ) {
158
						$connections_to_return[ $service_name ][ $id ] = $connection;
159
					}
160
				}
161
			}
162
163
			return $connections_to_return;
164
		}
165
166
		return false;
167
	}
168
169
	function get_connection_id( $connection ) {
170
		return $connection['connection_data']['id'];
171
	}
172
173
	function get_connection_unique_id( $connection ) {
174
		return $connection['connection_data']['token_id'];
175
	}
176
177
	function get_connection_meta( $connection ) {
178
		$connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
179
		return $connection;
180
	}
181
182
	function admin_page_load() {
183
		if ( isset( $_GET['action'] ) && 'error' === $_GET['action'] ) {
184
					add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 );
185
		}
186
	}
187
188
	function display_connection_error() {
189
		$code = false;
190
		if ( isset( $_GET['service'] ) ) {
191
			$service_name = $_GET['service'];
192
			$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 ) );
193
		} else {
194
			if ( isset( $_GET['publicize_error'] ) ) {
195
				$code = strtolower( $_GET['publicize_error'] );
196
				switch ( $code ) {
197
					case '400':
198
						$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' );
199
						break;
200
					case 'secret_mismatch':
201
						$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' );
202
						break;
203
					case 'empty_blog_id':
204
						$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' );
205
						break;
206
					case 'empty_state':
207
						$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() );
208
						break;
209
					default:
210
						$error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack' );
211
						break;
212
				}
213
			} else {
214
				$error = __( 'There was a problem connecting with Publicize. Please try again in a moment.', 'jetpack' );
215
			}
216
		}
217
		// Using the same formatting/style as Jetpack::admin_notices() error
218
		?>
219
		<div id="message" class="jetpack-message jetpack-err">
220
			<div class="squeezer">
221
				<h2><?php echo wp_kses( $error, array( 'a'      => array( 'href' => true ),
222
				                                       'code'   => true,
223
				                                       'strong' => true,
224
				                                       'br'     => true,
225
				                                       'b'      => true
226
					) ); ?></h2>
227
				<?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...
228
					<p><?php printf( __( 'Error code: %s', 'jetpack' ), esc_html( stripslashes( $code ) ) ); ?></p>
229
				<?php endif; ?>
230
			</div>
231
		</div>
232
		<?php
233
	}
234
235
	function display_disconnected() {
236
		echo "<div class='updated'>\n";
237
		echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "</p>\n";
238
		echo "</div>\n\n";
239
	}
240
241
	function globalization() {
242
		if ( 'on' == $_REQUEST['global'] ) {
243
			$globalize_connection = $_REQUEST['connection'];
244
			if ( ! current_user_can( $this->GLOBAL_CAP ) ) {
245
				return;
246
			}
247
248
			$this->globalize_connection( $globalize_connection );
249
		}
250
	}
251
252 View Code Duplication
	function globalize_connection( $connection_id ) {
253
		Jetpack::load_xml_rpc_client();
254
		$xml = new Jetpack_IXR_Client();
255
		$xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'globalize' );
256
257
		if ( ! $xml->isError() ) {
258
			$response = $xml->getResponse();
259
			$this->receive_updated_publicize_connections( $response );
260
		}
261
	}
262
263 View Code Duplication
	function unglobalize_connection( $connection_id ) {
264
		Jetpack::load_xml_rpc_client();
265
		$xml = new Jetpack_IXR_Client();
266
		$xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'unglobalize' );
267
268
		if ( ! $xml->isError() ) {
269
			$response = $xml->getResponse();
270
			$this->receive_updated_publicize_connections( $response );
271
		}
272
	}
273
274
	function connect_url( $service_name, $for = 'publicize' ) {
275
		return Jetpack_Keyring_Service_Helper::connect_url( $service_name, $for );
276
	}
277
278
	function refresh_url( $service_name, $for = 'publicize' ) {
279
		return Jetpack_Keyring_Service_Helper::refresh_url( $service_name, $for );
280
	}
281
282
	function disconnect_url( $service_name, $id ) {
283
		return Jetpack_Keyring_Service_Helper::disconnect_url( $service_name, $id );
284
	}
285
286
	/**
287
	 * Get social networks, either all available or only those that the site is connected to.
288
	 *
289
	 * @since 2.0.0
290
	 * @since 6.6.0 Removed Path. Service closed October 2018.
291
	 *
292
	 * @param string $filter Select the list of services that will be returned. Defaults to 'all', accepts 'connected'.
293
	 *
294
	 * @return array List of social networks.
295
	 */
296
	function get_services( $filter = 'all', $_blog_id = false, $_user_id = false ) {
297
		$services = array(
298
			'facebook'    => array(),
299
			'twitter'     => array(),
300
			'linkedin'    => array(),
301
			'tumblr'      => array(),
302
		);
303
304 View Code Duplication
		if ( 'all' == $filter ) {
305
			return $services;
306
		} else {
307
			$connected_services = array();
308
			foreach ( $services as $service_name => $empty ) {
309
				$connections = $this->get_connections( $service_name, $_blog_id, $_user_id );
310
				if ( $connections ) {
311
					$connected_services[ $service_name ] = $connections;
312
				}
313
			}
314
			return $connected_services;
315
		}
316
	}
317
318
	function get_connection( $service_name, $id, $_blog_id = false, $_user_id = false ) {
319
		// Stub
320
	}
321
322
	function flag_post_for_publicize( $new_status, $old_status, $post ) {
323
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
324
			return;
325
		}
326
327
		if ( 'publish' == $new_status && 'publish' != $old_status ) {
328
			/**
329
			 * Determines whether a post being published gets publicized.
330
			 *
331
			 * Side-note: Possibly our most alliterative filter name.
332
			 *
333
			 * @module publicize
334
			 *
335
			 * @since 4.1.0
336
			 *
337
			 * @param bool $should_publicize Should the post be publicized? Default to true.
338
			 * @param WP_POST $post Current Post object.
339
			 */
340
			$should_publicize = apply_filters( 'publicize_should_publicize_published_post', true, $post );
341
342
			if ( $should_publicize ) {
343
				update_post_meta( $post->ID, $this->PENDING, true );
344
			}
345
		}
346
	}
347
348
	function test_connection( $service_name, $connection ) {
349
350
		$id = $this->get_connection_id( $connection );
351
352
		Jetpack::load_xml_rpc_client();
353
		$xml = new Jetpack_IXR_Client();
354
		$xml->query( 'jetpack.testPublicizeConnection', $id );
355
356
		// Bail if all is well
357
		if ( ! $xml->isError() ) {
358
			return true;
359
		}
360
361
		$xml_response            = $xml->getResponse();
362
		$connection_test_message = $xml_response['faultString'];
363
364
		// Set up refresh if the user can
365
		$user_can_refresh = current_user_can( $this->GLOBAL_CAP );
366
		if ( $user_can_refresh ) {
367
			$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...
368
			$refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) );
369
			$refresh_url  = $this->refresh_url( $service_name );
370
		}
371
372
		$error_data = array(
373
			'user_can_refresh' => $user_can_refresh,
374
			'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...
375
			'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...
376
		);
377
378
		return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data );
379
	}
380
381
	/**
382
	 * Checks if post has already been shared by Publicize in the past.
383
	 *
384
	 * Jetpack uses two methods:
385
	 * 1. A POST_DONE . 'all' postmeta flag, or
386
	 * 2. if the post has already been published.
387
	 *
388
	 * @since 6.7.0
389
	 *
390
	 * @param integer $post_id Optional. Post ID to query connection status for: will use current post if missing.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post_id not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
391
	 *
392
	 * @return bool True if post has already been shared by Publicize, false otherwise.
393
	 */
394
	public function post_is_done_sharing( $post_id = null ) {
395
		// Defaults to current post if $post_id is null.
396
		$post = get_post( $post_id );
397
		if ( is_null( $post ) ) {
398
			return false;
399
		}
400
401
		return 'publish' == $post->post_status || get_post_meta( $post->ID, $this->POST_DONE . 'all', true );
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( $post_ID, $post = null, $update = null ) {
409
		if ( is_null( $post ) ) {
410
			return;
411
		}
412
		// Only do this when a post transitions to being published
413
		if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) {
414
			$connected_services = $this->get_all_connections();
415
			if ( ! empty( $connected_services ) ) {
416
				/**
417
				 * Fires when a post is saved that has is marked as pending publicizing
418
				 *
419
				 * @since 4.1.0
420
				 *
421
				 * @param int The post ID
422
				 */
423
				do_action_deprecated( 'jetpack_publicize_post', $post->ID, '4.8.0', 'jetpack_published_post_flags' );
424
			}
425
			delete_post_meta( $post->ID, $this->PENDING );
426
			update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
427
		}
428
	}
429
430
	function set_post_flags( $flags, $post ) {
431
		$flags['publicize_post'] = false;
432
		if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) {
433
			return $flags;
434
		}
435
		/** This filter is already documented in modules/publicize/publicize-jetpack.php */
436
		if ( ! apply_filters( 'publicize_should_publicize_published_post', true, $post ) ) {
437
			return $flags;
438
		}
439
440
		$connected_services = $this->get_all_connections();
441
442
		if ( empty( $connected_services ) ) {
443
			return $flags;
444
		}
445
446
		$flags['publicize_post'] = true;
447
448
		return $flags;
449
	}
450
451
	/**
452
	 * Options Code
453
	 */
454
455
	function options_page_facebook() {
456
		$connected_services = $this->get_all_connections();
457
		$connection         = $connected_services['facebook'][ $_REQUEST['connection'] ];
458
		$options_to_show    = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false );
459
460
		// Nonce check
461
		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
462
463
		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
464
465
		$page_selected   = false;
466
		if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
467
			$found = false;
468
			if ( $pages && isset( $pages->data ) && is_array( $pages->data )  ) {
469
				foreach ( $pages->data as $page ) {
470
					if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
471
						$found = true;
472
						break;
473
					}
474
				}
475
			}
476
477
			if ( $found ) {
478
				$page_selected   = $connection['connection_data']['meta']['facebook_page'];
479
			}
480
		}
481
482
		?>
483
484
		<div id="thickbox-content">
485
486
			<?php
487
			ob_start();
488
			Publicize_UI::connected_notice( 'Facebook' );
0 ignored issues
show
Bug introduced by
The method connected_notice() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
489
			$update_notice = ob_get_clean();
490
491
			if ( ! empty( $update_notice ) ) {
492
				echo $update_notice;
493
			}
494
			$page_info_message = sprintf(
495
				__( 'Facebook supports Publicize connections to Facebook Pages, but not to Facebook Profiles. <a href="%s">Learn More about Publicize for Facebook</a>', 'jetpack' ),
496
				'https://jetpack.com/support/publicize/facebook'
497
			);
498
499
			if ( $pages ) : ?>
500
				<p><?php _e( 'Publicize to my <strong>Facebook Page</strong>:', 'jetpack' ); ?></p>
501
				<table id="option-fb-fanpage">
502
					<tbody>
503
504
					<?php foreach ( $pages as $i => $page ) : ?>
505
						<?php if ( ! ( $i % 2 ) ) : ?>
506
							<tr>
507
						<?php endif; ?>
508
						<td class="radio"><input type="radio" name="option" data-type="page"
509
						                         id="<?php echo esc_attr( $page['id'] ) ?>"
510
						                         value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> />
511
						</td>
512
						<td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img
513
									src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>"
514
									width="50" height="50"/></label></td>
515
						<td class="details">
516
							<label for="<?php echo esc_attr( $page['id'] ) ?>">
517
								<span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
518
								<span class="category"><?php echo esc_html( $page['category'] ) ?></span>
519
							</label>
520
						</td>
521
						<?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
522
							</tr>
523
						<?php endif; ?>
524
					<?php endforeach; ?>
525
526
					</tbody>
527
				</table>
528
529
				<?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
0 ignored issues
show
Bug introduced by
The method global_checkbox() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
530
				<p style="text-align: center;">
531
					<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
532
					       class="button fb-options save-options" name="save"
533
					       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
534
					       rel="<?php echo wp_create_nonce( 'save_fb_token_' . $_REQUEST['connection'] ) ?>"/>
535
				</p><br/>
536
				<p><?php echo $page_info_message; ?></p>
537
			<?php else: ?>
538
				<div>
539
					<p><?php echo $page_info_message; ?></p>
540
					<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>
541
				</div>
542
			<?php endif; ?>
543
		</div>
544
		<?php
545
	}
546
547
	function options_save_facebook() {
548
		// Nonce check
549
		check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
550
551
		// Check for a numeric page ID
552
		$page_id = $_POST['selected_id'];
553
		if ( ! ctype_digit( $page_id ) ) {
554
			die( 'Security check' );
555
		}
556
557
		if ( 'page' != $_POST['type'] || ! isset( $_POST['selected_id'] ) ) {
558
			return;
559
		}
560
561
		// Publish to Page
562
		$options = array(
563
			'facebook_page'    => $page_id,
564
			'facebook_profile' => null
565
		);
566
567
		$this->set_remote_publicize_options( $_POST['connection'], $options );
568
	}
569
570
	function options_page_tumblr() {
571
		// Nonce check
572
		check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
573
574
		$connected_services = $this->get_all_connections();
575
		$connection         = $connected_services['tumblr'][ $_POST['connection'] ];
576
		$options_to_show    = $connection['connection_data']['meta']['options_responses'];
577
		$request            = $options_to_show[0];
578
579
		$blogs = $request['response']['user']['blogs'];
580
581
		$blog_selected = false;
582
583
		if ( ! empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
584
			foreach ( $blogs as $blog ) {
585
				if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
586
					$blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
587
					break;
588
				}
589
			}
590
591
		}
592
593
		// Use their Primary blog if they haven't selected one yet
594
		if ( ! $blog_selected ) {
595
			foreach ( $blogs as $blog ) {
596
				if ( $blog['primary'] ) {
597
					$blog_selected = $this->get_basehostname( $blog['url'] );
598
				}
599
			}
600
		} ?>
601
602
		<div id="thickbox-content">
603
604
			<?php
605
			ob_start();
606
			Publicize_UI::connected_notice( 'Tumblr' );
0 ignored issues
show
Bug introduced by
The method connected_notice() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
607
			$update_notice = ob_get_clean();
608
609
			if ( ! empty( $update_notice ) ) {
610
				echo $update_notice;
611
			}
612
			?>
613
614
			<p><?php _e( 'Publicize to my <strong>Tumblr blog</strong>:', 'jetpack' ); ?></p>
615
616
			<ul id="option-tumblr-blog">
617
618
				<?php
619
				foreach ( $blogs as $blog ) {
620
					$url = $this->get_basehostname( $blog['url'] ); ?>
621
					<li>
622
						<input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>"
623
						       value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
624
						<label for="<?php echo esc_attr( $url ) ?>"><span
625
								class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
626
					</li>
627
				<?php } ?>
628
629
			</ul>
630
631
			<?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
0 ignored issues
show
Bug introduced by
The method global_checkbox() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
632
633
			<p style="text-align: center;">
634
				<input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>"
635
				       class="button tumblr-options save-options" name="save"
636
				       data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>"
637
				       rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>"/>
638
			</p> <br/>
639
		</div>
640
641
		<?php
642
	}
643
644
	function get_basehostname( $url ) {
645
		return parse_url( $url, PHP_URL_HOST );
646
	}
647
648
	function options_save_tumblr() {
649
		// Nonce check
650
		check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
651
		$options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
652
653
		$this->set_remote_publicize_options( $_POST['connection'], $options );
654
655
	}
656
657 View Code Duplication
	function set_remote_publicize_options( $id, $options ) {
658
		Jetpack::load_xml_rpc_client();
659
		$xml = new Jetpack_IXR_Client();
660
		$xml->query( 'jetpack.setPublicizeOptions', $id, $options );
661
662
		if ( ! $xml->isError() ) {
663
			$response = $xml->getResponse();
664
			Jetpack_Options::update_option( 'publicize_connections', $response );
665
			$this->globalization();
666
		}
667
	}
668
669
	function options_page_twitter() {
670
		Publicize_UI::options_page_other( 'twitter' );
0 ignored issues
show
Bug introduced by
The method options_page_other() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
671
	}
672
673
	function options_page_linkedin() {
674
		Publicize_UI::options_page_other( 'linkedin' );
0 ignored issues
show
Bug introduced by
The method options_page_other() does not seem to exist on object<Publicize_UI>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

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