get_access_token( $current_user->ID ); $is_user_connected = $user_token && ! is_wp_error( $user_token ); // If the user is already connected via Jetpack, then we're good. if ( $is_user_connected ) { return; } // If they're not connected, then remove the Publicize UI and tell them they need to connect first. global $publicize_ui; remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) ); // Do we really need `admin_styles`? With the new admin UI, it's breaking some bits. // Jetpack::init()->admin_styles();. add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 ); } /** * Show a warning when Publicize does not have a connection. */ public function admin_page_warning() { $jetpack = Jetpack::init(); $blog_name = get_bloginfo( 'blogname' ); if ( empty( $blog_name ) ) { $blog_name = home_url( '/' ); } ?>
array( $this, 'receive_updated_publicize_connections' ), ) ); } /** * Get a list of all connections. * * @return array */ public function get_all_connections() { $this->refresh_connections(); $connections = Jetpack_Options::get_option( 'publicize_connections' ); if ( isset( $connections['google_plus'] ) ) { unset( $connections['google_plus'] ); } return $connections; } /** * Get connections for a specific service. * * @param string $service_name 'facebook', 'twitter', etc. * @param false|int $_blog_id The blog ID. Use false (default) for the current blog. * @param false|int $_user_id The user ID. Use false (default) for the current user. * @return false|object[]|array[] */ public function get_connections( $service_name, $_blog_id = false, $_user_id = false ) { if ( false === $_user_id ) { $_user_id = $this->user_id(); } $connections = $this->get_all_connections(); $connections_to_return = array(); if ( ! empty( $connections ) && is_array( $connections ) ) { if ( ! empty( $connections[ $service_name ] ) ) { foreach ( $connections[ $service_name ] as $id => $connection ) { if ( $this->is_global_connection( $connection ) || $_user_id === (int) $connection['connection_data']['user_id'] ) { $connections_to_return[ $id ] = $connection; } } } return $connections_to_return; } return false; } /** * Get all connections for a specific user. * * @return array|false */ public function get_all_connections_for_user() { $connections = $this->get_all_connections(); $connections_to_return = array(); if ( ! empty( $connections ) ) { foreach ( (array) $connections as $service_name => $connections_for_service ) { foreach ( $connections_for_service as $id => $connection ) { $user_id = (int) $connection['connection_data']['user_id']; // phpcs:ignore WordPress.PHP.YodaConditions.NotYoda if ( $user_id === 0 || $this->user_id() === $user_id ) { $connections_to_return[ $service_name ][ $id ] = $connection; } } } return $connections_to_return; } return false; } /** * Get the ID of a connection. * * @param array $connection The connection. * @return string */ public function get_connection_id( $connection ) { return $connection['connection_data']['id']; } /** * Get the unique ID of a connection. * * @param array $connection The connection. * @return string */ public function get_connection_unique_id( $connection ) { return $connection['connection_data']['token_id']; } /** * Get the meta of a connection. * * @param array $connection The connection. * @return array */ public function get_connection_meta( $connection ) { $connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections. return $connection; } /** * Show error on settings page if applicable. */ public function admin_page_load() { $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( 'error' === $action ) { add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 ); } } /** * Display an error message. */ public function display_connection_error() { $code = false; // phpcs:disable WordPress.Security.NonceVerification.Recommended $service = isset( $_GET['service'] ) ? sanitize_text_field( wp_unslash( $_GET['service'] ) ) : null; $publicize_error = isset( $_GET['publicize_error'] ) ? sanitize_text_field( wp_unslash( $_GET['publicize_error'] ) ) : null; // phpcs:enable WordPress.Security.NonceVerification.Recommended if ( $service ) { /* translators: %s is the name of the Publicize service (e.g. Facebook, Twitter) */ $error = sprintf( __( 'There was a problem connecting to %s to create an authorized connection. Please try again in a moment.', 'jetpack' ), self::get_service_label( $service ) ); } else { if ( $publicize_error ) { $code = strtolower( $publicize_error ); switch ( $code ) { case '400': $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' ); break; case 'secret_mismatch': $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' ); break; case 'empty_blog_id': $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' ); break; case 'empty_state': /* translators: %s is the URL of the Jetpack admin page */ $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 Jetpack page within wp-admin.', 'jetpack' ), Jetpack::admin_url() ); break; default: $error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack' ); break; } } else { $error = __( 'There was a problem connecting with Publicize. Please try again in a moment.', 'jetpack' ); } } // Using the same formatting/style as Jetpack::admin_notices() error. ?> \n"; echo '' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "
\n"; echo "\n\n"; } /** * If applicable, globalize a connection. * * @param string $connection_id Connection ID. */ public function globalization( $connection_id ) { if ( isset( $_REQUEST['global'] ) && 'on' === $_REQUEST['global'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce check happens earlier in the process before we get here if ( ! current_user_can( $this->GLOBAL_CAP ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase return; } $this->globalize_connection( $connection_id ); } } /** * Globalize a connection. * * @param string $connection_id Connection ID. */ public function globalize_connection( $connection_id ) { $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'globalize' ); if ( ! $xml->isError() ) { $response = $xml->getResponse(); $this->receive_updated_publicize_connections( $response ); } } /** * Unglobalize a connection. * * @param string $connection_id Connection ID. */ public function unglobalize_connection( $connection_id ) { $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.globalizePublicizeConnection', $connection_id, 'unglobalize' ); if ( ! $xml->isError() ) { $response = $xml->getResponse(); $this->receive_updated_publicize_connections( $response ); } } /** * As Jetpack updates set the refresh transient to a random amount * in order to spread out updates to the connection data. * * @param string $version The Jetpack version being updated to. */ public function init_refresh_transient( $version ) { if ( version_compare( $version, '10.2.1', '>=' ) && ! get_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT ) ) { $this->set_refresh_wait_transient( wp_rand( 10, HOUR_IN_SECONDS * 24 ) ); } } /** * Grabs a fresh copy of the publicize connections data. * Only refreshes once every 12 hours or retries after an hour with an error. */ public function refresh_connections() { if ( get_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT ) ) { return; } $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.fetchPublicizeConnections' ); $wait_time = HOUR_IN_SECONDS * 24; if ( ! $xml->isError() ) { $response = $xml->getResponse(); $this->receive_updated_publicize_connections( $response ); } else { // Retry a bit quicker, but still wait. $wait_time = HOUR_IN_SECONDS; } $this->set_refresh_wait_transient( $wait_time ); } /** * Sets the transient to expire at the specified time in seconds. * This prevents us from attempting to refresh the data too often. * * @param int $wait_time The number of seconds before the transient should expire. */ public function set_refresh_wait_transient( $wait_time ) { set_transient( self::CONNECTION_REFRESH_WAIT_TRANSIENT, microtime( true ), $wait_time ); } /** * Get the Publicize connect URL from Keyring. * * @param string $service_name Name of the service to get connect URL for. * @param string $for What the URL is for. Default 'publicize'. * @return string */ public function connect_url( $service_name, $for = 'publicize' ) { return Jetpack_Keyring_Service_Helper::connect_url( $service_name, $for ); } /** * Get the Publicize refresh URL from Keyring. * * @param string $service_name Name of the service to get refresh URL for. * @param string $for What the URL is for. Default 'publicize'. * @return string */ public function refresh_url( $service_name, $for = 'publicize' ) { return Jetpack_Keyring_Service_Helper::refresh_url( $service_name, $for ); } /** * Get the Publicize disconnect URL from Keyring. * * @param string $service_name Name of the service to get disconnect URL for. * @param mixed $id ID of the conenction to disconnect. * @return string */ public function disconnect_url( $service_name, $id ) { return Jetpack_Keyring_Service_Helper::disconnect_url( $service_name, $id ); } /** * Get social networks, either all available or only those that the site is connected to. * * @since 2.0.0 * @since 6.6.0 Removed Path. Service closed October 2018. * * @param string $filter Select the list of services that will be returned. Defaults to 'all', accepts 'connected'. * @param false|int $_blog_id Get services for a specific blog by ID, or set to false for current blog. Default false. * @param false|int $_user_id Get services for a specific user by ID, or set to false for current user. Default false. * @return array List of social networks. */ public function get_services( $filter = 'all', $_blog_id = false, $_user_id = false ) { $services = array( 'facebook' => array(), 'twitter' => array(), 'linkedin' => array(), 'tumblr' => array(), ); if ( 'all' === $filter ) { return $services; } $connected_services = array(); foreach ( $services as $service_name => $empty ) { $connections = $this->get_connections( $service_name, $_blog_id, $_user_id ); if ( $connections ) { $connected_services[ $service_name ] = $connections; } } return $connected_services; } /** * Get a specific connection. Stub. * * @param string $service_name 'facebook', 'twitter', etc. * @param string $connection_id Connection ID. * @param false|int $_blog_id The blog ID. Use false (default) for the current blog. * @param false|int $_user_id The user ID. Use false (default) for the current user. * @return void */ public function get_connection( $service_name, $connection_id, $_blog_id = false, $_user_id = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable // Stub. } /** * Flag a post for Publicize after publishing. * * @param string $new_status New status of the post. * @param string $old_status Old status of the post. * @param WP_Post $post Post object. */ public function flag_post_for_publicize( $new_status, $old_status, $post ) { if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) { return; } $should_publicize = $this->should_submit_post_pre_checks( $post ); if ( 'publish' === $new_status && 'publish' !== $old_status ) { /** * Determines whether a post being published gets publicized. * * Side-note: Possibly our most alliterative filter name. * * @module publicize * * @since 4.1.0 * @since 10.9 No longer defaults to true. Adds checks to not publicize based on different contexts. * * @param bool $should_publicize Should the post be publicized? Default to true. * @param WP_POST $post Current Post object. */ $should_publicize = apply_filters( 'publicize_should_publicize_published_post', $should_publicize, $post ); if ( $should_publicize ) { update_post_meta( $post->ID, $this->PENDING, true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } } } /** * Test a connection. * * @param string $service_name Name of the service. * @param array $connection Connection to be tested. */ public function test_connection( $service_name, $connection ) { $id = $this->get_connection_id( $connection ); $xml = new Jetpack_IXR_Client(); $xml->query( 'jetpack.testPublicizeConnection', $id ); // Bail if all is well. if ( ! $xml->isError() ) { return true; } $xml_response = $xml->getResponse(); $connection_test_message = $xml_response['faultString']; // Set up refresh if the user can. $user_can_refresh = current_user_can( $this->GLOBAL_CAP ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase if ( $user_can_refresh ) { /* translators: %s is the name of a social media service */ $refresh_text = sprintf( _x( 'Refresh connection with %s', 'Refresh connection with {social media service}', 'jetpack' ), $this->get_service_label( $service_name ) ); $refresh_url = $this->refresh_url( $service_name ); } $error_data = array( 'user_can_refresh' => $user_can_refresh, 'refresh_text' => $refresh_text, 'refresh_url' => $refresh_url, ); return new WP_Error( 'pub_conn_test_failed', $connection_test_message, $error_data ); } /** * Checks if post has already been shared by Publicize in the past. * * Jetpack uses two methods: * 1. A POST_DONE . 'all' postmeta flag, or * 2. if the post has already been published. * * @since 6.7.0 * * @param integer $post_id Optional. Post ID to query connection status for: will use current post if missing. * * @return bool True if post has already been shared by Publicize, false otherwise. */ public function post_is_done_sharing( $post_id = null ) { // Defaults to current post if $post_id is null. $post = get_post( $post_id ); if ( $post === null ) { return false; } return 'publish' === $post->post_status || get_post_meta( $post->ID, $this->POST_DONE . 'all', true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } /** * Save a flag locally to indicate that this post has already been Publicized via the selected * connections. * * @param int $post_ID Post ID. * @param \WP_Post $post Post object. */ public function save_publicized( $post_ID, $post = null ) { if ( $post === null ) { return; } // Only do this when a post transitions to being published. // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase if ( get_post_meta( $post->ID, $this->PENDING ) && $this->post_type_is_publicizeable( $post->post_type ) ) { delete_post_meta( $post->ID, $this->PENDING ); update_post_meta( $post->ID, $this->POST_DONE . 'all', true ); } // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase } /** * Set post flags for Publicize. * * @param array $flags List of flags. * @param \WP_Post $post Post object. * @return array */ public function set_post_flags( $flags, $post ) { $flags['publicize_post'] = false; if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) { return $flags; } $should_publicize = $this->should_submit_post_pre_checks( $post ); /** This filter is already documented in modules/publicize/publicize-jetpack.php */ if ( ! apply_filters( 'publicize_should_publicize_published_post', $should_publicize, $post ) ) { return $flags; } $connected_services = $this->get_all_connections(); if ( empty( $connected_services ) ) { return $flags; } $flags['publicize_post'] = true; return $flags; } /** * Render Facebook options. */ public function options_page_facebook() { $connection_name = isset( $_REQUEST['connection'] ) ? filter_var( wp_unslash( $_REQUEST['connection'] ) ) : ''; // Nonce check. check_admin_referer( 'options_page_facebook_' . $connection_name ); $connected_services = $this->get_all_connections(); $connection = $connected_services['facebook'][ $connection_name ]; $options_to_show = ( ! empty( $connection['connection_data']['meta']['options_responses'] ) ? $connection['connection_data']['meta']['options_responses'] : false ); $pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false ); $page_selected = false; if ( ! empty( $connection['connection_data']['meta']['facebook_page'] ) ) { $found = false; if ( $pages && isset( $pages->data ) && is_array( $pages->data ) ) { foreach ( $pages->data as $page ) { if ( $page->id === (int) $connection['connection_data']['meta']['facebook_page'] ) { $found = true; break; } } } if ( $found ) { $page_selected = $connection['connection_data']['meta']['facebook_page']; } } ?>Facebook Page:', 'jetpack' ), array( 'strong' ) ); ?>
| /> |
Create a Facebook page to get started.', 'jetpack' ), 'https://www.facebook.com/pages/creation/', '_blank noopener noreferrer' ), array( 'a' => array( 'class', 'href', 'target' ) ) ); ?>
Tumblr blog:', 'jetpack' ), array( 'strong' ) ); ?>