IntenseDebate Comments enhance and encourage conversation on your blog or website. Full comment and account data sync between IntenseDebate and WordPress ensures that you will always have your comments. Custom integration with your WordPress admin panel makes moderation a piece of cake. Comment threading, reply-by-email, user accounts and reputations, comment voting, along with Twitter and friendfeed integrations enrich your readers' experience and make more of the internet aware of your blog and comments which drives traffic to you! To get started, please activate the plugin and adjust your IntenseDebate settings . Version: 2.9 Author: IntenseDebate & Automattic Author URI: http://intensedebate.com */ // CONSTANTS // This plugin's version define( 'ID_PLUGIN_VERSION', '2.9' ); // API Endpoints define( 'ID_BASEURL', 'http://intensedebate.com' ); define( 'ID_SERVICE', ID_BASEURL . '/services/v1/operations/postOperations.php' ); define( 'ID_USER_LOOKUP_SERVICE', ID_BASEURL . '/services/v1/users' ); define( 'ID_BLOG_LOOKUP_SERVICE', ID_BASEURL . '/services/v1/sites' ); // Local queue option name define( 'ID_REQUEST_QUEUE_NAME', 'id_request_queue' ); // Application identifier, passed with all API transactions define( 'ID_APPKEY', 'wpplugin' ); // Minimum tested version of WordPress for this version of the plugin define( 'ID_MIN_WP_VERSION', '2.8' ); // URL bases for linkage define( 'ID_COMMENT_MODERATION_PAGE', ID_BASEURL . '/wpIframe.php?acctid=' ); define( 'ID_REGISTRATION_PAGE', ID_BASEURL . '/signup' ); // Set to true to get a detailed log of operations in your error_log define( 'ID_DEBUG', false ); // Pre WP 2.6 compatibility if ( ! defined( 'WP_CONTENT_URL' ) ) define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' ); if ( ! defined( 'WP_PLUGIN_URL' ) ) define( 'WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins' ); // Load textdomain for internationalization load_plugin_textdomain( 'intensedebate' ); // Global var to ensure link wrapper script only outputs once $id_link_wrapper_output = false; // Override core mail notification functions with stubs if ( !function_exists( 'wp_notify_postauthor' ) ) { function wp_notify_postauthor() { } } if ( !function_exists( 'wp_notify_moderator' ) ) { function wp_notify_moderator() { } } // JSON support function id_got_json() { // WP 2.9+ handles everything for us if ( version_compare( get_bloginfo( 'version' ), '2.9', '>=' ) ) return true; // Functions exists already, assume they're good to go if ( function_exists( 'json_encode' ) && function_exists( 'json_decode' ) ) return true; // Load Services_JSON if we need it at this point if ( !class_exists( 'Services_JSON' ) ) include_once( dirname( __FILE__ ) . '/class.json.php' ); // This indicates that we need to define the functions. // Services_JSON *is* available one way or another at this point return false; } if ( !id_got_json() ) { function json_encode( $data ) { $json = new Services_JSON(); return( $json->encode( $data ) ); } function json_decode( $data ) { $json = new Services_JSON(); return( $json->decode( $data ) ); } } function id_get_user_meta( $id, $val ) { if ( function_exists( 'get_user_meta' ) ) return get_user_meta( $id, $val, true ); return get_usermeta( $id, $val ); } function id_delete_user_meta( $id, $val ) { if ( function_exists( 'delete_user_meta' ) ) return delete_user_meta( $id, $val ); return delete_usermeta( $id, $val ); } function id_get_author_name() { if ( function_exists( 'get_the_author_meta' ) ) return get_the_author_meta( 'display_name' ); return get_author_name(); } // Debug logging function id_debug_log( $text ) { if ( defined( 'ID_DEBUG' ) && true === ID_DEBUG ) { error_log( 'ID/' . ID_PLUGIN_VERSION . ': ' . $text ); } } // HOOK ASSIGNMENT function id_activate_hooks() { global $wpmu_version; // warning that we don't support this version of WordPress if ( empty( $wpmu_version ) && version_compare( get_bloginfo( 'version' ), ID_MIN_WP_VERSION, '<' ) ) { add_action( 'admin_head', 'id_wordpress_version_warning' ); return; } // hooks onto incoming requests add_action( 'init', 'id_request_handler' ); // IntenseDebate individual settings add_action( 'admin_notices', 'id_admin_notices' ); // IntenseDebate server settings add_action( 'admin_menu', 'id_menu_items' ); add_action( 'init', 'id_process_settings_page' ); if ( id_do_admin_hooks() ) { // scripts for admin settings page add_action( "admin_head", 'id_settings_head' ); // allow options.php to handle updates in WPMU and future WP versions add_filter( 'whitelist_options', 'id_whitelist_options' ); // add comment counts in best way available if ( id_is_active() ) { if ( version_compare( get_bloginfo( 'version' ), '2.8', '>=' ) ) add_action( 'admin_print_footer_scripts', 'id_get_comment_footer_script', 21 ); else add_action( 'admin_footer', 'id_get_comment_footer_script', 100 ); } } if ( is_admin() ) { // Always add comment moderation count in the admin area if ( version_compare( get_bloginfo( 'version' ), '2.8', '>=' ) ) add_action( 'admin_print_footer_scripts', 'id_admin_footer', 21 ); else add_action( 'admin_footer', 'id_admin_footer', 100 ); } if ( id_is_active() ) { // crud hooks add_action( 'wp_insert_comment', 'id_save_comment' ); add_action( 'trackback_post', 'id_save_comment' ); add_action( 'pingback_post', 'id_save_comment' ); add_action( 'edit_comment', 'id_save_comment' ); add_action( 'save_post', 'id_save_post' ); add_action( 'delete_post', 'id_delete_post' ); add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 ); add_action( 'trashed_comment', 'id_comment_trashed', 10 ); add_action( 'untrashed_comment', 'id_comment_untrashed', 10 ); // individual registration add_action( 'show_user_profile', 'id_show_user_profile' ); add_action( 'profile_update', 'id_profile_update' ); // Settings > Discussion sync add_action( 'load-options.php', 'id_discussion_settings_page' ); // Load ID comment template if ( 0 == get_option( 'id_useIDComments') ) { if ( !id_is_mobile() || ( id_is_mobile() && 0 != get_option( 'id_revertMobile' ) ) ) { add_filter( 'comments_template', 'id_comments_template' ); // swap out the comment count links add_filter( 'comments_number', 'id_get_comment_number' ); add_action( 'wp_footer', 'id_get_comment_footer_script', 21 ); add_action( 'get_footer', 'id_get_comment_footer_script', 100 ); } } // Disable email notifications properly add_filter( 'option_moderation_notify', create_function( '$a', 'return 0;' ) ); add_filter( 'option_comments_notify', create_function( '$a', 'return 0;' ) ); } if ( id_is_active() || id_queue_not_empty() ) { // fires the outgoing HTTP request queue for ID synching add_action( 'shutdown', 'id_ping_queue' ); } } // only load ID resources where they're needed function id_do_admin_hooks() { if ( !is_admin() ) return false; $basename = basename( $_SERVER['PHP_SELF'] ); // ID Comment moderation if ( 'admin.php' == $basename && !empty( $_REQUEST['page'] ) && 'intensedebate' == $_REQUEST['page'] ) return true; // ID Settings page if ( 'options-general.php' == $basename && !empty( $_REQUEST['page'] ) && 'id_settings' == $_REQUEST['page'] ) return true; // Whitelisted files if ( in_array( $basename, array( 'profile.php', 'options.php' ) ) ) return true; // Posts/Pages when ID comment links are enabled if ( 0 == get_option( 'id_jsCommentLinks' ) && ( 'edit.php' == $basename || 'edit-pages.php' == $basename ) ) return true; return false; } // adds new menu options to wp admin function id_menu_items() { // Replace the default Comments menu with the ID-enhanced one if ( id_is_active() && 0 == get_option( 'id_moderationPage' ) ) { global $menu; if ( function_exists( 'add_object_page' ) ) { // WP 2.7+ unset( $menu[25] ); add_object_page( __( 'Comments', 'intensedebate' ), __( 'Comments', 'intensedebate' ), 'moderate_comments', 'intensedebate', 'id_moderate_comments', WP_CONTENT_URL . '/plugins/intensedebate/comments.png' ); } else { // < WP 2.7 unset( $menu[20] ); add_menu_page( __( 'Comments', 'intensedebate' ), __( 'Comments', 'intensedebate' ), 'moderate_comments', 'intensedebate', 'id_moderate_comments' ); } } add_options_page( __( 'IntenseDebate Settings', 'intensedebate' ), 'IntenseDebate', 'manage_options', 'id_settings', 'id_settings_page' ); if ( !get_option( 'id_pdxsync' ) ) id_clear_orphan_comments(); } function id_whitelist_options( $options ) { $options['intensedebate'] = array( 'id_auto_login', 'id_moderationPage', 'id_useIDComments', 'id_jsCommentLinks', 'id_revertMobile' ); return $options; } function id_activate() { update_option( 'thread_comments', 1 ); } register_activation_hook( __FILE__, 'id_activate' ); function id_deactivate() { $fields = array( 'appKey' => ID_APPKEY, 'blogKey' => get_option( 'id_blogKey' ), 'blogid' => get_option( 'id_blogID' ), ); $queue = id_get_queue(); $op = $queue->add( 'plugin_deactivated', $fields, 'id_generic_callback' ); $queue->ping( array( $op ) ); } register_deactivation_hook( __FILE__, 'id_deactivate' ); // UTILITIES // Load Snoopy if WP HTTP isn't here, and Snoopy's not already loaded (< WP 2.7 compat) if ( !function_exists( 'wp_remote_get' ) && !function_exists( 'get_snoopy' ) ) { function get_snoopy() { include_once( ABSPATH.'/wp-includes/class-snoopy.php' ); return new Snoopy; } } function id_http_query( $url, $fields, $method = 'GET' ) { $results = ''; if ( function_exists( 'wp_remote_get' ) ) { // The preferred WP HTTP library is available if ( 'POST' == $method ) { $response = wp_remote_post( $url, array( 'body' => $fields ) ); if ( !is_wp_error( $response ) ) { $results = wp_remote_retrieve_body( $response ); id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results ); } else { id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $response->get_error_message() ); } } else { $url .= '?' . http_build_query( $fields ); $response = wp_remote_get( $url ); if ( !is_wp_error( $response ) ) { $results = wp_remote_retrieve_body( $response ); id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results ); } else { id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $response->get_error_message() ); } } } else { // Fall back to Snoopy $snoopy = get_snoopy(); if ( 'POST' == $method ) { if ( $snoopy->submit( $url, $fields ) ) { $results = $snoopy->results; id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results ); } else { id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $results ); } } else { $url .= '?' . http_build_query( $fields ); if ( $snoopy->fetch( $url ) ) { $results = $snoopy->results; id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results ); } else { id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $results ); } } } return $results; } // blog option function id_save_option( $name, $value ) { global $wpmu_version; if ( false === get_option( $name ) && empty( $wpmu_version ) ) { // Avoid WPMU options cache bug add_option( $name, $value, '', 'no' ); } else { update_option( $name, $value ); } id_debug_log( 'Save option: ' . $name . ' = ' . print_r( $value, true ) ); } // user options function id_save_usermeta_array( $user_id, $meta = array() ) { foreach( $meta as $n => $v ) { id_save_usermeta( $user_id, $n, $v ); } } // saves or wipes an individual meta field function id_save_usermeta( $user_id, $name, $value = null ) { if ( isset( $value ) && !empty( $value ) ) { update_usermeta( $user_id, $name, $value ); } else { id_delete_user_meta( $user_id, $name ); } } function id_user_connected() { $current_user = wp_get_current_user(); $user_id = $current_user->ID; $userID = id_get_user_meta( $user_id, 'id_userID' ); $userKey = id_get_user_meta( $user_id, 'id_userKey' ); return ( $userID && $userKey ); } // returns first non-null and non empty argment function id_coalesce() { $args = func_get_args(); foreach ( $args as $v ) { if ( isset( $v ) && !empty( $v ) ) return $v; } return null; } // hash generator function id_generate_token( $fields ) { return md5( time() . implode( '&', $fields ) ); } // determines whether ID has been activated via the settings page function id_is_active() { return ( get_option( 'id_blogID' ) && get_option( 'id_blogKey' ) && get_option( 'id_userID' ) && get_option( 'id_userKey' ) && get_option( 'id_blogAcct' ) ); } // pulls a passed parameter from indicated scopes function id_param( $name, $default = null, $scopes = null ) { if ( $scopes == null ) { $scopes = array( $_POST, $_GET ); } foreach ( $scopes as $thisScope ) { if ( isset( $thisScope[$name] ) ) { return $thisScope[$name]; } } return $default; } // inits queue object function id_get_queue() { global $id_q; if ( !$id_q ) { $id_q = new id_queue(); } return $id_q; } // pings queue object function id_ping_queue() { $queue = id_get_queue(); $queue->ping(); } function id_queue_not_empty() { $queue = id_get_queue(); $queue->load(); if ( count( $queue->operations ) ) { return true; } else { return false; } } // deconstructs query string if ( !function_exists( 'http_parse_query' ) ) { function http_parse_query( $array = NULL, $convention = '%s' ) { if ( count( $array ) == 0 ) { return ''; } else { if ( function_exists( 'http_build_query' ) ) { $query = http_build_query( $array ); } else { $query = ''; foreach ( $array as $key => $value ) { if ( is_array( $value ) ) { $new_convention = sprintf( $convention, $key ) . '[%s]'; $query .= http_parse_query( $value, $new_convention ); } else { $key = urlencode( $key ); $value = urlencode( $value ); $query .= sprintf( $convention, $key ) . "=$value&"; } } } return $query; } } } // CRUD OPERATION HOOKS function id_save_comment( $comment_ID = 0 ) { if ( 0 == $comment_ID ) return; $comment = new id_comment( array( 'comment_ID' => $comment_ID ) ); $comment->loadFromWP(); if ( $comment->comment_approved != 'spam' ) { // Don't send the spam $queue = id_get_queue(); $queue->add( 'save_comment', $comment->export(), 'id_generic_callback' ); } } function id_comment_status( $comment_id, $status ) { if ( $status == "delete" ) { $packet = new stdClass; $packet->comment_id = $comment_id; $packet->status = $status; $queue = id_get_queue(); $queue->add( 'update_comment_status', $packet, 'id_generic_callback' ); } else { $comment = new id_comment( array( 'comment_ID' => $comment_id ) ); $comment->loadFromWP(); if ( $status == "hold" ) $comment->comment_approved = 0; if ( $status == "approve" ) $comment->comment_approved = 1; if ( $status == "spam" ) $comment->comment_approved = "spam"; $queue = id_get_queue(); $queue->add( 'save_comment', $comment->export(), 'id_generic_callback' ); } } // Trash in WP == delete on ID function id_comment_trashed( $comment_id ) { id_comment_status( $comment_id, 'delete' ); } // Untrash on WP == new comment on ID function id_comment_untrashed( $comment_id ) { id_save_comment( $comment_id ); } function id_save_post( $post_id ) { $post = get_post( $post_id ); if ( 0 == $post->post_parent || 'page' == $post->post_type ) { $p = new id_post( $post ); $packet = $p->export(); $queue = id_get_queue(); $queue->add( 'save_post', $packet, 'id_generic_callback' ); } } function id_delete_post( $post_id ) { $packet = new stdClass; $packet->post_id = $post_id; $queue = id_get_queue(); $queue->add( 'delete_post', $packet, 'id_generic_callback' ); } // callbacks return true to remove from queue function id_generic_callback( $result, $response, $operation ) { $args = func_get_args(); if ( $result ) return true; if ( $response['attempt_retry'] ) return false; return true; } // DATA WRAPPERS class id_data_wrapper { var $properties = array(); // generic constructor. You can pass in an array/stdClass of // values for $props and prepopulate your object either using // local or remote names function id_data_wrapper( $props = null, $bRemoteLabels = false ) { if ( isset( $props ) ) { if ( $bRemoteLabels ) { $this->loadFromRemote( $props ); } else { $this->loadFromLocal( $props ); } } } // registers a property with the object. $localname is the WordPress column // name and also the internal property name, $remoteName is the ID field name function addProp( $localName, $remoteName = null, $defaultValue = null ) { $remoteName = isset( $remoteName ) ? $remoteName : $localName; $this->properties[$localName] = $remoteName; $this->$localName = $defaultValue; } // loads object with props from passed object, assumption is that the passed // object is keyed using local variable names function loadFromLocal( $o ) { $incomingProps = $this->scrubInputHash($o); foreach ( $this->properties as $local => $remote ) { if ( isset( $incomingProps[$local] ) ) { $this->$local = $incomingProps[$local]; } } } // loads object with props from remote object hash function loadFromRemote( $o ) { $props = array_flip( $this->properties ); $incomingProps = $this->scrubInputHash( $o ); foreach( $props as $remote => $local ) { if ( isset( $incomingProps[$remote] ) ) { $this->$local = $incomingProps[$remote]; } } } // makes an array out of whatever is passed in function scrubInputHash( $o ) { $incomingProps = $o; if ( !is_array( $o ) ) { $incomingProps = get_object_vars( $o ); } return $incomingProps; } function loadFromRemoteJson( $jsonString ) { $o = json_decode( $jsonString ); $this->loadFromRemote( $o ); } // exports object properties into remote property names function export( $bRemote = true ) { $o = array(); foreach ( $this->properties as $local => $remote ) { if ( $remote == "comment_text" ) $o[$remote] = trim( $this->$local ); // trim the comment text else $o[$remote] = $this->$local; } return $o; } function props() { $props = array(); foreach ( $this->properties as $n => $v ) { $props[$n] = $this->$n; } return $props; } } // COMMENT WRAPPER class id_comment extends id_data_wrapper { var $post = null; function id_comment( $props = null, $bRemoteLabels = false ) { $this->addProp( 'intensedebate_id' ); $this->addProp( 'comment_ID', 'comment_id' ); $this->addProp( 'comment_post_ID', 'comment_post_id' ); $this->addProp( 'comment_author' ); $this->addProp( 'comment_author_email' ); $this->addProp( 'comment_author_url' ); $this->addProp( 'comment_author_IP', 'comment_author_ip' ); $this->addProp( 'comment_date' ); $this->addProp( 'comment_date_gmt' ); $this->addProp( 'comment_content', 'comment_text' ); // $this->addProp( 'comment_karma' ); $this->addProp( 'comment_approved', 'comment_status' ); $this->addProp( 'comment_agent' ); $this->addProp( 'comment_type' ); $this->addProp( 'comment_parent' ); $this->addProp( 'user_id' ); $this->id_data_wrapper( $props, $bRemoteLabels ); } // loadFromWP // loads comment from WP database function loadFromWP() { if ( $this->comment_ID ) { $wp_comment = get_comment( $this->comment_ID, ARRAY_A ); $this->loadFromLocal( $wp_comment ); } } // saves back to WP database function save() { // Invalid comment? if ( !$this->valid() ) return false; if ( empty( $this->comment_date ) && !empty( $this->comment_date_gmt ) ) $this->comment_date = get_date_from_gmt( $this->comment_date_gmt ); $result = 0; remove_action( 'edit_comment', 'id_save_comment' ); remove_action( 'wp_insert_comment', 'id_save_comment' ); if ( $this->comment_ID && get_comment( $this->comment_ID ) ) { // Added by duplicateCheck() if matched against existing comment $result = wp_update_comment( $this->props() ); } else { $result = wp_insert_comment( wp_filter_comment( $this->props() ) ); if ( !$result ) { add_action( 'edit_comment', 'id_save_comment' ); add_action( 'wp_insert_comment', 'id_save_comment' ); return false; } $this->comment_ID = $result; } add_action( 'edit_comment', 'id_save_comment' ); add_action( 'wp_insert_comment', 'id_save_comment' ); return true; } // evaluates whether the comment is valid function valid() { $this->duplicateCheck(); return ( !empty( $this->comment_content ) && is_numeric( $this->comment_post_ID ) ); } // based on code in wp_allow_comment, updates internal reference so that updates happen on duplicates function duplicateCheck() { global $wpdb; extract( $this->props() ); // SQL to check for duplicate comment post $dupe = $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND ( comment_author = %s ", $comment_post_ID, $comment_author ); if ( $comment_author_email ) $dupe .= $wpdb->prepare( "OR comment_author_email = %s ", $comment_author_email ); $dupe .= $wpdb->prepare( ") AND comment_content = %s LIMIT 1", $comment_content ); // Duplicates don't actually cause an error, they just update the comment_ID internally to force an update if ( $id = $wpdb->get_var( $dupe ) ) $this->comment_ID = $id; } // associated post parent object function post() { if ( !$this->post ) { $this->post = new id_post( get_post( $this->comment_post_ID, ARRAY_A ) ); } return $this->post; } function export() { $o = parent::export(); $p = $this->post(); $o['post'] = $p->export(); return $o; } // the intensedebate_id actually has to be stored with the post because // there is no comment metadata function intensedebate_id( $intensedebate_id = null ) { $post = $this->post(); return $post->setRemoteID( $this->comment_ID, $intensedebate_id ); } } // POST WRAPPER class id_post extends id_data_wrapper { function id_post( $props = null, $bRemoteLabels = false ) { $this->addProp( 'ID', 'postid' ); $this->addProp( 'post_title', 'title' ); $this->addProp( 'guid' ); $this->addProp( 'url' ); $this->addProp( 'post_author_name', 'author' ); $this->addProp( 'post_author', 'authorid' ); $this->addProp( 'post_modified_gmt', 'date_gmt' ); $this->addProp( 'comment_status' ); $this->addProp( 'ping_status' ); // load passed props $this->id_data_wrapper( $props, $bRemoteLabels ); // load up inferred props $this->loadProprietaryProps(); } function loadProprietaryProps() { if ( $this->post_author ) { $a = get_userdata( $this->post_author ); $this->post_author_name = trim( $a->display_name ); } } // need the category names in an array function categories() { if ( function_exists( 'wp_get_post_categories' ) ) { $category_ids = (array) wp_get_post_categories( $this->ID ); $categories = array(); foreach ( $category_ids as $id ) { $c = get_category( $id ); $categories[] = $c->cat_name; } } else { global $wpdb; $results = $wpdb->get_results( $wpdb->prepare( "SELECT c.cat_name FROM {$wpdb->categories} c, {$wpdb->post2cat} pc WHERE pc.category_id = c.cat_ID AND pc.post_id = %d", $this->ID ), ARRAY_A ); $categories = array(); foreach ( $results as $row ) { $categories[] = $row['cat_name']; } } return $categories; } function comments() { return null; } function export() { $me = parent::export(); $me['comments'] = $this->comments(); $me['categories'] = $this->categories(); $me['url'] = get_permalink( $this->ID ); return $me; } function mapCategory( $categoryID ) { $c = get_category( $categoryID ); return $c->name; } function mapComment( $o ) { return $o->comment_ID; } function save() { if ( !$this->valid() ) return false; // watch for text-link-ads.com plugin if ( function_exists( "tla_send_updated_post_alert" ) ) remove_action( 'edit_post', 'tla_send_updated_post_alert' ); remove_action( 'save_post', 'id_save_post' ); $result = wp_update_post( get_object_vars( $this ) ); add_action( 'save_post', 'id_save_post' ); // add hooks for text-link-ads.com back in if ( function_exists( "tla_send_updated_post_alert" ) ) add_action( 'edit_post', 'tla_send_updated_post_alert' ); return $result; } function valid() { return $this->ID; } } // QUEUE class id_queue_operation { var $action, $callback, $operation_id, $time_gmt, $data, $response, $success; function id_queue_operation( $action, $data, $callback = null ) { $this->action = $action; $this->callback = $callback; $this->data = $data; $this->time_gmt = gmdate( "Y-m-d H:i:s" ); $this->operation_id = $this->id(); $this->success = false; $this->wp_version = get_bloginfo( 'version' ); $this->id_plugin_version = ID_PLUGIN_VERSION; } function id() { return md5( $this->action . $this->callback . $this->time_gmt . serialize( $this->data ) ); } } class id_queue { var $queueName = ID_REQUEST_QUEUE_NAME; var $url = ID_SERVICE; var $operations = array(); var $needs_save = false; function id_queue() { $this->load(); } function load() { $this->operations = get_option( $this->queueName ); if ( !is_array( $this->operations ) ) { $this->create(); } } function create() { $this->operations = array(); } function store() { if ( $this->needs_save ) { $this->compact_operations(); id_save_option( $this->queueName, $this->operations ); } } function compact_operations() { $num_ops = count( $this->operations ); for ( $o = 0; $o < $num_ops; $o++ ) { if ( in_array( $this->operations[ $o ]->action, array( 'save_comment', 'comment_status' ) ) && isset( $this->operations[ $o ]->data['comment_id'] ) ) { $this->operations[ $o ]->data = array( 'comment_id' => $this->operations[ $o ]->data['comment_id'] ); } } } function add( $action, $data, $callback = null ) { $op = new id_queue_operation( $action, $data, $callback ); return $this->queue( $op ); } function queue( $operation ) { $this->needs_save = true; if ( in_array( $operation->action, array( 'save_comment', 'comment_status' ) ) && isset( $operation->data->comment_id ) ) $operation->data = array( 'comment_id' => $operation->data->comment_id ); $this->operations[] = $operation; return $operation; } function ping( $operations = null ) { $this->process( $this->send( $operations ) ); $this->store(); } function send( $operations = null ) { if ( null == $operations ) $operations = $this->operations; if ( !count( $operations ) ) return false; if ( get_option( 'id_lock_queue' ) && get_option( 'id_lock_queue' ) > time() ) return false; // Filter out/limit requests $count = 0; $send = array(); $hold = array(); foreach ( $operations as $op ) { // Got enough requests for this time? // Sent less than 30s ago? if ( $count >= 10 || ( !empty( $op->running ) && ( time() - $op->running < 30 ) ) ) { $hold[] = $op; continue; } // Refresh comment data for certain requests if ( !empty( $op->action ) && in_array( $op->action, array( 'save_comment', 'comment_status' ) ) && !empty( $op->data ) && isset( $op->data[ 'comment_id' ] ) && ( substr( gmdate( 'Y-m-d H:i:s' ), 0, 18 ) != substr( $op->time_gmt, 0, 18 ) || empty( $op->data['comment_text'] ) ) ) { // Reload if not from this minute or if no comment text $comment = new id_comment( array( 'comment_ID' => $op->data[ 'comment_id' ] ) ); $comment->loadFromWP(); $data = $comment->export(); $op->data = $data; } // Send this one along with a timestamp to avoid doubling up $op->running = time(); $send[] = $op; $count++; } // Update queue to save timestamps $this->needs_save = true; $this->operations = array_merge( $hold, $send ); $fields = array( 'appKey' => ID_APPKEY, 'blogKey' => get_option( 'id_blogKey' ), 'blogid' => get_option( 'id_blogID' ), 'operations' => json_encode( $send ) ); $this->store(); return id_http_query( $this->url . '?blogid=' . urlencode( get_option( 'id_blogID' ) ), $fields, 'POST' ); } function process( $rawResults ) { // HTTP request failed? Leave queue alone and attempt to resend later if ( false == $rawResults ) return; // Need to update queue when we're done $this->needs_save = true; // Decode results string $results = json_decode( $rawResults ); // flip the array around using operation_id as the key $results = $this->reIndex( $results, 'operation_id' ); // loop through current queue and see if there are results for them $newQueue = array(); foreach ( $this->operations as $operation ) { if ( isset( $results[ $operation->operation_id ] ) ) { $result = $results[ $operation->operation_id ]; if ( isset( $operation->callback ) && function_exists( $operation->callback ) ) { // callback returns true == remove from queue // callback returns false == add back to queue $finished = call_user_func_array( $operation->callback, array( "result" => &$result->result, "response" => &$result->response, "operation" => &$operation ) ); $operation->success = $finished; $operation->response = $result->response; if ( !$finished ) { $newQueue[] = $operation; } } } else { // no result returned for that operation, requeue $newQueue[] = $operation; } } // store new queue $this->operations = $newQueue; } function testResults() { $results = array(); foreach ( $this->operations as $op ) { $result = new stdClass; $result->operation_id = $op->operation_id; $result->result = $op->data; $results[] = $result; } return json_encode( $results ); } function reIndex( $arrIn, $prop ) { $arrOut = array(); if ( isset( $arrIn ) ) { foreach ( $arrIn as $item ) { $arrOut[$item->$prop] = $item; } } return $arrOut; } } // REST SERVICE FUNCS function id_request_handler() { global $wpmu_version; // Blanket protection against accidental access to edit-comments.php $basename = basename( $_SERVER['REQUEST_URI'] ); if ( stristr( $basename, '?' ) ) $basename = substr( $basename, 0, strpos( $basename, '?' ) ); if ( 0 == get_option( 'id_moderationPage') && 'edit-comments.php' == $basename ) wp_redirect( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=intensedebate' ); // determine requested action $action = id_param( 'id_action' ); if ( !$action ) return; id_debug_log( 'Request for: ' . $action ); // translated func name $fn = 'id_REST_' . $action; if ( !function_exists( $fn ) ) { id_debug_log( 'Unknown action requested: ' . $fn ); id_request_error( 'Unknown action: ' . $fn ); return; } if ( 'id_REST_test_connection' == $fn ) { id_response_render( call_user_func( $fn ) ); } // token key $token = id_param( 'id_token' ); if ( $token !== get_option( 'id_import_token' ) ) { id_request_error( 'Missing or invalid token' ); return; } // calls named func $result = call_user_func( $fn ); //id_debug_log( 'Response: ' . print_r( $result, true ) ); id_response_render( $result ); } function id_request_error( $msg ) { $result = new stdClass(); $result->success = false; $result->error = $msg; id_response_render( $result ); } function id_request_message( $msg ) { $result = new stdClass(); $result->success = true; $result->data = null; $result->message = $msg; id_response_render( $result ); } function id_response_render( $result, $contentType = "application/json" ) { while ( @ob_end_clean() ) {} // Clear all buffers $charSet = get_bloginfo( 'charset' ); header( "Content-Type: {$contentType}; charset={$charSet}" ); die( json_encode( $result ) ); } function id_REST_ping() { return array( 'id_plugin_version' => ID_PLUGIN_VERSION, 'wp_version' => ( !empty( $wpmu_version ) ? 'WPMU/' : '' ) . get_bloginfo( 'version' ) ); } function id_REST_test_connection() { if ( !empty( $_POST['hash'] ) ) return array( 'hash' => preg_replace( '/[^a-f0-9]/', '', $_POST['hash'] ), 'random' => md5( mt_rand( 0, 1000 ) ) ); else wp_redirect( get_option( 'siteurl' ) ); } function id_REST_get_comments_by_user() { global $wpdb; $email = id_param( 'id_email', false ); $postid = id_param( 'id_postid', false ); $where = array(); if ( $email ) $where[] = $wpdb->prepare( "comment_author_email = %s", $email ); if ( $postid ) $where[] = $wpdb->prepare( "comment_post_ID = %d", $postid ); if ( !count( $where ) ) id_request_error( "Must supply id_email and optionally id_postid." ); $where[] = "comment_approved = 1"; $results = $wpdb->get_results( "SELECT * FROM {$wpdb->comments} WHERE " . implode( ' AND ', $where ) . " ORDER BY comment_ID DESC" ); if ( !count( $results ) ) { id_request_message( 'No comments' ); return array(); } return array_map( "id_export_comment", $results ); } // ACTION: import function id_REST_import() { global $wpdb; $curr_params = array(); $tot_params = array(); $remaining_params = array(); $post_where = ''; $post = id_param( 'id_post_id', false ); if ( false != $post ) { $post_where = ' comment_post_ID = ' . (int) $post . ' AND'; $tot_params[] = $post; $remaining_params[] = $post; } $current = get_option( 'id_import_comment_id' ); // Defaults to 0 if ( $current >= id_get_latest_comment_id() ) id_request_message( 'Import complete.' ); $import_offset = id_param( 'id_start_cid', 0 ); if ( $import_offset < 0 ) id_request_error( 'Start commentid must be a non-negative integer.' ); if ( $import_offset > 0 ) $current = $import_offset; id_debug_log( "Initiating import response with current = $current" ); $sql = "SELECT * FROM {$wpdb->comments} WHERE$post_where comment_ID >= " . (int) $current . " AND comment_approved != 'spam' ORDER BY comment_ID ASC LIMIT 100"; id_debug_log( $sql ); $results = $wpdb->get_results( $sql ); if ( !count( $results ) ) { id_debug_log( 'No comments to import.' ); id_save_option( 'id_signup_step', 3 ); id_request_message( 'Import complete.' ); } // Update each comment to use "external" names $comments = array_map( "id_export_comment", $results ); // mark the next comment_id for the next import request $lastCommentIndex = count( $comments ) - 1; $next_id = max( 0, (int) $comments[$lastCommentIndex]['comment_id'] + 1 ); id_save_option( 'id_import_comment_id', $next_id ); $result = new stdClass; $result->totalCommentCount = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE$post_where comment_approved != 'spam'", $tot_params ) ); $remaining_params[] = $next_id; $result->totalRemainingCount = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE$post_where comment_ID >= %d AND comment_approved != 'spam' ORDER BY comment_ID ASC", $remaining_params ) ); $result->time_gmt = gmdate( "Y-m-d H:i:s" ); $result->time = date( "Y-m-d H:i:s" ); $result->success = "true"; $result->next_id = $next_id; $result->data = $comments; return $result; } function id_export_comment( $o ) { $c = new id_comment( $o ); return $c->export(); } // ACTION: sync moderation settings from ID function id_REST_sync_moderation_settings() { $settings = id_param( 'settings' ); if ( empty( $settings ) ) return 'false'; id_debug_log( 'Updating moderation settings: ' . print_r( $settings, true ) ); // Decode and UnJSON the settings so we can work with them $settings = rawurldecode( stripslashes( $settings ) ); $opt = json_decode( $settings ); // Moderation links if ( isset( $opt->min_links_for_moderations ) ) update_option( 'comment_max_links', $opt->min_links_for_moderations ); // Update all the boolean values if ( 'T' == $opt->all_comments_require_approval ) update_option( 'comment_moderation', '1' ); else if ( 'F' == $opt->all_comments_require_approval ) update_option( 'comment_moderation', '' ); if ( 'T' == $opt->require_previously_approved ) update_option( 'comment_whitelist', '1' ); else if ( 'F' == $opt->require_previously_approved ) update_option( 'comment_whitelist', '' ); if ( 'T' == $opt->email_new_comments ) update_option( 'comments_notify', '1' ); else if ( 'F' == $opt->email_new_comments ) update_option( 'comments_notify', '' ); if ( 'T' == $opt->email_requires_moderation ) update_option( 'moderation_notify', '1' ); else if ( 'F' == $opt->email_requires_moderation ) update_option( 'moderation_notify', '' ); if ( 'T' == $opt->show_threads ) update_option( 'thread_comments', '1' ); else if ( 'F' == $opt->show_threads ) update_option( 'thread_comments', '' ); // Need to do some magic on the moderate/blacklist strings if ( isset( $opt->moderate_words ) || isset( $opt->moderate_ips ) || isset( $opt->moderate_emails ) ) { if ( !isset( $opt->moderate_words ) ) $opt->moderate_words = ''; if ( !isset( $opt->moderate_ips ) ) $opt->moderate_ips = ''; if ( !isset( $opt->moderate_emails ) ) $opt->moderate_emails = ''; $moderate_words = explode( ' ', $opt->moderate_words ); $moderate_ips = explode( ' ', $opt->moderate_ips ); $moderate_emails = explode( ' ', $opt->moderate_emails ); $moderate = array_merge( $moderate_words, $moderate_ips, $moderate_emails ); $moderate = implode( "\n", id_cleanup_moderation_array( $moderate ) ); update_option( 'moderation_keys', $moderate ); } if ( isset( $opt->blacklisted_words ) || isset( $opt->blacklisted_ips ) || isset( $opt->blacklisted_emails ) ) { if ( !isset( $opt->blacklisted_words ) ) $opt->blacklisted_words = ''; if ( !isset( $opt->blacklisted_ips ) ) $opt->blacklisted_ips = ''; if ( !isset( $opt->blacklisted_emails ) ) $opt->blacklisted_emails = ''; $blacklist_words = explode( ' ', $opt->blacklisted_words ); $blacklist_ips = explode( ' ', $opt->blacklisted_ips ); $blacklist_emails = explode( ' ', $opt->blacklisted_emails ); $blacklist = array_merge( $blacklist_words, $blacklist_ips, $blacklist_emails ); $blacklist = implode( "\n", id_cleanup_moderation_array( $blacklist ) ); update_option( 'blacklist_keys', $blacklist ); } if ( 'T' == $opt->akismet && get_option( 'wordpress_api_key' ) ) return get_option( 'wordpress_api_key' ); else return 'true'; } function id_cleanup_moderation_array( $arr ) { $clean = array(); foreach ( $arr as $val ) { $val = trim( $val ); if ( !$val ) continue; if ( !in_array( $val, $clean ) ) $clean[] = $val; } return $clean; } // ACTION: save_comment // Enter a new comment in to the system function id_REST_save_comment() { $rawComment = stripslashes( id_param( 'id_comment_data' ) ); id_debug_log( "Receive Comment: $rawComment" ); $comment = new id_comment(); $comment->loadFromRemoteJson( $rawComment ); $result = array( 'success' => $comment->save(), 'comment' => $comment->export() ); if ( 'delete' == $comment->comment_status ) { remove_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 ); wp_delete_comment( $comment->comment_ID ); add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 ); } return $result; } // ACTION: set_comment_status // ***Deleting is done by passing status=delete function id_REST_set_comment_status() { $newStatus = id_param( 'status', '' ); $comment_id = id_param( 'comment_id', 0 ); $rawComment = stripslashes( id_param( 'comment_data' ) ); if ( !$comment_id ) { if ( !$rawComment ) return false; $comment = new id_comment(); $comment->loadFromRemoteJson( $rawComment ); $comment->duplicateCheck(); // Will locate a match and update with the WP id if ( $comment->comment_ID ) { // Found it, carry on $comment_id = $comment->comment_ID; } else { // No match if ( 'delete' == $newStatus ) return true; // We were going to delete it anyway else return false; } } id_debug_log( "Receive Comment Status: $newStatus $comment_id" ); // Check if the status is already set, if so, still return true if ( $newStatus == wp_get_comment_status( $comment_id ) ) return true; else if ( $newStatus == "delete" && in_array( wp_get_comment_status( $comment_id ), array( "deleted", "trash" ) ) ) // handle cases that don't quite line up (delete=deleted and hold=unapproved) return true; else if ( $newStatus == "hold" && wp_get_comment_status( $comment_id ) == "unapproved" ) return true; // If not already set, then rename to local status, then attempt to set it and return the result remove_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 ); if ( 'delete' == $newStatus ) $result = wp_delete_comment( $comment_id ); else $result = wp_set_comment_status( $comment_id, $newStatus ); add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 ); return $result; } // ACTION: save_post function id_REST_save_post() { $rawPost = stripslashes( id_param( 'id_post_data' ) ); id_debug_log( "Receive Post Status: $rawPost" ); $data = json_decode( $rawPost ); if ( !isset( $data->postid ) ) return false; // Load current post $post = new id_post( get_post( $data->postid ) ); // Replace any incoming values foreach ( $data as $key => $val ) { if ( isset( $post->$key ) ) { $post->$key = $val; } } return array( 'success' => $post->save(), 'post' => $post->export() ); } // ACTION: reset queue function id_REST_reset_queue() { $queue = id_get_queue(); $queue->create(); return true; } // ACTION: get all operations queued in WP function id_REST_get_queue() { $queue = id_get_queue(); $queue->load(); return $queue->operations; } // ACTION: cancel a specific operation function id_REST_cancel_operation() { $queue = id_get_queue(); $queue->load(); $hash = id_param( 'id_operation_hash', false ); if ( !$hash ) return array( 'success' => false, 'hash' => $hash, 'operations' => count( $queue->operations ) ); $new_ops = array(); foreach ( $queue->operations as $operation ) { if ( $hash != $operation->operation_id ) $new_ops[] = $operation; } $queue->operations = $new_ops; $queue->needs_save = true; $queue->store(); return array( 'success' => true, 'hash' => $hash, 'operations' => count( $new_ops ) ); } // ACTION: restart import function id_REST_reset_import() { id_save_option( 'id_import_comment_id', '0' ); return true; } // ACTION: return the highest comment id in WP function id_REST_get_last_wp_comment_id() { return id_get_latest_comment_id(); } // ACTION: get the total number of approved comments // optionally provide &post_id= to get count for a specific post only function id_REST_get_approved_comment_count() { include_once ABSPATH . '/wp-admin/includes/template.php'; if ( $p = id_param( 'post_id', 0 ) ) $result = wp_count_comments( $p ); else $result = wp_count_comments(); return $result->approved; } // ACTION: Lock queue from sending requests for the next x seconds function id_REST_lock_queue() { $lock = id_param( 'id_lock_period', 300 ); // Defaults to 5 mins update_option( 'id_lock_queue', ( time() + $lock ) ); return get_option( 'id_lock_queue' ); } // AUTOLOGIN // drops autologin js after user has logged in via profile page, makes it so // user does not need to login to IntenseDebate if they've already logged in here function id_auto_login() { global $userdata; if ( empty( $userdata->ID ) || get_option( 'id_auto_login' ) == 1 ) return false; $wp_userID = $userdata->ID; $appKey = ID_APPKEY; $userID = id_get_user_meta( $wp_userID, 'id_userID' ); $userKey = id_get_user_meta( $wp_userID, 'id_userKey' ); if ( id_user_connected() ) { echo "\n"; } } // ADMIN BANNERS // displays prompt to login on the admin pages if user has not logged into IntenseDebate function id_admin_notices() { // global administrative settings prompt if ( !id_is_active() && !empty( $_GET['page'] ) && $_GET['page'] != 'id_settings' ) { $settingsurl = get_bloginfo( 'wpurl' ) . '/wp-admin/options-general.php?page=id_settings'; ?>
your settings.', 'intensedebate' ), $settingsurl ); ?>
WordPress profile to log in or register.', 'intensedebate' ), $profileurl ); ?>
It\'s easy.', 'intensedebate' ), ID_REGISTRATION_PAGE ); ?>
$username, 'id_userID' => null, 'id_userKey' => null ) ); return false; } // outgoing fields $fields = array(); $fields['username'] = $username; $fields['password'] = $password; $fields['wp_userID'] = $wp_userID; $fields['admin'] = current_user_can( 'manage_options' ); $queue = id_get_queue(); $op = $queue->add( 'user_login', $fields, 'id_profile_update_callback' ); $queue->ping( array( $op ) ); return true; } function id_profile_update_callback( &$result, &$response, &$operation ) { $args = func_get_args(); if ( $wp_userID = id_coalesce( @$operation->data['wp_userID'] ) ) { id_save_usermeta_array( $wp_userID, array( 'id_username' => id_coalesce( $operation->data['username'] ), 'id_userID' => id_coalesce( $response->userID ), 'id_userKey' => id_coalesce( $response->userKey ) ) ); } return true; } // user disconnect form function id_show_user_disconnect() { $current_user = wp_get_current_user(); $user_ID = $current_user->ID; ?>
' . id_get_user_meta( $user_ID, 'id_username' ) . '' ); ?>Read more here.', 'intensedebate' ), ID_BASEURL . '/wordpress#userSync' ); ?> |
class="idwp-message_error"> Login failed. Please check your credentials and try again.
id_username ); printf( __( 'Welcome %s!', 'intensedebate' ), $id_username ); ?> » .
Please note: While comments are being imported you might notice some of your comments appear to be missing from the IntenseDebate comment system. Don't worry though, your comments will be back as soon as they are imported.", 'intensedebate' ); ?>