diff -r 2f6f6f7551ca -r 32102edaa81b web/wp-content/plugins/twitter-tools/classes/aktt.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/wp-content/plugins/twitter-tools/classes/aktt.php Mon Nov 19 18:26:13 2012 +0100
@@ -0,0 +1,1193 @@
+Social plugin, please install this plugin.', 'twitter-tools'), 'http://wordpress.org/extend/plugins/social/'), 'error');
+ return;
+ }
+
+ /* Set our default settings. We need to do this at init() so
+ that any text domains (i18n) are registered prior to us setting
+ the labels. */
+ self::set_default_settings();
+
+ self::register_post_type();
+ self::register_taxonomies();
+
+ add_shortcode('aktt_tweets', 'aktt_shortcode_tweets');
+ add_shortcode('aktt_tweet', 'aktt_shortcode_tweet');
+
+ // General Hooks
+ add_action('wp', array('AKTT', 'controller'), 1);
+ add_filter('the_post', array('AKTT', 'the_post'));
+ add_filter('the_posts', array('AKTT', 'the_posts'));
+ add_action('social_account_disconnected', array('AKTT', 'social_account_disconnected'), 10, 2);
+ add_action('social_broadcast_response', array('AKTT', 'social_broadcast_response'), 10, 3);
+
+ // Admin Hooks
+ add_action('admin_init', array('AKTT', 'init_settings'), 0);
+ add_action('admin_init', array('AKTT', 'admin_controller'), 1);
+ add_action('admin_menu', array('AKTT', 'admin_menu'));
+ add_filter('plugin_action_links', array('AKTT', 'plugin_action_links'), 10, 2);
+ add_action('admin_enqueue_scripts', array('AKTT', 'admin_enqueue_scripts'));
+
+ // Cron Hooks
+ add_action('social_cron_15', array('AKTT', 'import_tweets'));
+ add_action('aktt_backfill_tweets', array('AKTT', 'backfill_tweets'));
+
+ // Set logging to admin screen settings
+ self::$debug = self::option('debug');
+ }
+
+
+ /**
+ * Sets the default settings for the plugin
+ *
+ * @return void
+ */
+ static function set_default_settings() {
+ // Set default settings
+ $yn_options = array(
+ '1' => __('Yes', 'twitter-tools'),
+ '0' => __('No', 'twitter-tools')
+ );
+ $settings = array(
+ 'tweet_admin_ui' => array(
+ 'name' => 'tweet_admin_ui',
+ 'value' => 1,
+ 'label' => __('Show admin screens for tweets', 'twitter-tools'),
+ 'type' => 'radio',
+ 'options' => $yn_options,
+ ),
+ 'tweet_visibility' => array(
+ 'name' => 'tweet_visibility',
+ 'value' => 1,
+ 'label' => __('Create URLs for tweets', 'twitter-tools'),
+ 'type' => 'radio',
+ 'options' => array(
+ '1' => sprintf(__('Yes (%s)', 'twitter-tools'), home_url('tweet/{tweet-id}')),
+ '0' => __('No', 'twitter-tools')
+ ),
+ ),
+ 'credit' => array(
+ 'name' => 'credit',
+ 'value' => 1,
+ 'label' => __('Give Twitter Tools credit', 'twitter-tools'),
+ 'type' => 'radio',
+ 'options' => $yn_options,
+ ),
+ 'debug' => array(
+ 'name' => 'debug',
+ 'value' => 0,
+ 'label' => __('Debug logging', 'twitter-tools'),
+ 'type' => 'radio',
+ 'options' => array(
+ '0' => __('Disabled', 'twitter-tools'),
+ '1' => __('Enabled (written to the PHP error log)', 'twitter-tools'),
+ ),
+ ),
+ );
+ self::$settings = apply_filters('aktt_default_settings', $settings);
+ }
+
+
+ /**
+ * Append a message of a certain type to the admin notices.
+ *
+ * @param string $msg
+ * @param string $type
+ * @return void
+ */
+ static function add_admin_notice($msg, $type = 'updated') {
+ self::$admin_notices[] = array(
+ 'type' => $type == 'error' ? $type : 'updated', // If it's not an error, set it to updated
+ 'msg' => $msg
+ );
+ }
+
+
+ /**
+ * Displays admin notices
+ *
+ * @return void
+ */
+ static function admin_notices() {
+ if (is_array(self::$admin_notices)) {
+ foreach (self::$admin_notices as $notice) {
+ extract($notice);
+ ?>
+
+ array(
+ 'name' => __('Tweets', 'twitter-tools'),
+ 'singular_name' => __('Tweet', 'twitter-tools')
+ ),
+ 'supports' => array(
+ 'editor',
+ 'thumbnail',
+ ),
+ 'public' => (bool) self::option('tweet_visibility'),
+ 'show_ui' => (bool) self::option('tweet_admin_ui'),
+ 'rewrite' => array(
+ 'slug' => 'tweets',
+ 'with_front' => false
+ ),
+ 'has_archive' => true,
+ ));
+ }
+
+
+ /**
+ * Register our taxonomies.
+ *
+ * @return void
+ */
+ static function register_taxonomies() {
+ $defaults = array(
+ 'public' => (bool) self::option('tweet_visibility'),
+ 'show_ui' => (bool) self::option('tweet_admin_ui'),
+ );
+ $taxonomies = array(
+ 'aktt_accounts' => array_merge($defaults, array(
+ 'labels' => array(
+ 'name' => __('Accounts', 'twitter-tools'),
+ 'singular_name' => __('Account', 'twitter-tools')
+ ),
+ 'rewrite' => array(
+ 'slug' => 'tweet-accounts',
+ 'with_front' => false
+ ),
+ )),
+ 'aktt_mentions' => array_merge($defaults, array(
+ 'labels' => array(
+ 'name' => __('Mentions', 'twitter-tools'),
+ 'singular_name' => __('Mention', 'twitter-tools')
+ ),
+ 'rewrite' => array(
+ 'slug' => 'tweet-mentions',
+ 'with_front' => false
+ ),
+ )),
+ 'aktt_hashtags' => array_merge($defaults, array(
+ 'labels' => array(
+ 'name' => __('Hashtags', 'twitter-tools'),
+ 'singular_name' => __('Hashtag', 'twitter-tools')
+ ),
+ 'rewrite' => array(
+ 'slug' => 'tweet-hashtags',
+ 'with_front' => false
+ ),
+ )),
+ 'aktt_types' => array_merge($defaults, array(
+ 'labels' => array(
+ 'name' => __('Types', 'twitter-tools'),
+ 'singular_name' => __('Type', 'twitter-tools')
+ ),
+ 'rewrite' => array(
+ 'slug' => 'tweet-types',
+ 'with_front' => false
+ ),
+ 'public' => false,
+ 'show_ui' => false,
+ )),
+ );
+ foreach ($taxonomies as $tax => $args) {
+ register_taxonomy($tax, self::$post_type, $args);
+ }
+ }
+
+
+ /**
+ * Get or update an option from the DB, and fall back to the default setting
+ *
+ * @param string $setting
+ * @return mixed
+ */
+ static function option($key, $value = null) {
+ // Do we have an option?
+ $option = get_option('aktt_v3_settings');
+ if (!is_null($value)) {
+ $option[$key] = $value;
+ return update_option('aktt_v3_settings', $option);
+ }
+ if (!empty($option) && is_array($option) && isset($option[$key])) {
+ $val = $option[$key];
+ }
+ else { // Get a default
+ $val = isset(self::$settings[$key]) ? self::$settings[$key]['value'] : null;
+ }
+ return apply_filters('aktt_get_option', $val, $key);
+ }
+
+
+ /**
+ * Utility function to get tweets (used by shortcode, widget, etc.)
+ *
+ * @param array $args
+ * @return array
+ */
+ static function get_tweets($args) {
+ $defaults = array(
+ 'account' => array(),
+ 'id' => null,
+ 'count' => 5,
+ 'offset' => 0,
+ 'mentions' => array(),
+ 'hashtags' => array(),
+ 'include_rts' => 0,
+ 'include_replies' => 0,
+ );
+ $taxonomies = array(
+ 'aktt_accounts' => array(
+ 'var' => 'account',
+ 'strip' => array()
+ ),
+ 'aktt_hashtags' => array(
+ 'var' => 'hashtags',
+ 'strip' => array('#')
+ ),
+ 'aktt_mentions' => array(
+ 'var' => 'mentions',
+ 'strip' => array('@')
+ )
+ );
+ foreach ($taxonomies as $data) {
+ $tax = $data['var'];
+ $strip = $data['strip'];
+ if (isset($args[$tax])) {
+ $terms = array();
+ foreach(explode(',', $args[$tax]) as $term) {
+ $term = trim(str_replace($strip, '', $term));
+ if (!empty($term)) {
+ $terms[] = $term;
+ }
+ }
+ $args[$tax] = $terms;
+ }
+ }
+ $params = array_merge($defaults, $args);
+ $query_data = array(
+ 'post_type' => 'aktt_tweet',
+ 'posts_per_page' => $params['count'],
+ 'offset' => $params['offset'],
+ );
+// set tweet ID
+ if (!empty($params['id'])) {
+ $query_data['meta_query'] = array(array(
+ 'key' => '_aktt_tweet_id',
+ 'value' => $params['id'],
+ 'compare' => '='
+ ));
+ }
+ else {
+// process tax data
+ $tax_query = array(
+ 'relation' => 'AND'
+ );
+// set accounts, mentions, hashtags
+ foreach ($taxonomies as $tax => $data) {
+ $var = $data['var'];
+ if (isset($params[$var]) && count($params[$var])) {
+ $query = array(
+ 'taxonomy' => $tax,
+ 'field' => 'slug',
+ 'terms' => array()
+ );
+ foreach ($params[$var] as $term) {
+ $query['terms'][] = $term;
+ }
+ $tax_query[] = $query;
+ }
+ }
+// always hide broadcasts - can be overridden with filter below
+ $type_terms = array(
+ 'social-broadcast'
+ );
+// other exclusions - this is a NOT IN query
+ if (!$params['include_rts']) {
+ $type_terms[] = 'retweet';
+ }
+ if (!$params['include_replies']) {
+ $type_terms[] = 'reply';
+ }
+ $tax_query[] = array(
+ 'taxonomy' => 'aktt_types',
+ 'field' => 'slug',
+ 'terms' => $type_terms,
+ 'operator' => 'NOT IN'
+ );
+ $query_data['tax_query'] = $tax_query;
+ }
+ $query = new WP_Query(apply_filters('aktt_get_tweets', $query_data));
+ return $query->posts;
+ }
+
+ /**
+ * Attach tweet data to post and replace entities in the post content
+ *
+ * @param stdClass $post
+ * @return stdClass
+ */
+ static function the_post($post) {
+ if ($post->post_type == self::$post_type && empty($post->tweet)) {
+ if ($raw_data = get_post_meta($post->ID, '_aktt_tweet_raw_data', true)) {
+ $post->tweet = new AKTT_Tweet(json_decode($raw_data));
+ $post->post_content = $post->tweet->link_entities();
+ }
+ if (has_post_thumbnail($post->ID)) {
+ $size = apply_filters('aktt_featured_image_size', 'medium');
+ $post->post_content .= "\n\n".get_the_post_thumbnail(null, $size);
+ }
+ }
+ return $post;
+ }
+
+ /**
+ * Attach tweet data to posts
+ *
+ * @param array $posts
+ * @return array
+ */
+ static function the_posts($posts) {
+ foreach ($posts as &$post) {
+ AKTT::the_post($post);
+ }
+ return $posts;
+ }
+
+ /**
+ * Prepends a "settings" link for our plugin on the plugins.php page
+ *
+ * @param array $links
+ * @param string $file -- filename of plugin
+ * @return array
+ */
+ function plugin_action_links($links, $file) {
+ if (basename($file) == basename(AKTT_FILE)) {
+ $settings_link = ''.__('Settings', 'twitter-tools').'';
+ array_unshift($links, $settings_link);
+ }
+ return $links;
+ }
+
+
+ /**
+ * Adds a link to the "Settings" menu in WP-Admin.
+ */
+ public function admin_menu() {
+ add_options_page(
+ __('Twitter Tools Options', 'twitter-tools'),
+ __('Twitter Tools', 'twitter-tools'),
+ self::$cap_options,
+ self::$menu_page_slug,
+ array('AKTT', 'settings_page')
+ );
+ }
+
+ static function maybe_create_db_index($col, $key_name = null, $table_name = null) {
+ global $wpdb;
+ if (empty($key_name)) {
+ $key_name = $col;
+ }
+ if (empty($table_name)) {
+ $table_name = $wpdb->posts;
+ }
+ // Add a GUID index if none exists
+ $results = $wpdb->get_results($wpdb->prepare("
+ SHOW INDEX
+ FROM $table_name
+ WHERE KEY_NAME = '%s'
+ ", $key_name));
+ if (!count($results)) {
+ $wpdb->query("
+ ALTER TABLE $table_name
+ ADD INDEX ($col)
+ "); // can's use $wpdb->prepare here
+ }
+ }
+
+ /**
+ * Initializes the plugin settings in WP admin, using the Settings API
+ *
+ * @return void
+ */
+ static function init_settings() {
+
+ // Register our parent setting (it contains an array of all our plugin-wide settings)
+ register_setting(
+ self::$menu_page_slug, // Page it belongs to
+ 'aktt_v3_settings', // option name
+ array('AKTT', 'sanitize_plugin_settings') // Sanitize callback
+ );
+
+ // Register our account settings
+ register_setting(
+ self::$menu_page_slug, // Page it belongs to
+ 'aktt_v3_accounts', // option name
+ array('AKTT', 'sanitize_account_settings') // Sanitize callback
+ );
+
+ }
+
+
+ /**
+ * Sanitization of values
+ *
+ * @param mixed $value
+ * @return int
+ */
+ static function sanitize_plugin_settings($value) {
+ self::maybe_create_db_index('guid');
+ flush_rewrite_rules(false);
+ if (is_array($value)) {
+ foreach ($value as $k => $v) {
+ $value[$k] = self::sanitize_plugin_setting($k, $v);
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * Sanitizes the ACCOUNT settings from the Twitter Tools' admin page.
+ *
+ * ** Option Storage Format **
+ *
+ * $option_value = array(
+ * $this->id => array(
+ * 'settings' => array(
+ * 'post_author' => 0,
+ * 'post_cats' => array(),
+ * 'post_tags' => array(),
+ * 'hashtag' => '',
+ * ),
+ * ),
+ * );
+ *
+ * @param array $value
+ * @return array
+ */
+ static function sanitize_account_settings($value) {
+ if (is_array($value)) {
+ foreach ($value as $id => &$acct) {
+ // If we don't have a settings array, get rid of it
+ if (!isset($acct['settings'])) {
+ unset($value[$id]);
+ continue;
+ }
+
+ // Loop over each setting and sanitize
+ foreach (array_keys(AKTT_Account::$settings) as $key) {
+ if (!isset($acct['settings'][$key])) {
+ $acct['settings'][$key] = null;
+ }
+ $acct['settings'][$key] = self::sanitize_account_setting($key, $acct['settings'][$key]);
+ }
+ }
+ }
+ else {
+ $value = null;
+ }
+ return $value;
+ }
+
+
+ static function sanitize_plugin_setting($key, $value) {
+ return self::sanitize_setting($key, $value, self::$settings[$key]['type']);
+ }
+
+ static function sanitize_account_setting($key, $value) {
+ return self::sanitize_setting($key, $value, AKTT_Account::$settings[$key]['type']);
+ }
+
+
+ /**
+ * Sanitizes a setting, based on a big switch statement
+ * that has each setting, and how to clean it.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @param string $type - type of setting (int, etc.)
+ * @return mixed - Clean value **If it matched a switch case**
+ */
+ static function sanitize_setting($key, $value, $type) {
+ switch ($type) {
+ case 'int':
+ $value = is_array($value) ? array_map('intval', $value) : intval($value);
+ break;
+ case 'no_html':
+ $value = is_array($value) ? array_map('wp_filter_nohtml_kses', $value) : wp_filter_nohtml_kses($value);
+ break;
+ case 'tags':
+ $value = trim($value);
+ if (!empty($value)) {
+ $tags_clean = array();
+ $tags_input = array_map('trim', explode(',', $value));
+ foreach ($tags_input as $tag) {
+ if (!empty($tag)) {
+ $tags_clean[] = $tag;
+ if (!get_term_by('name', $tag, 'post_tag')) {
+ wp_insert_term($tag, 'post_tag');
+ }
+ }
+ }
+ unset($tags_input);
+ $value = implode(', ', $tags_clean);
+ }
+ break;
+ case 'is_cat':
+ $term = get_term_by('id', $value, 'category');
+ $value = (!$term) ? 0 : $term->term_id;
+ break;
+ default:
+ $value = apply_filters('aktt_sanitize_setting', $value, $key, $type);
+ }
+ return $value;
+ }
+
+
+ /**
+ * Outputs the plugin's settings form. Utilizes the "settings" API in WP
+ *
+ * @return void
+ */
+ static function settings_page() {
+ global $wpdb;
+ $wpdb->aktt = $wpdb->prefix.'ak_twitter';
+ $upgrade_needed = in_array($wpdb->aktt, $wpdb->get_col("
+ SHOW TABLES
+ "));
+ if ($upgrade_needed) {
+ $upgrade_col = false;
+ $cols = $wpdb->get_results("
+ DESCRIBE $wpdb->aktt
+ ");
+ foreach ($cols as $col) {
+ if ($col->Field == 'upgrade_30') {
+ $upgrade_col = true;
+ break;
+ }
+ }
+ if ($upgrade_col) {
+ $upgrade_needed = (bool) $wpdb->get_var("
+ SELECT COUNT(*)
+ FROM $wpdb->aktt
+ WHERE upgrade_30 = 0
+ ");
+ }
+ }
+// check to see if CRON for backfilling data is scheduled
+ if (wp_next_scheduled('aktt_backfill_tweets') === false) {
+// check to see if it should be
+ $query = new WP_Query(array(
+ 'post_type' => AKTT::$post_type,
+ 'posts_per_page' => 10,
+ 'meta_key' => '_aktt_30_backfill_needed',
+ ));
+ if (count($query->posts)) {
+// schedule
+ wp_schedule_event(time() + 900, 'hourly', 'aktt_backfill_tweets');
+ }
+ unset($query);
+ }
+ self::get_social_accounts();
+ include(AKTT_PATH.'/views/admin.php');
+ }
+
+
+ /**
+ * Returns the nonce'd URL for manually kicking off updates
+ *
+ * @return string
+ */
+ static function get_manual_update_url() {
+ $url = add_query_arg(array('aktt_action' => 'manual_tweet_download'), admin_url('index.php'));
+ return wp_nonce_url($url, 'manual_tweet_download');
+ }
+
+
+ /**
+ * Loads the social twitter accounts into a static variable
+ *
+ * @return void
+ */
+ static function get_social_accounts() {
+ $social_twitter = Social::instance()->service('twitter');
+
+ // If we don't have a Social_Twitter object, get out
+ if (is_null($social_twitter)) {
+ return;
+ }
+
+ // If we don't have any Social Twitter accounts, get out
+ $social_accounts = $social_twitter->accounts();
+ if (empty($social_accounts)) {
+ return;
+ }
+
+ /* Loop over our social twitter accounts and create AKTT_Account objects
+ that will store the various configuration options for the twitter accounts. */
+ foreach ($social_accounts as $obj_id => $acct_obj) {
+ // If this account has already been assigned, continue on
+ if (isset(self::$accounts[$obj_id]) || !$acct_obj->universal()) {
+ continue;
+ }
+
+ /* Call a static method to load the object, so we
+ can ensure it was instantiated properly */
+ $o = AKTT_Account::load($acct_obj);
+
+ // Assign the object, only if we were successfully created
+ if (is_a($o, 'AKTT_Account')) {
+ self::$accounts[$obj_id] = $o;
+ }
+ }
+ }
+
+ /**
+ * Return the first account from the list, at random.
+ *
+ * @return mixed AKTT_Account object|bool
+ */
+ static function default_account() {
+ self::get_social_accounts();
+ if (count(self::$accounts)) {
+ foreach (self::$accounts as $account) {
+ if ($account->option('enabled')) {
+ return $account;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove an account when it is removed from Social
+ *
+ * @return void
+ */
+ static function social_account_disconnected($service, $id) {
+ if ($service == 'twitter') {
+ $accounts = get_option('aktt_v3_accounts');
+ if (is_array($accounts) && count($accounts) && isset($accounts[$id])) {
+ $account = Social::instance()->service('twitter')->account($id);
+ // If the account being removed was only a universal account, it will no longer
+ // be available (false). If it is still around as a personal account (but is not
+ // a universal account), then the !universal() check will handle that.
+ if ($account === false or !$account->universal()) {
+ unset($accounts[$id]);
+ update_option('aktt_v3_accounts', $accounts);
+ }
+ }
+ }
+ }
+
+ /**
+ * Iterates over all the twitter accounts in social and downloads and imports the tweets.
+ *
+ * @return void
+ */
+ function import_tweets() {
+ // load our accounts
+ self::get_social_accounts();
+
+ // See if we have any accounts to loop over
+ if (!is_array(self::$accounts) || empty(self::$accounts)) {
+ return;
+ }
+
+ // iterate over each account and download the tweets
+ foreach (self::$accounts as $id => $acct) {
+ // Download the tweets for that acct
+ if ($acct->option('enabled')) {
+ // could time out with lots of accounts, so a new request for each
+ $url = home_url('index.php').'?'.http_build_query(array(
+ 'aktt_action' => 'download_account_tweets',
+ 'acct_id' => $id,
+ 'social_api_key' => Social::option('system_cron_api_key')
+ ), null, '&');
+ self::log('Downloading tweets for '.$acct->social_acct->name().': '.$url);
+ wp_remote_get(
+ $url,
+ array(
+ 'timeout' => 0.01,
+ 'blocking' => false,
+ 'sslverify' => apply_filters('https_local_ssl_verify', true),
+ )
+ );
+ }
+ }
+ }
+
+
+ /**
+ * Find 10 tweets, backfill the data from Twitter
+ *
+ * @param int $count
+ * @return bool
+ */
+ function backfill_tweets($count = 10) {
+ self::log('#### Backfilling tweets ####');
+ $query = new WP_Query(array(
+ 'post_type' => AKTT::$post_type,
+ 'posts_per_page' => 10,
+ 'meta_key' => '_aktt_30_backfill_needed',
+ ));
+ if (!count($query->posts)) {
+ if (($timestamp = wp_next_scheduled('aktt_backfill_tweets')) !== false) {
+ wp_unschedule_event($timestamp, 'aktt_backfill_tweets');
+ }
+ return false;
+ }
+ foreach ($query->posts as $post) {
+ $tweet_id = get_post_meta($post->ID, '_aktt_tweet_id', true);
+ if (empty($tweet_id)) {
+ continue;
+ }
+ $url = home_url('index.php').'?'.http_build_query(array(
+ 'aktt_action' => 'backfill_tweet_data',
+ 'tweet_id' => $tweet_id,
+ 'social_api_key' => Social::option('system_cron_api_key')
+ ), null, '&');
+ self::log('Backfilling tweet '.$tweet_id.' '.$url);
+ wp_remote_get(
+ $url,
+ array(
+ 'timeout' => 0.01,
+ 'blocking' => false,
+ 'sslverify' => apply_filters('https_local_ssl_verify', true),
+ )
+ );
+ }
+ return true;
+ }
+
+ /**
+ * Create tweet when Social does a broadcast
+ *
+ * @param Social_Response $response
+ * @param string $key
+ * @param stdClass $post
+ * @return void
+ */
+ static function social_broadcast_response($response, $key, $post) {
+// get tweet
+ $data = $response->body();
+ $tweet = $data->response;
+// check if it's one of our enabled accounts
+ self::get_social_accounts();
+ foreach (self::$accounts as $account) {
+ if ($account->option('enabled') && $account->social_acct->id() == $tweet->user->id) {
+// populate AKTT_Tweet object, save
+ $t = new AKTT_Tweet($tweet);
+ $t->add();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Check for auth against Social's api key
+ *
+ * @return book
+ */
+ static function social_key_auth() {
+ return (bool) (!empty($_GET['social_api_key']) && stripslashes($_GET['social_api_key']) == Social::option('system_cron_api_key'));
+ }
+
+
+ /**
+ * Request handler
+ *
+ * @return void
+ */
+ function controller(){
+ if (isset($_GET['aktt_action'])) {
+ switch ($_GET['aktt_action']) {
+ case 'download_account_tweets':
+ if (empty($_GET['acct_id']) || !AKTT::social_key_auth()) {
+ wp_die(__('Sorry, try again.', 'twitter-tools'));
+ }
+ $acct_id = intval($_GET['acct_id']);
+ self::get_social_accounts();
+ if (isset(self::$accounts[$acct_id])) {
+ if ($tweets = self::$accounts[$acct_id]->download_tweets()) {
+ self::$accounts[$acct_id]->save_tweets($tweets);
+ }
+ }
+ die();
+ break;
+ case 'import_tweet':
+// check for status_id && auth key
+ if (empty($_GET['tweet_id']) || !AKTT::social_key_auth()) {
+ wp_die(__('Sorry, try again.', 'twitter-tools'));
+ }
+// check for account_name
+ $username = (!empty($_GET['username']) ? stripslashes($_GET['username']) : null);
+// download tweet
+ $tweet = self::download_tweet($_GET['tweet_id'], $username);
+ if (!is_a($tweet, 'stdClass')) {
+ wp_die('Failed to download tweet.');
+ }
+// store tweet
+ $t = new AKTT_Tweet($tweet);
+ if (!$t->exists_by_guid()) {
+ $t->add();
+ }
+ die();
+ break;
+ case 'backfill_tweet_data':
+ if (empty($_GET['tweet_id']) || !AKTT::social_key_auth()) {
+ wp_die(__('Sorry, try again.', 'twitter-tools'));
+ }
+ $t = new AKTT_Tweet(stripslashes($_GET['tweet_id']));
+ if (!$t->get_post()) {
+ die();
+ }
+ $usernames = wp_get_object_terms($t->post->ID, 'aktt_accounts');
+ $username = $usernames[0]->slug;
+
+ $tweet = self::download_tweet($_GET['tweet_id'], $username);
+
+ if (!is_a($tweet, 'stdClass')) {
+ wp_die('Failed to download tweet');
+ }
+ $t->update_twitter_data($tweet);
+ die();
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Request handler for admin
+ *
+ * @return void
+ */
+ function admin_controller(){
+ if (isset($_GET['aktt_action'])) {
+ switch ($_GET['aktt_action']) {
+ case 'manual_tweet_download':
+ // Permission & nonce checking
+ if (!check_admin_referer('manual_tweet_download') || !current_user_can(self::$cap_download)) {
+ wp_die(__('Sorry, try again.', 'twitter-tools'));
+ }
+
+ self::import_tweets();
+ echo json_encode(array(
+ 'result' => 'success',
+ 'msg' => __('Tweets are downloading…', 'twitter-tools')
+ ));
+ die();
+ break;
+ case 'upgrade-3.0':
+ // Permission checking
+ if (!current_user_can(self::$cap_options)) {
+ wp_die(__('Sorry, try again.', 'twitter-tools'));
+ }
+ include(AKTT_PATH.'/upgrade/3.0.php');
+ aktt_upgrade_30();
+ die();
+ break;
+ case 'upgrade-3.0-run':
+ // Permission checking
+ if (!current_user_can(self::$cap_options) || !wp_verify_nonce($_GET['nonce'], 'upgrade-3.0-run')) {
+ header('Content-type: application/json');
+ echo json_encode(array(
+ 'result' => 'error',
+ 'message' => __('Sorry, try again.', 'twitter-tools')
+ ));
+ die();
+ }
+ include(AKTT_PATH.'/upgrade/3.0.php');
+ $to_upgrade = aktt_upgrade_30_run();
+ header('Content-type: application/json');
+ echo json_encode(array(
+ 'result' => 'success',
+ 'to_upgrade' => $to_upgrade
+ ));
+ die();
+ break;
+ case 'tweets_updated':
+ self::add_admin_notice(__('Tweets are downloading...', 'twitter-tools'));
+ break;
+ }
+ }
+ }
+
+
+ /**
+ * Load JS resources necessary for admin... only on the twitter tools' settings page
+ *
+ * @param string $hook_suffix
+ * @return void
+ */
+ function admin_enqueue_scripts($hook_suffix) {
+ add_action('admin_footer', array('AKTT', 'admin_js'));
+ if ($hook_suffix == 'settings_page_twitter-tools') {
+ wp_enqueue_script('suggest');
+ add_action('admin_footer', array('AKTT', 'admin_js_suggest'));
+ }
+ }
+
+
+ /**
+ * Output the admin-side JavaScript
+ *
+ * @return void
+ */
+ static function admin_js() {
+?>
+
+
+
+'.esc_html(self::profile_prefix($username)).'';
+ }
+
+ static function profile_prefix($username, $prefix = '@') {
+ if (AKTT::substr($username, 0, 1) != '#') {
+ $username = '@'.$username;
+ }
+ return $username;
+ }
+
+ static function hashtag_url($hashtag) {
+ $hashtag = self::hashtag_prefix($hashtag);
+ return 'http://twitter.com/search?q='.urlencode($hashtag);
+ }
+
+ static function hashtag_link($hashtag) {
+ $hashtag = self::hashtag_prefix($hashtag);
+ return ''.esc_html($hashtag).'';
+ }
+
+ static function hashtag_prefix($hashtag, $prefix = '#') {
+ if (AKTT::substr($hashtag, 0, 1) != '#') {
+ $hashtag = '#'.$hashtag;
+ }
+ return $hashtag;
+ }
+
+ static function status_url($username, $id) {
+ return 'http://twitter.com/'.urlencode($username).'/status/'.urlencode($id);
+ }
+
+ static function download_tweet($status_id, $username = null) {
+ if (empty(AKTT::$accounts)) {
+ return false;
+ }
+ $account_found = $tweet = false;
+ if (!empty($username)) {
+ AKTT::get_social_accounts();
+ foreach (AKTT::$accounts as $id => $account) {
+ if ($username == $account->social_acct->name()) {
+ // proper account stored as $account
+ $account_found = true;
+ break;
+ }
+ }
+ if (!$account_found) {
+ $account = AKTT::$accounts[0]; // use any account
+ }
+ $response = Social::instance()->service('twitter')->request(
+ $account->social_acct,
+ 'statuses/show/'.urlencode($t->id).'.json',
+ array(
+ 'include_entities' => 1, // include explicit hashtags and mentions
+ 'include_rts' => 1, // include retweets
+ )
+ );
+ $content = $response->body();
+ if ($content->result == 'success') {
+ $tweets = $content->response;
+ if (!$tweets || !is_array($tweets) || count($tweets) != 1) {
+ $tweet = $tweet[0];
+ }
+ }
+ }
+ return $tweet;
+ }
+
+ static function gmt_to_wp_time($gmt_time) {
+ $timezone_string = get_option('timezone_string');
+ if (!empty($timezone_string)) {
+ // Not using get_option('gmt_offset') because it gets the offset for the
+ // current date/time which doesn't work for timezones with daylight savings time.
+ $gmt_date = date('Y-m-d H:i:s', $gmt_time);
+ $datetime = new DateTime($gmt_date);
+ $datetime->setTimezone(new DateTimeZone(get_option('timezone_string')));
+ $offset_in_secs = $datetime->getOffset();
+
+ return $gmt_time + $offset_in_secs;
+ }
+ else {
+ return $gmt_time + (get_option('gmt_offset') * 3600);
+ }
+ }
+
+ static function substr_replace($string, $replacement, $start, $length = null, $encoding = null) {
+ // from http://www.php.net/manual/en/function.substr-replace.php#90146
+ // via https://github.com/ruanyf/wp-twitter-tools/commit/56d1a4497483b2b39f434fdfab4797d8574088e5
+ if (extension_loaded('mbstring') === true) {
+ $string_length = (is_null($encoding) === true) ? mb_strlen($string) : mb_strlen($string, $encoding);
+
+ if ($start < 0) {
+ $start = max(0, $string_length + $start);
+ }
+ else if ($start > $string_length) {
+ $start = $string_length;
+ }
+ if ($length < 0) {
+ $length = max(0, $string_length - $start + $length);
+ }
+ else if ((is_null($length) === true) || ($length > $string_length)) {
+ $length = $string_length;
+ }
+ if (($start + $length) > $string_length) {
+ $length = $string_length - $start;
+ }
+ if (is_null($encoding) === true) {
+ return mb_substr($string, 0, $start) . $replacement
+ . mb_substr($string, $start + $length, $string_length - $start - $length);
+ }
+ return mb_substr($string, 0, $start, $encoding) . $replacement
+ . mb_substr($string, $start + $length, $string_length - $start - $length, $encoding);
+ }
+ else {
+ return (is_null($length) === true) ? substr_replace($string, $replacement, $start) : substr_replace($string, $replacement, $start, $length);
+ }
+ }
+
+ static function strlen($str, $encoding = null) {
+ if (function_exists('mb_strlen')) {
+ if (is_null($encoding) === true) {
+ return mb_strlen($str);
+ }
+ else {
+ return mb_strlen($str, $encoding);
+ }
+ }
+ else {
+ return strlen($str);
+ }
+ }
+
+ static function substr($str, $start, $length) {
+ if (function_exists('mb_substr')) {
+ return mb_substr($str, $start, $length);
+ }
+ else {
+ return substr($str, $start, $length);
+ }
+ }
+
+}
+
+