PageRenderTime 60ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/blog/wp-content/plugins/intensedebate/intensedebate.php

https://bitbucket.org/sergiohzlz/reportaprod
PHP | 2951 lines | 2265 code | 405 blank | 281 comment | 471 complexity | 7265dc7324e3bd692a086dfe27109a04 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, AGPL-1.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. Plugin Name: IntenseDebate
  4. Plugin URI: http://intensedebate.com/wordpress
  5. Description: <a href="http://www.intensedebate.com">IntenseDebate Comments</a> 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 <a href="./options-general.php?page=id_settings">IntenseDebate settings</a> .
  6. Version: 2.9
  7. Author: IntenseDebate & Automattic
  8. Author URI: http://intensedebate.com
  9. */
  10. // CONSTANTS
  11. // This plugin's version
  12. define( 'ID_PLUGIN_VERSION', '2.9' );
  13. // API Endpoints
  14. define( 'ID_BASEURL', 'http://intensedebate.com' );
  15. define( 'ID_SERVICE', ID_BASEURL . '/services/v1/operations/postOperations.php' );
  16. define( 'ID_USER_LOOKUP_SERVICE', ID_BASEURL . '/services/v1/users' );
  17. define( 'ID_BLOG_LOOKUP_SERVICE', ID_BASEURL . '/services/v1/sites' );
  18. // Local queue option name
  19. define( 'ID_REQUEST_QUEUE_NAME', 'id_request_queue' );
  20. // Application identifier, passed with all API transactions
  21. define( 'ID_APPKEY', 'wpplugin' );
  22. // Minimum tested version of WordPress for this version of the plugin
  23. define( 'ID_MIN_WP_VERSION', '2.8' );
  24. // URL bases for linkage
  25. define( 'ID_COMMENT_MODERATION_PAGE', ID_BASEURL . '/wpIframe.php?acctid=' );
  26. define( 'ID_REGISTRATION_PAGE', ID_BASEURL . '/signup' );
  27. // Set to true to get a detailed log of operations in your error_log
  28. define( 'ID_DEBUG', false );
  29. // Pre WP 2.6 compatibility
  30. if ( ! defined( 'WP_CONTENT_URL' ) )
  31. define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
  32. if ( ! defined( 'WP_PLUGIN_URL' ) )
  33. define( 'WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins' );
  34. // Load textdomain for internationalization
  35. load_plugin_textdomain( 'intensedebate' );
  36. // Global var to ensure link wrapper script only outputs once
  37. $id_link_wrapper_output = false;
  38. // Override core mail notification functions with stubs
  39. if ( !function_exists( 'wp_notify_postauthor' ) ) {
  40. function wp_notify_postauthor() { }
  41. }
  42. if ( !function_exists( 'wp_notify_moderator' ) ) {
  43. function wp_notify_moderator() { }
  44. }
  45. // JSON support
  46. function id_got_json() {
  47. // WP 2.9+ handles everything for us
  48. if ( version_compare( get_bloginfo( 'version' ), '2.9', '>=' ) )
  49. return true;
  50. // Functions exists already, assume they're good to go
  51. if ( function_exists( 'json_encode' ) && function_exists( 'json_decode' ) )
  52. return true;
  53. // Load Services_JSON if we need it at this point
  54. if ( !class_exists( 'Services_JSON' ) )
  55. include_once( dirname( __FILE__ ) . '/class.json.php' );
  56. // This indicates that we need to define the functions.
  57. // Services_JSON *is* available one way or another at this point
  58. return false;
  59. }
  60. if ( !id_got_json() ) {
  61. function json_encode( $data ) {
  62. $json = new Services_JSON();
  63. return( $json->encode( $data ) );
  64. }
  65. function json_decode( $data ) {
  66. $json = new Services_JSON();
  67. return( $json->decode( $data ) );
  68. }
  69. }
  70. function id_get_user_meta( $id, $val ) {
  71. if ( function_exists( 'get_user_meta' ) )
  72. return get_user_meta( $id, $val, true );
  73. return get_usermeta( $id, $val );
  74. }
  75. function id_delete_user_meta( $id, $val ) {
  76. if ( function_exists( 'delete_user_meta' ) )
  77. return delete_user_meta( $id, $val );
  78. return delete_usermeta( $id, $val );
  79. }
  80. function id_get_author_name() {
  81. if ( function_exists( 'get_the_author_meta' ) )
  82. return get_the_author_meta( 'display_name' );
  83. return get_author_name();
  84. }
  85. // Debug logging
  86. function id_debug_log( $text ) {
  87. if ( defined( 'ID_DEBUG' ) && true === ID_DEBUG ) {
  88. error_log( 'ID/' . ID_PLUGIN_VERSION . ': ' . $text );
  89. }
  90. }
  91. // HOOK ASSIGNMENT
  92. function id_activate_hooks() {
  93. global $wpmu_version;
  94. // warning that we don't support this version of WordPress
  95. if ( empty( $wpmu_version ) && version_compare( get_bloginfo( 'version' ), ID_MIN_WP_VERSION, '<' ) ) {
  96. add_action( 'admin_head', 'id_wordpress_version_warning' );
  97. return;
  98. }
  99. // hooks onto incoming requests
  100. add_action( 'init', 'id_request_handler' );
  101. // IntenseDebate individual settings
  102. add_action( 'admin_notices', 'id_admin_notices' );
  103. // IntenseDebate server settings
  104. add_action( 'admin_menu', 'id_menu_items' );
  105. add_action( 'init', 'id_process_settings_page' );
  106. if ( id_do_admin_hooks() ) {
  107. // scripts for admin settings page
  108. add_action( "admin_head", 'id_settings_head' );
  109. // allow options.php to handle updates in WPMU and future WP versions
  110. add_filter( 'whitelist_options', 'id_whitelist_options' );
  111. // add comment counts in best way available
  112. if ( id_is_active() ) {
  113. if ( version_compare( get_bloginfo( 'version' ), '2.8', '>=' ) )
  114. add_action( 'admin_print_footer_scripts', 'id_get_comment_footer_script', 21 );
  115. else
  116. add_action( 'admin_footer', 'id_get_comment_footer_script', 100 );
  117. }
  118. }
  119. if ( is_admin() ) {
  120. // Always add comment moderation count in the admin area
  121. if ( version_compare( get_bloginfo( 'version' ), '2.8', '>=' ) )
  122. add_action( 'admin_print_footer_scripts', 'id_admin_footer', 21 );
  123. else
  124. add_action( 'admin_footer', 'id_admin_footer', 100 );
  125. }
  126. if ( id_is_active() ) {
  127. // crud hooks
  128. add_action( 'wp_insert_comment', 'id_save_comment' );
  129. add_action( 'trackback_post', 'id_save_comment' );
  130. add_action( 'pingback_post', 'id_save_comment' );
  131. add_action( 'edit_comment', 'id_save_comment' );
  132. add_action( 'save_post', 'id_save_post' );
  133. add_action( 'delete_post', 'id_delete_post' );
  134. add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 );
  135. add_action( 'trashed_comment', 'id_comment_trashed', 10 );
  136. add_action( 'untrashed_comment', 'id_comment_untrashed', 10 );
  137. // individual registration
  138. add_action( 'show_user_profile', 'id_show_user_profile' );
  139. add_action( 'profile_update', 'id_profile_update' );
  140. // Settings > Discussion sync
  141. add_action( 'load-options.php', 'id_discussion_settings_page' );
  142. // Load ID comment template
  143. if ( 0 == get_option( 'id_useIDComments') ) {
  144. if ( !id_is_mobile() || ( id_is_mobile() && 0 != get_option( 'id_revertMobile' ) ) ) {
  145. add_filter( 'comments_template', 'id_comments_template' );
  146. // swap out the comment count links
  147. add_filter( 'comments_number', 'id_get_comment_number' );
  148. add_action( 'wp_footer', 'id_get_comment_footer_script', 21 );
  149. add_action( 'get_footer', 'id_get_comment_footer_script', 100 );
  150. }
  151. }
  152. // Disable email notifications properly
  153. add_filter( 'option_moderation_notify', create_function( '$a', 'return 0;' ) );
  154. add_filter( 'option_comments_notify', create_function( '$a', 'return 0;' ) );
  155. }
  156. if ( id_is_active() || id_queue_not_empty() ) {
  157. // fires the outgoing HTTP request queue for ID synching
  158. add_action( 'shutdown', 'id_ping_queue' );
  159. }
  160. }
  161. // only load ID resources where they're needed
  162. function id_do_admin_hooks() {
  163. if ( !is_admin() )
  164. return false;
  165. $basename = basename( $_SERVER['PHP_SELF'] );
  166. // ID Comment moderation
  167. if ( 'admin.php' == $basename && !empty( $_REQUEST['page'] ) && 'intensedebate' == $_REQUEST['page'] )
  168. return true;
  169. // ID Settings page
  170. if ( 'options-general.php' == $basename && !empty( $_REQUEST['page'] ) && 'id_settings' == $_REQUEST['page'] )
  171. return true;
  172. // Whitelisted files
  173. if ( in_array( $basename, array( 'profile.php', 'options.php' ) ) )
  174. return true;
  175. // Posts/Pages when ID comment links are enabled
  176. if ( 0 == get_option( 'id_jsCommentLinks' ) && ( 'edit.php' == $basename || 'edit-pages.php' == $basename ) )
  177. return true;
  178. return false;
  179. }
  180. // adds new menu options to wp admin
  181. function id_menu_items() {
  182. // Replace the default Comments menu with the ID-enhanced one
  183. if ( id_is_active() && 0 == get_option( 'id_moderationPage' ) ) {
  184. global $menu;
  185. if ( function_exists( 'add_object_page' ) ) { // WP 2.7+
  186. unset( $menu[25] );
  187. add_object_page(
  188. __( 'Comments', 'intensedebate' ),
  189. __( 'Comments', 'intensedebate' ),
  190. 'moderate_comments',
  191. 'intensedebate',
  192. 'id_moderate_comments',
  193. WP_CONTENT_URL . '/plugins/intensedebate/comments.png'
  194. );
  195. } else { // < WP 2.7
  196. unset( $menu[20] );
  197. add_menu_page(
  198. __( 'Comments', 'intensedebate' ),
  199. __( 'Comments', 'intensedebate' ),
  200. 'moderate_comments',
  201. 'intensedebate',
  202. 'id_moderate_comments'
  203. );
  204. }
  205. }
  206. add_options_page(
  207. __( 'IntenseDebate Settings', 'intensedebate' ),
  208. 'IntenseDebate',
  209. 'manage_options',
  210. 'id_settings',
  211. 'id_settings_page'
  212. );
  213. if ( !get_option( 'id_pdxsync' ) )
  214. id_clear_orphan_comments();
  215. }
  216. function id_whitelist_options( $options ) {
  217. $options['intensedebate'] = array( 'id_auto_login', 'id_moderationPage', 'id_useIDComments', 'id_jsCommentLinks', 'id_revertMobile' );
  218. return $options;
  219. }
  220. function id_activate() {
  221. update_option( 'thread_comments', 1 );
  222. }
  223. register_activation_hook( __FILE__, 'id_activate' );
  224. function id_deactivate() {
  225. $fields = array(
  226. 'appKey' => ID_APPKEY,
  227. 'blogKey' => get_option( 'id_blogKey' ),
  228. 'blogid' => get_option( 'id_blogID' ),
  229. );
  230. $queue = id_get_queue();
  231. $op = $queue->add( 'plugin_deactivated', $fields, 'id_generic_callback' );
  232. $queue->ping( array( $op ) );
  233. }
  234. register_deactivation_hook( __FILE__, 'id_deactivate' );
  235. // UTILITIES
  236. // Load Snoopy if WP HTTP isn't here, and Snoopy's not already loaded (< WP 2.7 compat)
  237. if ( !function_exists( 'wp_remote_get' ) && !function_exists( 'get_snoopy' ) ) {
  238. function get_snoopy() {
  239. include_once( ABSPATH.'/wp-includes/class-snoopy.php' );
  240. return new Snoopy;
  241. }
  242. }
  243. function id_http_query( $url, $fields, $method = 'GET' ) {
  244. $results = '';
  245. if ( function_exists( 'wp_remote_get' ) ) {
  246. // The preferred WP HTTP library is available
  247. if ( 'POST' == $method ) {
  248. $response = wp_remote_post( $url, array( 'body' => $fields ) );
  249. if ( !is_wp_error( $response ) ) {
  250. $results = wp_remote_retrieve_body( $response );
  251. id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results );
  252. } else {
  253. id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $response->get_error_message() );
  254. }
  255. } else {
  256. $url .= '?' . http_build_query( $fields );
  257. $response = wp_remote_get( $url );
  258. if ( !is_wp_error( $response ) ) {
  259. $results = wp_remote_retrieve_body( $response );
  260. id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results );
  261. } else {
  262. id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $response->get_error_message() );
  263. }
  264. }
  265. } else {
  266. // Fall back to Snoopy
  267. $snoopy = get_snoopy();
  268. if ( 'POST' == $method ) {
  269. if ( $snoopy->submit( $url, $fields ) ) {
  270. $results = $snoopy->results;
  271. id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results );
  272. } else {
  273. id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $results );
  274. }
  275. } else {
  276. $url .= '?' . http_build_query( $fields );
  277. if ( $snoopy->fetch( $url ) ) {
  278. $results = $snoopy->results;
  279. id_debug_log( "Successfully Sent: " . serialize( $fields ) . " - " . $results );
  280. } else {
  281. id_debug_log( "Failed to Send: " . serialize( $fields ) . " - " . $results );
  282. }
  283. }
  284. }
  285. return $results;
  286. }
  287. // blog option
  288. function id_save_option( $name, $value ) {
  289. global $wpmu_version;
  290. if ( false === get_option( $name ) && empty( $wpmu_version ) ) { // Avoid WPMU options cache bug
  291. add_option( $name, $value, '', 'no' );
  292. } else {
  293. update_option( $name, $value );
  294. }
  295. id_debug_log( 'Save option: ' . $name . ' = ' . print_r( $value, true ) );
  296. }
  297. // user options
  298. function id_save_usermeta_array( $user_id, $meta = array() ) {
  299. foreach( $meta as $n => $v ) {
  300. id_save_usermeta( $user_id, $n, $v );
  301. }
  302. }
  303. // saves or wipes an individual meta field
  304. function id_save_usermeta( $user_id, $name, $value = null ) {
  305. if ( isset( $value ) && !empty( $value ) ) {
  306. update_usermeta( $user_id, $name, $value );
  307. } else {
  308. id_delete_user_meta( $user_id, $name );
  309. }
  310. }
  311. function id_user_connected() {
  312. $current_user = wp_get_current_user();
  313. $user_id = $current_user->ID;
  314. $userID = id_get_user_meta( $user_id, 'id_userID' );
  315. $userKey = id_get_user_meta( $user_id, 'id_userKey' );
  316. return ( $userID && $userKey );
  317. }
  318. // returns first non-null and non empty argment
  319. function id_coalesce() {
  320. $args = func_get_args();
  321. foreach ( $args as $v ) {
  322. if ( isset( $v ) && !empty( $v ) )
  323. return $v;
  324. }
  325. return null;
  326. }
  327. // hash generator
  328. function id_generate_token( $fields ) {
  329. return md5( time() . implode( '&', $fields ) );
  330. }
  331. // determines whether ID has been activated via the settings page
  332. function id_is_active() {
  333. return (
  334. get_option( 'id_blogID' ) &&
  335. get_option( 'id_blogKey' ) &&
  336. get_option( 'id_userID' ) &&
  337. get_option( 'id_userKey' ) &&
  338. get_option( 'id_blogAcct' )
  339. );
  340. }
  341. // pulls a passed parameter from indicated scopes
  342. function id_param( $name, $default = null, $scopes = null ) {
  343. if ( $scopes == null ) {
  344. $scopes = array( $_POST, $_GET );
  345. }
  346. foreach ( $scopes as $thisScope ) {
  347. if ( isset( $thisScope[$name] ) ) {
  348. return $thisScope[$name];
  349. }
  350. }
  351. return $default;
  352. }
  353. // inits queue object
  354. function id_get_queue() {
  355. global $id_q;
  356. if ( !$id_q ) {
  357. $id_q = new id_queue();
  358. }
  359. return $id_q;
  360. }
  361. // pings queue object
  362. function id_ping_queue() {
  363. $queue = id_get_queue();
  364. $queue->ping();
  365. }
  366. function id_queue_not_empty() {
  367. $queue = id_get_queue();
  368. $queue->load();
  369. if ( count( $queue->operations ) ) {
  370. return true;
  371. }
  372. else {
  373. return false;
  374. }
  375. }
  376. // deconstructs query string
  377. if ( !function_exists( 'http_parse_query' ) ) {
  378. function http_parse_query( $array = NULL, $convention = '%s' ) {
  379. if ( count( $array ) == 0 ) {
  380. return '';
  381. } else {
  382. if ( function_exists( 'http_build_query' ) ) {
  383. $query = http_build_query( $array );
  384. } else {
  385. $query = '';
  386. foreach ( $array as $key => $value ) {
  387. if ( is_array( $value ) ) {
  388. $new_convention = sprintf( $convention, $key ) . '[%s]';
  389. $query .= http_parse_query( $value, $new_convention );
  390. } else {
  391. $key = urlencode( $key );
  392. $value = urlencode( $value );
  393. $query .= sprintf( $convention, $key ) . "=$value&";
  394. }
  395. }
  396. }
  397. return $query;
  398. }
  399. }
  400. }
  401. // CRUD OPERATION HOOKS
  402. function id_save_comment( $comment_ID = 0 ) {
  403. if ( 0 == $comment_ID )
  404. return;
  405. $comment = new id_comment( array( 'comment_ID' => $comment_ID ) );
  406. $comment->loadFromWP();
  407. if ( $comment->comment_approved != 'spam' ) {
  408. // Don't send the spam
  409. $queue = id_get_queue();
  410. $queue->add( 'save_comment', $comment->export(), 'id_generic_callback' );
  411. }
  412. }
  413. function id_comment_status( $comment_id, $status ) {
  414. if ( $status == "delete" ) {
  415. $packet = new stdClass;
  416. $packet->comment_id = $comment_id;
  417. $packet->status = $status;
  418. $queue = id_get_queue();
  419. $queue->add( 'update_comment_status', $packet, 'id_generic_callback' );
  420. } else {
  421. $comment = new id_comment( array( 'comment_ID' => $comment_id ) );
  422. $comment->loadFromWP();
  423. if ( $status == "hold" )
  424. $comment->comment_approved = 0;
  425. if ( $status == "approve" )
  426. $comment->comment_approved = 1;
  427. if ( $status == "spam" )
  428. $comment->comment_approved = "spam";
  429. $queue = id_get_queue();
  430. $queue->add( 'save_comment', $comment->export(), 'id_generic_callback' );
  431. }
  432. }
  433. // Trash in WP == delete on ID
  434. function id_comment_trashed( $comment_id ) {
  435. id_comment_status( $comment_id, 'delete' );
  436. }
  437. // Untrash on WP == new comment on ID
  438. function id_comment_untrashed( $comment_id ) {
  439. id_save_comment( $comment_id );
  440. }
  441. function id_save_post( $post_id ) {
  442. $post = get_post( $post_id );
  443. if ( 0 == $post->post_parent || 'page' == $post->post_type ) {
  444. $p = new id_post( $post );
  445. $packet = $p->export();
  446. $queue = id_get_queue();
  447. $queue->add( 'save_post', $packet, 'id_generic_callback' );
  448. }
  449. }
  450. function id_delete_post( $post_id ) {
  451. $packet = new stdClass;
  452. $packet->post_id = $post_id;
  453. $queue = id_get_queue();
  454. $queue->add( 'delete_post', $packet, 'id_generic_callback' );
  455. }
  456. // callbacks return true to remove from queue
  457. function id_generic_callback( $result, $response, $operation ) {
  458. $args = func_get_args();
  459. if ( $result ) return true;
  460. if ( $response['attempt_retry'] ) return false;
  461. return true;
  462. }
  463. // DATA WRAPPERS
  464. class id_data_wrapper {
  465. var $properties = array();
  466. // generic constructor. You can pass in an array/stdClass of
  467. // values for $props and prepopulate your object either using
  468. // local or remote names
  469. function id_data_wrapper( $props = null, $bRemoteLabels = false ) {
  470. if ( isset( $props ) ) {
  471. if ( $bRemoteLabels ) {
  472. $this->loadFromRemote( $props );
  473. } else {
  474. $this->loadFromLocal( $props );
  475. }
  476. }
  477. }
  478. // registers a property with the object. $localname is the WordPress column
  479. // name and also the internal property name, $remoteName is the ID field name
  480. function addProp( $localName, $remoteName = null, $defaultValue = null ) {
  481. $remoteName = isset( $remoteName ) ? $remoteName : $localName;
  482. $this->properties[$localName] = $remoteName;
  483. $this->$localName = $defaultValue;
  484. }
  485. // loads object with props from passed object, assumption is that the passed
  486. // object is keyed using local variable names
  487. function loadFromLocal( $o ) {
  488. $incomingProps = $this->scrubInputHash($o);
  489. foreach ( $this->properties as $local => $remote ) {
  490. if ( isset( $incomingProps[$local] ) ) {
  491. $this->$local = $incomingProps[$local];
  492. }
  493. }
  494. }
  495. // loads object with props from remote object hash
  496. function loadFromRemote( $o ) {
  497. $props = array_flip( $this->properties );
  498. $incomingProps = $this->scrubInputHash( $o );
  499. foreach( $props as $remote => $local ) {
  500. if ( isset( $incomingProps[$remote] ) ) {
  501. $this->$local = $incomingProps[$remote];
  502. }
  503. }
  504. }
  505. // makes an array out of whatever is passed in
  506. function scrubInputHash( $o ) {
  507. $incomingProps = $o;
  508. if ( !is_array( $o ) ) {
  509. $incomingProps = get_object_vars( $o );
  510. }
  511. return $incomingProps;
  512. }
  513. function loadFromRemoteJson( $jsonString ) {
  514. $o = json_decode( $jsonString );
  515. $this->loadFromRemote( $o );
  516. }
  517. // exports object properties into remote property names
  518. function export( $bRemote = true ) {
  519. $o = array();
  520. foreach ( $this->properties as $local => $remote ) {
  521. if ( $remote == "comment_text" )
  522. $o[$remote] = trim( $this->$local ); // trim the comment text
  523. else
  524. $o[$remote] = $this->$local;
  525. }
  526. return $o;
  527. }
  528. function props() {
  529. $props = array();
  530. foreach ( $this->properties as $n => $v ) {
  531. $props[$n] = $this->$n;
  532. }
  533. return $props;
  534. }
  535. }
  536. // COMMENT WRAPPER
  537. class id_comment extends id_data_wrapper {
  538. var $post = null;
  539. function id_comment( $props = null, $bRemoteLabels = false ) {
  540. $this->addProp( 'intensedebate_id' );
  541. $this->addProp( 'comment_ID', 'comment_id' );
  542. $this->addProp( 'comment_post_ID', 'comment_post_id' );
  543. $this->addProp( 'comment_author' );
  544. $this->addProp( 'comment_author_email' );
  545. $this->addProp( 'comment_author_url' );
  546. $this->addProp( 'comment_author_IP', 'comment_author_ip' );
  547. $this->addProp( 'comment_date' );
  548. $this->addProp( 'comment_date_gmt' );
  549. $this->addProp( 'comment_content', 'comment_text' );
  550. // $this->addProp( 'comment_karma' );
  551. $this->addProp( 'comment_approved', 'comment_status' );
  552. $this->addProp( 'comment_agent' );
  553. $this->addProp( 'comment_type' );
  554. $this->addProp( 'comment_parent' );
  555. $this->addProp( 'user_id' );
  556. $this->id_data_wrapper( $props, $bRemoteLabels );
  557. }
  558. // loadFromWP
  559. // loads comment from WP database
  560. function loadFromWP() {
  561. if ( $this->comment_ID ) {
  562. $wp_comment = get_comment( $this->comment_ID, ARRAY_A );
  563. $this->loadFromLocal( $wp_comment );
  564. }
  565. }
  566. // saves back to WP database
  567. function save() {
  568. // Invalid comment?
  569. if ( !$this->valid() )
  570. return false;
  571. if ( empty( $this->comment_date ) && !empty( $this->comment_date_gmt ) )
  572. $this->comment_date = get_date_from_gmt( $this->comment_date_gmt );
  573. $result = 0;
  574. remove_action( 'edit_comment', 'id_save_comment' );
  575. remove_action( 'wp_insert_comment', 'id_save_comment' );
  576. if ( $this->comment_ID && get_comment( $this->comment_ID ) ) { // Added by duplicateCheck() if matched against existing comment
  577. $result = wp_update_comment( $this->props() );
  578. } else {
  579. $result = wp_insert_comment( wp_filter_comment( $this->props() ) );
  580. if ( !$result ) {
  581. add_action( 'edit_comment', 'id_save_comment' );
  582. add_action( 'wp_insert_comment', 'id_save_comment' );
  583. return false;
  584. }
  585. $this->comment_ID = $result;
  586. }
  587. add_action( 'edit_comment', 'id_save_comment' );
  588. add_action( 'wp_insert_comment', 'id_save_comment' );
  589. return true;
  590. }
  591. // evaluates whether the comment is valid
  592. function valid() {
  593. $this->duplicateCheck();
  594. return ( !empty( $this->comment_content ) && is_numeric( $this->comment_post_ID ) );
  595. }
  596. // based on code in wp_allow_comment, updates internal reference so that updates happen on duplicates
  597. function duplicateCheck() {
  598. global $wpdb;
  599. extract( $this->props() );
  600. // SQL to check for duplicate comment post
  601. $dupe = $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND ( comment_author = %s ", $comment_post_ID, $comment_author );
  602. if ( $comment_author_email )
  603. $dupe .= $wpdb->prepare( "OR comment_author_email = %s ", $comment_author_email );
  604. $dupe .= $wpdb->prepare( ") AND comment_content = %s LIMIT 1", $comment_content );
  605. // Duplicates don't actually cause an error, they just update the comment_ID internally to force an update
  606. if ( $id = $wpdb->get_var( $dupe ) )
  607. $this->comment_ID = $id;
  608. }
  609. // associated post parent object
  610. function post() {
  611. if ( !$this->post ) {
  612. $this->post = new id_post( get_post( $this->comment_post_ID, ARRAY_A ) );
  613. }
  614. return $this->post;
  615. }
  616. function export() {
  617. $o = parent::export();
  618. $p = $this->post();
  619. $o['post'] = $p->export();
  620. return $o;
  621. }
  622. // the intensedebate_id actually has to be stored with the post because
  623. // there is no comment metadata
  624. function intensedebate_id( $intensedebate_id = null ) {
  625. $post = $this->post();
  626. return $post->setRemoteID( $this->comment_ID, $intensedebate_id );
  627. }
  628. }
  629. // POST WRAPPER
  630. class id_post extends id_data_wrapper {
  631. function id_post( $props = null, $bRemoteLabels = false ) {
  632. $this->addProp( 'ID', 'postid' );
  633. $this->addProp( 'post_title', 'title' );
  634. $this->addProp( 'guid' );
  635. $this->addProp( 'url' );
  636. $this->addProp( 'post_author_name', 'author' );
  637. $this->addProp( 'post_author', 'authorid' );
  638. $this->addProp( 'post_modified_gmt', 'date_gmt' );
  639. $this->addProp( 'comment_status' );
  640. $this->addProp( 'ping_status' );
  641. // load passed props
  642. $this->id_data_wrapper( $props, $bRemoteLabels );
  643. // load up inferred props
  644. $this->loadProprietaryProps();
  645. }
  646. function loadProprietaryProps() {
  647. if ( $this->post_author ) {
  648. $a = get_userdata( $this->post_author );
  649. $this->post_author_name = trim( $a->display_name );
  650. }
  651. }
  652. // need the category names in an array
  653. function categories() {
  654. if ( function_exists( 'wp_get_post_categories' ) ) {
  655. $category_ids = (array) wp_get_post_categories( $this->ID );
  656. $categories = array();
  657. foreach ( $category_ids as $id ) {
  658. $c = get_category( $id );
  659. $categories[] = $c->cat_name;
  660. }
  661. } else {
  662. global $wpdb;
  663. $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 );
  664. $categories = array();
  665. foreach ( $results as $row ) {
  666. $categories[] = $row['cat_name'];
  667. }
  668. }
  669. return $categories;
  670. }
  671. function comments() {
  672. return null;
  673. }
  674. function export() {
  675. $me = parent::export();
  676. $me['comments'] = $this->comments();
  677. $me['categories'] = $this->categories();
  678. $me['url'] = get_permalink( $this->ID );
  679. return $me;
  680. }
  681. function mapCategory( $categoryID ) {
  682. $c = get_category( $categoryID );
  683. return $c->name;
  684. }
  685. function mapComment( $o ) {
  686. return $o->comment_ID;
  687. }
  688. function save() {
  689. if ( !$this->valid() )
  690. return false;
  691. // watch for text-link-ads.com plugin
  692. if ( function_exists( "tla_send_updated_post_alert" ) )
  693. remove_action( 'edit_post', 'tla_send_updated_post_alert' );
  694. remove_action( 'save_post', 'id_save_post' );
  695. $result = wp_update_post( get_object_vars( $this ) );
  696. add_action( 'save_post', 'id_save_post' );
  697. // add hooks for text-link-ads.com back in
  698. if ( function_exists( "tla_send_updated_post_alert" ) )
  699. add_action( 'edit_post', 'tla_send_updated_post_alert' );
  700. return $result;
  701. }
  702. function valid() {
  703. return $this->ID;
  704. }
  705. }
  706. // QUEUE
  707. class id_queue_operation {
  708. var $action, $callback, $operation_id, $time_gmt, $data, $response, $success;
  709. function id_queue_operation( $action, $data, $callback = null ) {
  710. $this->action = $action;
  711. $this->callback = $callback;
  712. $this->data = $data;
  713. $this->time_gmt = gmdate( "Y-m-d H:i:s" );
  714. $this->operation_id = $this->id();
  715. $this->success = false;
  716. $this->wp_version = get_bloginfo( 'version' );
  717. $this->id_plugin_version = ID_PLUGIN_VERSION;
  718. }
  719. function id() {
  720. return md5( $this->action . $this->callback . $this->time_gmt . serialize( $this->data ) );
  721. }
  722. }
  723. class id_queue {
  724. var $queueName = ID_REQUEST_QUEUE_NAME;
  725. var $url = ID_SERVICE;
  726. var $operations = array();
  727. var $needs_save = false;
  728. function id_queue() {
  729. $this->load();
  730. }
  731. function load() {
  732. $this->operations = get_option( $this->queueName );
  733. if ( !is_array( $this->operations ) ) {
  734. $this->create();
  735. }
  736. }
  737. function create() {
  738. $this->operations = array();
  739. }
  740. function store() {
  741. if ( $this->needs_save ) {
  742. $this->compact_operations();
  743. id_save_option( $this->queueName, $this->operations );
  744. }
  745. }
  746. function compact_operations() {
  747. $num_ops = count( $this->operations );
  748. for ( $o = 0; $o < $num_ops; $o++ ) {
  749. if ( in_array( $this->operations[ $o ]->action, array( 'save_comment', 'comment_status' ) ) && isset( $this->operations[ $o ]->data['comment_id'] ) ) {
  750. $this->operations[ $o ]->data = array( 'comment_id' => $this->operations[ $o ]->data['comment_id'] );
  751. }
  752. }
  753. }
  754. function add( $action, $data, $callback = null ) {
  755. $op = new id_queue_operation( $action, $data, $callback );
  756. return $this->queue( $op );
  757. }
  758. function queue( $operation ) {
  759. $this->needs_save = true;
  760. if ( in_array( $operation->action, array( 'save_comment', 'comment_status' ) ) && isset( $operation->data->comment_id ) )
  761. $operation->data = array( 'comment_id' => $operation->data->comment_id );
  762. $this->operations[] = $operation;
  763. return $operation;
  764. }
  765. function ping( $operations = null ) {
  766. $this->process( $this->send( $operations ) );
  767. $this->store();
  768. }
  769. function send( $operations = null ) {
  770. if ( null == $operations )
  771. $operations = $this->operations;
  772. if ( !count( $operations ) )
  773. return false;
  774. if ( get_option( 'id_lock_queue' ) && get_option( 'id_lock_queue' ) > time() )
  775. return false;
  776. // Filter out/limit requests
  777. $count = 0;
  778. $send = array();
  779. $hold = array();
  780. foreach ( $operations as $op ) {
  781. // Got enough requests for this time?
  782. // Sent less than 30s ago?
  783. if ( $count >= 10 || ( !empty( $op->running ) && ( time() - $op->running < 30 ) ) ) {
  784. $hold[] = $op;
  785. continue;
  786. }
  787. // Refresh comment data for certain requests
  788. if ( !empty( $op->action )
  789. && in_array( $op->action, array( 'save_comment', 'comment_status' ) )
  790. && !empty( $op->data )
  791. && isset( $op->data[ 'comment_id' ] )
  792. && ( 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
  793. $comment = new id_comment( array( 'comment_ID' => $op->data[ 'comment_id' ] ) );
  794. $comment->loadFromWP();
  795. $data = $comment->export();
  796. $op->data = $data;
  797. }
  798. // Send this one along with a timestamp to avoid doubling up
  799. $op->running = time();
  800. $send[] = $op;
  801. $count++;
  802. }
  803. // Update queue to save timestamps
  804. $this->needs_save = true;
  805. $this->operations = array_merge( $hold, $send );
  806. $fields = array(
  807. 'appKey' => ID_APPKEY,
  808. 'blogKey' => get_option( 'id_blogKey' ),
  809. 'blogid' => get_option( 'id_blogID' ),
  810. 'operations' => json_encode( $send )
  811. );
  812. $this->store();
  813. if ( !count( $send ) )
  814. return false;
  815. return id_http_query( $this->url . '?blogid=' . urlencode( get_option( 'id_blogID' ) ), $fields, 'POST' );
  816. }
  817. function process( $rawResults ) {
  818. // HTTP request failed? Leave queue alone and attempt to resend later
  819. if ( false == $rawResults )
  820. return;
  821. // Need to update queue when we're done
  822. $this->needs_save = true;
  823. // Decode results string
  824. $results = json_decode( $rawResults );
  825. // flip the array around using operation_id as the key
  826. $results = $this->reIndex( $results, 'operation_id' );
  827. // loop through current queue and see if there are results for them
  828. $newQueue = array();
  829. foreach ( $this->operations as $operation ) {
  830. if ( isset( $results[ $operation->operation_id ] ) ) {
  831. $result = $results[ $operation->operation_id ];
  832. if ( isset( $operation->callback ) && function_exists( $operation->callback ) ) {
  833. // callback returns true == remove from queue
  834. // callback returns false == add back to queue
  835. $finished = call_user_func_array( $operation->callback, array( "result" => &$result->result, "response" => &$result->response, "operation" => &$operation ) );
  836. $operation->success = $finished;
  837. $operation->response = $result->response;
  838. if ( !$finished ) {
  839. $newQueue[] = $operation;
  840. }
  841. }
  842. } else {
  843. // no result returned for that operation, requeue
  844. $newQueue[] = $operation;
  845. }
  846. }
  847. // store new queue
  848. $this->operations = $newQueue;
  849. }
  850. function testResults() {
  851. $results = array();
  852. foreach ( $this->operations as $op ) {
  853. $result = new stdClass;
  854. $result->operation_id = $op->operation_id;
  855. $result->result = $op->data;
  856. $results[] = $result;
  857. }
  858. return json_encode( $results );
  859. }
  860. function reIndex( $arrIn, $prop ) {
  861. $arrOut = array();
  862. if ( isset( $arrIn ) ) {
  863. foreach ( $arrIn as $item ) {
  864. $arrOut[$item->$prop] = $item;
  865. }
  866. }
  867. return $arrOut;
  868. }
  869. }
  870. // REST SERVICE FUNCS
  871. function id_request_handler() {
  872. global $wpmu_version;
  873. // Blanket protection against accidental access to edit-comments.php
  874. $basename = basename( $_SERVER['REQUEST_URI'] );
  875. if ( stristr( $basename, '?' ) )
  876. $basename = substr( $basename, 0, strpos( $basename, '?' ) );
  877. if ( 0 == get_option( 'id_moderationPage') && 'edit-comments.php' == $basename )
  878. wp_redirect( get_bloginfo( 'wpurl' ) . '/wp-admin/admin.php?page=intensedebate' );
  879. // determine requested action
  880. $action = id_param( 'id_action' );
  881. if ( !$action )
  882. return;
  883. id_debug_log( 'Request for: ' . $action );
  884. // translated func name
  885. $fn = 'id_REST_' . $action;
  886. if ( !function_exists( $fn ) ) {
  887. id_debug_log( 'Unknown action requested: ' . $fn );
  888. id_request_error( 'Unknown action: ' . $fn );
  889. return;
  890. }
  891. if ( 'id_REST_test_connection' == $fn ) {
  892. id_response_render( call_user_func( $fn ) );
  893. }
  894. // token key
  895. $token = id_param( 'id_token' );
  896. if ( $token !== get_option( 'id_import_token' ) ) {
  897. id_request_error( 'Missing or invalid token' );
  898. return;
  899. }
  900. // calls named func
  901. $result = call_user_func( $fn );
  902. //id_debug_log( 'Response: ' . print_r( $result, true ) );
  903. id_response_render( $result );
  904. }
  905. function id_request_error( $msg ) {
  906. $result = new stdClass();
  907. $result->success = false;
  908. $result->error = $msg;
  909. id_response_render( $result );
  910. }
  911. function id_request_message( $msg ) {
  912. $result = new stdClass();
  913. $result->success = true;
  914. $result->data = null;
  915. $result->message = $msg;
  916. id_response_render( $result );
  917. }
  918. function id_response_render( $result, $contentType = "application/json" ) {
  919. while ( @ob_end_clean() ) {} // Clear all buffers
  920. $charSet = get_bloginfo( 'charset' );
  921. header( "Content-Type: {$contentType}; charset={$charSet}" );
  922. die( json_encode( $result ) );
  923. }
  924. function id_REST_ping() {
  925. return array( 'id_plugin_version' => ID_PLUGIN_VERSION, 'wp_version' => ( !empty( $wpmu_version ) ? 'WPMU/' : '' ) . get_bloginfo( 'version' ) );
  926. }
  927. function id_REST_test_connection() {
  928. if ( !empty( $_POST['hash'] ) )
  929. return array( 'hash' => preg_replace( '/[^a-f0-9]/', '', $_POST['hash'] ), 'random' => md5( mt_rand( 0, 1000 ) ) );
  930. else
  931. wp_redirect( get_option( 'siteurl' ) );
  932. }
  933. function id_REST_get_comments_by_user() {
  934. global $wpdb;
  935. $email = id_param( 'id_email', false );
  936. $postid = id_param( 'id_postid', false );
  937. $where = array();
  938. if ( $email )
  939. $where[] = $wpdb->prepare( "comment_author_email = %s", $email );
  940. if ( $postid )
  941. $where[] = $wpdb->prepare( "comment_post_ID = %d", $postid );
  942. if ( !count( $where ) )
  943. id_request_error( "Must supply id_email and optionally id_postid." );
  944. $where[] = "comment_approved = 1";
  945. $results = $wpdb->get_results( "SELECT * FROM {$wpdb->comments} WHERE " . implode( ' AND ', $where ) . " ORDER BY comment_ID DESC" );
  946. if ( !count( $results ) ) {
  947. id_request_message( 'No comments' );
  948. return array();
  949. }
  950. return array_map( "id_export_comment", $results );
  951. }
  952. // ACTION: import
  953. function id_REST_import() {
  954. global $wpdb;
  955. $curr_params = array();
  956. $tot_params = array();
  957. $remaining_params = array();
  958. $post_where = '';
  959. $post = id_param( 'id_post_id', false );
  960. if ( false != $post ) {
  961. $post_where = ' comment_post_ID = ' . (int) $post . ' AND';
  962. $tot_params[] = $post;
  963. $remaining_params[] = $post;
  964. }
  965. $current = get_option( 'id_import_comment_id' ); // Defaults to 0
  966. if ( $current >= id_get_latest_comment_id() )
  967. id_request_message( 'Import complete.' );
  968. $import_offset = id_param( 'id_start_cid', 0 );
  969. if ( $import_offset < 0 )
  970. id_request_error( 'Start commentid must be a non-negative integer.' );
  971. if ( $import_offset > 0 )
  972. $current = $import_offset;
  973. id_debug_log( "Initiating import response with current = $current" );
  974. $sql = "SELECT * FROM {$wpdb->comments} WHERE$post_where comment_ID >= " . (int) $current . " AND comment_approved != 'spam' ORDER BY comment_ID ASC LIMIT 100";
  975. id_debug_log( $sql );
  976. $results = $wpdb->get_results( $sql );
  977. if ( !count( $results ) ) {
  978. id_debug_log( 'No comments to import.' );
  979. id_save_option( 'id_signup_step', 3 );
  980. id_request_message( 'Import complete.' );
  981. }
  982. // Update each comment to use "external" names
  983. $comments = array_map( "id_export_comment", $results );
  984. // mark the next comment_id for the next import request
  985. $lastCommentIndex = count( $comments ) - 1;
  986. $next_id = max( 0, (int) $comments[$lastCommentIndex]['comment_id'] + 1 );
  987. id_save_option( 'id_import_comment_id', $next_id );
  988. $result = new stdClass;
  989. $result->totalCommentCount = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE$post_where comment_approved != 'spam'", $tot_params ) );
  990. $remaining_params[] = $next_id;
  991. $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 ) );
  992. $result->time_gmt = gmdate( "Y-m-d H:i:s" );
  993. $result->time = date( "Y-m-d H:i:s" );
  994. $result->success = "true";
  995. $result->next_id = $next_id;
  996. $result->data = $comments;
  997. return $result;
  998. }
  999. function id_export_comment( $o ) {
  1000. $c = new id_comment( $o );
  1001. return $c->export();
  1002. }
  1003. // ACTION: sync moderation settings from ID
  1004. function id_REST_sync_moderation_settings() {
  1005. $settings = id_param( 'settings' );
  1006. if ( empty( $settings ) )
  1007. return 'false';
  1008. id_debug_log( 'Updating moderation settings: ' . print_r( $settings, true ) );
  1009. // Decode and UnJSON the settings so we can work with them
  1010. $settings = rawurldecode( stripslashes( $settings ) );
  1011. $opt = json_decode( $settings );
  1012. // Moderation links
  1013. if ( isset( $opt->min_links_for_moderations ) )
  1014. update_option( 'comment_max_links', $opt->min_links_for_moderations );
  1015. // Update all the boolean values
  1016. if ( 'T' == $opt->all_comments_require_approval )
  1017. update_option( 'comment_moderation', '1' );
  1018. else if ( 'F' == $opt->all_comments_require_approval )
  1019. update_option( 'comment_moderation', '' );
  1020. if ( 'T' == $opt->require_previously_approved )
  1021. update_option( 'comment_whitelist', '1' );
  1022. else if ( 'F' == $opt->require_previously_approved )
  1023. update_option( 'comment_whitelist', '' );
  1024. if ( 'T' == $opt->email_new_comments )
  1025. update_option( 'comments_notify', '1' );
  1026. else if ( 'F' == $opt->email_new_comments )
  1027. update_option( 'comments_notify', '' );
  1028. if ( 'T' == $opt->email_requires_moderation )
  1029. update_option( 'moderation_notify', '1' );
  1030. else if ( 'F' == $opt->email_requires_moderation )
  1031. update_option( 'moderation_notify', '' );
  1032. if ( 'T' == $opt->show_threads )
  1033. update_option( 'thread_comments', '1' );
  1034. else if ( 'F' == $opt->show_threads )
  1035. update_option( 'thread_comments', '' );
  1036. // Need to do some magic on the moderate/blacklist strings
  1037. if ( isset( $opt->moderate_words ) || isset( $opt->moderate_ips ) || isset( $opt->moderate_emails ) ) {
  1038. if ( !isset( $opt->moderate_words ) ) $opt->moderate_words = '';
  1039. if ( !isset( $opt->moderate_ips ) ) $opt->moderate_ips = '';
  1040. if ( !isset( $opt->moderate_emails ) ) $opt->moderate_emails = '';
  1041. $moderate_words = explode( ' ', $opt->moderate_words );
  1042. $moderate_ips = explode( ' ', $opt->moderate_ips );
  1043. $moderate_emails = explode( ' ', $opt->moderate_emails );
  1044. $moderate = array_merge( $moderate_words, $moderate_ips, $moderate_emails );
  1045. $moderate = implode( "\n", id_cleanup_moderation_array( $moderate ) );
  1046. update_option( 'moderation_keys', $moderate );
  1047. }
  1048. if ( isset( $opt->blacklisted_words ) || isset( $opt->blacklisted_ips ) || isset( $opt->blacklisted_emails ) ) {
  1049. if ( !isset( $opt->blacklisted_words ) ) $opt->blacklisted_words = '';
  1050. if ( !isset( $opt->blacklisted_ips ) ) $opt->blacklisted_ips = '';
  1051. if ( !isset( $opt->blacklisted_emails ) ) $opt->blacklisted_emails = '';
  1052. $blacklist_words = explode( ' ', $opt->blacklisted_words );
  1053. $blacklist_ips = explode( ' ', $opt->blacklisted_ips );
  1054. $blacklist_emails = explode( ' ', $opt->blacklisted_emails );
  1055. $blacklist = array_merge( $blacklist_words, $blacklist_ips, $blacklist_emails );
  1056. $blacklist = implode( "\n", id_cleanup_moderation_array( $blacklist ) );
  1057. update_option( 'blacklist_keys', $blacklist );
  1058. }
  1059. if ( 'T' == $opt->akismet && get_option( 'wordpress_api_key' ) )
  1060. return get_option( 'wordpress_api_key' );
  1061. else
  1062. return 'true';
  1063. }
  1064. function id_cleanup_moderation_array( $arr ) {
  1065. $clean = array();
  1066. foreach ( $arr as $val ) {
  1067. $val = trim( $val );
  1068. if ( !$val )
  1069. continue;
  1070. if ( !in_array( $val, $clean ) )
  1071. $clean[] = $val;
  1072. }
  1073. return $clean;
  1074. }
  1075. // ACTION: save_comment
  1076. // Enter a new comment in to the system
  1077. function id_REST_save_comment() {
  1078. $rawComment = stripslashes( id_param( 'id_comment_data' ) );
  1079. id_debug_log( "Receive Comment: $rawComment" );
  1080. $comment = new id_comment();
  1081. $comment->loadFromRemoteJson( $rawComment );
  1082. $result = array(
  1083. 'success' => $comment->save(),
  1084. 'comment' => $comment->export()
  1085. );
  1086. if ( 'delete' == $comment->comment_status ) {
  1087. remove_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 );
  1088. wp_delete_comment( $comment->comment_ID );
  1089. add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 );
  1090. }
  1091. return $result;
  1092. }
  1093. // ACTION: set_comment_status
  1094. // ***Deleting is done by passing status=delete
  1095. function id_REST_set_comment_status() {
  1096. $newStatus = id_param( 'status', '' );
  1097. $comment_id = id_param( 'comment_id', 0 );
  1098. $rawComment = stripslashes( id_param( 'comment_data' ) );
  1099. if ( !$comment_id ) {
  1100. if ( !$rawComment )
  1101. return false;
  1102. $comment = new id_comment();
  1103. $comment->loadFromRemoteJson( $rawComment );
  1104. $comment->duplicateCheck(); // Will locate a match and update with the WP id
  1105. if ( $comment->comment_ID ) {
  1106. // Found it, carry on
  1107. $comment_id = $comment->comment_ID;
  1108. } else {
  1109. // No match
  1110. if ( 'delete' == $newStatus )
  1111. return true; // We were going to delete it anyway
  1112. else
  1113. return false;
  1114. }
  1115. }
  1116. id_debug_log( "Receive Comment Status: $newStatus $comment_id" );
  1117. // Check if the status is already set, if so, still return true
  1118. if ( $newStatus == wp_get_comment_status( $comment_id ) )
  1119. return true;
  1120. 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)
  1121. return true;
  1122. else if ( $newStatus == "hold" && wp_get_comment_status( $comment_id ) == "unapproved" )
  1123. return true;
  1124. // If not already set, then rename to local status, then attempt to set it and return the result
  1125. remove_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 );
  1126. if ( 'delete' == $newStatus )
  1127. $result = wp_delete_comment( $comment_id );
  1128. else
  1129. $result = wp_set_comment_status( $comment_id, $newStatus );
  1130. add_action( 'wp_set_comment_status', 'id_comment_status', 10, 2 );
  1131. return $result;
  1132. }
  1133. // ACTION: save_post
  1134. function id_REST_save_post() {
  1135. $rawPost = stripslashes( id_param( 'id_post_data' ) );
  1136. id_debug_log( "Receive Post Status: $rawPost" );
  1137. $data = json_decode( $rawPost );
  1138. if ( !isset( $data->postid ) )
  1139. return false;
  1140. // Load current post
  1141. $post = new id_post( get_post( $data->postid ) );
  1142. // Replace any incoming values
  1143. foreach ( $data as $key => $val ) {
  1144. if ( isset( $post->$key ) ) {
  1145. $post->$key = $val;
  1146. }
  1147. }
  1148. return array(
  1149. 'success' => $post->save(),
  1150. 'post' => $post->export()
  1151. );
  1152. }
  1153. // ACTION: reset queue
  1154. function id_REST_reset_queue() {
  1155. $queue = id_get_queue();
  1156. $queue->create();
  1157. return true;
  1158. }
  1159. // ACTION: get all operations queued in WP
  1160. function id_REST_get_queue() {
  1161. $queue = id_get_queue();
  1162. $queue->load();
  1163. return $queue->operations;
  1164. }
  1165. // ACTION: cancel a specific operation
  1166. function id_REST_cancel_operation() {
  1167. $queue = id_get_queue();
  1168. $queue->load();
  1169. $hash = id_param( 'id_operation_hash', false );
  1170. if ( !$hash )
  1171. return array( 'success' => false, 'hash' => $hash, 'operations' => count( $queue->operations ) );
  1172. $new_ops = array();
  1173. foreach ( $queue->operations as $operation ) {
  1174. if ( $hash != $operation->operation_id )
  1175. $new_ops[] = $operation;
  1176. }
  1177. $queue->operations = $new_ops;
  1178. $queue->needs_save = true;
  1179. $queue->store();
  1180. return array( 'success' => true, 'hash' => $hash, 'operations' => count( $new_ops ) );
  1181. }
  1182. // ACTION: restart import
  1183. function id_REST_reset_import() {
  1184. id_save_option( 'id_import_comment_id', '0' );
  1185. return true;
  1186. }
  1187. // ACTION: return the highest comment id in WP
  1188. function id_REST_get_last_wp_comment_id() {
  1189. return id_get_latest_comment_id();
  1190. }
  1191. // ACTION: get the total number of approved comments
  1192. // optionally provide &post_id= to get count for a specific post only
  1193. function id_REST_get_approved_comment_count() {
  1194. include_once ABSPATH . '/wp-admin/includes/template.php';
  1195. if ( $p = id_param( 'post_id', 0 ) )
  1196. $result = wp_count_comments( $p );
  1197. else
  1198. $result = wp_count_comments();
  1199. return $result->approved;
  1200. }
  1201. // ACTION: Lock queue from sending requests for the next x seconds
  1202. function id_REST_lock_queue() {
  1203. $lock = id_param( 'id_lock_period', 300 ); // Defaults to 5 mins
  1204. update_option( 'id_lock_queue', ( time() + $lock ) );
  1205. return get_option( 'id_lock_queue' );
  1206. }
  1207. // AUTOLOGIN
  1208. // drops autologin js after user has logged in via profile page, makes it so
  1209. // user does not need to login to IntenseDebate if they've already logged in here
  1210. function id_auto_login() {
  1211. global $userdata;
  1212. if ( empty( $userdata->ID ) || get_option( 'id_auto_login' ) == 1 )
  1213. return false;
  1214. $wp_userID = $userdata->ID;
  1215. $appKey = ID_APPKEY;
  1216. $userID = id_get_user_meta( $wp_userID, 'id_userID' );
  1217. $userKey = id_get_user_meta( $wp_userID, 'id_userKey' );
  1218. if ( id_user_connected() ) {
  1219. echo "<script type=\"text/javascript\" src=\"" . ID_BASEURL . "/services/v1/jsLogin.php?appKey={$appKey}&amp;userid={$userID}&amp;userKey={$userKey}\"></script>\n";
  1220. }
  1221. }
  1222. // ADMIN BANNERS
  1223. // displays prompt to login on the admin pages if user has not logged into IntenseDebate
  1224. function id_admin_notices() {
  1225. // global administrative settings prompt
  1226. if ( !id_is_active() && !empty( $_GET['page'] ) && $_GET['page'] != 'id_settings' ) {
  1227. $settingsurl = get_bloginfo( 'wpurl' ) . '/wp-admin/options-general.php?page=id_settings';
  1228. ?>
  1229. <div class="updated fade-ff0000">
  1230. <p><strong><?php printf( __( 'The IntenseDebate plugin is enabled but you need to adjust <a href="%s">your settings</a>.', 'intensedebate' ), $settingsurl ); ?></strong></p>
  1231. </div>
  1232. <?php
  1233. return;
  1234. }
  1235. // user profile settings prompt
  1236. if ( !id_user_connected() && !empty( $_GET['page'] ) && $_GET['page'] != 'id_settings' && $_GET['page'] != 'id_registration' ) {
  1237. $profileurl = get_bloginfo( 'wpurl' ) . '/wp-admin/profile.php#intensedebatelogin';
  1238. ?>
  1239. <div class="updated fade-ff0000">
  1240. <p><strong><?php printf( __( 'Connect to your IntenseDebate account. Go to your <a href="%s">WordPress profile</a> to log in or register.', 'intensedebate' ), $profileurl ); ?></strong></p>
  1241. </div>
  1242. <?php
  1243. return;
  1244. }
  1245. // import reset via link
  1246. if ( isset( $_GET['id_reset'] ) && 'true' == $_GET['id_reset'] ) {
  1247. ?>
  1248. <div class="updated fade-ff0000">
  1249. <p><strong><?php _e( 'Your comments are now being re-imported in the background.', 'intensedebate' ); ?></strong></p>
  1250. </div>
  1251. <?php
  1252. return;
  1253. }
  1254. }
  1255. function id_wordpress_version_warning() {
  1256. ?>
  1257. <div class="updated fade-ff0000">
  1258. <p><strong><?php printf( __( "We're sorry, but the IntenseDebate plugin is not supported for versions of WordPress lower than %s.", 'intensedebate' ), ID_MIN_WP_VERSION ); ?></strong></p>
  1259. </div>
  1260. <?php
  1261. }
  1262. // PROFILE PAGE
  1263. function id_show_user_profile() {
  1264. if ( id_user_connected() ) {
  1265. id_show_user_disconnect();
  1266. return;
  1267. }
  1268. global $userdata;
  1269. $id_username = id_coalesce( $userdata->id_username );
  1270. ?>
  1271. <a name="intensedebatelogin">&nbsp;</a><br/>
  1272. <h2><img src="<?php echo ID_BASEURL ?>/images/intensedebate.png" alt="IntenseDebate Logo" class="idwp-logo" /> <?php _e( 'User Synchronization', 'intensedebate' ); ?></h2>
  1273. <table class="form-table">
  1274. <tbody>
  1275. <tr>
  1276. <th><label for="id_username"><?php _e( 'Username', 'intensedebate' ); ?></label></th>
  1277. <td><input type="text" id="id_username" name="id_username" value="<?php echo $id_username; ?>" /></td>
  1278. </tr>
  1279. <tr>
  1280. <th><label for="id_password"><?php _e( 'Password', 'intensedebate' ); ?></label></th>
  1281. <td><input type="password" id="id_password" class="required" name="id_password" value="" /></td>
  1282. </tr>
  1283. </tbody>
  1284. </table>
  1285. <p><?php printf( __( 'Not registered with IntenseDebate yet? <a target="_blank" href="%s">It\'s easy</a>.', 'intensedebate' ), ID_REGISTRATION_PAGE ); ?></p>
  1286. <?php
  1287. }
  1288. function id_profile_update( $wp_userID = 0 ) {
  1289. // validation
  1290. if ( !$wp_userID ) {
  1291. return false;
  1292. }
  1293. // Don't clear credentials when they were just being displayed
  1294. if ( 'true' == id_param( 'id_connected' ) )
  1295. return;
  1296. $username = id_param( 'id_username' );
  1297. $password = id_param( 'id_password' );
  1298. if ( !$username || !$password ) {
  1299. id_save_usermeta_array( $wp_userID, array(
  1300. 'id_username' => $username,
  1301. 'id_userID' => null,
  1302. 'id_userKey' => null
  1303. ) );
  1304. return false;
  1305. }
  1306. // outgoing fields
  1307. $fields = array();
  1308. $fields['username'] = $username;
  1309. $fields['password'] = $password;
  1310. $fields['wp_userID'] = $wp_userID;
  1311. $fields['admin'] = current_user_can( 'manage_options' );
  1312. $queue = id_get_queue();
  1313. $op = $queue->add( 'user_login', $fields, 'id_profile_update_callback' );
  1314. $queue->ping( array( $op ) );
  1315. return true;
  1316. }
  1317. function id_profile_update_callback( &$result, &$response, &$operation ) {
  1318. $args = func_get_args();
  1319. if ( $wp_userID = id_coalesce( @$operation->data['wp_userID'] ) ) {
  1320. id_save_usermeta_array( $wp_userID, array(
  1321. 'id_username' => id_coal

Large files files are truncated, but you can click here to view the full file