web/wp-content/plugins/social/social.php
changeset 196 5e8dcbe22c24
equal deleted inserted replaced
195:c7c0fbc09788 196:5e8dcbe22c24
       
     1 <?php
       
     2 /*
       
     3 Plugin Name: Social
       
     4 Plugin URI: http://mailchimp.com/social-plugin-for-wordpress/
       
     5 Description: Broadcast newly published posts and pull in discussions using integrations with Twitter and Facebook. Brought to you by <a href="http://mailchimp.com">MailChimp</a>.
       
     6 Version: 2.6
       
     7 Author: Crowd Favorite
       
     8 Author URI: http://crowdfavorite.com/
       
     9 */
       
    10 
       
    11 if (!class_exists('Social')) { // try to avoid double-loading...
       
    12 
       
    13 /**
       
    14  * Social Core
       
    15  *
       
    16  * @package Social
       
    17  */
       
    18 final class Social {
       
    19 
       
    20 	/**
       
    21 	 * @var  string  URL of the API
       
    22 	 */
       
    23 	public static $api_url = 'https://sopresto.mailchimp.com/';
       
    24 
       
    25 	/**
       
    26 	 * @var  string  version number
       
    27 	 */
       
    28 	public static $version = '2.6';
       
    29 
       
    30 	/**
       
    31 	 * @var  string  CRON lock directory.
       
    32 	 */
       
    33 	public static $cron_lock_dir = null;
       
    34 
       
    35 	/**
       
    36 	 * @var  string  plugins URL
       
    37 	 */
       
    38 	public static $plugins_url = '';
       
    39 
       
    40 	/**
       
    41 	 * @var  string  plugins file path
       
    42 	 */
       
    43 	public static $plugins_path = '';
       
    44 
       
    45 	/**
       
    46 	 * @var  bool  loaded by theme?
       
    47 	 */
       
    48 	public static $loaded_by_theme = false;
       
    49 
       
    50 	/**
       
    51 	 * @var  string  duplicate comment message
       
    52 	 */
       
    53 	public static $duplicate_comment_message = 'duplicate comment';
       
    54 
       
    55 	/**
       
    56 	 * @var  Social_Log  logger
       
    57 	 */
       
    58 	private static $log = null;
       
    59 
       
    60 	/**
       
    61 	 * @var  array  default options
       
    62 	 */
       
    63 	protected static $options = array(
       
    64 		'debug' => false,
       
    65 		'install_date' => 0,
       
    66 		'installed_version' => 0,
       
    67 		'broadcast_format' => '{title}: {content} {url}',
       
    68 		'comment_broadcast_format' => '{content} {url}',
       
    69 		'system_cron_api_key' => null,
       
    70 		'fetch_comments' => '1',
       
    71 		'broadcast_by_default' => '0',
       
    72 		'use_standard_comments' => '0',
       
    73 	);
       
    74 
       
    75 	/**
       
    76 	 * @var  Social  instance of Social
       
    77 	 */
       
    78 	public static $instance = null;
       
    79 
       
    80 	/**
       
    81 	 * Loads the instance of Social.
       
    82 	 *
       
    83 	 * @static
       
    84 	 * @return Social
       
    85 	 */
       
    86 	public static function instance() {
       
    87 		if (self::$instance === null) {
       
    88 			self::$instance = new self;
       
    89 		}
       
    90 
       
    91 		return self::$instance;
       
    92 	}
       
    93 
       
    94 	/**
       
    95 	 * Handles the auto loading of classes.
       
    96 	 *
       
    97 	 * @static
       
    98 	 *
       
    99 	 * @param  string  $class
       
   100 	 *
       
   101 	 * @return bool
       
   102 	 */
       
   103 	public static function auto_load($class) {
       
   104 		if (substr($class, 0, 7) == 'Social_' or substr($class, 0, 7) == 'Kohana_') {
       
   105 			try {
       
   106 				$file = Social::$plugins_path.'lib/'.str_replace('_', '/', strtolower($class)).'.php';
       
   107 				$file = apply_filters('social_auto_load_file', $file, $class);
       
   108 				if (file_exists($file)) {
       
   109 					require $file;
       
   110 
       
   111 					return true;
       
   112 				}
       
   113 
       
   114 				return false;
       
   115 			}
       
   116 			catch (Exception $e) {
       
   117 				Social::log(sprintf(__('Failed to auto load class %s.', 'social'), $class));
       
   118 			}
       
   119 		}
       
   120 
       
   121 		return true;
       
   122 	}
       
   123 
       
   124 	/**
       
   125 	 * Returns the broadcast format tokens.
       
   126 	 *
       
   127 	 * Format:
       
   128 	 *
       
   129 	 *     {key} => __('Description', 'social')
       
   130 	 *
       
   131 	 * @static
       
   132 	 * @return array
       
   133 	 */
       
   134 	public static function broadcast_tokens() {
       
   135 		$query = new WP_Query(array(
       
   136 			'posts_per_page' => 1
       
   137 		));
       
   138 		if (count($query->posts) and $post = $query->posts[0]) {
       
   139 			$url = wp_get_shortlink($post->ID);
       
   140 			$date = get_date_from_gmt($post->post_date_gmt);
       
   141 		}
       
   142 		else {
       
   143 			$url = home_url('?p=123');
       
   144 			$date = get_date_from_gmt(current_time('mysql', true));
       
   145 		}
       
   146 
       
   147 		$defaults = array(
       
   148 			'{url}' => sprintf(__('Example: %s', 'social'), $url),
       
   149 			'{title}' => '',
       
   150 			'{content}' => '',
       
   151 			'{date}' => sprintf(__('Example: %s', 'social'), $date),
       
   152 			'{author}' => '',
       
   153 		);
       
   154 
       
   155 		return apply_filters('social_broadcast_tokens', $defaults);
       
   156 	}
       
   157 
       
   158 	/**
       
   159 	 * Returns the comment broadcast format tokens.
       
   160 	 *
       
   161 	 * Format:
       
   162 	 *
       
   163 	 *     {key} => __('Description', 'social')
       
   164 	 *
       
   165 	 * @static
       
   166 	 * @return mixed
       
   167 	 */
       
   168 	public static function comment_broadcast_tokens() {
       
   169 		$defaults = array(
       
   170 			'{content}' => '',
       
   171 			'{url}' => '',
       
   172 		);
       
   173 		return apply_filters('social_comment_broadcast_tokens', $defaults);
       
   174 	}
       
   175 
       
   176 	/**
       
   177 	 * Sets or gets an option based on the key defined.
       
   178 	 *
       
   179 	 * Get Format:
       
   180 	 *
       
   181 	 *     Running Social::option('option_name') will load "social_option_name" using get_option()
       
   182 	 *
       
   183 	 * Set Format:
       
   184 	 *
       
   185 	 *     Running Social::option('option_name', 'new_value') will update "social_option_name" to "new_value"
       
   186 	 *     using update_option().
       
   187 	 *
       
   188 	 * @static
       
   189 	 * @param  string  $key     option key
       
   190 	 * @param  mixed   $value   option value
       
   191 	 * @return bool|mixed
       
   192 	 * @uses get_option()
       
   193 	 * @uses update_option()
       
   194 	 */
       
   195 	public static function option($key, $value = null) {
       
   196 		if ($value === null) {
       
   197 			$default = null;
       
   198 			if (isset(Social::$options[$key])) {
       
   199 				$default = Social::$options[$key];
       
   200 			}
       
   201 
       
   202 			return get_option('social_'.$key, $default);
       
   203 		}
       
   204 
       
   205 		update_option('social_'.$key, $value);
       
   206 		return false;
       
   207 	}
       
   208 
       
   209 	/**
       
   210 	 * Add a message to the log.
       
   211 	 *
       
   212 	 * @static
       
   213 	 * @param  string  $message    message to add to the log
       
   214 	 * @param  array   $args       arguments to pass to the writer
       
   215 	 * @param  string  $context    context of the log message
       
   216 	 * @param  bool    $backtrace  show the backtrace
       
   217 	 * @return void
       
   218 	 */
       
   219 	public static function log($message, array $args = null, $context = null, $backtrace = false) {
       
   220 		Social::$log->write($message, $args, $context, $backtrace);
       
   221 	}
       
   222 
       
   223 	/**
       
   224 	 * Sets the loaded by theme.
       
   225 	 *
       
   226 	 * @static
       
   227 	 * @return void
       
   228 	 */
       
   229 	public static function social_loaded_by_theme() {
       
   230 		self::$loaded_by_theme = true;
       
   231 	}
       
   232 
       
   233 	/**
       
   234 	 * Sets the customer die handler.
       
   235 	 *
       
   236 	 * @static
       
   237 	 * @param  string  $handler
       
   238 	 * @return array
       
   239 	 */
       
   240 	public static function wp_die_handler($handler) {
       
   241 		return array('Social', 'wp_comment_die_handler');
       
   242 	}
       
   243 
       
   244 	/**
       
   245 	 * Don't actually die for aggregation runs.
       
   246 	 *
       
   247 	 * @static
       
   248 	 * @param  string  $message
       
   249 	 * @param  string  $title
       
   250 	 * @param  array   $args
       
   251 	 * @return mixed
       
   252 	 */
       
   253 	public static function wp_comment_die_handler($message, $title, $args) {
       
   254 		if ($message == __('Duplicate comment detected; it looks as though you&#8217;ve already said that!')) {
       
   255 			// Keep going
       
   256 			throw new Exception(Social::$duplicate_comment_message);
       
   257 		}
       
   258 	}
       
   259 
       
   260 	/**
       
   261 	 * @var  bool  is Social enabled?
       
   262 	 */
       
   263 	private $_enabled = null;
       
   264 
       
   265 	/**
       
   266 	 * Returns an array of all of the services.
       
   267 	 *
       
   268 	 * Format of the data returned:
       
   269 	 *
       
   270 	 *     $services = array(
       
   271 	 *         'twitter' => Social_Service_Twitter,
       
   272 	 *         'facebook' => Social_Service_Facebook,
       
   273 	 *         // ... any other services registered
       
   274 	 *     )
       
   275 	 *
       
   276 	 * @return array
       
   277 	 */
       
   278 	public function services() {
       
   279 		return $this->load_services();
       
   280 	}
       
   281 
       
   282 	/**
       
   283 	 * Returns a service by access key.
       
   284 	 *
       
   285 	 * Loading a service:
       
   286 	 *
       
   287 	 *     $twitter = Social::instance()->service('twitter');
       
   288 	 *
       
   289 	 * @param  string  $key    service key
       
   290 	 * @return mixed Social_Service|Social_Service_Twitter|Social_Service_Facebook|false
       
   291 	 */
       
   292 	public function service($key) {
       
   293 		$services = $this->load_services();
       
   294 		if (!isset($services[$key])) {
       
   295 			return false;
       
   296 		}
       
   297 		return $services[$key];
       
   298 	}
       
   299 	
       
   300 	/**
       
   301 	 * Returns a service by comment type.
       
   302 	 *
       
   303 	 * Loading a service:
       
   304 	 *
       
   305 	 *     $twitter = Social::instance()->service_for_comment_type('social-twitter-rt');
       
   306 	 *
       
   307 	 * @param  string  $key    service key
       
   308 	 * @return mixed  Social_Service|Social_Service_Twitter|Social_Service_Facebook|false
       
   309 	 */
       
   310 	public function service_for_comment_type($comment_type) {
       
   311 		$services = $this->load_services();
       
   312 		foreach ($services as $service) {
       
   313 			if (in_array($comment_type, $service->comment_types())) {
       
   314 				return $service;
       
   315 			}
       
   316 		}
       
   317 		return false;
       
   318 	}
       
   319 
       
   320 	/**
       
   321 	 * Initializes Social.
       
   322 	 *
       
   323 	 * @wp-action  init
       
   324 	 * @return void
       
   325 	 */
       
   326 	public function init() {
       
   327 		// Load the language translations
       
   328 		if (Social::$loaded_by_theme) {
       
   329 			$path = trailingslashit(Social::$plugins_path).'lang';
       
   330 			load_theme_textdomain('social', $path);
       
   331 		}
       
   332 		else {
       
   333 			$plugin_dir = basename(dirname(SOCIAL_FILE)).'/lang';
       
   334 			load_plugin_textdomain('social', false, $plugin_dir);
       
   335 		}
       
   336 
       
   337 		if (version_compare(PHP_VERSION, '5.2.4', '<')) {
       
   338 			deactivate_plugins(basename(__FILE__)); // Deactivate ourself
       
   339 			wp_die(__("Sorry, Social requires PHP 5.2.4 or higher. Ask your host how to enable PHP 5 as the default on your servers.", 'social'));
       
   340 		}
       
   341 
       
   342 		// Just activated?
       
   343 		if (!Social::option('install_date')) {
       
   344 			Social::option('install_date', current_time('timestamp', 1));
       
   345 			Social::option('system_cron_api_key', wp_generate_password(16, false));
       
   346 		}
       
   347 
       
   348 		// Plugins URL
       
   349 		$url = plugins_url('', SOCIAL_FILE);
       
   350 		Social::$plugins_url = trailingslashit(apply_filters('social_plugins_url', $url));
       
   351 
       
   352 		Social::$plugins_path = trailingslashit(apply_filters('social_plugins_path', SOCIAL_PATH));
       
   353 
       
   354 		// Set the logger
       
   355 		Social::$log = Social_Log::factory();
       
   356 
       
   357 		// Require Facebook and Twitter by default.
       
   358 		require Social::$plugins_path.'social-twitter.php';
       
   359 		require Social::$plugins_path.'social-facebook.php';
       
   360 	}
       
   361 
       
   362 	/**
       
   363 	 * Auth Cookie expiration for API users.
       
   364 	 *
       
   365 	 * @return int
       
   366 	 */
       
   367 	public function auth_cookie_expiration() {
       
   368 		return 31536000; // 1 Year
       
   369 	}
       
   370 
       
   371 	/**
       
   372 	 * Enqueues the assets for Social.
       
   373 	 *
       
   374 	 * @wp-action  wp_enqueue_scripts
       
   375 	 * @wp-action  load-post-new.php
       
   376 	 * @wp-action  load-post.php
       
   377 	 * @wp-action  load-profile.php
       
   378 	 * @wp-action  load-settings_page_social
       
   379 	 * @return void
       
   380 	 */
       
   381 	public function enqueue_assets() {
       
   382 		if (Social::option('use_standard_comments') == '1') {
       
   383 			return;
       
   384 		}
       
   385 		// JS/CSS
       
   386 		if (!defined('SOCIAL_COMMENTS_JS')) {
       
   387 			define('SOCIAL_COMMENTS_JS', Social::$plugins_url.'assets/social.js');
       
   388 		}
       
   389 		if (SOCIAL_COMMENTS_JS !== false) {
       
   390 			wp_enqueue_script('jquery');
       
   391 			wp_enqueue_script('social_js', SOCIAL_COMMENTS_JS, array('jquery'), Social::$version, true);
       
   392 			wp_localize_script('social_js', 'Sociali18n', array(
       
   393 				'commentReplyTitle' => __('Post a Reply', 'social'),
       
   394 			));
       
   395 		}
       
   396 
       
   397 		if (!is_admin()) {
       
   398 			if (!defined('SOCIAL_COMMENTS_CSS')) {
       
   399 				define('SOCIAL_COMMENTS_CSS', Social::$plugins_url.'assets/comments.css');
       
   400 			}
       
   401 			if (SOCIAL_COMMENTS_CSS !== false) {
       
   402 				wp_enqueue_style('social_comments', SOCIAL_COMMENTS_CSS, array(), Social::$version, 'screen');
       
   403 			}
       
   404 		}
       
   405 
       
   406 	}
       
   407 
       
   408 	/**
       
   409 	 * Enqueues the assets for Social.
       
   410 	 *
       
   411 	 * @wp-action  admin_enqueue_scripts
       
   412 	 * @return void
       
   413 	 */
       
   414 	public function admin_enqueue_assets() {
       
   415 		if (!defined('SOCIAL_ADMIN_JS')) {
       
   416 			define('SOCIAL_ADMIN_JS', Social::$plugins_url.'assets/admin.js');
       
   417 		}
       
   418 
       
   419 		if (!defined('SOCIAL_ADMIN_CSS')) {
       
   420 			define('SOCIAL_ADMIN_CSS', Social::$plugins_url.'assets/admin.css');
       
   421 		}
       
   422 
       
   423 		if (SOCIAL_ADMIN_CSS !== false) {
       
   424 			wp_enqueue_style('social_admin', SOCIAL_ADMIN_CSS, array(), Social::$version, 'screen');
       
   425 		}
       
   426 
       
   427 		if (SOCIAL_ADMIN_JS !== false) {
       
   428 			wp_enqueue_script('social_admin', SOCIAL_ADMIN_JS, array(), Social::$version, true);
       
   429 			$data = apply_filters('social_admin_js_strings', array(
       
   430 				'protectedTweet' => __('Protected Tweet', 'social'),
       
   431 				'invalidUrl' => __('Invalid URL', 'social'),
       
   432 			));
       
   433 			wp_localize_script('social_admin', 'socialAdminL10n', $data);
       
   434 		}
       
   435 	}
       
   436 
       
   437 	/**
       
   438 	 * Loads the services on every page if the user is an admin.
       
   439 	 *
       
   440 	 * @wp-action  admin_init
       
   441 	 * @return void
       
   442 	 */
       
   443 	public function admin_init() {
       
   444 		if (current_user_can('manage_options') or current_user_can('publish_posts')) {
       
   445 			// Trigger upgrade?
       
   446 			if (isset($_GET['page']) and $_GET['page'] == basename(SOCIAL_FILE)) {
       
   447 				global $wpdb;
       
   448 
       
   449 				// First check for the semaphore options, they need to be added before the upgrade starts.
       
   450 				$results = $wpdb->get_results("
       
   451 					SELECT option_id
       
   452 					  FROM $wpdb->options
       
   453 					 WHERE option_name IN ('social_locked', 'social_unlocked')
       
   454 				");
       
   455 				if (!count($results)) {
       
   456 					update_option('social_unlocked', '1');
       
   457 					update_option('social_last_lock_time', current_time('mysql', 1));
       
   458 					update_option('social_semaphore', '0');
       
   459 				}
       
   460 
       
   461 				if (version_compare(Social::option('installed_version'), Social::$version, '<')) {
       
   462 					$this->_enabled = false;
       
   463 					$this->upgrade();
       
   464 				}
       
   465 			}
       
   466 
       
   467 			if ($this->_enabled === null) {
       
   468 				$this->load_services();
       
   469 			}
       
   470 		}
       
   471 
       
   472 		// Redirect to the home_url() if the user is a commenter.
       
   473 		if (!current_user_can('publish_posts')) {
       
   474 			$commenter = get_user_meta(get_current_user_id(), 'social_commenter', true);
       
   475 			if (!empty($commenter) and $commenter == 'true') {
       
   476 				wp_redirect(trailingslashit(home_url()));
       
   477 			}
       
   478 		}
       
   479 	}
       
   480 
       
   481 	/**
       
   482 	 * Checks to see if system crons are disabled.
       
   483 	 *
       
   484 	 * @wp-action  load-settings_page_social
       
   485 	 * @return void
       
   486 	 */
       
   487 	public function check_system_cron() {
       
   488 		Social::log('Checking system CRON');
       
   489 		// Schedule CRONs
       
   490 		if (Social::option('fetch_comments') == '1') {
       
   491 			if (wp_next_scheduled('social_cron_15_init') === false) {
       
   492 				Social::log('Adding Social 15 CRON schedule');
       
   493 				wp_schedule_event(time() + 900, 'every15min', 'social_cron_15_init');
       
   494 			}
       
   495 			wp_remote_get(
       
   496 				admin_url('options_general.php?'.http_build_query(array(
       
   497 					'social_controller' => 'cron',
       
   498 					'social_action' => 'check_crons',
       
   499 					'social_api_key' => Social::option('system_cron_api_key')
       
   500 				), null, '&')),
       
   501 				array(
       
   502 					'timeout' => 0.01,
       
   503 					'blocking' => false,
       
   504 					'sslverify' => apply_filters('https_local_ssl_verify', true),
       
   505 				)
       
   506 			);
       
   507 		}
       
   508 	}
       
   509 
       
   510 	/**
       
   511 	 * Handlers requests.
       
   512 	 *
       
   513 	 * @wp-action  init
       
   514 	 * @return void
       
   515 	 */
       
   516 	public function request_handler() {
       
   517 		if (isset($_GET['social_controller'])) {
       
   518 			Social_Request::factory()->execute();
       
   519 		}
       
   520 	}
       
   521 
       
   522 	/**
       
   523 	 * Adds a link to the "Settings" menu in WP-Admin.
       
   524 	 *
       
   525 	 * @wp-action  admin_menu
       
   526 	 * @return void
       
   527 	 */
       
   528 	public function admin_menu() {
       
   529 		add_options_page(
       
   530 			__('Social Options', 'social'),
       
   531 			__('Social', 'social'),
       
   532 			'manage_options',
       
   533 			basename(SOCIAL_FILE),
       
   534 			array(
       
   535 				$this,
       
   536 				'admin_options_form'
       
   537 			)
       
   538 		);
       
   539 	}
       
   540 
       
   541 	/**
       
   542 	 * Add Settings link to plugins - code from GD Star Ratings
       
   543 	 *
       
   544 	 * @wp-filter  plugin_action_links
       
   545 	 * @param  array   $links
       
   546 	 * @param  string  $file
       
   547 	 * @return array
       
   548 	 */
       
   549 	public function add_settings_link($links, $file) {
       
   550 		static $this_plugin;
       
   551 		if (!$this_plugin) {
       
   552 			$this_plugin = plugin_basename(__FILE__);
       
   553 		}
       
   554 
       
   555 		if ($file == $this_plugin) {
       
   556 			$settings_link = '<a href="'.esc_url(admin_url('options-general.php?page=social.php')).'">'.__('Settings', 'social').'</a>';
       
   557 			array_unshift($links, $settings_link);
       
   558 		}
       
   559 		return $links;
       
   560 	}
       
   561 
       
   562 	/**
       
   563 	 * Handles the display of different messages for admin notices.
       
   564 	 *
       
   565 	 * @wp-action  admin_notices
       
   566 	 * @action     admin_notices
       
   567 	 */
       
   568 	public function admin_notices() {
       
   569 		if (current_user_can('manage_options') or current_user_can('publish_posts')) {
       
   570 			// Upgrade notice
       
   571 			if (version_compare(Social::option('installed_version'), Social::$version, '<')) {
       
   572 				$message = sprintf(__('Social is shiny and new! Please <a href="%s">verify and save your settings</a> to complete the upgrade.', 'social'), esc_url(Social::settings_url()));
       
   573 				echo '<div class="error"><p>'.$message.'</p></div>';
       
   574 			}
       
   575 
       
   576 			$suppress_no_accounts_notice = get_user_meta(get_current_user_id(), 'social_suppress_no_accounts_notice', true);
       
   577 			if (!$this->_enabled and (!isset($_GET['page']) or $_GET['page'] != basename(SOCIAL_FILE)) and empty($suppress_no_accounts_notice)) {
       
   578 				$dismiss = sprintf(__('<a href="%s" class="social_dismiss">[Dismiss]</a>', 'social'), esc_url(admin_url('options-general.php?social_controller=settings&social_action=suppress_no_accounts_notice')));
       
   579 				$message = sprintf(__('To start using Social, please <a href="%s">add an account</a>.', 'social'), esc_url(Social::settings_url()));
       
   580 				echo '<div class="error"><p>'.$message.' '.$dismiss.'</p></div>';
       
   581 			}
       
   582 
       
   583 			if (isset($_GET['page']) and $_GET['page'] == basename(SOCIAL_FILE)) {
       
   584 				// CRON Lock
       
   585 				if (Social::option('cron_lock_error') !== null) {
       
   586 					$upload_dir = wp_upload_dir();
       
   587 					if (is_writeable(Social::$plugins_path) or (isset($upload_dir['basedir']) and is_writeable($upload_dir['basedir']))) {
       
   588 						delete_option('social_cron_lock_error');
       
   589 					}
       
   590 					else {
       
   591 						if (isset($upload_dir['basedir'])) {
       
   592 							$message = sprintf(__('Social requires that either %s or %s be writable for CRON jobs.', 'social'), esc_html(Social::$plugins_path), esc_html($upload_dir['basedir']));
       
   593 						}
       
   594 						else {
       
   595 							$message = sprintf(__('Social requires that %s is writable for CRON jobs.', 'social'), esc_html(Social::$plugins_path));
       
   596 						}
       
   597 
       
   598 						echo '<div class="error"><p>'.esc_html($message).'</p></div>';
       
   599 					}
       
   600 				}
       
   601 
       
   602 				// Enable notice?
       
   603 				$suppress_enable_notice = get_user_meta(get_current_user_id(), 'social_suppress_enable_notice', true);
       
   604 				if (empty($suppress_enable_notice)) {
       
   605 					$message = __('When you enable Social, users will be created when they log in with Facebook or Twitter to comment. These users are created without a role and will be prevented from accessing the admin side of WordPress until an administrator edits the user to give them a role.', 'social');
       
   606 					$dismiss = sprintf(__('<a href="%s" class="social_dismiss">[Dismiss]</a>', 'social'), esc_url(admin_url('options-general.php?social_controller=settings&social_action=suppress_enable_notice')));
       
   607 					echo '<div class="updated"><p>'.$message.' '.$dismiss.'</p></div>';
       
   608 				}
       
   609 			}
       
   610 
       
   611 			// Log write error
       
   612 			$error = Social::option('log_write_error');
       
   613 			if ($error == '1') {
       
   614 				echo '<div class="error"><p>'.
       
   615 					sprintf(__('%s needs to be writable for Social\'s logging. <a href="%" class="social_dismiss">[Dismiss]</a>', 'social'), esc_html(Social::$plugins_path), esc_url(admin_url('options-general.php?social_controller=settings&social_action=clear_log_write_error'))).
       
   616 					'</p></div>';
       
   617 			}
       
   618 		}
       
   619 
       
   620 		// Deauthed accounts
       
   621 		$deauthed = Social::option('deauthed');
       
   622 		if (!empty($deauthed)) {
       
   623 			foreach ($deauthed as $service => $data) {
       
   624 				foreach ($data as $id => $message) {
       
   625 					$dismiss = sprintf(__('<a href="%s" class="%s">[Dismiss]</a>', 'social'), esc_url(admin_url('options-general.php?social_controller=settings&social_action=clear_deauth&id='.$id.'&service='.$service)), 'social_dismiss');
       
   626 					echo '<div class="error"><p>'.esc_html($message).' '.$dismiss.'</p></div>';
       
   627 				}
       
   628 			}
       
   629 		}
       
   630 
       
   631 		// Errored broadcasting?
       
   632 		global $post;
       
   633 		if (isset($post->ID)) {
       
   634 			$error_accounts = get_post_meta($post->ID, '_social_broadcast_error', true);
       
   635 			if (!empty($error_accounts)) {
       
   636 				$message = Social_View::factory('wp-admin/post/broadcast/error/notice', array(
       
   637 					'social' => $this,
       
   638 					'accounts' => $error_accounts,
       
   639 					'post' => $post,
       
   640 				));
       
   641 				echo '<div class="error" id="social-broadcast-error">'.$message.'</div>';
       
   642 
       
   643 				delete_post_meta($post->ID, '_social_broadcast_error');
       
   644 			}
       
   645 		}
       
   646 
       
   647 		// 2.0 Upgrade?
       
   648 		$upgrade_2_0 = get_user_meta(get_current_user_id(), 'social_2.0_upgrade', true);
       
   649 		if (!empty($upgrade_2_0)) {
       
   650 			if (current_user_can('manage_options')) {
       
   651 				$output = __('Social needs to re-authorize your Facebook account(s). Please re-connect your <a href="%s">global</a> and <a href="%s">personal</a> accounts.', 'social');
       
   652 				$output = sprintf($output, esc_url(Social::settings_url()), esc_url(admin_url('profile.php#social-accounts')));
       
   653 			}
       
   654 			else {
       
   655 				$output = __('Social needs to re-authorize your Facebook account(s).. Please re-connect your <a href="%s">personal</a> accounts.', 'social');
       
   656 				$output = sprintf($output, esc_url(admin_url('profile.php#social-networks')));
       
   657 			}
       
   658 
       
   659 			$dismiss = sprintf(__('<a href="%s" class="%s">[Dismiss]</a>', 'social'), esc_url(admin_url('options-general.php?social_controller=settings&social_action=clear_2_0_upgrade')), 'social_dismiss');
       
   660 			echo '<div class="error"><p>'.$output.' '.$dismiss.'</p></div>';
       
   661 		}
       
   662 	}
       
   663 
       
   664 	/**
       
   665 	 * Displays the admin options form.
       
   666 	 *
       
   667 	 * @return void
       
   668 	 */
       
   669 	public function admin_options_form() {
       
   670 		Social_Request::factory('settings/index')->execute();
       
   671 	}
       
   672 
       
   673 	/**
       
   674 	 * Shows the user's social network accounts.
       
   675 	 *
       
   676 	 * @wp-action  show_user_profile
       
   677 	 * @param  object  $profileuser
       
   678 	 * @return void
       
   679 	 */
       
   680 	public function show_user_profile($profileuser) {
       
   681 		$default_accounts = get_user_meta($profileuser->ID, 'social_default_accounts', true);
       
   682 		if (empty($default_accounts)) {
       
   683 			$default_accounts = array();
       
   684 		}
       
   685 		$accounts = array();
       
   686 		foreach ($this->services() as $key => $service) {
       
   687 			if (!isset($accounts[$key])) {
       
   688 				$accounts[$key] = array();
       
   689 			}
       
   690 			foreach ($service->accounts() as $account) {
       
   691 				if ($account->personal()) {
       
   692 					$accounts[$key][] = $account->id();
       
   693 				}
       
   694 			}
       
   695 		}
       
   696 		echo Social_View::factory('wp-admin/profile', array(
       
   697 			'defaults' => $default_accounts,
       
   698 			'services' => $this->services(),
       
   699 			'accounts' => $accounts,
       
   700 		));
       
   701 	}
       
   702 
       
   703 	/**
       
   704 	 * Saves the default accounts for the user.
       
   705 	 *
       
   706 	 * @wp-action personal_options_update
       
   707 	 * @param  int  $user_id
       
   708 	 * @return void
       
   709 	 */
       
   710 	public function personal_options_update($user_id) {
       
   711 		// Store the default accounts
       
   712 		$accounts = array();
       
   713 		if (isset($_POST['social_default_accounts']) and is_array($_POST['social_default_accounts'])) {
       
   714 			foreach ($_POST['social_default_accounts'] as $account) {
       
   715 				$account = explode('|', $account);
       
   716 				$accounts[$account[0]][] = $account[1];
       
   717 			}
       
   718 		}
       
   719 
       
   720 		// TODO abstract this to the facebook plugin
       
   721 		if (isset($_POST['social_default_pages']) and is_array($_POST['social_default_pages'])) {
       
   722 			if (!isset($accounts['facebook'])) {
       
   723 				$accounts['facebook'] = array(
       
   724 					'pages' => array()
       
   725 				);
       
   726 			}
       
   727 			$accounts['facebook']['pages'] = $_POST['social_default_pages'];
       
   728 		}
       
   729 
       
   730 		if (count($accounts)) {
       
   731 			update_user_meta($user_id, 'social_default_accounts', $accounts);
       
   732 		}
       
   733 		else {
       
   734 			delete_user_meta($user_id, 'social_default_accounts');
       
   735 		}
       
   736 
       
   737 		// Save Enabled child accounts
       
   738 		$is_profile = true;
       
   739 		$enabled_child_accounts = is_array($_POST['social_enabled_child_accounts']) ? $_POST['social_enabled_child_accounts'] : array();
       
   740 		foreach ($this->services() as $service_key => $service) {
       
   741 			$updated_accounts = array();
       
   742 			foreach ($service->accounts() as $account) {
       
   743 				//default service to empty array in case it is not set
       
   744 				$enabled_child_accounts[$service_key] = isset($enabled_child_accounts[$service_key]) ? $enabled_child_accounts[$service_key] : array();
       
   745 
       
   746 				$account->update_enabled_child_accounts($enabled_child_accounts[$service_key]);
       
   747 				$updated_accounts[$account->id()] = $account->as_object();
       
   748 			}
       
   749 			$service->accounts($updated_accounts)->save($is_profile);
       
   750 		}
       
   751 	}
       
   752 
       
   753 	/**
       
   754 	 * Return array of enabled social broadcasting post types
       
   755 	 *
       
   756 	 * @static
       
   757 	 * @return array
       
   758 	 */
       
   759 	public static function broadcasting_enabled_post_types() {
       
   760 		return apply_filters('social_broadcasting_enabled_post_types', get_post_types(array(
       
   761 			'public' => true,
       
   762 			'hierarchical' => false
       
   763 		)));
       
   764 	}
       
   765 	
       
   766 	/**
       
   767 	 * Check if a post type has broadcasting enabled
       
   768 	 *
       
   769 	 * @static
       
   770 	 * @param  string  $post_type  post type to check for
       
   771 	 * @return bool
       
   772 	 */
       
   773 	public static function broadcasting_enabled_for_post_type($post_type = null) {
       
   774 		return (bool) in_array($post_type, self::broadcasting_enabled_post_types());
       
   775 	}
       
   776 
       
   777 	/**
       
   778 	 * Add Meta Boxes
       
   779 	 *
       
   780 	 * @wp-action  do_meta_boxes
       
   781 	 * @return void
       
   782 	 */
       
   783 	public function do_meta_boxes() {
       
   784 		global $post;
       
   785 
       
   786 		if ($post !== null && Social::option('disable_broadcasting') != 1) {
       
   787 			foreach (self::broadcasting_enabled_post_types() as $post_type) {
       
   788 				add_meta_box('social_meta_broadcast', __('Social Broadcasting', 'social'), array(
       
   789 					$this,
       
   790 					'add_meta_box_broadcast'
       
   791 				), $post_type, 'side', 'high');
       
   792 	
       
   793 				$fetch = Social::option('fetch_comments');
       
   794 				if ($this->_enabled and !empty($fetch)) {
       
   795 					if ($post->post_status == 'publish') {
       
   796 						add_meta_box('social_meta_aggregation_log', __('Social Comments', 'social'), array(
       
   797 							$this,
       
   798 							'add_meta_box_log'
       
   799 						), $post_type, 'normal', 'core');
       
   800 					}
       
   801 				}
       
   802 			}
       
   803 		}
       
   804 	}
       
   805 
       
   806 	/**
       
   807 	 * Adds the broadcasting meta box.
       
   808 	 *
       
   809 	 * @return void
       
   810 	 */
       
   811 	public function add_meta_box_broadcast() {
       
   812 		global $post;
       
   813 
       
   814 		$broadcasted = '';
       
   815 		$broadcasted_ids = get_post_meta($post->ID, '_social_broadcasted_ids', true);
       
   816 		if (!empty($broadcasted_ids)) {
       
   817 			$broadcasted = Social_View::factory('wp-admin/post/meta/broadcast/parts/broadcasted', array(
       
   818 				'services' => $this->services(),
       
   819 				'ids' => $broadcasted_ids,
       
   820 				'post' => $post,
       
   821 			));
       
   822 		}
       
   823 
       
   824 		$show_broadcast = false;
       
   825 		foreach ($this->services() as $service) {
       
   826 			if (count($service->accounts())) {
       
   827 				$show_broadcast = true;
       
   828 				break;
       
   829 			}
       
   830 		}
       
   831 
       
   832 		// Content
       
   833 		$button = '';
       
   834 		$content = '';
       
   835 		if ($show_broadcast) {
       
   836 			if ($post->post_status != 'private') {
       
   837 				switch ($post->post_status) {
       
   838 					case 'pending':
       
   839 						$button = 'Edit';
       
   840 						$accounts = get_post_meta($post->ID, '_social_broadcast_accounts', true);
       
   841 						$content = Social_View::factory('wp-admin/post/meta/broadcast/pending', array(
       
   842 							'accounts' => $accounts,
       
   843 							'services' => $this->services(),
       
   844 						));
       
   845 						break;
       
   846 					case 'future':
       
   847 						$button = 'Edit';
       
   848 						$accounts = get_post_meta($post->ID, '_social_broadcast_accounts', true);
       
   849 						$content = Social_View::factory('wp-admin/post/meta/broadcast/scheduled', array(
       
   850 							'services' => $this->services(),
       
   851 							'accounts' => $accounts,
       
   852 						));
       
   853 						break;
       
   854 					case 'publish':
       
   855 						$button = 'Broadcast';
       
   856 						break;
       
   857 					default:
       
   858 						if ($post->post_status == 'draft' and !empty($broadcasted_ids)) {
       
   859 							$content = '';
       
   860 						}
       
   861 						else {
       
   862 							$notify = false;
       
   863 							if (get_post_meta($post->ID, '_social_notify', true) == '1') {
       
   864 								$notify = true;
       
   865 							}
       
   866 							else if (Social::option('broadcast_by_default') == '1') {
       
   867 								$notify = true;
       
   868 							}
       
   869 
       
   870 							$content = Social_View::factory('wp-admin/post/meta/broadcast/default', array(
       
   871 								'post' => $post,
       
   872 								'notify' => $notify,
       
   873 							));
       
   874 						}
       
   875 						break;
       
   876 				}
       
   877 			}
       
   878 			else {
       
   879 				$content = Social_View::factory('wp-admin/post/meta/broadcast/private');
       
   880 			}
       
   881 
       
   882 			// Button
       
   883 			if (!empty($button)) {
       
   884 				$button = Social_View::factory('wp-admin/post/meta/broadcast/parts/button', array(
       
   885 					'broadcasted' => $broadcasted,
       
   886 					'button_text' => $button,
       
   887 				));
       
   888 			}
       
   889 		}
       
   890 
       
   891 		echo Social_View::factory('wp-admin/post/meta/broadcast/shell', array(
       
   892 			'post' => $post,
       
   893 			'content' => $content,
       
   894 			'broadcasted' => $broadcasted,
       
   895 			'button' => $button
       
   896 		));
       
   897 	}
       
   898 
       
   899 	/**
       
   900 	 * Adds the aggregation log meta box.
       
   901 	 *
       
   902 	 * @return void
       
   903 	 */
       
   904 	public function add_meta_box_log() {
       
   905 		global $post;
       
   906 
       
   907 		$next_run = get_post_meta($post->ID, '_social_aggregation_next_run', true);
       
   908 		if (empty($next_run)) {
       
   909 			$next_run = __('Not Scheduled', 'social');
       
   910 		}
       
   911 		else {
       
   912 			$next_run = Social_Aggregation_Queue::next_run($next_run);
       
   913 		}
       
   914 
       
   915 		echo Social_View::factory('wp-admin/post/meta/log/shell', array(
       
   916 			'post' => $post,
       
   917 			'next_run' => $next_run,
       
   918 		));
       
   919 	}
       
   920 
       
   921 	/**
       
   922 	 * Show the broadcast options if publishing.
       
   923 	 *
       
   924 	 * @wp-filter  redirect_post_location
       
   925 	 * @param  string  $location  default post-publish location
       
   926 	 * @param  int     $post_id   post ID
       
   927 	 * @return string|void
       
   928 	 */
       
   929 	public function redirect_post_location($location, $post_id) {
       
   930 		if ((isset($_POST['social_notify']) and $_POST['social_notify'] == '1') and
       
   931 			(isset($_POST['visibility']) and $_POST['visibility'] !== 'private')
       
   932 		) {
       
   933 			update_post_meta($post_id, '_social_notify', '1');
       
   934 			if (isset($_POST['publish']) or isset($_POST['social_broadcast'])) {
       
   935 				Social_Request::factory('broadcast/options')->post(array(
       
   936 					'post_ID' => $post_id,
       
   937 					'location' => $location,
       
   938 				))->execute();
       
   939 			}
       
   940 		}
       
   941 		else {
       
   942 			delete_post_meta($post_id, '_social_notify');
       
   943 		}
       
   944 		return $location;
       
   945 	}
       
   946 
       
   947 	/**
       
   948 	 * Removes post meta if the post is going to private.
       
   949 	 *
       
   950 	 * @wp-action  transition_post_status
       
   951 	 * @param  string  $new
       
   952 	 * @param  string  $old
       
   953 	 * @param  object  $post
       
   954 	 * @return void
       
   955 	 */
       
   956 	public function transition_post_status($new, $old, $post) {
       
   957 		if ($new == 'private') {
       
   958 			delete_post_meta($post->ID, '_social_notify');
       
   959 			delete_post_meta($post->ID, '_social_broadcast_accounts');
       
   960 
       
   961 			foreach ($this->services() as $key => $service) {
       
   962 				delete_post_meta($post->ID, '_social_'.$key.'_content');
       
   963 			}
       
   964 		}
       
   965 		else {
       
   966 			$xmlrpc = false;
       
   967 			if ($new == 'publish') {
       
   968 				if ( ( defined('XMLRPC_REQUEST') or defined('SOCIAL_MAIL_PUBLISH') ) and $old != 'publish') {
       
   969 					$xmlrpc = true;
       
   970 					$this->xmlrpc_publish_post($post);
       
   971 				}
       
   972 				if (self::broadcasting_enabled_for_post_type($post->post_type)) {
       
   973 					Social_Aggregation_Queue::factory()->add($post->ID)->save();
       
   974 				}
       
   975 			}
       
   976 
       
   977 			// Sends previously saved broadcast information
       
   978 			if ($xmlrpc or ($old == 'future' and !in_array($new, array('future', 'draft')))) {
       
   979 				Social_Request::factory('broadcast/run')->query(array(
       
   980 					'post_ID' => $post->ID
       
   981 				))->execute();
       
   982 			}
       
   983 		}
       
   984 	}
       
   985 
       
   986 	/**
       
   987 	 * Broadcasts the post on XML RPC requests.
       
   988 	 *
       
   989 	 * @param  object  $post
       
   990 	 * @return void
       
   991 	 */
       
   992 	public function xmlrpc_publish_post($post) {
       
   993 		if ($post and Social::option('broadcast_by_default') == '1') {
       
   994 			Social::log('Broadcasting triggered by XML-RPC.');
       
   995 
       
   996 			$broadcast_accounts = array();
       
   997 			$broadcast_content = array();
       
   998 			$broadcast_meta = array();
       
   999 
       
  1000 			foreach ($this->default_accounts($post) as $service_key => $accounts) {
       
  1001 				$service = $this->service($service_key);
       
  1002 				if ($service !== false) {
       
  1003 					$broadcast_content[$service_key] = array();
       
  1004 					$broadcast_meta[$service_key] = array();
       
  1005 					foreach ($accounts as $key => $id) {
       
  1006 						// TODO abstract this to the Facebook plugin
       
  1007 						if ($service_key == 'facebook' and $key === 'pages') {
       
  1008 							foreach ($id as $account_id => $pages) {
       
  1009 								$account = $service->account($account_id);
       
  1010 
       
  1011 								// TODO This could use some DRY love
       
  1012 								$universal_pages = $account->pages();
       
  1013 								$personal_pages = $account->pages(null, true);
       
  1014 
       
  1015 								foreach ($pages as $page_id) {
       
  1016 									if (!isset($broadcast_accounts[$service_key])) {
       
  1017 										$broadcast_accounts[$service_key] = array();
       
  1018 									}
       
  1019 
       
  1020 									if (!isset($broadcast_accounts[$service_key][$page_id])) {
       
  1021 										if (isset($universal_pages[$page_id])) {
       
  1022 											$broadcast_accounts[$service_key][$page_id] = (object) array(
       
  1023 												'id' => $page_id,
       
  1024 												'name' => $universal_pages[$page_id]->name,
       
  1025 												'universal' => true,
       
  1026 												'page' => true,
       
  1027 											);
       
  1028 										}
       
  1029 										else if (isset($personal_pages[$page_id])) {
       
  1030 											$broadcast_accounts[$service_key][$page_id] = (object) array(
       
  1031 												'id' => $page_id,
       
  1032 												'name' => $personal_pages[$page_id]->name,
       
  1033 												'universal' => false,
       
  1034 												'page' => true,
       
  1035 											);
       
  1036 										}
       
  1037 									}
       
  1038 									$broadcast_content[$service_key][$page_id] = $service->format_content($post, Social::option('broadcast_format'));
       
  1039 									$broadcast_meta[$service_key][$page_id] = $service->get_broadcast_extras($page_id, $post);
       
  1040 								}
       
  1041 							}
       
  1042 						}
       
  1043 						else {
       
  1044 							$account = $service->account($id);
       
  1045 							if ($account !== false) {
       
  1046 								if (!isset($broadcast_accounts[$service_key])) {
       
  1047 									$broadcast_accounts[$service_key] = array();
       
  1048 								}
       
  1049 
       
  1050 								$broadcast_accounts[$service_key][$account->id()] = (object) array(
       
  1051 									'id' => $account->id(),
       
  1052 									'universal' => $account->universal()
       
  1053 								);
       
  1054 
       
  1055 								$broadcast_content[$service_key][$account->id()] = $service->format_content($post, Social::option('broadcast_format'));
       
  1056 								$broadcast_meta[$service_key][$account->id()] = $service->get_broadcast_extras($account->id(), $post);
       
  1057 							}
       
  1058 						}
       
  1059 					}
       
  1060 				}
       
  1061 			}
       
  1062 
       
  1063 			update_post_meta($post->ID, '_social_broadcast_content', addslashes_deep($broadcast_content));
       
  1064 			update_post_meta($post->ID, '_social_broadcast_meta', addslashes_deep($broadcast_meta));
       
  1065 
       
  1066 			if (count($broadcast_accounts)) {
       
  1067 				Social::log('There are default accounts, running broadcast');
       
  1068 				update_post_meta($post->ID, '_social_broadcast_accounts', addslashes_deep($broadcast_accounts));
       
  1069 			}
       
  1070 		}
       
  1071 	}
       
  1072 
       
  1073 	/**
       
  1074 	 * Loads the default accounts for the post.
       
  1075 	 *
       
  1076 	 * @param  object  $post
       
  1077 	 * @return array
       
  1078 	 */
       
  1079 	public function default_accounts($post) {
       
  1080 		$default_accounts = Social::option('default_accounts');
       
  1081 		$author_default_accounts = get_user_meta($post->post_author, 'social_default_accounts', true);
       
  1082 		if (is_array($author_default_accounts)) {
       
  1083 			foreach ($author_default_accounts as $service_key => $accounts) {
       
  1084 				if (!isset($default_accounts[$service_key])) {
       
  1085 					$default_accounts[$service_key] = $accounts;
       
  1086 				}
       
  1087 				else {
       
  1088 					foreach ($accounts as $key => $account) {
       
  1089 						if ($key === 'pages') {
       
  1090 							if (!isset($default_accounts[$key]['pages'])) {
       
  1091 								$default_accounts[$key]['pages'] = $account;
       
  1092 							}
       
  1093 							else {
       
  1094 								foreach ($account as $page_id) {
       
  1095 									if (!in_array($page_id, $default_accounts[$key]['pages'])) {
       
  1096 										$default_accounts[$key]['pages'][] = $page_id;
       
  1097 									}
       
  1098 								}
       
  1099 							}
       
  1100 						}
       
  1101 						else {
       
  1102 							$default_accounts[$service_key][] = $account;
       
  1103 						}
       
  1104 					}
       
  1105 				}
       
  1106 			}
       
  1107 		}
       
  1108 
       
  1109 		return apply_filters('social_default_accounts', $default_accounts, $post);
       
  1110 	}
       
  1111 
       
  1112 	/**
       
  1113 	 * Sets the broadcasted IDs for the post.
       
  1114 	 *
       
  1115 	 * @param  int  $post_id  post id
       
  1116 	 * @param  string  $service  service key
       
  1117 	 * @param  string  $broadcasted_id  broadcasted id
       
  1118 	 * @param  string  $message  broadcasted message
       
  1119 	 * @param  Social_Service_Account  $account  account
       
  1120 	 * @param  Social_Response  $response  response object
       
  1121 	 * @return void
       
  1122 	 */
       
  1123 	public function add_broadcasted_id($post_id, $service, $broadcasted_id, $message, $account, Social_Response $response = null) {
       
  1124 		$broadcasted_ids = get_post_meta($post_id, '_social_broadcasted_ids', true);
       
  1125 		if (empty($broadcasted_ids)) {
       
  1126 			$broadcasted_ids = array();
       
  1127 		}
       
  1128 
       
  1129 		if (!isset($broadcasted_ids[$service])) {
       
  1130 			$broadcasted_ids[$service] = array();
       
  1131 		}
       
  1132 
       
  1133 		if (!isset($broadcasted_ids[$service][$account->id()])) {
       
  1134 			$broadcasted_ids[$service][$account->id()] = array();
       
  1135 		}
       
  1136 
       
  1137 		if (!isset($broadcasted_ids[$service][$account->id()][$broadcasted_id])) {
       
  1138 			$urls = array(
       
  1139 				get_permalink($post_id)
       
  1140 			);
       
  1141 
       
  1142 			$shortlink = wp_get_shortlink($post_id);
       
  1143 			if (!in_array($shortlink, $urls)) {
       
  1144 				$urls[] = $shortlink;
       
  1145 			}
       
  1146 
       
  1147 			$home_url = home_url('?p='.$post_id);
       
  1148 			if (!in_array($home_url, $urls)) {
       
  1149 				$urls[] = $home_url;
       
  1150 			}
       
  1151 
       
  1152 			$data = array(
       
  1153 				'message' => $message,
       
  1154 				'urls' => $urls
       
  1155 			);
       
  1156 			$data = apply_filters('social_save_broadcasted_ids_data', $data, $account, $service, $post_id, $response);
       
  1157 			$broadcasted_ids[$service][$account->id()][$broadcasted_id] = $data;
       
  1158 			update_post_meta($post_id, '_social_broadcasted_ids', $broadcasted_ids);
       
  1159 		}
       
  1160 	}
       
  1161 
       
  1162 	/**
       
  1163 	 * Adds the 15 minute interval.
       
  1164 	 *
       
  1165 	 * @wp-filter  cron_schedules
       
  1166 	 * @param  array  $schedules
       
  1167 	 * @return array
       
  1168 	 */
       
  1169 	public function cron_schedules($schedules) {
       
  1170 		$schedules['every15min'] = array(
       
  1171 			'interval' => 900,
       
  1172 			'display' => 'Every 15 minutes'
       
  1173 		);
       
  1174 		return $schedules;
       
  1175 	}
       
  1176 
       
  1177 	/**
       
  1178 	 * Sends a request to initialize CRON 15.
       
  1179 	 *
       
  1180 	 * @wp-action  social_cron_15_init
       
  1181 	 * @return void
       
  1182 	 */
       
  1183 	public function cron_15_init() {
       
  1184 		Social::log('Running cron_15_init');
       
  1185 		Social_Request::factory('cron/cron_15')->query('api_key', Social::option('system_cron_api_key'))->execute();
       
  1186 	}
       
  1187 
       
  1188 	/**
       
  1189 	 * Runs the aggregation loop.
       
  1190 	 *
       
  1191 	 * @wp-action  social_cron_15
       
  1192 	 * @return void
       
  1193 	 */
       
  1194 	public function run_aggregation() {
       
  1195 		$semaphore = Social_Semaphore::factory();
       
  1196 		$queue = Social_Aggregation_Queue::factory();
       
  1197 
       
  1198 		foreach ($queue->runnable() as $timestamp => $posts) {
       
  1199 			foreach ($posts as $id => $interval) {
       
  1200 				$post = get_post($id);
       
  1201 				if ($post !== null) {
       
  1202 					$queue->add($id, $interval)->save();
       
  1203 					$semaphore->increment();
       
  1204 					$this->request(home_url('index.php?social_controller=aggregation&social_action=run&post_id='.$id), 'run');
       
  1205 				}
       
  1206 				else {
       
  1207 					$queue->remove($id, $timestamp)->save();
       
  1208 				}
       
  1209 			}
       
  1210 		}
       
  1211 	}
       
  1212 
       
  1213 	/**
       
  1214 	 * Removes the post from the aggregation queue.
       
  1215 	 *
       
  1216 	 * @wp-action  delete_post
       
  1217 	 * @param  int  $post_id
       
  1218 	 * @return void
       
  1219 	 */
       
  1220 	public function delete_post($post_id) {
       
  1221 		Social_Aggregation_Queue::factory()->remove($post_id);
       
  1222 	}
       
  1223 
       
  1224 	/**
       
  1225 	 * Hides the Site Admin link for social-based users.
       
  1226 	 *
       
  1227 	 * @wp-filter register
       
  1228 	 * @param  string  $link
       
  1229 	 * @return string
       
  1230 	 */
       
  1231 	public function register($link) {
       
  1232 		if (is_user_logged_in()) {
       
  1233 			$commenter = get_user_meta(get_current_user_id(), 'social_commenter', true);
       
  1234 			if (!empty($commenter)) {
       
  1235 				return '';
       
  1236 			}
       
  1237 		}
       
  1238 
       
  1239 		return $link;
       
  1240 	}
       
  1241 
       
  1242 	/**
       
  1243 	 * Sets the user role.
       
  1244 	 *
       
  1245 	 * @wp-action set_user_role
       
  1246 	 * @param  int     $user_id
       
  1247 	 * @param  string  $role
       
  1248 	 */
       
  1249 	public function set_user_role($user_id, $role) {
       
  1250 		if (!empty($role)) {
       
  1251 			delete_user_meta($user_id, 'social_commenter');
       
  1252 		}
       
  1253 	}
       
  1254 
       
  1255 	/**
       
  1256 	 * Show the disconnect link for social-based users.
       
  1257 	 *
       
  1258 	 * @wp-filter loginout
       
  1259 	 * @param  string  $link
       
  1260 	 * @return string
       
  1261 	 */
       
  1262 	public function loginout($link) {
       
  1263 		if (is_user_logged_in()) {
       
  1264 			$commenter = get_user_meta(get_current_user_id(), 'social_commenter', true);
       
  1265 			if (!empty($commenter)) {
       
  1266 				foreach ($this->services() as $key => $service) {
       
  1267 					$account = reset($service->accounts());
       
  1268 					if ($account) {
       
  1269 						return $service->disconnect_link($account);
       
  1270 					}
       
  1271 				}
       
  1272 			}
       
  1273 		}
       
  1274 		else {
       
  1275 			$link = explode('>'.__('Log in'), $link);
       
  1276 			$link = $link[0].' id="social_login">'.__('Log in').$link[1];
       
  1277 		}
       
  1278 
       
  1279 		return $link;
       
  1280 	}
       
  1281 
       
  1282 	/**
       
  1283 	 * Increments the service comment counter.
       
  1284 	 *
       
  1285 	 * @static
       
  1286 	 * @param  array  $items
       
  1287 	 * @param  array  $groups
       
  1288 	 */
       
  1289 	public static function add_social_items_count($items, &$groups) {
       
  1290 		foreach ($items as $group => $_items) {
       
  1291 			if ($group == 'parent') {
       
  1292 				self::add_social_items_count($_items, $groups);
       
  1293 			}
       
  1294 			else {
       
  1295 				if (!isset($groups['social-'.$group])) {
       
  1296 					$groups['social-'.$group] = 0;
       
  1297 				}
       
  1298 
       
  1299 				$groups['social-'.$group] = $groups['social-'.$group] + count($_items);
       
  1300 			}
       
  1301 		}
       
  1302 	}
       
  1303 
       
  1304 	/**
       
  1305 	 * Overrides the default WordPress comments_template function.
       
  1306 	 *
       
  1307 	 * @wp-filter  comments_template
       
  1308 	 * @return string
       
  1309 	 */
       
  1310 	public function comments_template($path) {
       
  1311 		global $post;
       
  1312 
       
  1313 		if (!(
       
  1314 			is_singular() and 
       
  1315 			(have_comments() or $post->comment_status == 'open') and 
       
  1316 			Social::option('use_standard_comments') != '1'
       
  1317 		)) {
       
  1318 			return $path;
       
  1319 		}
       
  1320 
       
  1321 		if (!defined('SOCIAL_COMMENTS_FILE')) {
       
  1322 			define('SOCIAL_COMMENTS_FILE', trailingslashit(dirname(SOCIAL_FILE)).'views/comments.php');
       
  1323 		}
       
  1324 
       
  1325 		return SOCIAL_COMMENTS_FILE;
       
  1326 	}
       
  1327 
       
  1328 	/**
       
  1329 	 * Returns an array of comment types that display avatars.
       
  1330 	 *
       
  1331 	 * @wp-filter  get_avatar_comment_types
       
  1332 	 * @param  array  $types  default WordPress types
       
  1333 	 * @return array
       
  1334 	 */
       
  1335 	public function get_avatar_comment_types($types) {
       
  1336 		$types[] = 'wordpress';
       
  1337 		return $types;
       
  1338 	}
       
  1339 
       
  1340 	/**
       
  1341 	 * Gets the avatar based on the comment type.
       
  1342 	 *
       
  1343 	 * @wp-filter  get_avatar
       
  1344 	 * @param  string  $avatar
       
  1345 	 * @param  object  $comment
       
  1346 	 * @param  int     $size
       
  1347 	 * @param  string  $default
       
  1348 	 * @param  string  $alt
       
  1349 	 * @return string
       
  1350 	 */
       
  1351 	public function get_avatar($avatar, $comment, $size, $default, $alt) {
       
  1352 		$image = null;
       
  1353 		if (is_object($comment)) {
       
  1354 			$image = get_comment_meta($comment->comment_ID, 'social_profile_image_url', true);
       
  1355 			if (empty($image)) {
       
  1356 				$image = null;
       
  1357 			}
       
  1358 		}
       
  1359 		else {
       
  1360 			// Commenter?
       
  1361 			$social_avatar = get_user_meta($comment, 'social_avatar', true);
       
  1362 			if (!empty($social_avatar)) {
       
  1363 				$image = $social_avatar;
       
  1364 			}
       
  1365 		}
       
  1366 
       
  1367 		if ($image !== null) {
       
  1368 			$image = esc_url($image);
       
  1369 			$size = esc_attr($size);
       
  1370 			$type = '';
       
  1371 			if (is_object($comment)) {
       
  1372 				$type = esc_attr($comment->comment_type);
       
  1373 			}
       
  1374 
       
  1375 			$image = esc_url($image);
       
  1376 			$image_format = apply_filters('social_get_avatar_image_format', '<img alt="%1$s" src="%2$s" class="avatar avatar-%3$s photo %4$s" height="%3$s" width="%3$s" />');
       
  1377 			return sprintf($image_format, $alt, $image, $size, $type);
       
  1378 		}
       
  1379 
       
  1380 		return $avatar;
       
  1381 	}
       
  1382 
       
  1383 	/**
       
  1384 	 * Sets the comment type upon being saved.
       
  1385 	 *
       
  1386 	 * @wp-action  comment_post
       
  1387 	 * @param  int  $comment_ID
       
  1388 	 */
       
  1389 	public function comment_post($comment_ID) {
       
  1390 		global $wpdb;
       
  1391 
       
  1392 		$comment = get_comment($comment_ID);
       
  1393 		$services = $this->services();
       
  1394 		if (!empty($services)) {
       
  1395 			$account_id = $_POST['social_post_account'];
       
  1396 			foreach ($services as $key => $service) {
       
  1397 				$output = $service->format_comment_content($comment, Social::option('comment_broadcast_format'));
       
  1398 				foreach ($service->accounts() as $account) {
       
  1399 					if ($account_id == $account->id()) {
       
  1400 						if (isset($_POST['post_to_service'])) {
       
  1401 							$in_reply_to_status_id = get_comment_meta($_POST['comment_parent'], 'social_status_id', true);
       
  1402 							if ($comment->comment_approved == '0') {
       
  1403 								update_comment_meta($comment_ID, 'social_to_broadcast', $_POST['social_post_account']);
       
  1404 								if (!empty($in_reply_to_status_id)) {
       
  1405 									update_comment_meta($comment_ID, 'social_in_reply_to_status_id', addslashes_deep($in_reply_to_status_id));
       
  1406 								}
       
  1407 							}
       
  1408 							else {
       
  1409 								$args = array();
       
  1410 								if (!empty($in_reply_to_status_id)) {
       
  1411 									$args['in_reply_to_status_id'] = $in_reply_to_status_id;
       
  1412 									delete_comment_meta($comment_ID, 'social_in_reply_to_status_id');
       
  1413 								}
       
  1414 								Social::log(sprintf(__('Broadcasting comment #%s to %s using account #%s.', 'social'), $comment_ID, $service->title(), $account->id()));
       
  1415 								$response = $service->broadcast($account, $output, $args, null, $comment_ID);
       
  1416 								if ($response === false or $response->id() === '0') {
       
  1417 									wp_delete_comment($comment_ID);
       
  1418 									Social::log(sprintf(__('Error: Broadcast comment #%s to %s using account #%s, please go back and try again.', 'social'), $comment_ID, esc_html($service->title()), esc_html($account->id())));
       
  1419 									wp_die(sprintf(__('Error: Your comment could not be sent to %s, please go back and try again.', 'social'), esc_html($service->title())));
       
  1420 								}
       
  1421 
       
  1422 								$wpdb->query($wpdb->prepare("
       
  1423 									UPDATE $wpdb->comments
       
  1424 									   SET comment_type = %s
       
  1425 									 WHERE comment_ID = %s
       
  1426 								", 'social-'.$service->key(), $comment_ID));
       
  1427 
       
  1428 								$this->set_comment_aggregated_id($comment_ID, $service->key(), $response->id());
       
  1429 								update_comment_meta($comment_ID, 'social_status_id', addslashes_deep($response->id()));
       
  1430 								update_comment_meta($comment_ID, 'social_raw_data', addslashes_deep(base64_encode(json_encode($response->body()->response))));
       
  1431 								Social::log(sprintf(__('Broadcasting comment #%s to %s using account #%s COMPLETE.', 'social'), $comment_ID, $service->title(), $account->id()));
       
  1432 							}
       
  1433 						}
       
  1434 
       
  1435 						update_comment_meta($comment_ID, 'social_account_id', addslashes_deep($account_id));
       
  1436 						update_comment_meta($comment_ID, 'social_profile_image_url', addslashes_deep($account->avatar()));
       
  1437 						update_comment_meta($comment_ID, 'social_comment_type', addslashes_deep('social-'.$service->key()));
       
  1438 
       
  1439 						if ($comment->user_id != '0') {
       
  1440 							$comment->comment_author = $account->name();
       
  1441 							$comment->comment_author_url = $account->url();
       
  1442 							wp_update_comment(get_object_vars($comment));
       
  1443 						}
       
  1444 						Social::log(sprintf(__('Comment #%s saved.', 'social'), $comment_ID));
       
  1445 						break;
       
  1446 					}
       
  1447 				}
       
  1448 			}
       
  1449 		}
       
  1450 	}
       
  1451 
       
  1452 	/**
       
  1453 	 * Sets the comment to be approved.
       
  1454 	 *
       
  1455 	 * @wp-action  wp_set_comment_status
       
  1456 	 * @param  int     $comment_id
       
  1457 	 * @param  string  $comment_status
       
  1458 	 * @return void
       
  1459 	 */
       
  1460 	public function wp_set_comment_status($comment_id, $comment_status) {
       
  1461 		if ($comment_status == 'approve') {
       
  1462 			global $wpdb;
       
  1463 			$results = $wpdb->get_results($wpdb->prepare("
       
  1464 				SELECT user_id, m.meta_value
       
  1465 				  FROM $wpdb->commentmeta AS m
       
  1466 				  JOIN $wpdb->comments AS c
       
  1467 				    ON m.comment_id = c.comment_ID
       
  1468 				 WHERE m.meta_key = %s
       
  1469 				   AND m.comment_id = %s
       
  1470 			", 'social_to_broadcast', $comment_id));
       
  1471 			if (!empty($results)) {
       
  1472 				$result = reset($results);
       
  1473 				$accounts = get_user_meta($result->user_id, 'social_accounts', true);
       
  1474 				if (!empty($accounts)) {
       
  1475 					foreach ($accounts as $service => $accounts) {
       
  1476 						$service = $this->service($service);
       
  1477 						if ($service !== false) {
       
  1478 							$account = null;
       
  1479 							if (!$service->account_exists($result->meta_value)) {
       
  1480 								foreach ($accounts as $id => $account) {
       
  1481 									if ($id == $result->meta_value) {
       
  1482 										$class = 'Social_Service_'.$service->key().'_Account';
       
  1483 										$account = new $class($account);
       
  1484 										break;
       
  1485 									}
       
  1486 								}
       
  1487 							}
       
  1488 							else {
       
  1489 								$account = $service->account($result->meta_value);
       
  1490 							}
       
  1491 
       
  1492 							if ($account !== null) {
       
  1493 								Social::log(sprintf(__('Broadcasting comment #%s to %s using account #%s.', 'social'), $comment_id, $service->title(), $account->id()));
       
  1494 								$comment = get_comment($comment_id);
       
  1495 
       
  1496 								$in_reply_to_status_id = get_comment_meta($comment_id, 'social_in_reply_to_status_id', true);
       
  1497 								$args = array();
       
  1498 								if (!empty($in_reply_to_status_id)) {
       
  1499 									$args['in_reply_to_status_id'] = $in_reply_to_status_id;
       
  1500 									delete_comment_meta($comment_id, 'social_in_reply_to_status_id');
       
  1501 								}
       
  1502 
       
  1503 								$output = $service->format_comment_content($comment, Social::option('comment_broadcast_format'));
       
  1504 								$response = $service->broadcast($account, $output, $args, null, $comment_id);
       
  1505 								if ($response === false or $response->id() === false) {
       
  1506 									wp_delete_comment($comment_id);
       
  1507 									Social::log(sprintf(__('Error: Broadcast comment #%s to %s using account #%s, please go back and try again.', 'social'), $comment_id, $service->title(), $account->id()));
       
  1508 								}
       
  1509 
       
  1510 								$wpdb->query($wpdb->prepare("
       
  1511 									UPDATE $wpdb->comments
       
  1512 									   SET comment_type = %s
       
  1513 									 WHERE comment_ID = %s
       
  1514 								", 'social-'.$service->key(), $comment_id));
       
  1515 
       
  1516 								$this->set_comment_aggregated_id($comment_id, $service->key(), $response->id());
       
  1517 								update_comment_meta($comment_id, 'social_status_id', addslashes_deep($response->id()));
       
  1518 								update_comment_meta($comment_id, 'social_raw_data', addslashes_deep(base64_encode(json_encode($response->body()->response))));
       
  1519 								Social::log(sprintf(__('Broadcasting comment #%s to %s using account #%s COMPLETE.', 'social'), $comment_id, $service->title(), $account->id()));
       
  1520 							}
       
  1521 						}
       
  1522 					}
       
  1523 				}
       
  1524 
       
  1525 				delete_comment_meta($comment_id, 'social_to_broadcast');
       
  1526 			}
       
  1527 		}
       
  1528 	}
       
  1529 
       
  1530 	/**
       
  1531 	 * Sets the comment aggregation ID.
       
  1532 	 *
       
  1533 	 * Format of the stored data (serialized):
       
  1534 	 *
       
  1535 	 *     array(
       
  1536 	 *         'twitter' => array(
       
  1537 	 *             1234567890,
       
  1538 	 *             0987654321,
       
  1539 	 *             // ... Other aggregated IDs
       
  1540 	 *         ),
       
  1541 	 *         'facebook' => array(
       
  1542 	 *             1234567890_1234567890,
       
  1543 	 *             0987654321_0987654321,
       
  1544 	 *             // ... Other aggregated IDs
       
  1545 	 *         )
       
  1546 	 *     )
       
  1547 	 *
       
  1548 	 * @param  int     $comment_id
       
  1549 	 * @param  string  $service
       
  1550 	 * @param  int     $broadcasted_id
       
  1551 	 * @return void
       
  1552 	 */
       
  1553 	private function set_comment_aggregated_id($comment_id, $service, $broadcasted_id) {
       
  1554 		$comment = get_comment($comment_id);
       
  1555 		if (is_object($comment)) {
       
  1556 			$aggregated_ids = get_post_meta($comment->comment_post_ID, '_social_aggregated_ids', true);
       
  1557 			if (empty($aggregated_ids)) {
       
  1558 				$aggregated_ids = array();
       
  1559 			}
       
  1560 
       
  1561 			if (!isset($aggregated_ids[$service])) {
       
  1562 				$aggregated_ids[$service] = array();
       
  1563 			}
       
  1564 
       
  1565 			if (!in_array($broadcasted_id, $aggregated_ids[$service])) {
       
  1566 				$aggregated_ids[$service][] = $broadcasted_id;
       
  1567 			}
       
  1568 
       
  1569 			update_post_meta($comment->comment_post_ID, '_social_aggregated_ids', $aggregated_ids);
       
  1570 		}
       
  1571 	}
       
  1572 
       
  1573 	/**
       
  1574 	 * Counts the different types of comments.
       
  1575 	 *
       
  1576 	 * @wp-filter social_comments_array
       
  1577 	 * @static
       
  1578 	 * @param  array  $comments
       
  1579 	 * @param  int    $post_id
       
  1580 	 * @return array
       
  1581 	 */
       
  1582 	public function comments_array(array $comments, $post_id) {
       
  1583 		$groups = array();
       
  1584 		if (isset($comments['social_groups'])) {
       
  1585 			$groups = $comments['social_groups'];
       
  1586 		}
       
  1587 
       
  1588 		// count the comment types for output in tab headers
       
  1589 		foreach ($comments as $comment) {
       
  1590 			if (is_object($comment)) {
       
  1591 				if (empty($comment->comment_type)) {
       
  1592 					$comment->comment_type = 'wordpress';
       
  1593 				}
       
  1594 
       
  1595 				if (!isset($groups[$comment->comment_type])) {
       
  1596 					$groups[$comment->comment_type] = 1;
       
  1597 				}
       
  1598 				else {
       
  1599 					++$groups[$comment->comment_type];
       
  1600 				}
       
  1601 				if (isset($comment->social_items) and is_array($comment->social_items)) {
       
  1602 					$groups[$comment->comment_type] += count($comment->social_items);
       
  1603 				}
       
  1604 			}
       
  1605 		}
       
  1606 
       
  1607 		$comments['social_groups'] = apply_filters('social_comments_array_groups', $groups, $comments);
       
  1608 
       
  1609 		return $comments;
       
  1610 	}
       
  1611 
       
  1612 	/**
       
  1613 	 * Displays a comment.
       
  1614 	 *
       
  1615 	 * @param  object  $comment  comment object
       
  1616 	 * @param  array   $args
       
  1617 	 * @param  int     $depth
       
  1618 	 */
       
  1619 	public function comment($comment, array $args = array(), $depth = 0) {
       
  1620 		$GLOBALS['comment'] = $comment;
       
  1621 
       
  1622 		$social_items = '';
       
  1623 		$status_url = null;
       
  1624 		$comment_type = $comment->comment_type;
       
  1625 		$ignored_types = apply_filters('social_ignored_comment_types', array(
       
  1626 			'wordpress',
       
  1627 			'pingback'
       
  1628 		));
       
  1629 		// set the comment type to WordPress if we can't load the Social service (perhaps it was deactivated)
       
  1630 		// and the type isn't an ignored type
       
  1631 		if (!($service = $this->service_for_comment_type($comment->comment_type)) && !in_array($comment->comment_type, $ignored_types)) {
       
  1632 			$comment_type = 'wordpress';
       
  1633 		}
       
  1634 		// set Social Items for Social comments
       
  1635 		if (!in_array($comment->comment_type, $ignored_types)) {
       
  1636 			$status_id = get_comment_meta($comment->comment_ID, 'social_status_id', true);
       
  1637 			if (!empty($status_id)) {
       
  1638 				$status_url = $service->status_url(get_comment_author(), $status_id);
       
  1639 			}
       
  1640 			// Social items?
       
  1641 			if (!empty($comment->social_items)) {
       
  1642 				if (is_object($service) && method_exists($service, 'key')) {
       
  1643 					$avatar_size = apply_filters('social_items_comment_avatar_size', array(
       
  1644 						'width' => 18,
       
  1645 						'height' => 18,
       
  1646 					));
       
  1647 					$social_items = Social_View::factory('comment/social_item', array(
       
  1648 						'items' => $comment->social_items,
       
  1649 						'service' => $service,
       
  1650 						'avatar_size' => $avatar_size
       
  1651 					));
       
  1652 				}
       
  1653 				else {
       
  1654 					Social::log('service not set for: '.print_r($comment, true));
       
  1655 					ob_start();
       
  1656 					var_dump($service);
       
  1657 					Social::log('$service: '.ob_get_clean());
       
  1658 				}
       
  1659 			}
       
  1660 		}
       
  1661 
       
  1662 		echo Social_View::factory('comment/comment', array(
       
  1663 			'comment_type' => $comment_type,
       
  1664 			'comment' => $comment,
       
  1665 			'service' => $service,
       
  1666 			'status_url' => $status_url,
       
  1667 			'depth' => $depth,
       
  1668 			'args' => $args,
       
  1669 			'social_items' => $social_items,
       
  1670 		));
       
  1671 	}
       
  1672 
       
  1673 	/**
       
  1674 	 * Adds the Aggregate Comments link to the post row actions.
       
  1675 	 *
       
  1676 	 * @param  array    $actions
       
  1677 	 * @param  WP_Post  $post
       
  1678 	 * @return array
       
  1679 	 */
       
  1680 	public function post_row_actions(array $actions, $post) {
       
  1681 		if ($post->post_status == 'publish' && in_array(Social::option('fetch_comments'), array('1', '2'))) {
       
  1682 			$actions['social_aggregation'] = sprintf(__('<a href="%s" rel="%s">Social Comments</a>', 'social'), esc_url(wp_nonce_url(admin_url('options-general.php?social_controller=aggregation&social_action=run&post_id='.$post->ID), 'run')), $post->ID).
       
  1683 				'<img src="'.esc_url(admin_url('images/wpspin_light.gif')).'" class="social_run_aggregation_loader" />';
       
  1684 		}
       
  1685 		return $actions;
       
  1686 	}
       
  1687 
       
  1688 	/**
       
  1689 	 * Adds the aggregation functionality to the admin bar.
       
  1690 	 *
       
  1691 	 * @return void
       
  1692 	 */
       
  1693 	public function admin_bar_menu() {
       
  1694 		global $wp_admin_bar;
       
  1695 
       
  1696 		$current_object = get_queried_object();
       
  1697 
       
  1698 		if (empty($current_object)) {
       
  1699 			return;
       
  1700 		}
       
  1701 
       
  1702 		if (!empty($current_object->post_type)
       
  1703 			and ($post_type_object = get_post_type_object($current_object->post_type))
       
  1704 				and current_user_can($post_type_object->cap->edit_post, $current_object->ID)
       
  1705 					and ($post_type_object->show_ui or 'attachment' == $current_object->post_type)
       
  1706 						and (in_array(Social::option('fetch_comments'), array('1', '2')))
       
  1707 		) {
       
  1708 			$wp_admin_bar->add_menu(array(
       
  1709 				'parent' => 'comments',
       
  1710 				'id' => 'social-find-comments',
       
  1711 				'title' => __('Find Social Comments', 'social')
       
  1712 					.'<span class="social-aggregation-spinner" style="display: none;">&nbsp;(
       
  1713 						<span class="social-dot dot-active">.</span>
       
  1714 						<span class="social-dot">.</span>
       
  1715 						<span class="social-dot">.</span>
       
  1716 					)</span>',
       
  1717 				'href' => esc_url(wp_nonce_url(admin_url('options-general.php?social_controller=aggregation&social_action=run&post_id='.$current_object->ID), 'run')),
       
  1718 			));
       
  1719 			$wp_admin_bar->add_menu(array(
       
  1720 				'parent' => 'comments',
       
  1721 				'id' => 'social-add-tweet-by-url',
       
  1722 				'title' => __('Add Tweet by URL', 'social')
       
  1723 					.'<form class="social-add-tweet" style="display: none;" method="get" action="'.esc_url(wp_nonce_url(admin_url('options-general.php?social_controller=import&social_action=from_url&social_service=twitter&post_id='.$current_object->ID), 'from_url')).'">
       
  1724 						<input type="text" size="20" name="url" value="" autocomplete="off" />
       
  1725 						<input type="submit" name="social-add-tweet-button" name="social-add-tweet-button" value="'.__('Add Tweet by URL', 'social').'" />
       
  1726 					</form>',
       
  1727 				'href' => esc_url(get_edit_post_link($current_object->ID)),
       
  1728 			));
       
  1729 		}
       
  1730 	}
       
  1731 	
       
  1732 	function admin_bar_footer_css() {
       
  1733 ?>
       
  1734 <style class="text/css">
       
  1735 #wpadminbar #wp-admin-bar-comments .social-aggregation-spinner {
       
  1736 	background: transparent;
       
  1737 	white-space: nowrap;
       
  1738 }
       
  1739 #wpadminbar .social-aggregation-spinner .dot-active {
       
  1740 	font-weight: bold;
       
  1741 }
       
  1742 #wpadminbar #wp-admin-bar-social-add-tweet-by-url form {
       
  1743 	display: block;
       
  1744 	line-height: 100%;
       
  1745 	margin: 0;
       
  1746 	padding: 5px;
       
  1747 }
       
  1748 #wpadminbar #wp-admin-bar-social-add-tweet-by-url input {
       
  1749 	color: #333;
       
  1750 	font-size: 11px;
       
  1751 	font-weight: normal;
       
  1752 	line-height: 1;
       
  1753 	margin-bottom: 3px;
       
  1754 	padding: 3px;
       
  1755 	text-shadow: none;
       
  1756 	width: 90%;
       
  1757 }
       
  1758 #wpadminbar #wp-admin-bar-social-add-tweet-by-url input[type="submit"] {
       
  1759 	margin: 0;
       
  1760 }
       
  1761 #wpadminbar #wp-admin-bar-social-add-tweet-by-url .loading {
       
  1762 	background: url(<?php echo admin_url('images/wpspin_light.gif'); ?>) center center no-repeat;
       
  1763 }
       
  1764 #wpadminbar #wp-admin-bar-social-add-tweet-by-url p.msg {
       
  1765 	color: #333;
       
  1766 	font-size: 12px;
       
  1767 	font-weight: normal;
       
  1768 	margin: 0;
       
  1769 	padding: 0;
       
  1770 	text-align: center;
       
  1771 	text-shadow: none;
       
  1772 }
       
  1773 #wpadminbar #wp-admin-bar-social-add-tweet-by-url p.error {
       
  1774 	color: #900;
       
  1775 }
       
  1776 </style>
       
  1777 <?php
       
  1778 	}
       
  1779 
       
  1780 	function admin_bar_footer_js() {
       
  1781 ?>
       
  1782 <script type="text/javascript">
       
  1783 var socialAdminBarMsgs = {
       
  1784 	'protected': '<?php echo esc_js(__('Protected Tweet', 'social')); ?>',
       
  1785 	'invalid': '<?php echo esc_js(__('Invalid URL', 'social')); ?>',
       
  1786 	'success': '<?php echo esc_js(__('Tweet Imported!', 'social')); ?>'
       
  1787 };
       
  1788 </script>
       
  1789 <?php
       
  1790 	}
       
  1791 
       
  1792 	/**
       
  1793 	 * Runs the upgrade only if the installed version is older than the current version.
       
  1794 	 *
       
  1795 	 * @return void
       
  1796 	 */
       
  1797 	private function upgrade() {
       
  1798 		define('SOCIAL_UPGRADE', true);
       
  1799 		global $wpdb; // Don't delete, this is used in upgrade files.
       
  1800 
       
  1801 		$upgrades = array(
       
  1802 			Social::$plugins_path.'upgrades/2.0.php',
       
  1803 		);
       
  1804 		$upgrades = apply_filters('social_upgrade_files', $upgrades);
       
  1805 		foreach ($upgrades as $file) {
       
  1806 			if (file_exists($file)) {
       
  1807 				include_once $file;
       
  1808 			}
       
  1809 		}
       
  1810 
       
  1811 		Social::option('installed_version', Social::$version);
       
  1812 	}
       
  1813 
       
  1814 	/**
       
  1815 	 * Are there accounts connected?
       
  1816 	 *
       
  1817 	 * @return bool
       
  1818 	 */
       
  1819 	public function have_accounts() {
       
  1820 		foreach ($this->services() as $service) {
       
  1821 			if (count($service->accounts())) {
       
  1822 				return true;
       
  1823 			}
       
  1824 		}
       
  1825 
       
  1826 		return false;
       
  1827 	}
       
  1828 
       
  1829 	/**
       
  1830 	 * Removes an account from the default broadcast accounts.
       
  1831 	 *
       
  1832 	 * @param  string  $service
       
  1833 	 * @param  int     $id
       
  1834 	 * @return void
       
  1835 	 */
       
  1836 	public function remove_from_default_accounts($service, $id) {
       
  1837 		Social::log('Removing from default accounts #:id', array('id' => $id));
       
  1838 		if (defined('IS_PROFILE_PAGE')) {
       
  1839 			$defaults = get_user_meta(get_current_user_id(), 'social_default_accounts', true);
       
  1840 		}
       
  1841 		else {
       
  1842 			$defaults = Social::option('default_accounts');
       
  1843 		}
       
  1844 
       
  1845 		if (!empty($defaults) and isset($defaults[$service])) {
       
  1846 			Social::log('Old default accounts: :accounts', array('accounts' => print_r($defaults, true)));
       
  1847 
       
  1848 			$_ids = array();
       
  1849 			foreach ($defaults[$service] as $key => $_id) {
       
  1850 				if ($_id != $id) {
       
  1851 					$_ids[$key] = $_id;
       
  1852 				}
       
  1853 			}
       
  1854 
       
  1855 			// TODO abstract this to the Facebook plugin
       
  1856 			if ($service == 'facebook' and isset($_ids['pages'])) {
       
  1857 				$pages = $_ids['pages'];
       
  1858 				unset($_ids['pages']);
       
  1859 				sort($_ids);
       
  1860 				foreach ($pages as $account_id => $account_pages) {
       
  1861 					if ($account_id != $id) {
       
  1862 						$_ids['pages'][$account_id] = $account_pages;
       
  1863 					}
       
  1864 				}
       
  1865 			}
       
  1866 
       
  1867 			$defaults[$service] = $_ids;
       
  1868 			if (!count($defaults[$service])) {
       
  1869 				unset($defaults[$service]);
       
  1870 			}
       
  1871 			Social::log('New default accounts: :accounts', array('accounts' => print_r($defaults, true)));
       
  1872 			if (defined('IS_PROFILE_PAGE')) {
       
  1873 				update_user_meta(get_current_user_id(), 'social_default_accounts', $defaults);
       
  1874 			}
       
  1875 			else {
       
  1876 				Social::option('default_accounts', $defaults);
       
  1877 			}
       
  1878 		}
       
  1879 	}
       
  1880 
       
  1881 	/**
       
  1882 	 * Recursively applies wp_kses() to an array/stdClass.
       
  1883 	 *
       
  1884 	 * @param  mixed  $object
       
  1885 	 * @return mixed
       
  1886 	 */
       
  1887 	public function kses($object) {
       
  1888 		if (is_object($object)) {
       
  1889 			$_object = new stdClass;
       
  1890 		}
       
  1891 		else {
       
  1892 			$_object = array();
       
  1893 		}
       
  1894 
       
  1895 		foreach ($object as $key => $val) {
       
  1896 			if (is_object($val) or is_array($val)) {
       
  1897 				if (is_object($_object)) {
       
  1898 					$_object->$key = $this->kses($val);
       
  1899 				}
       
  1900 				else if (is_array($_object)) {
       
  1901 					$_object[$key] = $this->kses($val);
       
  1902 				}
       
  1903 			}
       
  1904 			else {
       
  1905 				if (is_object($_object)) {
       
  1906 					$_object->$key = wp_kses($val, array());
       
  1907 				}
       
  1908 				else {
       
  1909 					$_object[$key] = wp_kses($val, array());
       
  1910 				}
       
  1911 			}
       
  1912 		}
       
  1913 
       
  1914 		return $_object;
       
  1915 	}
       
  1916 
       
  1917 	/**
       
  1918 	 * Handles the remote timeout requests for Social.
       
  1919 	 *
       
  1920 	 * @param  string  $url        url to request
       
  1921 	 * @param  string  $nonce_key  key to use when generating the nonce
       
  1922 	 * @param  bool    $post       set to true to do a wp_remote_post
       
  1923 	 * @return void
       
  1924 	 */
       
  1925 	private function request($url, $nonce_key = null, $post = false) {
       
  1926 		if ($nonce_key !== null) {
       
  1927 			$url = str_replace('&amp;', '&', wp_nonce_url($url, $nonce_key));
       
  1928 		}
       
  1929 
       
  1930 		$data = array(
       
  1931 			'timeout' => 0.01,
       
  1932 			'blocking' => false,
       
  1933 			'sslverify' => apply_filters('https_local_ssl_verify', true),
       
  1934 		);
       
  1935 
       
  1936 		if ($post) {
       
  1937 			Social::log('POST request to: :url', array(
       
  1938 				'url' => $url
       
  1939 			));
       
  1940 			wp_remote_post($url, $data);
       
  1941 		}
       
  1942 		else {
       
  1943 			Social::log('GET request to: :url', array(
       
  1944 				'url' => $url
       
  1945 			));
       
  1946 			wp_remote_get($url, $data);
       
  1947 		}
       
  1948 	}
       
  1949 
       
  1950 	/**
       
  1951 	 * Loads the services.
       
  1952 	 *
       
  1953 	 * @return array
       
  1954 	 */
       
  1955 	private function load_services() {
       
  1956 		if ((isset($_GET['page']) and $_GET['page'] == basename(SOCIAL_FILE)) or defined('IS_PROFILE_PAGE')) {
       
  1957 			$services = false;
       
  1958 		}
       
  1959 		else {
       
  1960 			$services = wp_cache_get('services', 'social');
       
  1961 		}
       
  1962 
       
  1963 		if ($services === false) {
       
  1964 			$services = array();
       
  1965 			// Register services
       
  1966 			$registered_services = apply_filters('social_register_service', array());
       
  1967 			if (is_array($registered_services) and count($registered_services)) {
       
  1968 				$accounts = Social::option('accounts');
       
  1969 				foreach ($registered_services as $service) {
       
  1970 					if (!isset($services[$service])) {
       
  1971 						$service_accounts = array();
       
  1972 
       
  1973 						if (isset($accounts[$service]) and count($accounts[$service])) {
       
  1974 							// Flag social as enabled, we have at least one account.
       
  1975 							if ($this->_enabled === null) {
       
  1976 								$this->_enabled = true;
       
  1977 							}
       
  1978 
       
  1979 							foreach ($accounts[$service] as $account_id => $account) {
       
  1980 								// TODO Shouldn't have to do this. Fix later.
       
  1981 								$account->personal = '0';
       
  1982 								$service_accounts[$account_id] = $account;
       
  1983 							}
       
  1984 						}
       
  1985 
       
  1986 						$class = 'Social_Service_'.$service;
       
  1987 						$services[$service] = new $class($service_accounts);
       
  1988 					}
       
  1989 				}
       
  1990 				wp_cache_set('services', $services, 'social');
       
  1991 			}
       
  1992 		}
       
  1993 		else if ($this->_enabled === null and is_array($services)) {
       
  1994 			foreach ($services as $service) {
       
  1995 				if (count($service->accounts())) {
       
  1996 					$this->_enabled = true;
       
  1997 					break;
       
  1998 				}
       
  1999 			}
       
  2000 		}
       
  2001 
       
  2002 // don't return global services for commenters
       
  2003 		$commenter = get_user_meta(get_current_user_id(), 'social_commenter', true);
       
  2004 		if ($commenter == 'true' && !current_user_can('publish_posts')) {
       
  2005 			foreach ($services as $key => $accounts) {
       
  2006 				$services[$key]->clear_accounts();
       
  2007 			}
       
  2008 		}
       
  2009 
       
  2010 		$personal_accounts = get_user_meta(get_current_user_id(), 'social_accounts', true);
       
  2011 		if (is_array($personal_accounts)) {
       
  2012 			foreach ($personal_accounts as $key => $_accounts) {
       
  2013 				if (count($_accounts) and isset($services[$key])) {
       
  2014 					$class = 'Social_Service_'.$key.'_Account';
       
  2015 					foreach ($_accounts as $account_id => $account) {
       
  2016 						// TODO Shouldn't have to do this. Fix later.
       
  2017 						$account->universal = '0';
       
  2018 						if ($services[$key]->account_exists($account_id) and !defined('IS_PROFILE_PAGE')) {
       
  2019 							$account = $this->merge_accounts($services[$key]->account($account_id)->as_object(), $account, $key);
       
  2020 						}
       
  2021 						$account = new $class((object) $account);
       
  2022 						$services[$key]->account($account);
       
  2023 						// Flag social as enabled, we have at least one account.
       
  2024 						if ($this->_enabled === null) {
       
  2025 							$this->_enabled = true;
       
  2026 						}
       
  2027 					}
       
  2028 				}
       
  2029 			}
       
  2030 		}
       
  2031 
       
  2032 		return $services;
       
  2033 	}
       
  2034 
       
  2035 	/**
       
  2036 	 * Merges universal with personal account.
       
  2037 	 *
       
  2038 	 * @param  array   $arr1
       
  2039 	 * @param  array   $arr2
       
  2040 	 * @param  string  $service_key
       
  2041 	 * @return object
       
  2042 	 */
       
  2043 	private function merge_accounts($arr1, $arr2, $service_key) {
       
  2044 		$arr1->personal = true;
       
  2045 		return apply_filters('social_merge_accounts', $arr1, $arr2, $service_key);
       
  2046 	}
       
  2047 
       
  2048 	/**
       
  2049 	 * Checks to see if the array is an associative array.
       
  2050 	 *
       
  2051 	 * @param  array  $arr
       
  2052 	 * @return bool
       
  2053 	 */
       
  2054 	private function is_assoc($arr) {
       
  2055 		$keys = array_keys($arr);
       
  2056 		return array_keys($keys) !== $keys;
       
  2057 	}
       
  2058 
       
  2059 	/**
       
  2060 	 * Builds the settings URL for the plugin.
       
  2061 	 *
       
  2062 	 * @param  array  $params
       
  2063 	 * @param  bool   $personal
       
  2064 	 * @return string
       
  2065 	 */
       
  2066 	public static function settings_url(array $params = null, $personal = false) {
       
  2067 		if ($params !== null) {
       
  2068 			foreach ($params as $key => $value) {
       
  2069 				$params[$key] = urlencode($value);
       
  2070 			}
       
  2071 		}
       
  2072 
       
  2073 		if (!current_user_can('manage_options') or $personal) {
       
  2074 			$file = 'profile.php';
       
  2075 		}
       
  2076 		else {
       
  2077 			$file = 'options-general.php';
       
  2078 			$params['page'] = basename(SOCIAL_FILE);
       
  2079 		}
       
  2080 
       
  2081 		$url = add_query_arg($params, admin_url($file));
       
  2082 
       
  2083 		if (!current_user_can('manage_options') or $personal) {
       
  2084 			$url .= '#social-networks';
       
  2085 		}
       
  2086 
       
  2087 		return $url;
       
  2088 	}
       
  2089 	
       
  2090 	/**
       
  2091 	 * Filter the where clause for pulling comments for feeds (to exclude meta comments).
       
  2092 	 *
       
  2093 	 * @param  string  $where
       
  2094 	 * @return string
       
  2095 	 */
       
  2096 	public static function comments_feed_exclusions($where) {
       
  2097 		global $wpdb;
       
  2098 		$meta_types = array();
       
  2099 // get services
       
  2100 		$services = Social::instance()->services();
       
  2101 // ask each service for it's "meta" comment types
       
  2102 		foreach ($services as $service) {
       
  2103 			$meta_types = array_merge($meta_types, $service->comment_types_meta());
       
  2104 		}
       
  2105 		$meta_types = array_unique($meta_types);
       
  2106 		if (count($meta_types)) {
       
  2107 			$where .= " AND comment_type NOT IN ('".implode("', '", array_map('social_wpdb_escape', $meta_types))."') ";
       
  2108 		}
       
  2109 		return $where;
       
  2110 	}
       
  2111 	
       
  2112 	/**
       
  2113 	 * Filter the image tag to implement lazy loading support for meta comments.
       
  2114 	 *
       
  2115 	 * @param  string  $image_format
       
  2116 	 * @return string
       
  2117 	 */
       
  2118 	public static function social_item_output_image_format($image_format) {
       
  2119 		if (class_exists('LazyLoad_Images')) {
       
  2120 			// would be great if the plugin provided an API for this, until then we'll copy the code
       
  2121 			$placeholder_image = apply_filters( 'lazyload_images_placeholder_image', LazyLoad_Images::get_url( 'images/1x1.trans.gif' ) );
       
  2122 			$image_format = '<img src="'.esc_url($placeholder_image).'" data-lazy-src="%1$s" width="%2$s" height="%3$s" alt="%4$s" /><noscript>'.$image_format.'</noscript>';
       
  2123 		}
       
  2124 		return $image_format;
       
  2125 	}
       
  2126 
       
  2127 	/**
       
  2128 	 * Filter the image tag to implement lazy loading support for avatars.
       
  2129 	 *
       
  2130 	 * @param  string  $image_format
       
  2131 	 * @return string
       
  2132 	 */
       
  2133 	public static function social_get_avatar_image_format($image_format) {
       
  2134 		if (class_exists('LazyLoad_Images')) {
       
  2135 			// would be great if the plugin provided an API for this, until then we'll copy the code
       
  2136 			$placeholder_image = apply_filters( 'lazyload_images_placeholder_image', LazyLoad_Images::get_url( 'images/1x1.trans.gif' ) );
       
  2137 			$image_format = '<img alt="%1$s" src="'.esc_url($placeholder_image).'" data-lazy-src="%2$s" class="avatar avatar-%3$s photo %4$s" height="%3$s" width="%3$s" /><noscript>'.$image_format.'</noscript>';
       
  2138 		}
       
  2139 		return $image_format;
       
  2140 	}
       
  2141 
       
  2142 } // End Social
       
  2143 
       
  2144 if (!function_exists('addslashes_deep')) {
       
  2145 /**
       
  2146  * Navigates through an array and adds slashes to the values.
       
  2147  *
       
  2148  * If an array is passed, the array_map() function causes a callback to pass the
       
  2149  * value back to the function. Slashes will be added to this value.
       
  2150  *
       
  2151  * @since 3.4.0?
       
  2152  *
       
  2153  * @param array|string $value The array or string to be slashed.
       
  2154  * @return array|string Slashed array (or string in the callback).
       
  2155  */
       
  2156 function addslashes_deep($value) {
       
  2157 	if ( is_array($value) ) {
       
  2158 		$value = array_map('addslashes_deep', $value);
       
  2159 	} elseif ( is_object($value) ) {
       
  2160 		$vars = get_object_vars( $value );
       
  2161 		foreach ($vars as $key=>$data) {
       
  2162 			$value->{$key} = addslashes_deep( $data );
       
  2163 		}
       
  2164 	} else {
       
  2165 		$value = addslashes($value);
       
  2166 	}
       
  2167 
       
  2168 	return $value;
       
  2169 }
       
  2170 }
       
  2171 
       
  2172 function social_wpdb_escape($str) {
       
  2173 	global $wpdb;
       
  2174 	return $wpdb->escape($str);
       
  2175 }
       
  2176 
       
  2177 function social_wp_mail_indicator() {
       
  2178 	define('SOCIAL_MAIL_PUBLISH', true);
       
  2179 }
       
  2180 
       
  2181 $social_file = __FILE__;
       
  2182 if (isset($plugin)) {
       
  2183 	$social_file = $plugin;
       
  2184 }
       
  2185 else if (isset($mu_plugin)) {
       
  2186 	$social_file = $mu_plugin;
       
  2187 }
       
  2188 else if (isset($network_plugin)) {
       
  2189 	$social_file = $network_plugin;
       
  2190 }
       
  2191 
       
  2192 define('SOCIAL_FILE', $social_file);
       
  2193 define('SOCIAL_PATH', WP_PLUGIN_DIR.'/'.basename(dirname($social_file)).'/');
       
  2194 
       
  2195 // Register Social's autoloading
       
  2196 spl_autoload_register(array('Social', 'auto_load'));
       
  2197 
       
  2198 $social = Social::instance();
       
  2199 
       
  2200 // General Actions
       
  2201 add_action('init', array($social, 'init'), 1);
       
  2202 add_action('init', array($social, 'request_handler'), 2);
       
  2203 add_action('admin_init', array($social, 'admin_init'), 1);
       
  2204 add_action('load-settings_page_social', array($social, 'check_system_cron'));
       
  2205 add_action('load-social.php', array($social, 'check_system_cron'));
       
  2206 add_action('comment_post', array($social, 'comment_post'));
       
  2207 add_action('wp_set_comment_status', array($social, 'wp_set_comment_status'), 10, 3);
       
  2208 add_action('admin_notices', array($social, 'admin_notices'));
       
  2209 add_action('transition_post_status', array($social, 'transition_post_status'), 10, 3);
       
  2210 add_action('show_user_profile', array($social, 'show_user_profile'));
       
  2211 add_action('do_meta_boxes', array($social, 'do_meta_boxes'));
       
  2212 add_action('delete_post', array($social, 'delete_post'));
       
  2213 add_action('wp_enqueue_scripts', array($social, 'enqueue_assets'));
       
  2214 add_action('load-post-new.php', array($social, 'enqueue_assets'));
       
  2215 add_action('load-post.php', array($social, 'enqueue_assets'));
       
  2216 add_action('load-profile.php', array($social, 'enqueue_assets'));
       
  2217 add_action('load-settings_page_social', array($social, 'enqueue_assets'));
       
  2218 add_action('admin_enqueue_scripts', array($social, 'admin_enqueue_assets'));
       
  2219 add_action('admin_bar_menu', array($social, 'admin_bar_menu'), 95);
       
  2220 add_action('wp_after_admin_bar_render', array($social, 'admin_bar_footer_css'));
       
  2221 add_action('wp_after_admin_bar_render', array($social, 'admin_bar_footer_js'));
       
  2222 add_action('set_user_role', array($social, 'set_user_role'), 10, 2);
       
  2223 add_action('wp-mail.php', 'social_wp_mail_indicator');
       
  2224 add_action('social_settings_save', array('Social_Service_Facebook', 'social_settings_save'));
       
  2225 
       
  2226 // CRON Actions
       
  2227 add_action('social_cron_15_init', array($social, 'cron_15_init'));
       
  2228 add_action('social_cron_15', array($social, 'run_aggregation'));
       
  2229 
       
  2230 // Admin Actions
       
  2231 add_action('admin_menu', array($social, 'admin_menu'));
       
  2232 add_action('personal_options_update', array($social, 'personal_options_update'));
       
  2233 
       
  2234 // Filters
       
  2235 add_filter('cron_schedules', array($social,'cron_schedules'));
       
  2236 add_filter('plugin_action_links', array($social, 'add_settings_link'), 10, 2);
       
  2237 add_filter('redirect_post_location', array($social, 'redirect_post_location'), 10, 2);
       
  2238 add_filter('comments_template', array($social, 'comments_template'));
       
  2239 add_filter('get_avatar_comment_types', array($social, 'get_avatar_comment_types'));
       
  2240 add_filter('get_avatar', array($social, 'get_avatar'), 10, 5);
       
  2241 add_filter('register', array($social, 'register'));
       
  2242 add_filter('loginout', array($social, 'loginout'));
       
  2243 add_filter('post_row_actions', array($social, 'post_row_actions'), 10, 2);
       
  2244 add_filter('social_comments_array', array($social, 'comments_array'), 100, 2);
       
  2245 add_filter('comment_feed_where', array($social, 'comments_feed_exclusions'));
       
  2246 add_filter('social_settings_default_accounts', array('Social_Service_Facebook', 'social_settings_default_accounts'), 10, 2);
       
  2247 add_filter('social_item_output_image_format', array($social, 'social_item_output_image_format'));
       
  2248 add_filter('social_get_avatar_image_format', array($social, 'social_get_avatar_image_format'));
       
  2249 
       
  2250 // Service filters
       
  2251 add_filter('social_auto_load_class', array($social, 'auto_load_class'));
       
  2252 
       
  2253 } // End class_exists check