0.3
@@ -1,3 +0,0 @@
-[submodule "lib/acTwitterConversation"] - path = lib/acTwitterConversation - url = https://github.com/adriancrepaz/acTwitterConversation.git
@@ -141,7 +141,6 @@ * COMMENTS
*/ function get_comments ( &$post_id, &$silo_id ) { $baseurl = sprintf("https://api.500px.com/v1/photos/%s/comments", $silo_id); - $results = $this->request ( $baseurl, 'comments' ); if ($results && is_array($results) && !empty($results)) { $auto = ( $this->get_option( 'auto_approve' ) == 1 ) ? 1 : 0;@@ -172,6 +171,31 @@
$this->insert_comment ( $post_id, $c, $element, $avatar ); } + } + + + // temporarily hack + $baseurl = sprintf( "https://api.500px.com/v1/photos/%s?", $silo_id ); + $params = array( + 'comments' => 1, + ); + $starturl = $baseurl . http_build_query( $params ); + $result = $this->request ( $starturl, 'photo' ); + + if ($result && is_array($result) && !empty($result)) { + $geo = array ( + 16 => 'geo_latitude', + 17 => 'geo_longitude' + ); + + foreach ($geo as $check => $meta_key ) { + if ( isset($result[$check]) && !empty($result[$check])) { + update_post_meta ($post_id, $meta_key, $result[$check]); + Keyring_Util::debug(sprintf(__('adding geo data for %s','keyring'), $post_id)); + } + } + + } }
@@ -79,13 +79,13 @@ if ($results && is_array($results) && !empty($results)) {
$auto = ( $this->get_option( 'auto_approve' ) == 1 ) ? 1 : 0; $type = $this->methods[ 'likes' ]; + $tpl = __( '<a href="%s" rel="nofollow">%s</a> liked this entry on <a href="https://facebook.com" rel="nofollow">facebook</a>','keyring'); foreach ( $results as $element ) { $avatar = sprintf('https://graph.facebook.com/%s/picture', $element->id ); $author_url = 'https://facebook.com/' . $element->id; $name = $element->name; - $tpl = __( '<a href="%s" rel="nofollow">%s</a> liked this entry on <a href="https://facebook.com" rel="nofollow">facebook</a>','keyring'); $c = array ( 'comment_author' => $name,
@@ -0,0 +1,169 @@
+<?php + +function Keyring_Instagram_Reactions() { + +class Keyring_Instagram_Reactions extends Keyring_Reactions_Base { + const SLUG = 'instagram_reactions'; + const LABEL = 'Instagram - comments and likes'; + const KEYRING_SERVICE = 'Keyring_Service_Instagram'; + const KEYRING_NAME = 'instagram'; + const REQUESTS_PER_LOAD = 3; // How many remote requests should be made before reloading the page? + const NUM_PER_REQUEST = 50; // Number of images per request to ask for + + const SILONAME = 'instagram.com'; + + function __construct() { + $this->methods = array ( + // method name => comment type + 'likes' => 'like', + 'comments' => 'comment' + ); + + //$this->methods = array ('votes', 'favs', 'comments'); + parent::__construct(); + } + + function make_all_requests( $method, $post ) { + extract($post); + + if (empty($post_id)) + return new Keyring_Error( + 'keyring-instagram-reactions-missing-post-id', + __( 'Missing post ID to make request for.', 'keyring') + ); + + if (empty($syndication_url)) + return new Keyring_Error( + 'keyring-instagram-reactions-missing-syndication-url', + __( 'Missing syndication URL.', 'keyring') + ); + + // get media id here + $api = file_get_contents(sprintf('https://api.instagram.com/oembed?url=%s', $syndication_url)); + $apiObj = json_decode($api,true); + if ( !isset($apiObj['media_id']) || empty($apiObj['media_id'])) + return new Keyring_Error( + 'keyring-instagram-reactions-photo-id-not-found', + __( 'Cannot get photo ID out of syndication URL.', 'keyring' ) + ); + + $silo_id = $apiObj['media_id']; + + $func = 'get_' . $method; + if ( !method_exists( $this, $func ) ) + return new Keyring_Error( + 'keyring-instagram-reactions-missing-func', + sprintf(__( 'Function is missing for this method (%s), cannot proceed!', 'keyring'), $method) + ); + + return $this->$func ( $post_id, $silo_id ); + } + + /** + * LIKES + */ + + function get_likes ( $post_id, $silo_id ) { + $baseurl = sprintf ('https://api.instagram.com/v1/media/%s/likes?', $silo_id ); + + $params = array( + 'access_token' => $this->service->token->token, + ); + + $url = $baseurl . http_build_query( $params ); + $data = $this->service->request( $url, array( 'method' => $this->request_method, 'timeout' => 10 ) ); + + if ( Keyring_Util::is_error( $data ) ) + Keyring_Util::Debug (json_encode($data)); + + if ($data->data && is_array($data->data) && !empty($data->data)) { + + $auto = ( $this->get_option( 'auto_approve' ) == 1 ) ? 1 : 0; + $type = $this->methods[ 'likes' ]; + $tpl = __( '<a href="%s" rel="nofollow">%s</a> liked this entry on <a href="https://instagram.com" rel="nofollow">instagram</a>','keyring'); + + foreach ( $data->data as $element ) { + + $name = empty($element->full_name) ? $element->username : $element->full_name; + $email = $element->username .'@'. self::SILONAME; + $avatar = empty ($element->profile_picture) ? '' : $element->profile_picture; + $author_url = 'https://instagram.com/' . $element->username; + + $c = array ( + 'comment_author' => $name, + 'comment_author_url' => $author_url, + 'comment_author_email' => $email, + 'comment_post_ID' => $post_id, + 'comment_type' => $type, + //'comment_date' => date("Y-m-d H:i:s", $element->favedate ), + //'comment_date_gmt' => date("Y-m-d H:i:s", $element->favedate ), + 'comment_agent' => get_class($this), + 'comment_approved' => $auto, + 'comment_content' => sprintf( $tpl, $author_url, $name ), + ); + + $this->insert_comment ( $post_id, $c, $element, $avatar); + } + } + } + + /** + * COMMENTS + */ + + function get_comments ( $post_id, $silo_id ) { + $baseurl = sprintf ('https://api.instagram.com/v1/media/%s/comments?', $silo_id ); + + $params = array( + 'access_token' => $this->service->token->token, + ); + + $url = $baseurl . http_build_query( $params ); + $data = $this->service->request( $url, array( 'method' => $this->request_method, 'timeout' => 10 ) ); + + if ( Keyring_Util::is_error( $data ) ) + Keyring_Util::Debug (json_encode($data)); + + + if ($data->data && is_array($data->data) && !empty($data->data)) { + + $auto = ( $this->get_option( 'auto_approve' ) == 1 ) ? 1 : 0; + $type = $this->methods[ 'comments' ]; + + foreach ( $data->data as $element ) { + + $name = empty($element->from->full_name) ? $element->from->username : $element->from->full_name; + $email = $element->from->username .'@'. self::SILONAME; + $avatar = empty ($element->from->profile_picture) ? '' : $element->from->profile_picture; + $author_url = 'https://instagram.com/' . $element->from->username; + + $c = array ( + 'comment_author' => $name, + 'comment_author_url' => $author_url, + 'comment_author_email' => $email, + 'comment_post_ID' => $post_id, + 'comment_type' => $type, + 'comment_date' => date("Y-m-d H:i:s", $element->created_time ), + 'comment_date_gmt' => date("Y-m-d H:i:s", $element->created_time ), + 'comment_agent' => get_class($this), + 'comment_approved' => $auto, + 'comment_content' => $element->text + ); + + $this->insert_comment ( $post_id, $c, $element, $avatar); + } + } + } + +}} + + +add_action( 'init', function() { + Keyring_Instagram_Reactions(); // Load the class code from above + keyring_register_reactions( + Keyring_Instagram_Reactions::SLUG, + 'Keyring_Instagram_Reactions', + plugin_basename( __FILE__ ), + __( 'Import comments and likes from Instagram for your syndicated posts.', 'keyring' ) + ); +} );
@@ -51,6 +51,7 @@ const LABEL = ''; // the line that will show up in Import page
const KEYRING_NAME = ''; // Keyring service name; SLUG is not used to avoid conflict with Keyring Social Importer const KEYRING_SERVICE = ''; // Full class name of the Keyring_Service this importer requires const REQUESTS_PER_LOAD = 3; // How many posts should queried before moving over to the next branch / reload the page + const REQUESTS_PER_AUTO = 16; const KEYRING_VERSION = '1.4'; // Minimum version of Keyring required const SILONAME = ''; // identifier for the silo in the syndication_url field entry@@ -60,7 +61,7 @@ const OPTNAME_POSTS = 'posts'; // option key for posts array
const SCHEDULE = 'daily'; // this may break many things, careful if you wish to change it const SCHEDULETIME = 36400; // in tandem with the previous - const RESCHEDULE = 30; + const RESCHEDULE = 60; // You shouldn't need to edit (or override) these ones var $step = 'greet';@@ -100,11 +101,14 @@
// additional comment types add_action('admin_comment_types_dropdown', array(&$this, 'comment_types_dropdown')); + // ... + add_filter('get_avatar_comment_types', array( &$this, 'add_comment_types')); + // additional cron schedules add_filter( 'cron_schedules', array(&$this, 'cron' )); // additional avatar filter - add_filter( 'get_avatar' , 'Keyring_Reactions_Base::get_avatar' , 1 , 5 ); + add_filter( 'get_avatar' , array(&$this, 'get_avatar'), 1, 5 ); // If a request is made for a new connection, pass it off to Keyring if (@@ -127,11 +131,6 @@ $this->service = call_user_func( array( static::KEYRING_SERVICE, 'init' ) );
$this->service->set_token( $token ); } - // Make sure we have a scheduled job to handle auto-imports if enabled - // but delay it for good reasons - if ( $this->get_option( 'auto_import' ) && !wp_get_schedule( $this->schedule ) ) - wp_schedule_event( time() + static::SCHEDULETIME, static::SCHEDULE, $this->schedule ); - // jump to the first worker $this->handle_request(); }@@ -167,6 +166,17 @@ return $types;
} /** + * + */ + public function add_comment_types ( $types ) { + foreach ($this->methods as $method => $type ) { + if (!in_array( $type, $types )) + array_push( $types, $type ); + } + return $types; + } + + /** * add our own, ridiculously intense schedule for chanining all the requests * wee need for the imports *@@ -175,12 +185,14 @@ *
* @return array the filtered WP CRON schedules */ public function cron ( $schedules ) { + /* if (!isset($schedules[ $this->optname ])) { $schedules[ $this->optname ] = array( 'interval' => static::RESCHEDULE, 'display' => sprintf(__( '%s auto import' ), static::SLUG ) ); } + */ return $schedules; }@@ -208,6 +220,7 @@ $safe_alt = '';
else $safe_alt = esc_attr($alt); + return sprintf( '<img alt="%s" src="%s" class="avatar photo u-photo" style="width: %spx; height: %spx;" />', $safe_alt, $c_avatar, $size, $size ); }@@ -217,13 +230,31 @@ * You'll need to validate/santize things, and probably store options in the DB. When you're
* done, set $this->step = 'import' to continue, or 'options' to show the options form again. */ protected function handle_request_options() { - $bools = array('auto_import','auto_approve'); + $auto_import = (isset( $_POST['auto_import']) && !empty($_POST['auto_import'])) ? true : false; + + $auto_approve = (isset( $_POST['auto_approve']) && !empty($_POST['auto_approve'])) ? true : false; + + /* + if ( $this->get_option('auto_import') && !wp_get_schedule( $this->schedule ) ) { + wp_schedule_event( time() + static::SCHEDULETIME, static::SCHEDULE, $this->schedule ); + } + elseif ( $this->get_option('auto_import') && wp_get_schedule( $this->schedule != static::SCHEDULE ) ) { + wp_clear_scheduled_hook ( $this->schedule ); + wp_schedule_event( time() + static::SCHEDULETIME, static::SCHEDULE, $this->schedule ); + } + elseif ( !$this->get_option('auto_import') ) { + Keyring_Util::Debug('Ez most fut?'); + wp_clear_scheduled_hook ( $this->schedule ); + } + */ - foreach ( $bools as $bool ) { - if ( isset( $_POST[$bool] ) ) - $_POST[$bool] = true; - else - $_POST[$bool] = false; + wp_clear_scheduled_hook ( $this->schedule ); + + if ($auto_import) { + wp_schedule_event( time() + static::SCHEDULETIME, static::SCHEDULE, $this->schedule ); + } + else { + $this->cleanup(); } // If there were errors, output them, otherwise store options and start importing@@ -231,12 +262,12 @@ if ( count( $this->errors ) ) {
$this->step = 'greet'; } else { $this->set_option( array( - 'auto_import' => (bool) $_POST['auto_import'], - 'auto_approve' => (bool) $_POST['auto_approve'], - 'limit_posts' => sanitize_text_field($_POST['limit_posts']), + 'auto_import' => $auto_import, + 'auto_approve' => $auto_approve, + 'limit_posts' => sanitize_text_field($_POST['limit_posts']), ) ); - $this->step = 'import'; + $this->step = 'done'; } }@@ -300,7 +331,7 @@ if ( is_array( $name ) )
$this->options = array_merge( (array) $this->options, $name ); else if ( is_null( $name ) && is_null( $val ) ) { // $name = null to reset all options $this->options = array(); - wp_unschedule_event( time(), $this->schedule ); + wp_clear_scheduled_hook ( $this->schedule ); } else if ( is_null( $val ) && isset( $this->options[ $name ] ) ) unset( $this->options[ $name ] );@@ -379,9 +410,9 @@ break;
} // If we're "refreshing", then just act like it's an auto import - if ( isset( $_POST['refresh'] ) ) { - $this->auto_import = true; - } + //if ( isset( $_POST['refresh'] ) ) { + // $this->auto_import = true; + //} // Write a custom request handler in the extending class here // to handle processing/storing options for import. Make sure to@@ -414,7 +445,6 @@ switch ( $this->step ) {
case 'greet': $this->greet(); break; - case 'options': $this->options(); break;@@ -423,6 +453,7 @@ $this->do_import();
break; case 'import_single': $this->do_single_import(); + break; case 'done': $this->done(); break;@@ -738,16 +769,20 @@ * We're also not using the batch mode (X posts per page load) but instead
* one-by-one so one iteration of the WP CRON event will not take that long * and may not cause issues later on. */ - public function do_auto_import() { + public function do_auto_import( ) { defined( 'WP_IMPORTING' ) or define( 'WP_IMPORTING', true ); do_action( 'import_start' ); set_time_limit( 0 ); + Keyring_Util::debug( static::SLUG . sprintf(' auto import: init')); + // In case auto-import has been disabled, clear all jobs and bail if ( !$this->get_option( 'auto_import' ) ) { + Keyring_Util::debug( static::SLUG . sprintf(' auto import: clearing hook')); wp_clear_scheduled_hook( 'keyring_' . static::SLUG . '_import_auto' ); return; } + // Need a token to do anything with this if ( !$this->service->get_token() ) return;@@ -756,13 +791,13 @@ require_once ABSPATH . 'wp-admin/includes/import.php';
require_once ABSPATH . 'wp-admin/includes/post.php'; require_once ABSPATH . 'wp-admin/includes/comment.php'; - $this->auto_import = true; $next = 0; $position = 0; + $num = 0; $this->get_posts(); - if ( !$this->finished ) { + while ( !$this->finished && $num < static::REQUESTS_PER_AUTO ) { $position = $this->get_option( static::OPTNAME_POSTPOS, 0); if ( !is_array($this->posts) || !isset($this->posts[$position]) )@@ -772,8 +807,9 @@ __( 'The post to work with does not exist in the posts array. Something is definitely wrong.', 'keyring' )
); $todo = $this->posts[$position]; - $msg = sprintf(__('Starting auto import for #%s', 'keyring'), $todo['post_id']); - Keyring_Util::debug($msg); + Keyring_Util::debug( static::SLUG . sprintf(' auto import: doing %s/%s', $position, count($this->posts)-1 )); + //$msg = sprintf(__('Starting auto import for #%s', 'keyring'), $todo['post_id']); + //Keyring_Util::debug($msg); foreach ( $this->methods as $method => $type ) { $msg = sprintf(__('Processing %s for post #%s', 'keyring'), $method, $todo['post_id']);@@ -786,29 +822,30 @@ print $result;
} $next = $position+1; + $num++; // we're done, clean up - if ($next >= sizeof($this->posts)) { + if ( $next >= count($this->posts) ) { $this->finished = true; - $this->cleanup(); - Keyring_Util::debug( static::SLUG . ' auto import finished' ); - - // set the original schedule, starting with the defined next offset - wp_reschedule_event( time() + static::SCHEDULETIME, static::SCHEDULE , $this->schedule ); + break; } - // we're not finished yet else { $this->set_option( static::OPTNAME_POSTPOS, $next ); - Keyring_Util::debug( static::SLUG . ' auto import: there is more coming' ); - - // the next run of this very job should be - // near immediate, otherwise we'd never finish with all the post; - // event this way a few thousand posts will result in issues - // for sure, so there has to be something - wp_reschedule_event( time() + static::RESCHEDULE , $this->optname, $this->schedule ); } } + Keyring_Util::debug( sprintf ('%s auto import: current batch finised (%s to %s out of %s )', static::SLUG, (int) ($position - static::REQUESTS_PER_AUTO), $position, count($this->posts)-1 )); + + if ( $this->finished || $next >= count($this->posts) ) { + Keyring_Util::debug( sprintf ('%s auto import: FINISHED', static::SLUG)); + $this->cleanup(); + do_action( 'keyring_import_done', $this->optname ); + } + else { + Keyring_Util::debug( sprintf ('%s auto import: Rescheduling event', static::SLUG)); + wp_schedule_single_event( time() + static::RESCHEDULE, $this->schedule ); + } + do_action( 'import_end' ); }@@ -969,11 +1006,22 @@ do_action( 'keyring_import_done', $this->optname );
} /** + * When they're complete, give them a quick summary and a link back to their website. + */ + function saved() { + $this->header(); + echo '<h2>' . __( 'Setting saved!', 'keyring' ) . '</h2>'; + $this->footer(); + } + + /** * reset internal variables */ function cleanup() { - $this->set_option( static::OPTNAME_POSTS, array() ); - $this->set_option( static::OPTNAME_POSTPOS , 0 ); + $msg = __('DOING CLEANUP', 'keyring'); + Keyring_Util::debug($msg); + $this->set_option( static::OPTNAME_POSTS ); + $this->set_option( static::OPTNAME_POSTPOS ); } /**@@ -1052,10 +1100,10 @@ // safety first
$comment['comment_author_email'] = filter_var ( $comment['comment_author_email'], FILTER_SANITIZE_EMAIL ); $comment['comment_author_url'] = filter_var ( $comment['comment_author_url'], FILTER_SANITIZE_URL ); $comment['comment_author'] = filter_var ( $comment['comment_author'], FILTER_SANITIZE_STRING); - $comment['comment_content'] = filter_var ( $comment['comment_content'], FILTER_SANITIZE_SPECIAL_CHARS ); + //$comment['comment_content'] = filter_var ( $comment['comment_content'], FILTER_SANITIZE_SPECIAL_CHARS ); //test if we already have this imported - $args = array( + $testargs = array( 'author_email' => $comment['comment_author_email'], 'post_id' => $post_id, );@@ -1063,7 +1111,7 @@
// so if the type is comment and you add type = 'comment', WP will not return the comments // such logical! if ( $comment['comment_type'] != 'comment') - $args['type'] = $comment['comment_type']; + $testargs['type'] = $comment['comment_type']; // in case it's a fav or a like, the date field is not always present // but there should be only one of those, so the lack of a date field indicates@@ -1087,7 +1135,7 @@ 'second' => $t[2],
); */ - $args['date_query'] = $comment['comment_date']; + $testargs['date_query'] = $comment['comment_date']; //test if we already have this imported Keyring_Util::debug(sprintf(__('checking comment existence for %s (with date) for post #%s','keyring'), $comment['comment_author_email'], $post_id));@@ -1101,7 +1149,7 @@ //test if we already have this imported
Keyring_Util::debug(sprintf(__('checking comment existence for %s (no date) for post #%s','keyring'), $comment['comment_author_email'], $post_id)); } - $existing = get_comments($args); + $existing = get_comments($testargs); // no matching comment yet, insert it if (empty($existing)) {@@ -1136,8 +1184,6 @@ // info
$r = sprintf (__("Already exists: %s from %s for #%s", 'keyring'), $comment['comment_type'], $comment['comment_author'], $post_id ); } - Keyring_Util::debug($r); - return $comment_id; }@@ -1151,6 +1197,9 @@ if ( !$info )
$info = __( 'Import reactions from %s and save them as Comments within WordPress.', 'keyring' ); $name = $class::LABEL; + $options = get_option( 'keyring-' . $class::SLUG ); + if ( !empty( $options['auto_import'] ) && !empty( $options['token'] ) ) + $name = '✓ ' . $name; register_importer( $slug,
@@ -1,9 +1,9 @@
=== Keyring Reactions Importer === Contributors: cadeyrn -Tags: facebook, flickr, 500px, backfeed, indieweb, comments, likes, favorites +Tags: instagram, facebook, flickr, 500px, backfeed, indieweb, comments, likes, favorites Requires at least: 3.0 Tested up to: 4.1 -Stable tag: 0.2 +Stable tag: 0.3 License: GPLv3 License URI: http://www.gnu.org/licenses/gpl-3.0.html@@ -31,6 +31,7 @@
* [500px](https://500px.com/) - comments, favs, likes * [Flickr](https://flickr.com/) - comments, favs * [Facebook](https://facebook.com/) - comments, likes +* [Instagram](https://instagram.com) - comments, likes The plugin uses the brilliant [Keyring](https://wordpress.org/plugins/keyring/) for handling networks and us based on [Keyring Social Importers](https://wordpress.org/plugins/keyring-social-importers/); both from [Beau Lebens](http://dentedreality.com.au/).@@ -42,6 +43,11 @@ 3. Activate the desired importer.
4. Make sure WP-Cron is not disabled fully in case you wish to use auto-import. == Changelog == + += 0.3 = +*2015-04-16* + +* adding Instagram = 0.2 = *2015-03-13*