. * * * Plugin Name: Facebook Page Publish * Plugin URI: http://wordpress.org/extend/plugins/facebook-page-publish/ * Description: Publishes your posts on the wall of a Facebook profile or page. * Author: Martin Tschirsich * Version: 0.3.9 * Author URI: http://www.tu-darmstadt.de/~m_t/ */ /********************************************************************** * Constants **********************************************************************/ #error_reporting(E_ALL); define('FPP_VERSION', '0.3.9'); define('FPP_BASE_DIR', dirname(__file__)); define('FPP_BASE_URL', WP_PLUGIN_URL.'/'.str_replace(basename( __FILE__), '', plugin_basename(__FILE__))); define('FPP_ADMIN_URL', admin_url('admin.php?page='.urlencode(plugin_basename(__FILE__)))); define('FPP_DEFAULT_POST_TO_FACEBOOK', false); // Checkbox admin panel always preselected define('FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH', 340); // Facebook link description allows max. 420 characters, 340 are always shown define('FPP_REQUEST_TIMEOUT', 20); // The default 5s are not sufficient on some servers define('FPP_TEXT_DOMAIN', 'facebook-page-publish'); /********************************************************************** * Exceptions **********************************************************************/ class CommunicationException extends Exception { public function __construct($message = null, $code = 0) { if (!empty($message)) $message .= '
'; $message .= '[Error occured at line '.$this->getLine().']'; parent::__construct($message, $code); } } class FacebookUnreachableException extends CommunicationException { public function __construct($message = null, $code = 0) { if (empty($message)) { $message = __('Facebook is not reachable from your server.', FPP_TEXT_DOMAIN).' '.__('Check the connection!', FPP_TEXT_DOMAIN).''; } else { $message = sprintf(__('Facebook is not reachable from your server: %s', FPP_TEXT_DOMAIN), $message).'
'.__('Check your connection!', FPP_TEXT_DOMAIN).''; } parent::__construct($message, $code); } } class FacebookErrorException extends CommunicationException { public function __construct($message, $code = 0) { $message = sprintf(__('Facebook returned an error: %s', FPP_TEXT_DOMAIN), $message); parent::__construct($message, $code); } } class FacebookUnexpectedErrorException extends CommunicationException { public function __construct($message = null, $code = 0) { if (empty($message)) { $message = __('Facebook returned an unexpected error.', FPP_TEXT_DOMAIN).' '.__('Try to resolve this issue, update the plugin or inform the author about the problem.', FPP_TEXT_DOMAIN); } else { $message = sprintf(__('Facebook returned an unexpected error: %s', FPP_TEXT_DOMAIN), $message).'
'.__('Try to resolve this issue, update the plugin or inform the author about the problem.', FPP_TEXT_DOMAIN); } parent::__construct($message, $code); } } class FacebookUnexpectedDataException extends CommunicationException { public function __construct($message = null, $code = 0) { if (empty($message)) { $message = __('Facebook returned an unexpected dataset.', FPP_TEXT_DOMAIN).' '.__('Try to resolve this issue, update the plugin or inform the author about the problem.', FPP_TEXT_DOMAIN); } else { $message = sprintf(__('Facebook returned an unexpected dataset: %s', FPP_TEXT_DOMAIN), $message).'
'.__('Try to resolve this issue, update the plugin or inform the author about the problem.', FPP_TEXT_DOMAIN); } parent::__construct($message, $code); } } /********************************************************************** * Action handler **********************************************************************/ # Add publish actions for all post types (posts, pages, attachements, custom post types): $post_types = get_post_types(array('exclude_from_search' => false), 'objects'); foreach ($post_types as $post_type) { add_action('future_'.$post_type->name, 'fpp_future_action'); add_action('publish_'.$post_type->name, 'fpp_publish_action'); } add_action('admin_init', 'fpp_admin_init_action'); add_action('admin_menu', 'fpp_admin_menu_action'); add_action('wp_head', 'fpp_head_action'); add_action('post_submitbox_start', 'fpp_post_submitbox_start_action'); add_action('init', 'fpp_init_action'); function fpp_init_action() { //global $locale; $locale='de_DE'; load_plugin_textdomain(FPP_TEXT_DOMAIN, false, dirname(plugin_basename(__FILE__))); } /** * Called on html head rendering. Prints meta tags to make posts appear * correctly in Facebook. */ function fpp_head_action() { global $post; if (is_object($post) /*&& ($post->post_type == 'post') */ && is_singular()) { fpp_render_meta_tags($post); } } /** * Called on admin menu rendering, adds an options page and its * rendering callback. * * @see fpp_render_options_page() */ function fpp_admin_menu_action() { $page = add_options_page(__('Facebook Page Publish Options', FPP_TEXT_DOMAIN), __('Facebook Page Publish', FPP_TEXT_DOMAIN), 'manage_options', __FILE__, 'fpp_render_options_page'); add_action('admin_print_scripts-'.$page, 'fpp_admin_print_scripts_action'); add_action('admin_print_styles-'.$page, 'fpp_admin_print_styles_action'); } /** * Called when a user accesses the admin area. Registers settings and a * sanitization callback. Initializes the plugin options when a version * update has been detected. * * @see fpp_validate_options */ function fpp_admin_init_action() { register_setting('fpp_options_group', 'fpp_options', 'fpp_validate_options'); $version = get_option('fpp_installed_version'); if ($version != FPP_VERSION) { fpp_initialize_options(); } } /** * Loads media gallery scripts. * * @last_review 0.3.0 */ function fpp_admin_print_scripts_action() { wp_enqueue_script('media-upload'); wp_enqueue_script('thickbox'); wp_register_script('fpp-upload', FPP_BASE_URL.'fpp_script.js', array('jquery','media-upload','thickbox')); wp_enqueue_script('fpp-upload'); } /** * Loads media gallery styles. * * @last_review 0.3.0 */ function fpp_admin_print_styles_action() { wp_enqueue_style('thickbox'); } /** * Called when the submitbox is rendered. Renders a publish to Facebook * button if the current user has the 'publish_posts' permission. * * @last_review 0.3.0 */ function fpp_post_submitbox_start_action() { global $post; if (is_object($post) and /*($post->post_type == 'post') and*/ current_user_can('publish_posts')) { fpp_render_post_button(); } } /** * Called on any_to_future post state transition (scheduled post). * Marks any given post for publishing on Facebook * - if it was send directly from the admin panel and the * post-to-facebook checkbox was checked. * Marks any given post for NOT publishing on Facebook * - if it was send directly from the admin panel and the * post-to-facebook checkbox was NOT checked. * * @last_review 0.3.0 */ function fpp_future_action($post_id) { $send_from_admin = isset($_REQUEST['fpp_send_from_admin']); if ($send_from_admin) { $post = get_post($post_id); if (/*($post->post_type == 'post')*/ true) { if (!empty($_REQUEST['fpp_post_to_facebook'])) { // Directly send from the user (admin panel) with active checkbox $options = get_option('fpp_options'); update_post_meta($post->ID, '_fpp_is_scheduled', true); } else { update_post_meta($post->ID, '_fpp_is_scheduled', false); } } } } /** * Called on any_to_publish post state transition (published post). * Publishes any given non password protected post to Facebook * - if it was send directly from the admin panel and the * post-to-facebook checkbox was checked. * - if it was previously marked for publishing on Facebook (scheduled). * - if it was NOT send directly from the admin panel and the plugin * is set to always post on Facebook and the post is not already * published (on wordpress or Facebook). * * @see fpp_render_post_button() */ function fpp_publish_action($post_id) { $post = get_post($post_id); if (/*($post->post_type == 'post')*/ true) { $object_access_token = get_option('fpp_object_access_token'); if (!empty($object_access_token)) { // Incomplete plugin configuration, do nothing, report no error $send_from_admin = isset($_REQUEST['fpp_send_from_admin']); unset($_REQUEST['fpp_send_from_admin']); // Sometimes fpp_publish_action is called twice in a row $options = get_option('fpp_options'); try { if ($send_from_admin && !empty($_REQUEST['fpp_post_to_facebook'])) { // Directly send from the user (admin panel) with active post checkbox // If post was already published, delete it from FB: $post_id = get_post_meta($post->ID, '_fpp_post_id', true); if (!empty($post_id)) { // Old posts (version <= 0.3.7) do not contain a post_id fpp_unpublish_from_facebook($post_id, $options['object_id'], get_option('fpp_object_access_token')); } $post_id = fpp_publish_to_facebook($post, $options['object_id'], get_option('fpp_object_access_token')); update_post_meta($post->ID, '_fpp_is_published', true); update_post_meta($post->ID, '_fpp_post_id', $post_id); } else if (get_post_meta($post->ID, '_fpp_is_scheduled', true) == true) { // Scheduled post previously marked for Facebook publishing by the user // If post was already published, delete it from FB: $post_id = get_post_meta($post->ID, '_fpp_post_id', true); if (!empty($post_id)) { // Old posts (version <= 0.3.7) do not contain a post_id fpp_unpublish_from_facebook($post_id, $options['object_id'], get_option('fpp_object_access_token')); } $post_id = fpp_publish_to_facebook($post, $options['object_id'], get_option('fpp_object_access_token')); update_post_meta($post->ID, '_fpp_is_published', true); delete_post_meta($post->ID, '_fpp_is_scheduled'); update_post_meta($post->ID, '_fpp_post_id', $post_id); } else if (!$send_from_admin && (array_search('_fpp_is_scheduled', get_post_custom_keys($post->ID)) === false) && !get_post_meta($post->ID, '_fpp_is_published', true) && ($_POST['original_post_status'] != 'publish')) { // not send from admin panel, not already published (FB and WP), user never decided for or against publishing if (empty($post->post_password) and fpp_get_default_publishing($post)) { // Dont post password protected posts without the users consient // If post was already published, delete it from FB: $post_id = get_post_meta($post->ID, '_fpp_post_id', true); if (!empty($post_id)) { // Old posts (version <= 0.3.7) do not contain a post_id fpp_unpublish_from_facebook($post_id, $options['object_id'], get_option('fpp_object_access_token')); } $post_id = fpp_publish_to_facebook($post, $options['object_id'], get_option('fpp_object_access_token')); update_post_meta($post->ID, '_fpp_is_published', true); update_post_meta($post->ID, '_fpp_post_id', $post_id); } } } catch (CommunicationException $exception) { update_option('fpp_error', sprintf(__('

While publishing "%1$s" to Facebook, an error occured:

%2$s

', FPP_TEXT_DOMAIN), $post->post_title, $exception->getMessage())); } } } } /********************************************************************** * Facebook functions **********************************************************************/ /** * Publishes the given post to a Facebook page. * * @param post Wordpress post to publish * @param object_id Facebook page or wall ID * @param object_acces_token Access token for the given object * @return Facebook(!) post id * * @last_review 0.3.8 */ function fpp_publish_to_facebook($post, $object_id, $object_acces_token) { $options = get_option('fpp_options'); if (empty($post->post_password) and $options['show_post_text']) { $message = fpp_extract_message(apply_filters('the_excerpt', $post->post_excerpt), $options['show_post_link']); if (empty($message)) $message = fpp_extract_message(apply_filters('the_content', $post->post_content), $options['show_post_link']); if ($options['show_post_link']) { $message = wp_kses($message, array('a' => array('href' => array()))); $message = preg_replace('/]*?href *= *["|\']([^"|\']+).[^>]*?>(.*?)<\/a>\s*/is', '${2} ${1} ', $message); $message = trim(stripslashes(html_entity_decode($message, ENT_QUOTES, 'UTF-8'))); } else { $message = trim(stripslashes(html_entity_decode(wp_filter_nohtml_kses($message), ENT_QUOTES, 'UTF-8'))); } // Remove empty lines: $message = preg_replace("/\n\s*\n(\n|\s)*/s", "\n",$message); if (strpos($message, '') !== false) { $message = substr($message, 0, strpos($message, '')); } // Remove HTML Comments: $message = preg_replace('//Uis', '', $message); if (strlen($message) >= FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH) { $last_space_pos = strrpos(substr($message, 0, FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH - 3), ' '); $message = substr($message, 0, !empty($last_space_pos) ? $last_space_pos : FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH - 3).__('...', FPP_TEXT_DOMAIN); } } else { $message = ''; // Password protected, no content displayed. } // Publish: $request = new WP_Http; // Facebook bug 19336 is resolved, so /links should work (usage of /feed no longer necessary): $api_url = 'https://graph.facebook.com/'.urlencode($object_id).'/links'; $body = array('message' => $message, 'link' => get_permalink($post->ID), 'access_token' => $object_acces_token); $response = $request->request($api_url, array('method' => 'POST', 'body' => $body, 'timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); // Error detection: if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); $json_response = json_decode($response['body']); if (is_object($json_response) and property_exists($json_response, 'error')) { throw new FacebookUnexpectedErrorException((is_object($json_response->error) and property_exists($json_response->error, 'message')) ? $json_response->error->message : ''); } return $json_response->id; // Return ID of the published link (usefull to delete it later). } /** * Extract a message to be posted on Facebook from a text string that * may contain html, WP shortcodes etc. * * @param string * @param include_links Include URLs from HTML links if true * @return extracted message ready to be posted on Facebook */ function fpp_extract_message($string, $include_links) { $message = do_shortcode($string); $message = preg_replace('~<\s*\bscript\b[^>]*>(.*?)<\s*\/\s*script\s*>~is', '', $message); // Remove javascript code (not only tags) $message = preg_replace('//Uis', '', $message); // Remove HTML comments (not only tags) if ($include_links) { $message = wp_kses($message, array('a' => array('href' => array()))); $message = preg_replace('/]*?href *= *["|\']([^"|\']+).[^>]*?>(.*?)<\/a>\s*/is', '${2} ${1} ', $message); $message = trim(stripslashes(html_entity_decode($message, ENT_QUOTES, 'UTF-8'))); } else { $message = trim(stripslashes(html_entity_decode(wp_filter_nohtml_kses($message), ENT_QUOTES, 'UTF-8'))); } // Remove empty lines: $message = preg_replace("/\n\s*\n(\n|\s)*/s", "\n",$message); if (strpos($message, '') !== false) { $message = substr($message, 0, strpos($message, '')); } if (strlen($message) >= FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH) { $last_space_pos = strrpos(substr($message, 0, FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH - 3), ' '); $message = substr($message, 0, !empty($last_space_pos) ? $last_space_pos : FPP_FACEBOOK_LINK_DESCRIPTION_MAX_LENGTH - 3).__('...', FPP_TEXT_DOMAIN); } return $message; } /** * Removes the given post from a Facebook page. If a post with the given * ID does not exist on FB, the return value is 'false. * * @param post_id Facebook(!) post ID * @param object_id Facebook page or wall ID * @param object_acces_token Access token for the given object * @return True if post was found and removed * * @last_review 0.3.8 */ function fpp_unpublish_from_facebook($post_id, $object_id, $object_acces_token) { $request = new WP_Http; $api_url = 'https://graph.facebook.com/'.urlencode($object_id).'_'.urlencode($post_id).'?method=delete'; $body = array('access_token' => $object_acces_token); $response = $request->request($api_url, array('method' => 'POST', 'body' => $body, 'timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); // Error detection: if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); $object = json_decode($response['body']); if (is_object($object) and property_exists($object, 'error')) { if (property_exists($object->error, 'message')) { if (strpos($object->error->message, 'Invalid parameter') !== false) return false; throw new FacebookUnexpectedErrorException($object->error->message); } throw new FacebookUnexpectedErrorException(''); } return $response['body'] === 'true'; } /** * Checks whether a given access_token is valid and has the give * permissions. * * @param object_id Page or profile ID * @param object_type Either 'page' or 'profile' * @param object_access_token The access token to validate * @param permissions Array of permission strings to validate * @return True if access_token valid and all permissions granted * * @last_review 0.3.1 */ function fpp_verify_profile_access_permissions($profile_access_token, $permissions) { $request = new WP_Http; $api_url = 'https://api.facebook.com/method/fql.query?access_token='.urlencode($profile_access_token).'&format=json&query='.urlencode('SELECT '.implode(',', $permissions).' FROM permissions WHERE uid = me()'); $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException((!empty($response->errors) ? array_pop(array_pop($response->errors)) : '')); $json_response = json_decode($response['body']); if (is_object($json_response) and property_exists($json_response, 'error_msg')) { if (property_exists($json_response, 'error_code') and ($json_response->error_code == 190)) // Access token expired or invalid return false; if (property_exists($json_response, 'error_code') and ($json_response->error_code == 104)) // 'Requires valid signature'-error return false; throw new FacebookUnexpectedErrorException($json_response->error_msg); } if (!is_array($json_response)) { throw new FacebookUnexpectedDataException(); } $json_response = array_pop($json_response); if (!is_object($json_response)) { throw new FacebookUnexpectedDataException(); } foreach ($permissions as $permission) { if (!property_exists($json_response, $permission) or empty($json_response->$permission)) return false; } return true; } function fpp_verify_page_access_token($page_id, $page_access_token) { $request = new WP_Http; $api_url = 'https://graph.facebook.com/'.urlencode($page_id).'?access_token='.urlencode($page_access_token); $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); # TODO: verify access_permissions... return ($response['response']['code'] == 200); } /** * Classifies Facebook object ids. * * @param object_ids Array of Facebook object ids * @return map with a type string for each Facebook object id * * @last_review 0.3.0 */ function fpp_classify_facebook_objects($object_ids) { $numerical_object_ids = array_filter($object_ids, 'is_numeric'); // Alphabetical id's produce a Facebook error. $request = new WP_Http; $api_url = 'https://api.facebook.com/method/fql.query?format=json&query='.urlencode('SELECT id, type FROM object_url WHERE id IN ('.implode(',', $numerical_object_ids).')'); $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); $json_response = json_decode($response['body']); if (is_object($json_response) and property_exists($json_response, 'error')) { throw new FacebookUnexpectedErrorException((is_object($json_response->error) and property_exists($json_response->error, 'message')) ? $json_response->error->message : ''); } if (!is_array($json_response)) { throw new FacebookUnexpectedDataException(); } $result = array(); $float_object_ids = array_map('floatval', $numerical_object_ids); // PHP <= 5.2 is missing JSON_BIGINT foreach ($json_response as $json_response_entry) { if (!property_exists($json_response_entry, 'type') or !property_exists($json_response_entry, 'id')) throw new FacebookUnexpectedDataException(); $result[$numerical_object_ids[array_search($json_response_entry->id, $float_object_ids)]] = $json_response_entry->type; } foreach ($object_ids as $object_id) { if (!array_key_exists($object_id, $result)) $result[$object_id]= ''; } return $result; } /** * Checks whether a given Facebook application id and its secret are * valid. * * @param app_id Application id to verify * @param app_secret Application secret * @param redirect_uri URL equal to the URL in the Facebook app settings * @return True if the given application id and secret are valid * * @last_review 0.3.0 */ function fpp_is_valid_facebook_application($app_id, $app_secret, $redirect_uri) { $request = new WP_Http; $api_url = 'https://graph.facebook.com/oauth/access_token?client_id='.urlencode($app_id).'&client_secret='.urlencode($app_secret).'&redirect_uri='.urlencode($redirect_uri).'&code=SOME_INVALID_CODE'; $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); $object = json_decode($response['body']); if (property_exists($object, 'error')) { if (property_exists($object->error, 'message')) { if (strpos($object->error->message, 'Error validating client secret') !== false) return false; if (strpos($object->error->message, 'Invalid verification code format') !== false) return true; if (strpos($object->error->message, 'Invalid redirect_uri') !== false) throw new FacebookErrorException(sprintf(__('The site URL in your Facebook application settings does not match your wordpress blog URL. Please refer to the detailed setup instructions.', FPP_TEXT_DOMAIN), FPP_BASE_URL.'setup.htm#site_url')); throw new FacebookUnexpectedErrorException($object->error->message); } throw new FacebookUnexpectedErrorException(); } throw new FacebookUnexpectedDataException(); } /** * Acquires an object access token with all these permissions that * were specified when retrieving the code. * * @param app_id Application ID * @param app_secret Application secret * @param object_id Facebook page or profile ID * @param object_type Either 'profile' or 'page' * @param redirect_uri URL used to get the transaction code * @param code Transaction code (refer to the OAuth protocoll docs) * * @last_rewiev 0.3.1 */ function fpp_acquire_profile_access_token($app_id, $app_secret, $redirect_uri, $code) { $request = new WP_Http; $api_url = 'https://graph.facebook.com/oauth/access_token?client_id='.urlencode($app_id).'&redirect_uri='.urlencode($redirect_uri).'&client_secret='.urlencode($app_secret).'&code='.urlencode($code); $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)) : ''); $json_response = json_decode($response['body']); if (is_object($json_response) and property_exists($json_response, 'error') and property_exists($json_response->error, 'message')) { if (is_string($json_response->error->message) and (strpos($json_response->error->message, 'Code was invalid or expired') !== false)) { throw new FacebookErrorException(__('Your authorization code was invalid or expired. Please try again. If the problem persists update the plugin or inform the author.', FPP_TEXT_DOMAIN)); } else throw new FacebookUnexpectedErrorException($json_response->error->message); } $access_token_url = $response['body']; preg_match('/^.+=\s*(.+)/', $access_token_url, $matches); if (!empty($matches[1])) return $matches[1]; throw new FacebookUnexpectedDataException(); } function fpp_acquire_page_access_token($page_id, $profile_access_token) { $request = new WP_Http; $api_url = 'https://graph.facebook.com/me/accounts?access_token='.urlencode($profile_access_token); $response = $request->get($api_url, array('timeout' => FPP_REQUEST_TIMEOUT, 'sslverify' => fpp_get_ssl_verify())); if (array_key_exists('errors', $response)) throw new FacebookUnreachableException(!empty($response->errors) ? array_pop(array_pop($response->errors)): ''); $json_response = json_decode($response['body']); if (!is_object($json_response) || !property_exists($json_response, 'data')) throw new FacebookUnexpectedErrorException(__('Can\'t access Facebook user account information.', FPP_TEXT_DOMAIN)); foreach ($json_response->data as $account) { if ($account->id == $page_id) { if (!property_exists($account, 'access_token')) throw new FacebookUnexpectedErrorException(__('Some or all access permissions for your page are missing.', FPP_TEXT_DOMAIN)); $page_access_token = $account->access_token; break; } } if (!isset($page_access_token)) throw new FacebookErrorException(__('Your Facebook user account data contains no page with the given ID. You have to be administrator of the given page.', FPP_TEXT_DOMAIN)); return $page_access_token; } /********************************************************************** * Getter **********************************************************************/ /** * Determines whether a post should be pulished by default or not, * depending on the plugin options and the post category. */ function fpp_get_default_publishing($post) { $options = get_option('fpp_options'); if ($options['default_publishing'] == 'all') return true; if ($options['default_publishing'] == 'category') { $categories = get_the_category($post->ID); foreach ($categories as $category) { if (array_search($category->cat_ID, $options['default_publishing_categories']) !== false) return true; } } return false; } /** * @return True if SSL certificates should be checked */ function fpp_get_ssl_verify() { $options = get_option('fpp_options'); return !$options['ignore_ssl']; } /** * @param object_type Array of string or string, either 'page' or 'profile' * @return Write permissions for a given Facebook object as string * @last_review 0.3.1 */ function fpp_get_required_permissions($object_type) { if (!is_array($object_type)) $object_type = array($object_type); $permissions = array('offline_access', 'share_item'); if (array_search('page', $object_type) !== false) { $permissions[] = 'manage_pages'; } if (array_search('group', $object_type) !== false) { $permissions[] = 'user_groups'; } return $permissions; } /** * @return Post author name as a string * @last_review 0.3.1 */ function fpp_get_post_author($post) { $user_info = get_userdata($post->post_author); $author = trim(apply_filters('the_author', $user_info->display_name)); if (empty($author)) { $author = $user_info->user_login; } return $author; } /** * @return Post categories as csv string * @last_review 0.3.0 */ function fpp_get_post_categories($post) { $categories = get_the_category($post->ID); $description = ''; if (!empty($categories)) { $description = $categories[0]->cat_name; for ($i = 1; $i < sizeof($categories); ++$i) $description .= ', '.apply_filters('the_category', $categories[$i]->cat_name); } return $description; } /** * @return URL of the featured or first embedded or attachement image as string * @last_review 0.3.1 */ function fpp_get_post_image($post) { $image_url = ''; if (current_theme_supports('post-thumbnails')) { // get_post_thumbnail_id must be supported by the theme! $thumbnail_id = get_post_thumbnail_id($post->ID); if ($thumbnail_id !== null) { $image_url = wp_get_attachment_image_src($thumbnail_id); $image_url = $image_url[0]; } } if (empty($image_url)) { // Image from post content and/or excerpt preg_match('/post_excerpt).apply_filters('the_content', $post->post_content), $matches); if (!empty($matches[1])) $image_url = $matches[1]; } if (empty($image_url)) { $images = get_children('post_type=attachment&post_mime_type=image&post_parent='.$post->ID); if (!empty($images)) { foreach ($images as $image_id => $value) { $image = wp_get_attachment_image_src($image_id); $image_url = $image[0]; break; } } } return $image_url; } /********************************************************************** * HTML rendering **********************************************************************/ /** * Renders the options page. Uses the settings API (options validation, checking and storing by WP). * Also validates certain options (Facebook access) that need redirecting. * @last_review 0.3.1 */ function fpp_render_options_page() { $options = get_option('fpp_options'); $error = get_option('fpp_error'); if (!empty($error)) { echo '
'.$error.'
'; update_option('fpp_error', ''); } $profile_access_token = get_option('fpp_profile_access_token'); if ($options['app_id_valid'] and $options['app_secret_valid'] and empty($profile_access_token) and array_key_exists('code', $_GET)) { // User clicked the authorize button, get profile_access_token: try { $profile_access_token = fpp_acquire_profile_access_token($options['app_id'], $options['app_secret'], FPP_ADMIN_URL, $_GET['code']); update_option('fpp_profile_access_token', $profile_access_token); update_option('fpp_object_access_token', ''); } catch (CommunicationException $exception) { echo '

'.$exception->getMessage().'

'.__('Your application\'s access permissions could not be granted.', FPP_TEXT_DOMAIN).'

'; } } // Check if access tokens are valid: if ($options['app_id_valid'] and $options['app_secret_valid']) { try { // Verify only profile access token (== object access token): if (!fpp_verify_profile_access_permissions($profile_access_token, fpp_get_required_permissions(array('page', 'profile', 'group')))) { $profile_access_token = ''; $object_access_token = ''; update_option('fpp_object_access_token', $object_access_token); update_option('fpp_profile_access_token', $profile_access_token); throw new CommunicationException(__('Some or all access permissions are missing. Please click the button Grant access rights! and authorize the plugin to post to your Facebook profile or page.', FPP_TEXT_DOMAIN)); } $object_access_token = get_option('fpp_object_access_token'); // Acquire object access token if empty: if (!empty($profile_access_token) and $options['object_id_valid'] and empty($object_access_token)) { if ($options['object_type'] == 'page') { $object_access_token = fpp_acquire_page_access_token($options['object_id'], $profile_access_token); update_option('fpp_object_access_token', $object_access_token); } else { update_option('fpp_object_access_token', $profile_access_token); } } // Verify page access and profile access token together: if ($options['object_id_valid'] and ($options['object_type'] == 'page')) { if (!fpp_verify_page_access_token($options['object_id'], $object_access_token)) { $profile_access_token = ''; $object_access_token = ''; update_option('fpp_object_access_token', $object_access_token); update_option('fpp_profile_access_token', $profile_access_token); throw new CommunicationException(__('Some or all access permissions are missing. Please click the button Grant access rights! and authorize the plugin to post to your Facebook profile or page.', FPP_TEXT_DOMAIN)); } } } catch (CommunicationException $exception) { echo '

'.$exception->getMessage().'

'.__('Your page or profile\'s access permissions could not be verified.', FPP_TEXT_DOMAIN).'

'; } } ?>

detailed setup instructions for help.', FPP_TEXT_DOMAIN), FPP_BASE_URL.'setup.htm') ?>

? '.__('Grant access rights!', FPP_TEXT_DOMAIN).''; } else echo ''.__('Access granted.', FPP_TEXT_DOMAIN).'';// Renew for '.$options['app_id'].''; } else echo ''.__('Grant access rights!', FPP_TEXT_DOMAIN).''; ?>
?

? '; echo ''; } ?>




http://wordpress.org. Lorem ipsum dolor...', FPP_TEXT_DOMAIN) ?>





|

'; // Required by FB echo ''; // Required by FB echo ''; $description = array(); if ($options['show_post_author']) { $description[] = esc_attr(fpp_get_post_author($post));/*, ENT_COMPAT, 'UTF-8')*/ } if ($options['show_post_categories']) { $categories = esc_attr(fpp_get_post_categories($post));/*, ENT_COMPAT, 'UTF-8')*/ if (!empty($categories)) $description[] = $categories; } echo ''; if (($options['show_thumbnail'] == 'post') and empty($post->post_password)) { $image_url = fpp_get_post_image($post); } else if ($options['show_thumbnail'] == 'gravatar') { preg_match('/post_author), $matches); if (!empty($matches[1])) $image_url = $matches[1]; } else if (($options['show_thumbnail'] == 'none') or empty($options['default_thumbnail_url'])) { if ($options['show_post_categories'] or $options['show_post_author']) { $image_url = FPP_BASE_URL.'line.png'; } else { $image_url = FPP_BASE_URL.'line_small.png'; } } if (!isset($image_url) or empty($image_url)) { if (!empty($options['default_thumbnail_url'])) { $image_url = $options['default_thumbnail_url']; } else { if ($options['show_post_categories'] or $options['show_post_author']) { $image_url = FPP_BASE_URL.'line.png'; } else { $image_url = FPP_BASE_URL.'line_small.png'; } } } echo ''; } /** * Renders a 'publish to facebook' checkbox. Renders the box only if * the current post is a real post, not a page or something else. */ function fpp_render_post_button() { global $post; $object_access_token = get_option('fpp_object_access_token'); if (!array_pop(get_post_meta($post->ID, '_fpp_is_published'))) { echo ''; } else { echo ''; } if (empty($object_access_token)) { echo '
'.sprintf(__('Facebook Page Publish is not set up.
Please check your plugin settings.', FPP_TEXT_DOMAIN), 'options-general.php?page='.plugin_basename(__FILE__)).'
'; } if ($post->post_status == "private") { echo '
'.__('Private posts are not published', FPP_TEXT_DOMAIN).'
'; } echo ''; $error = get_option('fpp_error'); if (!empty($error)) { echo '
'.sprintf(__('Your Facebook Page Publish plugin reports an error. Please check your plugin settings.', FPP_TEXT_DOMAIN), 'options-general.php?page='.plugin_basename(__FILE__)).'
'; } } /********************************************************************** * Others **********************************************************************/ /** * @last_review 0.3.0 */ function fpp_validate_options($input) { $options = get_option('fpp_options'); // Customization options: $options['show_thumbnail'] = $input['show_thumbnail']; $options['show_post_author'] = array_key_exists('show_post_author', $input) && !empty($input['show_post_author']); $options['show_post_categories'] = array_key_exists('show_post_categories', $input) && !empty($input['show_post_categories']); $options['show_post_text'] = array_key_exists('show_post_text', $input) && !empty($input['show_post_text']); $options['show_post_link'] = array_key_exists('show_post_link', $input) && !empty($input['show_post_link']); $options['default_thumbnail_url'] = trim($input['default_thumbnail_url']); // Validate customization options: if (($options['show_thumbnail'] == 'default') and (substr($options['default_thumbnail_url'], 0, 4) !== 'http')) add_settings_error('fpp_options', 'customization_error', __('The given default thumbnail URL is not valid. Any valid URL has to start with http:// or https://.', FPP_TEXT_DOMAIN).'

'.__('Facebook won\'t be able to display the choosen default thumbnail.', FPP_TEXT_DOMAIN).'

'); // Connection options: if ($options['app_id'] != $input['app_id']) { update_option('fpp_profile_access_token', ''); update_option('fpp_object_access_token', ''); } else if ($options['object_id'] != $input['object_id']) { update_option('fpp_object_access_token', ''); } $options['app_id'] = $input['app_id']; $options['object_id'] = $input['object_id']; $options['app_secret'] = $input['app_secret']; $options['app_id_valid'] = false; $options['object_id_valid'] = false; $options['object_type'] = ''; $options['app_secret_valid'] = false; $options['ignore_ssl'] = array_key_exists('ignore_ssl', $input) && !empty($input['ignore_ssl']); $options['default_publishing'] = $input['default_publishing']; $options['default_publishing_categories'] = array_key_exists('default_publishing_categories', $input) ? $input['default_publishing_categories'] : array(); // Validate connection options: try { if (!empty($options['app_id']) or !empty($options['object_id'])) { $object_classification = fpp_classify_facebook_objects(array($options['app_id'], $options['object_id'])); $options['app_id_valid'] = $object_classification[$options['app_id']] == 'application'; $options['object_type'] = $object_classification[$options['object_id']]; $options['object_id_valid'] = (($options['object_type'] == 'profile') or ($options['object_type'] == 'page') or ($options['object_type'] == 'group') or ($options['object_type'] == 'application')); } $options['app_secret_valid'] = (!empty($options['app_secret']) and $options['app_id_valid']) ? fpp_is_valid_facebook_application($options['app_id'], $options['app_secret'], FPP_ADMIN_URL) : false; if (!empty($options['app_id']) and !$options['app_id_valid']) { throw new FacebookErrorException(__('Invalid application ID.', FPP_TEXT_DOMAIN).' '.sprintf(__('Please refer to the detailed setup instructions.', FPP_TEXT_DOMAIN), FPP_BASE_URL.'setup.htm#app_id')); } if (!empty($options['object_id']) and !$options['object_id_valid']) { throw new FacebookErrorException(__('Invalid user or page ID.', FPP_TEXT_DOMAIN).' '.sprintf(__('Please refer to the detailed setup instructions.', FPP_TEXT_DOMAIN), FPP_BASE_URL.'setup.htm#object_id')); } if (!$options['app_secret_valid'] and $options['app_id_valid']) throw new FacebookErrorException(__('Invalid application secret.', FPP_TEXT_DOMAIN).' '.sprintf(__('Please refer to the detailed setup instructions.', FPP_TEXT_DOMAIN), FPP_BASE_URL.'setup.htm#app_secret')); } catch (CommunicationException $exception) { add_settings_error('fpp_options', 'connection_error', $exception->getMessage().'

'.__('Your connection options could not be validated.', FPP_TEXT_DOMAIN).'

'); } return $options; } /** * Initializes the plugin options with either default or existing * values (in case there is already a version installed). */ function fpp_initialize_options() { // default options: $options = array( 'app_id' => '', 'app_id_valid' => false, 'app_secret' => '', 'app_secret_valid' => false, 'object_id' => '', 'object_id_valid' => false, 'object_type' => '', 'ignore_ssl' => false, 'default_publishing' => 'all', 'default_publishing_categories' => array(), 'default_thumbnail_url' => '', 'show_post_categories' => true, 'show_post_author' => true, 'show_post_text' => true, 'show_post_link' => true, 'show_thumbnail' => 'gravatar'); $current_version = get_option('fpp_installed_version'); $current_options = get_option('fpp_options'); $object_access_token = get_option('fpp_object_access_token'); $profile_access_token = get_option('fpp_profile_access_token'); // Plugin previously installed: if (is_array($current_options)) { foreach ($options as $key => $value) { if (array_key_exists($key, $current_options)) { $options[$key] = $current_options[$key]; } } if (empty($current_version)) { // version <= 0.2.2 $options['app_id_valid'] = !empty($current_options['page_id']); $options['app_secret_valid'] = !empty($current_options['page_id']); $options['object_id'] = $current_options['page_id']; $options['object_id_valid'] = !empty($current_options['page_id']); $options['object_type'] = 'page'; $options['show_thumbnail'] = $current_options['show_gravatar'] ? 'gravatar' : 'post'; $object_access_token = get_option('fpp_page_access_token'); delete_option('fpp_page_access_token'); delete_option('fpp_post_to_facebook'); } } update_option('fpp_options', $options); update_option('fpp_object_access_token', $object_access_token); update_option('fpp_profile_access_token', $profile_access_token); update_option('fpp_error', ''); update_option('fpp_installed_version', FPP_VERSION); } ?>