<?php
/**
* Associate Facebook friends and pages with a post
*
* @since 1.1
*/
class Facebook_Social_Publisher_Settings {
/**
* Setting page identifier.
*
* @since 1.1
*
* @var string
*/
const PAGE_SLUG = 'facebook-social-publisher';
/**
* Define the option name used to process the form.
*
* @since 1.1
*
* @var string
*/
const PUBLISH_OPTION_NAME = 'facebook_publish';
/**
* Option name for target Facebook page.
*
* @since 1.1
*
* @var string
*/
const OPTION_PUBLISH_TO_PAGE = 'facebook_publish_page';
/**
* Option name for advanced Facebook Open Graph action functionality.
*
* @since 1.2.4
*
* @var string
*/
const OPTION_OG_ACTION = 'facebook_og_action';
/**
* The hook suffix assigned by add_submenu_page()
*
* @since 1.1
* @var string
*/
protected $hook_suffix = '';
/**
* The current user object.
*
* @since 1.1
*
* @var WP_User
*/
protected $current_user;
/**
* Does the current WordPress user have an associated Facebook account stored?
*
* @since 1.1
*
* @var boolean
*/
protected $user_associated_with_facebook_account = false;
/**
* Reference the social plugin by name
*
* @since 1.1
*
* @return string social plugin name
*/
public static function social_plugin_name() {
return __( 'Social Publisher', 'facebook' );
}
/**
* Navigate to the settings page through the Facebook top-level menu item.
*
* @since 1.1
*
* @uses add_submenu_page()
* @param string $parent_slug Facebook top-level menu item slug
* @return string submenu hook suffix
*/
public static function add_submenu_item( $parent_slug ) {
$social_publisher_settings = new Facebook_Social_Publisher_Settings();
$hook_suffix = add_submenu_page(
$parent_slug,
self::social_plugin_name(),
self::social_plugin_name(),
'manage_options',
self::PAGE_SLUG,
array( &$social_publisher_settings, 'settings_page' )
);
if ( $hook_suffix ) {
$social_publisher_settings->hook_suffix = $hook_suffix;
register_setting( $hook_suffix, self::PUBLISH_OPTION_NAME, array( 'Facebook_Social_Publisher_Settings', 'sanitize_publish_options' ) );
add_action( 'load-' . $hook_suffix, array( &$social_publisher_settings, 'onload' ) );
}
return $hook_suffix;
}
/**
* Load extra assets early in the page build process to tap into proper hooks
*
* @since 1.1
*
* @return void
*/
public function onload() {
// prep user-specific functionality and comparisons
$this->current_user = wp_get_current_user();
if ( ! class_exists( 'Facebook_User' ) )
require_once( dirname( dirname(__FILE__) ) . '/facebook-user.php' );
// does the current user have associated Facebook account data stored in WordPress?
$facebook_user_data = Facebook_User::get_user_meta( $this->current_user->ID, 'fb_data', true );
if ( is_array( $facebook_user_data ) && isset( $facebook_user_data['fb_uid'] ) ) {
$this->user_associated_with_facebook_account = true;
add_action( 'admin_enqueue_scripts', array( 'Facebook_Social_Publisher_Settings', 'enqueue_scripts' ) );
} else {
$this->user_associated_with_facebook_account = false;
}
$this->settings_api_init();
}
/**
* Load the page
*
* @since 1.1
*
* @return void
*/
public function settings_page() {
if ( ! isset( $this->hook_suffix ) )
return;
Facebook_Settings::settings_page_template( $this->hook_suffix, sprintf( __( '%s Settings', 'facebook' ), self::social_plugin_name() ) );
}
/**
* Hook into the settings API.
*
* @since 1.1
*
* @uses add_settings_section()
* @uses add_settings_field()
* @return void
*/
private function settings_api_init() {
if ( ! isset( $this->hook_suffix ) )
return;
// Timeline customizations
$section = 'facebook-publish-advanced';
add_settings_section(
$section,
__( 'Facebook Timeline', 'facebook' ),
array( &$this, 'section_timeline_publish' ),
$this->hook_suffix
);
add_settings_field(
'facebook-author-profile',
__( 'Facebook permissions', 'facebook' ),
array( 'Facebook_Social_Publisher_Settings', 'display_facebook_author' ),
$this->hook_suffix
);
add_settings_field(
'facebook-publish-author',
__( 'Publish to my Timeline', 'facebook' ),
array( &$this, 'display_publish_author' ),
$this->hook_suffix,
$section
);
add_settings_field(
'facebook-og-action',
__( 'Enable Open Graph features', 'facebook' ),
array( &$this, 'display_og_action' ),
$this->hook_suffix,
$section
);
$section = 'facebook-publish-page-section';
add_settings_section(
$section,
__( 'Facebook Page', 'facebook' ),
array( &$this, 'section_page_publish' ),
$this->hook_suffix
);
add_settings_field(
'facebook-publish-page',
_x( 'Publish to a page', 'Publish to a Facebook Page', 'facebook' ),
array( &$this, 'display_publish_page' ),
$this->hook_suffix,
$section
);
self::inline_help_content();
}
/**
* Add the login JavaScript to the WordPress script queue.
*
* @since 1.5
*
* @uses wp_enqueue_script()
* @return void
*/
public static function enqueue_scripts() {
global $wp_scripts;
if ( ! class_exists( 'Facebook_Settings' ) )
require_once( dirname(__FILE__) . '/settings.php' );
$handle = Facebook_Settings::register_login_script();
wp_enqueue_script( $handle );
// attach initialization JavaScript to WordPress enqueue. enqueue function for execution with Facebook SDK for JavaScript async loader
$script = 'jQuery(document).one("facebook-login-load",function(){if(FB_WP.queue && FB_WP.queue.add){FB_WP.queue.add(function(){FB_WP.admin.login.page.init()})}});';
$data = $wp_scripts->get_data( $handle, 'data' );
if ( $data )
$script = $data . "\n" . $script;
$wp_scripts->add_data( $handle, 'data', $script );
}
/**
* Introduce the publish to Facebook feature.
*
* @since 1.1
*
* @global Facebook_Loader $facebook_loader Facebook application id
* @return void
*/
public function section_timeline_publish() {
global $facebook_loader;
$app_id = '';
if ( isset( $facebook_loader ) && isset( $facebook_loader->credentials ) && isset( $facebook_loader->credentials['app_id'] ) )
$app_id = $facebook_loader->credentials['app_id'];
$yay = ' <span style="font-style:bold;color:green">✓</span>';
$boo = ' <span style="font-style:bold;color:red">X</span>';
echo '<p>' . esc_html( __( 'Promote social engagement and readership by publishing new posts to the Facebook Timeline of a connected author.', 'facebook' ) ) . '</p>';
echo '<p>' . sprintf( esc_html( __( 'Open Graph %s', 'facebook' ) ), '<a href="' . esc_url( 'https://developers.facebook.com/docs/wordpress/open-graph-action/', array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr( __( 'Facebook Open Graph action submission process', 'facebook' ) ) . '">' . esc_html( __( 'prerequisites', 'facebook' ) ) . '</a>' ) . ': </p>';
echo '<ol>';
echo '<li>' . esc_html( sprintf( _x( 'A Facebook application identifier associated with %s', 'Facebook app id for the website', 'facebook' ), get_bloginfo( 'name' ) ) );
if ( $app_id )
echo $yay;
else
echo $boo;
echo '</li>';
echo '<li>';
$og_action = esc_html( __( 'Associate an Open Graph action-object pair for your application:', 'facebook' ) ) . ' ' . sprintf( esc_html( _x( 'people can %1$s an %2$s', 'Open Graph. people can ACTION an OBJECT', 'facebook' ) ), '<strong>publish</strong>', '<strong>article</strong>' );
if ( $app_id )
echo '<a href="' . esc_url( 'https://developers.facebook.com/apps/' . $app_id . '/opengraph/getting-started/', array( 'http', 'https' ) ) . '" target="_blank">' . $og_action . '</a>';
else
echo $og_action;
echo '</li>';
unset( $og_action );
echo '<li>';
echo esc_html( __( 'Authenticate with Facebook to allow your Facebook application to post to your Timeline or Page on your behalf when a post is published', 'facebook' ) );
if ( $this->user_associated_with_facebook_account )
echo $yay;
else
echo $boo;
echo '</li>';
echo '<li>' . esc_html( __( 'Publish an article to your Facebook Timeline', 'facebook' ) ) . '</li>';
$og_action_text = esc_html( __( 'your Publish action', 'facebook' ) );
echo '<li>' . sprintf( esc_html( _x( 'Submit %s for approval.', 'Submit the Facebook Open Graph action name for approval.', 'facebook' ) ), $app_id ? '<a href="' . esc_url( 'https://developers.facebook.com/apps/' . $app_id . '/opengraph/action_type/331247406956072', array( 'http', 'https' ) ) . '" target="_blank">' . $og_action_text . '</a>' : $og_action_text );
echo ' ' . esc_html( __( 'Request optional capabilities:', 'facebook' ) ) . ' <a href="' . esc_url( 'https://developers.facebook.com/docs/submission-process/opengraph/guidelines/action-properties/#usermessages', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( _x( 'User Messages', 'Facebook Open Graph action capability permissions name: users may author a message associated with the action.', 'facebook' ) ) . '</a>, <a href="' . esc_url( 'https://developers.facebook.com/docs/submission-process/opengraph/guidelines/action-properties/#mentiontagging', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( _x( 'Tags', 'Facebook Open Graph action capability permissions name: users may mention tag friends in an action', 'facebook' ) ) . '</a>, <a href="' . esc_url( 'https://developers.facebook.com/docs/submission-process/opengraph/guidelines/action-properties/#explicitlyshared', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( _x( 'Explicitly Shared', 'Facebook Open Graph action capability: user has explicitly chosen to share the action to his or her Facebook Timeline', 'facebook' ) ) . '</a></li>';
unset( $og_action_text );
echo '</ol>';
}
/**
* Describe publish to Facebook Page functionality.
*
* @since 1.2.4
*
* @return void
*/
public function section_page_publish() {
echo '<p>' . sprintf( esc_html( __( 'Publish to a Facebook Page using the credentials of a Facebook account with %s permissions for the Page.', 'facebook' ) ), '<a href="' . esc_html( 'https://www.facebook.com/help/289207354498410/', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( _x( 'content creator', 'Facebook Page permissions grant classification for a Facebook user', 'facebook' ) ) . '</a>' ) . '</p>';
}
/**
* Publish new posts to your Facebook timeline.
*
* @since 1.1
*
* @return void
*/
public static function display_publish_author() {
echo '<p>' . sprintf( esc_html( __( 'An author can associate his or her WordPress account with a Facebook account on his or her %s', 'facebook' ) ), '<a href="' . esc_url( self_admin_url( 'profile.php' ), array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( __( 'profile page', 'facebook' ) ) . '</a>' ) . '</p>';
}
/**
* Publish new posts to your Facebook page.
*
* @since 1.1
*
* @return void
*/
public function display_publish_page() {
$existing_page = get_option( self::OPTION_PUBLISH_TO_PAGE );
if ( is_array( $existing_page ) && isset( $existing_page['id'] ) && isset( $existing_page['name'] ) && isset( $existing_page['access_token'] ) ) {
$page_id = $existing_page['id'];
} else {
$page_id = '';
}
echo '<div id="facebook-page"';
if ( $page_id ) {
echo ' data-fbid="' . esc_attr( $existing_page['id'] ) . '" data-name="' . esc_attr( $existing_page['name'] ) . '">';
echo '<p>';
echo sprintf( esc_html( _x( 'Publishing to %s', 'Currently publishing to the specified Facebook Page', 'facebook' ) ), '<a href="' . esc_url( ( isset( $existing_page['link'] ) ? $existing_page['link'] : 'https://www.facebook.com/' . $existing_page['id'] ), array( 'http', 'https' ) ) . '" title="' . esc_attr( sprintf( __( '%s page on Facebook', 'facebook' ), $existing_page['name'] ) ) . '" target="_blank">' . esc_html( $existing_page['name'] ) . '</a>' );
unset( $link );
// indicate the account responsible for publishing to the Facebook Page
if ( is_multi_author() && isset( $existing_page['set_by_user'] ) ) {
if ( $this->current_user->ID == $existing_page['set_by_user'] ) {
echo '. ' . esc_html( _x( 'Saved by you.', 'Saved by the current viewer of the page.', 'facebook' ) );
} else {
$setter = get_userdata( $existing_page['set_by_user'] );
if ( $setter && isset( $setter->display_name ) ) {
echo '. ' . esc_html( sprintf( _x( 'Saved by %s.', 'saved by person name', 'facebook' ), $setter->display_name ) );
}
}
}
echo '</p>';
} else {
echo '>';
}
if ( $this->user_associated_with_facebook_account ) {
// edits only avaialble to WordPress accounts connected with a Facebook account
echo '<div id="facebook-login" data-option="' . self::PUBLISH_OPTION_NAME . '[page_timeline]"></div>';
if ( ! class_exists( 'Facebook_User' ) )
require_once( dirname( dirname(__FILE__) ) . '/facebook-user.php' );
// page permissions require active user access token
Facebook_User::extend_access_token();
} else {
// send to profile page to connect an account if no connected account stored for current WP user
echo '<p><a href="' . esc_url( self_admin_url( 'profile.php' ), array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( 'Add a Facebook account to your WordPress account' ) . '</a></p>';
}
echo '</div>';
}
/**
* Display an option for the publisher to enable advanced Open Graph action functionality.
*
* @since 1.2.4
*
* @return void
*/
public function display_og_action() {
$id = 'og-action';
echo '<div><input type="checkbox" class="checkbox" name="' . self::PUBLISH_OPTION_NAME . '[og_action]" id="' . $id . '" value="1"';
checked( get_option( self::OPTION_OG_ACTION ) );
echo ' /> <label for="' . $id . '">' . esc_html( __( 'Post to Facebook Timeline using Open Graph actions', 'facebook' ) ) . '</label></div>';
echo '<p class="description">' . esc_html( __( 'Publish new posts to Facebook using Open Graph actions.', 'facebook' ) ) . ' ' . esc_html( __( 'Increases News Feed engagement through news-specific classification, explicitly shared posts, custom messages, and mention tagging.', 'facebook' ) ) . '</p>';
}
/**
* Display inline help for publisher functionality.
*
* @since 1.1.11
*
* @return string HTML
*/
public static function help_tab_publisher() {
$content = '<p>' . esc_html( __( 'The Facebook plugin for WordPress can publish to Facebook on your behalf through a properly configured Facebook application when a public post type becomes public.', 'facebook' ) ) . ' ' . esc_html( __( 'An author must grant your application permission to publish to his or her Facebook Timeline before the post will appear.', 'facebook' ) ) . ' ' . esc_html( __( 'A Facebook account with the ability to create content on one or more Facebook Pages may store publishing permissions for use by your WordPress site.', 'facebook' ) ) . '</p>';
$content .= '<p>' . esc_html( sprintf( __( 'You must associate an Open Graph action-object pair for your Facebook application and submit the action to Facebook for approval before articles from %s and its authors will appear in Facebook News Feed.', 'facebook' ), get_bloginfo('name') ) ) . ' ' . esc_html( __( "The Facebook plugin for WordPress cannot programmatically verify your application's Open Graph approval status.", 'facebook' ) ) . '</p>';
return $content;
}
/**
* Display help content on the settings page.
*
* @since 1.1
*
* @uses get_current_screen()
* @return void
*/
public static function inline_help_content() {
$screen = get_current_screen();
if ( ! $screen ) // null if global not set
return;
$screen->add_help_tab( array(
'id' => 'facebook-publish-help',
'title' => __( 'Publish to Facebook', 'facebook' ),
'content' => self::help_tab_publisher()
) );
$screen->set_help_sidebar( '<p><a href="' . esc_url( 'https://developers.facebook.com/apps/', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( __( 'Facebook Apps Tool', 'facebook' ) ) . '</a></p><p><a href="' . esc_url( 'https://developers.facebook.com/docs/wordpress/', array( 'http', 'https' ) ) . '" target="_blank">' . esc_html( __( 'Plugin help page', 'facebook' ) ) . '</a></p>' );
}
/**
* Update the Facebook page information stored for the site.
*
* @since 1.1
*
* @uses update_option()
* @global Facebook_Loader $facebook_loader request app access secret to hash app access token
* @param array $page_data data returned from Facebook Graph API permissions call
* @return void
*/
public static function update_publish_to_page( $page_data ) {
global $facebook_loader;
if ( ! ( is_array( $page_data ) && ! empty( $page_data ) && isset( $page_data['id'] ) ) )
return;
$current_user_id = get_current_user_id();
if ( ! $current_user_id )
return;
if ( ! class_exists( 'Facebook_User' ) )
require_once( dirname( dirname(__FILE__) ) . '/facebook-user.php' );
// request access token based on current user session and specified page
$write_pages = Facebook_User::get_permissioned_pages( 'CREATE_CONTENT' );
if ( ! ( $write_pages && is_array( $write_pages ) && isset( $write_pages[ $page_data['id'] ] ) && isset( $write_pages[ $page_data['id'] ]['name'] ) && isset( $write_pages[ $page_data['id'] ]['access_token'] ) ) )
return;
if ( ! class_exists( 'Facebook_WP_Extend' ) )
require_once( dirname( dirname(__FILE__) ) . '/includes/facebook-php-sdk/class-facebook-wp.php' );
// get long lived access token
$access_token = Facebook_WP_Extend::exchange_token( $write_pages[ $page_data['id'] ]['access_token'] );
if ( ! $access_token )
return;
$value = array(
'id' => $page_data['id'],
'name' => $write_pages[ $page_data['id'] ]['name'],
'access_token' => $access_token,
'set_by_user' => $current_user_id
);
if ( isset( $write_pages[ $page_data['id'] ]['link'] ) )
$value['link'] = $write_pages[ $page_data['id'] ]['link'];
if ( isset( $facebook_loader->credentials['app_secret'] ) )
$value['appsecret_proof'] = hash_hmac( 'sha256', $access_token, $facebook_loader->credentials['app_secret'] );
update_option( self::OPTION_PUBLISH_TO_PAGE, $value );
}
/**
* Set the appropriate settings for each form component.
*
* @since 1.1
*
* @param array $options social publisher options
* @return array clean option sets.
*/
public static function sanitize_publish_options( $options ) {
if ( ! is_array( $options ) || empty( $options ) )
return array();
$og_action_field = 'og_action';
if ( isset( $options[ $og_action_field ] ) ) {
update_option( self::OPTION_OG_ACTION, '1' );
} else {
delete_option( self::OPTION_OG_ACTION );
}
unset( $og_action_field );
$page_field = 'page_timeline';
if ( isset( $options[ $page_field ] ) ) {
$page_id = trim( $options[ $page_field ] );
if ( $page_id ) {
// check if page is stored
$existing_page = get_option( self::OPTION_PUBLISH_TO_PAGE );
if ( is_array( $existing_page ) && isset( $existing_page['id'] ) ) {
// process the option to delete the stored page
if ( $options[ $page_field ] === 'delete' ) {
delete_option( self::OPTION_PUBLISH_TO_PAGE );
} else if ( $page_id != $existing_page['id'] ) {
self::update_publish_to_page( array( 'id' => $page_id ) );
}
} else {
self::update_publish_to_page( array( 'id' => $page_id ) );
}
}
unset( $page_id );
}
unset( $page_field );
return false;
}
}
?>