Publicize_Base

The Jetpack by WordPress.com Publicize Base class.

Defined (1)

The class is defined in the following location(s).

/modules/publicize/publicize.php  
  1. abstract class Publicize_Base { 
  2.  
  3. /** 
  4. * Services that are currently connected to the given user 
  5. * through publicize. 
  6. */ 
  7. public $connected_services = array(); 
  8.  
  9. /** 
  10. * Sservices that are supported by publicize. They don't 
  11. * neccessarly need to be connected to the current user. 
  12. */ 
  13. public $services; 
  14.  
  15. /** 
  16. * key names for post meta 
  17. */ 
  18. public $ADMIN_PAGE = 'wpas'; 
  19. public $POST_MESS = '_wpas_mess'; 
  20. public $POST_SKIP = '_wpas_skip_'; // connection id appended to indicate that a connection should NOT be publicized to 
  21. public $POST_DONE = '_wpas_done_'; // connection id appended to indicate a connection has already been publicized to 
  22. public $USER_AUTH = 'wpas_authorize'; 
  23. public $USER_OPT = 'wpas_'; 
  24. public $PENDING = '_publicize_pending'; // ready for Publicize to do its thing 
  25. public $POST_SERVICE_DONE = '_publicize_done_external'; // array of external ids where we've Publicized 
  26.  
  27. /** 
  28. * default pieces of the message used in constructing the 
  29. * content pushed out to other social networks 
  30. */ 
  31.  
  32. public $default_prefix = ''; 
  33. public $default_message = '%title%'; 
  34. public $default_suffix = ' '; 
  35.  
  36. /** 
  37. * What WP capability is require to create/delete global connections? 
  38. * All users with this cap can unglobalize all other global connections, and globalize any of their own 
  39. * Globalized connections cannot be unselected by users without this capability when publishing 
  40. */ 
  41. public $GLOBAL_CAP = 'edit_others_posts'; 
  42.  
  43. /** 
  44. * Sets up the basics of Publicize 
  45. */ 
  46. function __construct() { 
  47. $this->default_message = Publicize_Util::build_sprintf( array( 
  48. /** 
  49. * Filter the default Publicize message. 
  50. * @module publicize 
  51. * @since 2.0.0 
  52. * @param string $this->default_message Publicize's default message. Default is the post title. 
  53. */ 
  54. apply_filters( 'wpas_default_message', $this->default_message ),  
  55. 'title',  
  56. 'url',  
  57. ) ); 
  58.  
  59. $this->default_prefix = Publicize_Util::build_sprintf( array( 
  60. /** 
  61. * Filter the message prepended to the Publicize custom message. 
  62. * @module publicize 
  63. * @since 2.0.0 
  64. * @param string $this->default_prefix String prepended to the Publicize custom message. 
  65. */ 
  66. apply_filters( 'wpas_default_prefix', $this->default_prefix ),  
  67. 'url',  
  68. ) ); 
  69.  
  70. $this->default_suffix = Publicize_Util::build_sprintf( array( 
  71. /** 
  72. * Filter the message appended to the Publicize custom message. 
  73. * @module publicize 
  74. * @since 2.0.0 
  75. * @param string $this->default_suffix String appended to the Publicize custom message. 
  76. */ 
  77. apply_filters( 'wpas_default_suffix', $this->default_suffix ),  
  78. 'url',  
  79. ) ); 
  80.  
  81. /** 
  82. * Filter the capability to change global Publicize connection options. 
  83. * All users with this cap can unglobalize all other global connections, and globalize any of their own 
  84. * Globalized connections cannot be unselected by users without this capability when publishing. 
  85. * @module publicize 
  86. * @since 2.2.1 
  87. * @param string $this->GLOBAL_CAP default capability in control of global Publicize connection options. Default to edit_others_posts. 
  88. */ 
  89. $this->GLOBAL_CAP = apply_filters( 'jetpack_publicize_global_connections_cap', $this->GLOBAL_CAP ); 
  90.  
  91. // stage 1 and 2 of 3-stage Publicize. Flag for Publicize on creation, save meta,  
  92. // then check meta and publicze based on that. stage 3 implemented on wpcom 
  93. add_action( 'transition_post_status', array( $this, 'flag_post_for_publicize' ), 10, 3 ); 
  94. add_action( 'save_post', array( &$this, 'save_meta' ), 20, 2 ); 
  95.  
  96. // Connection test callback 
  97. add_action( 'wp_ajax_test_publicize_conns', array( $this, 'test_publicize_conns' ) ); 
  98.  
  99. /** 
  100. * Functions to be implemented by the extended class (publicize-wpcom or publicize-jetpack) 
  101. */ 
  102. abstract function get_connection_id( $connection ); 
  103. abstract function connect_url( $service_name ); 
  104. abstract function disconnect_url( $service_name, $id ); 
  105. abstract function get_connection_meta( $connection ); 
  106. abstract function get_services( $filter ); 
  107. abstract function get_connections( $service, $_blog_id = false, $_user_id = false ); 
  108. abstract function get_connection( $service, $id, $_blog_id = false, $_user_id = false ); 
  109. abstract function flag_post_for_publicize( $new_status, $old_status, $post ); 
  110. abstract function test_connection( $service_name, $connection ); 
  111. abstract function disconnect( $service, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ); 
  112.  
  113. /** 
  114. * Shared Functions 
  115. */ 
  116.  
  117. /** 
  118. * Returns an external URL to the connection's profile 
  119. */ 
  120. function get_profile_link( $service_name, $c ) { 
  121. $cmeta = $this->get_connection_meta( $c ); 
  122.  
  123. if ( isset( $cmeta['connection_data']['meta']['link'] ) ) { 
  124. if ( 'facebook' == $service_name && 0 === strpos( parse_url( $cmeta['connection_data']['meta']['link'], PHP_URL_PATH ), '/app_scoped_user_id/' ) ) { 
  125. // App-scoped Facebook user IDs are not usable profile links 
  126. return false; 
  127.  
  128. return $cmeta['connection_data']['meta']['link']; 
  129. } elseif ( 'facebook' == $service_name && isset( $cmeta['connection_data']['meta']['facebook_page'] ) ) { 
  130. return 'https://facebook.com/' . $cmeta['connection_data']['meta']['facebook_page']; 
  131. } elseif ( 'tumblr' == $service_name && isset( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) ) { 
  132. return 'http://' . $cmeta['connection_data']['meta']['tumblr_base_hostname']; 
  133. } elseif ( 'twitter' == $service_name ) { 
  134. return 'https://twitter.com/' . substr( $cmeta['external_display'], 1 ); // Has a leading '@' 
  135. } elseif ( 'google_plus' == $service_name && isset( $cmeta['connection_data']['meta']['google_plus_page'] ) ) { 
  136. return 'https://plus.google.com/' . $cmeta['connection_data']['meta']['google_plus_page']; 
  137. } elseif ( 'google_plus' == $service_name ) { 
  138. return 'https://plus.google.com/' . $cmeta['external_id']; 
  139. } else if ( 'linkedin' == $service_name ) { 
  140. if ( !isset( $cmeta['connection_data']['meta']['profile_url'] ) ) { 
  141. return false; 
  142.  
  143. $profile_url_query = parse_url( $cmeta['connection_data']['meta']['profile_url'], PHP_URL_QUERY ); 
  144. wp_parse_str( $profile_url_query, $profile_url_query_args ); 
  145. if ( isset( $profile_url_query_args['key'] ) ) { 
  146. $id = $profile_url_query_args['key']; 
  147. } elseif ( isset( $profile_url_query_args['id'] ) ) { 
  148. $id = $profile_url_query_args['id']; 
  149. } else { 
  150. return false; 
  151.  
  152. return esc_url_raw( add_query_arg( 'id', urlencode( $id ), 'http://www.linkedin.com/profile/view' ) ); 
  153. } else { 
  154. return false; // no fallback. we just won't link it 
  155.  
  156. /** 
  157. * Returns a display name for the connection 
  158. */ 
  159. function get_display_name( $service_name, $c ) { 
  160. $cmeta = $this->get_connection_meta( $c ); 
  161.  
  162. if ( isset( $cmeta['connection_data']['meta']['display_name'] ) ) { 
  163. return $cmeta['connection_data']['meta']['display_name']; 
  164. } elseif ( $service_name == 'tumblr' && isset( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) ) { 
  165. return $cmeta['connection_data']['meta']['tumblr_base_hostname']; 
  166. } elseif ( $service_name == 'twitter' ) { 
  167. return $cmeta['external_display']; 
  168. } else { 
  169. $connection_display = $cmeta['external_display']; 
  170. if ( empty( $connection_display ) ) 
  171. $connection_display = $cmeta['external_name']; 
  172. return $connection_display; 
  173.  
  174. public static function get_service_label( $service_name ) { 
  175. switch ( $service_name ) { 
  176. case 'linkedin': 
  177. return 'LinkedIn'; 
  178. break; 
  179. case 'google_plus': 
  180. return 'Google+'; 
  181. break; 
  182. case 'twitter': 
  183. case 'facebook': 
  184. case 'tumblr': 
  185. default: 
  186. return ucfirst( $service_name ); 
  187. break; 
  188.  
  189. function show_options_popup( $service_name, $c ) { 
  190. $cmeta = $this->get_connection_meta( $c ); 
  191.  
  192. // always show if no selection has been made for facebook 
  193. if ( 'facebook' == $service_name && empty( $cmeta['connection_data']['meta']['facebook_profile'] ) && empty( $cmeta['connection_data']['meta']['facebook_page'] ) ) 
  194. return true; 
  195.  
  196. // always show if no selection has been made for tumblr 
  197. if ( 'tumblr' == $service_name && empty ( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) ) 
  198. return true; 
  199.  
  200. // if we have the specific conncetion info.. 
  201. if ( isset( $_GET['id'] ) ) { 
  202. if ( $cmeta['connection_data']['id'] == $_GET['id'] ) 
  203. return true; 
  204. } else { 
  205. // otherwise, just show if this is the completed step / first load 
  206. if ( !empty( $_GET['action'] ) && 'completed' == $_GET['action'] && !empty( $_GET['service'] ) && $service_name == $_GET['service'] && ! in_array( $_GET['service'], array( 'facebook', 'tumblr' ) ) ) 
  207. return true; 
  208.  
  209. return false; 
  210.  
  211. function user_id() { 
  212. global $current_user; 
  213. return $current_user->ID; 
  214.  
  215. function blog_id() { 
  216. return get_current_blog_id(); 
  217.  
  218. /** 
  219. * Returns true if a user has a connection to a particular service, false otherwise 
  220. */ 
  221. function is_enabled( $service, $_blog_id = false, $_user_id = false ) { 
  222. if ( !$_blog_id ) 
  223. $_blog_id = $this->blog_id(); 
  224.  
  225. if ( !$_user_id ) 
  226. $_user_id = $this->user_id(); 
  227.  
  228. $connections = $this->get_connections( $service, $_blog_id, $_user_id ); 
  229. return ( is_array( $connections ) && count( $connections ) > 0 ? true : false ); 
  230.  
  231. /** 
  232. * Fires when a post is saved, checks conditions and saves state in postmeta so that it 
  233. * can be picked up later by @see ::publicize_post() 
  234. */ 
  235. function save_meta( $post_id, $post ) { 
  236. $cron_user = null; 
  237. $submit_post = true; 
  238.  
  239. if ( ! $this->post_type_is_publicizeable( $post->post_type ) ) 
  240. return; 
  241.  
  242. // Don't Publicize during certain contexts: 
  243.  
  244. // - import 
  245. if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) { 
  246. $submit_post = false; 
  247.  
  248. // - on quick edit, autosave, etc but do fire on p2, quickpress, and instapost ajax 
  249. if ( 
  250. defined( 'DOING_AJAX' ) 
  251. && 
  252. DOING_AJAX 
  253. && 
  254. !did_action( 'p2_ajax' ) 
  255. && 
  256. !did_action( 'wp_ajax_json_quickpress_post' ) 
  257. && 
  258. !did_action( 'wp_ajax_instapost_publish' ) 
  259. && 
  260. !did_action( 'wp_ajax_post_reblog' ) 
  261. ) { 
  262. $submit_post = false; 
  263.  
  264. // - bulk edit 
  265. if ( isset( $_GET['bulk_edit'] ) ) { 
  266. $submit_post = false; 
  267.  
  268. // - API/XML-RPC Test Posts 
  269. if ( 
  270. defined( 'XMLRPC_REQUEST' ) 
  271. && 
  272. XMLRPC_REQUEST 
  273. || 
  274. defined( 'APP_REQUEST' ) 
  275. && 
  276. APP_REQUEST 
  277. && 
  278. 0 === strpos( $post->post_title, 'Temporary Post Used For Theme Detection' ) 
  279. ) { 
  280. $submit_post = false; 
  281.  
  282. // only work with certain statuses (avoids inherits, auto drafts etc) 
  283. if ( !in_array( $post->post_status, array( 'publish', 'draft', 'future' ) ) ) { 
  284. $submit_post = false; 
  285.  
  286. // don't publish password protected posts 
  287. if ( '' !== $post->post_password ) { 
  288. $submit_post = false; 
  289.  
  290. // Did this request happen via wp-admin? 
  291. $from_web = 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && isset( $_POST[$this->ADMIN_PAGE] ); 
  292.  
  293. if ( ( $from_web || defined( 'POST_BY_EMAIL' ) ) && isset( $_POST['wpas_title'] ) ) { 
  294. if ( empty( $_POST['wpas_title'] ) ) { 
  295. delete_post_meta( $post_id, $this->POST_MESS ); 
  296. } else { 
  297. update_post_meta( $post_id, $this->POST_MESS, trim( stripslashes( $_POST['wpas_title'] ) ) ); 
  298.  
  299. // change current user to provide context for get_services() if we're running during cron 
  300. if ( defined( 'DOING_CRON' ) && DOING_CRON ) { 
  301. $cron_user = (int) $GLOBALS['user_ID']; 
  302. wp_set_current_user( $post->post_author ); 
  303.  
  304. /** 
  305. * In this phase, we mark connections that we want to SKIP. When Publicize is actually triggered,  
  306. * it will Publicize to everything *except* those marked for skipping. 
  307. */ 
  308. foreach ( (array) $this->get_services( 'connected' ) as $service_name => $connections ) { 
  309. foreach ( $connections as $connection ) { 
  310. $connection_data = ''; 
  311. if ( method_exists( $connection, 'get_meta' ) ) 
  312. $connection_data = $connection->get_meta( 'connection_data' ); 
  313. elseif ( ! empty( $connection['connection_data'] ) ) 
  314. $connection_data = $connection['connection_data']; 
  315.  
  316. /** This action is documented in modules/publicize/ui.php */ 
  317. if ( false == apply_filters( 'wpas_submit_post?', $submit_post, $post_id, $service_name, $connection_data ) ) { 
  318. delete_post_meta( $post_id, $this->PENDING ); 
  319. continue; 
  320.  
  321. if ( !empty( $connection->unique_id ) ) 
  322. $unique_id = $connection->unique_id; 
  323. else if ( !empty( $connection['connection_data']['token_id'] ) ) 
  324. $unique_id = $connection['connection_data']['token_id']; 
  325.  
  326. // This was a wp-admin request, so we need to check the state of checkboxes 
  327. if ( $from_web ) { 
  328. // delete stray service-based post meta 
  329. delete_post_meta( $post_id, $this->POST_SKIP . $service_name ); 
  330.  
  331. // We *unchecked* this stream from the admin page, or it's set to readonly, or it's a new addition 
  332. if ( empty( $_POST[$this->ADMIN_PAGE]['submit'][$unique_id] ) ) { 
  333. // Also make sure that the service-specific input isn't there. 
  334. // If the user connected to a new service 'in-page' then a hidden field with the service 
  335. // name is added, so we just assume they wanted to Publicize to that service. 
  336. if ( empty( $_POST[$this->ADMIN_PAGE]['submit'][$service_name] ) ) { 
  337. // Nothing seems to be checked, so we're going to mark this one to be skipped 
  338. update_post_meta( $post_id, $this->POST_SKIP . $unique_id, 1 ); 
  339. continue; 
  340. } else { 
  341. // clean up any stray post meta 
  342. delete_post_meta( $post_id, $this->POST_SKIP . $unique_id ); 
  343. } else { 
  344. // The checkbox for this connection is explicitly checked -- make sure we DON'T skip it 
  345. delete_post_meta( $post_id, $this->POST_SKIP . $unique_id ); 
  346.  
  347. /** 
  348. * Fires right before the post is processed for Publicize. 
  349. * Users may hook in here and do anything else they need to after meta is written,  
  350. * and before the post is processed for Publicize. 
  351. * @since 2.1.2 
  352. * @param bool $submit_post Should the post be publicized. 
  353. * @param int $post->ID Post ID. 
  354. * @param string $service_name Service name. 
  355. * @param array $connection Array of connection details. 
  356. */ 
  357. do_action( 'publicize_save_meta', $submit_post, $post_id, $service_name, $connection ); 
  358.  
  359. if ( defined( 'DOING_CRON' ) && DOING_CRON ) { 
  360. wp_set_current_user( $cron_user ); 
  361.  
  362. // Next up will be ::publicize_post() 
  363.  
  364. /** 
  365. * Is a given post type Publicize-able? 
  366. * Not every CPT lends itself to Publicize-ation. Allow CPTs to register by adding their CPT via 
  367. * the publicize_post_types array filter. 
  368. * @param string $post_type The post type to check. 
  369. * $return bool True if the post type can be Publicized. 
  370. */ 
  371. function post_type_is_publicizeable( $post_type ) { 
  372. if ( 'post' == $post_type ) 
  373. return true; 
  374.  
  375. return post_type_supports( $post_type, 'publicize' ); 
  376.  
  377. /** 
  378. * Runs tests on all the connections and returns the results to the caller 
  379. */ 
  380. function test_publicize_conns() { 
  381. $test_results = array(); 
  382.  
  383. foreach ( (array) $this->get_services( 'connected' ) as $service_name => $connections ) { 
  384. foreach ( $connections as $connection ) { 
  385.  
  386. $id = $this->get_connection_id( $connection ); 
  387.  
  388. $connection_test_passed = true; 
  389. $connection_test_message = __( 'This connection is working correctly.' , 'jetpack' ); 
  390. $user_can_refresh = false; 
  391. $refresh_text = ''; 
  392. $refresh_url = ''; 
  393.  
  394. $connection_test_result = true; 
  395. if ( method_exists( $this, 'test_connection' ) ) { 
  396. $connection_test_result = $this->test_connection( $service_name, $connection ); 
  397.  
  398. if ( is_wp_error( $connection_test_result ) ) { 
  399. $connection_test_passed = false; 
  400. $connection_test_message = $connection_test_result->get_error_message(); 
  401. $error_data = $connection_test_result->get_error_data(); 
  402.  
  403. $user_can_refresh = $error_data['user_can_refresh']; 
  404. $refresh_text = $error_data['refresh_text']; 
  405. $refresh_url = $error_data['refresh_url']; 
  406.  
  407. $test_results[] = array( 
  408. 'connectionID' => $id,  
  409. 'serviceName' => $service_name,  
  410. 'connectionTestPassed' => $connection_test_passed,  
  411. 'connectionTestMessage' => esc_attr( $connection_test_message ),  
  412. 'userCanRefresh' => $user_can_refresh,  
  413. 'refreshText' => esc_attr( $refresh_text ),  
  414. 'refreshURL' => $refresh_url 
  415. ); 
  416.  
  417. wp_send_json_success( $test_results );