Brak opisu

class-jetpack-post-by-email.php 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <?php
  2. /**
  3. * Class Jetpack_Post_By_Email
  4. *
  5. * @package automattic/jetpack
  6. */
  7. use Automattic\Jetpack\Connection\Tokens;
  8. use Automattic\Jetpack\Redirect;
  9. /**
  10. * Class Jetpack_Post_By_Email
  11. */
  12. class Jetpack_Post_By_Email {
  13. /**
  14. * Initialize PBE.
  15. *
  16. * @return Jetpack_Post_By_Email
  17. */
  18. public static function init() {
  19. static $instance = null;
  20. if ( ! $instance ) {
  21. $instance = new Jetpack_Post_By_Email();
  22. }
  23. return $instance;
  24. }
  25. /**
  26. * Singleton
  27. */
  28. private function __construct() {
  29. add_action( 'init', array( $this, 'action_init' ) );
  30. }
  31. /**
  32. * Adds hooks for PBE.
  33. */
  34. public function action_init() {
  35. if ( ! current_user_can( 'edit_posts' ) ) {
  36. return;
  37. }
  38. add_action( 'profile_personal_options', array( $this, 'user_profile' ) );
  39. add_action( 'admin_print_scripts-profile.php', array( $this, 'profile_scripts' ) );
  40. add_action( 'wp_ajax_jetpack_post_by_email_enable', array( $this, 'create_post_by_email_address' ) );
  41. add_action( 'wp_ajax_jetpack_post_by_email_regenerate', array( $this, 'regenerate_post_by_email_address' ) );
  42. add_action( 'wp_ajax_jetpack_post_by_email_disable', array( $this, 'delete_post_by_email_address' ) );
  43. }
  44. /**
  45. * Enqueues scripts for user profile page.
  46. */
  47. public function profile_scripts() {
  48. wp_enqueue_script( 'post-by-email', plugins_url( 'post-by-email.js', __FILE__ ), array( 'jquery' ), JETPACK__VERSION, true );
  49. wp_localize_script(
  50. 'post-by-email',
  51. 'pbeVars',
  52. array(
  53. 'rest_nonce' => wp_create_nonce( 'wp_rest' ),
  54. )
  55. );
  56. wp_enqueue_style( 'post-by-email', plugins_url( 'post-by-email.css', __FILE__ ), array(), JETPACK__VERSION );
  57. wp_style_add_data( 'post-by-email', 'jetpack-inline', true );
  58. }
  59. /**
  60. * Check if the user is connected.
  61. *
  62. * @return bool True if connected. False if not.
  63. */
  64. public function check_user_connection() {
  65. $user_token = ( new Tokens() )->get_access_token( get_current_user_id() );
  66. $is_user_connected = $user_token && ! is_wp_error( $user_token );
  67. // If the user is already connected via Jetpack, then we're good.
  68. if ( $is_user_connected ) {
  69. return true;
  70. }
  71. return false;
  72. }
  73. /**
  74. * Adds field to user profile page.
  75. */
  76. public function user_profile() {
  77. $blog_name = get_bloginfo( 'blogname' );
  78. if ( empty( $blog_name ) ) {
  79. $blog_name = home_url( '/' );
  80. }
  81. ?>
  82. <div id="post-by-email" class="jetpack-targetable">
  83. <h3><?php esc_html_e( 'Post by Email', 'jetpack' ); ?></h3>
  84. <table class="form-table">
  85. <tr>
  86. <th scope="row"><?php esc_html_e( 'Email Address', 'jetpack' ); ?><span id="jp-pbe-spinner" class="spinner"></span></th>
  87. <td>
  88. <div id="jp-pbe-error" class="jetpack-inline-error"></div>
  89. <?php
  90. if ( $this->check_user_connection() ) {
  91. $email = $this->get_post_by_email_address();
  92. $enable_button_style = empty( $email ) ? '' : 'display: none;';
  93. $info_style = empty( $email ) ? 'display: none;' : '';
  94. ?>
  95. <input type="button" name="jp-pbe-enable" id="jp-pbe-enable" class="button" value="<?php esc_attr_e( 'Enable Post By Email', 'jetpack' ); ?>" style="<?php echo esc_attr( $enable_button_style ); ?>" />
  96. <div id="jp-pbe-info" style="<?php echo esc_attr( $info_style ); ?>">
  97. <p id="jp-pbe-email-wrapper">
  98. <input type="text" id="jp-pbe-email" value="<?php echo esc_attr( $email ); ?>" readonly="readonly" class="regular-text" />
  99. <span class="description"><a target="_blank" rel="noopener noreferrer" href="<?php echo esc_url( Redirect::get_url( 'jetpack-support-post-by-email' ) ); ?>"><?php esc_html_e( 'More information', 'jetpack' ); ?></a></span>
  100. </p>
  101. <p>
  102. <input type="button" name="jp-pbe-regenerate" id="jp-pbe-regenerate" class="button" value="<?php esc_attr_e( 'Regenerate Address', 'jetpack' ); ?> " />
  103. <input type="button" name="jp-pbe-disable" id="jp-pbe-disable" class="button" value="<?php esc_attr_e( 'Disable Post By Email', 'jetpack' ); ?> " />
  104. </p>
  105. </div>
  106. <?php
  107. } else {
  108. $jetpack = Jetpack::init();
  109. ?>
  110. <p class="jetpack-inline-message">
  111. <?php
  112. printf(
  113. /* translators: Placeholder is the site's name from WordPress settings. */
  114. esc_html( wptexturize( __( 'To use Post By Email, you need to link your %s account to your WordPress.com account.', 'jetpack' ) ) ),
  115. '<strong>' . esc_html( $blog_name ) . '</strong>'
  116. );
  117. ?>
  118. <br />
  119. <?php echo esc_html( wptexturize( __( "If you don't have a WordPress.com account yet, you can sign up for free in just a few seconds.", 'jetpack' ) ) ); ?>
  120. </p>
  121. <p>
  122. <a href="<?php echo esc_url( $jetpack->build_connect_url( false, get_edit_profile_url( get_current_user_id() ) . '#post-by-email', 'unlinked-user-pbe' ) ); ?>" class="button button-connector" id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a>
  123. </p>
  124. <?php
  125. }
  126. ?>
  127. </td>
  128. </tr>
  129. </table>
  130. </div>
  131. <?php
  132. }
  133. /**
  134. * XMLRPC Query to WP.com for PBE e-mail address for user.
  135. *
  136. * @return string|null PBE E-mail Address or null on error.
  137. */
  138. public function get_post_by_email_address() {
  139. $xml = $this->init_rest_connection();
  140. $xml->query( 'jetpack.getPostByEmailAddress' );
  141. if ( $xml->isError() ) {
  142. return null;
  143. }
  144. $response = $xml->getResponse();
  145. if ( empty( $response ) ) {
  146. return null;
  147. }
  148. return $response;
  149. }
  150. /**
  151. * Process the REST API request to modify the "Post by Email" settings.
  152. *
  153. * @param string $action Allowed values: 'create', 'regenerate', 'delete'.
  154. *
  155. * @return array|false
  156. */
  157. public function process_api_request( $action ) {
  158. $endpoint = null;
  159. $error_message = esc_html__( 'Please try again later.', 'jetpack' );
  160. $result = false;
  161. switch ( $action ) {
  162. case 'create':
  163. $endpoint = 'jetpack.createPostByEmailAddress';
  164. $error_message = esc_html__( 'Unable to create the Post by Email address. Please try again later.', 'jetpack' );
  165. break;
  166. case 'regenerate':
  167. $endpoint = 'jetpack.regeneratePostByEmailAddress';
  168. $error_message = esc_html__( 'Unable to regenerate the Post by Email address. Please try again later.', 'jetpack' );
  169. break;
  170. case 'delete':
  171. $endpoint = 'jetpack.deletePostByEmailAddress';
  172. $error_message = esc_html__( 'Unable to delete the Post by Email address. Please try again later.', 'jetpack' );
  173. break;
  174. }
  175. if ( $endpoint ) {
  176. $result = $this->process_rest_proxy_request( $endpoint, $error_message );
  177. }
  178. return $result;
  179. }
  180. /**
  181. * AJAX endpoint to create a new e-mail address.
  182. */
  183. public function create_post_by_email_address() {
  184. _doing_it_wrong( __METHOD__, esc_html__( "Use REST API endpoint '/wp-json/jetpack/v4/settings' instead.", 'jetpack' ), 'jetpack-8.4' );
  185. self::process_ajax_proxy_request(
  186. 'jetpack.createPostByEmailAddress',
  187. __( 'Unable to create your Post By Email address. Please try again later.', 'jetpack' )
  188. );
  189. }
  190. /**
  191. * AJAX endpoint to regenerate PBE e-mail address.
  192. */
  193. public function regenerate_post_by_email_address() {
  194. _doing_it_wrong( __METHOD__, esc_html__( "Use REST API endpoint '/wp-json/jetpack/v4/settings' instead.", 'jetpack' ), 'jetpack-8.4' );
  195. self::process_ajax_proxy_request(
  196. 'jetpack.regeneratePostByEmailAddress',
  197. __( 'Unable to regenerate your Post By Email address. Please try again later.', 'jetpack' )
  198. );
  199. }
  200. /**
  201. * AJAX endpoint to delete a PBE e-mail address.
  202. */
  203. public function delete_post_by_email_address() {
  204. _doing_it_wrong( __METHOD__, esc_html__( "Use REST API endpoint '/wp-json/jetpack/v4/settings' instead.", 'jetpack' ), 'jetpack-8.4' );
  205. self::process_ajax_proxy_request(
  206. 'jetpack.deletePostByEmailAddress',
  207. __( 'Unable to disable your Post By Email address. Please try again later.', 'jetpack' )
  208. );
  209. }
  210. /**
  211. * The AJAX proxying method for backward compatibility.
  212. * To be removed in the upcoming versions.
  213. *
  214. * @param string $endpoint Jetpack API endpoint.
  215. * @param string $error_message Error message to be returned if something goes wrong.
  216. *
  217. * @deprecated
  218. */
  219. public function __process_ajax_proxy_request( $endpoint, $error_message ) { // phpcs:ignore
  220. $this->process_ajax_proxy_request( $endpoint, $error_message );
  221. }
  222. /**
  223. * Back end function to abstract the xmlrpc function calls to wpcom.
  224. *
  225. * @param string $endpoint Jetpack API endpoint.
  226. * @param string $error_message Error message to be returned if something goes wrong.
  227. *
  228. * @deprecated
  229. */
  230. private function process_ajax_proxy_request( $endpoint, $error_message ) {
  231. _deprecated_function( __METHOD__, 'jetpack-8.4', '_process_rest_proxy_request' );
  232. if ( ! current_user_can( 'edit_posts' ) ) {
  233. wp_send_json_error( $error_message );
  234. }
  235. if ( empty( $_REQUEST['pbe_nonce'] ) || ! wp_verify_nonce( $_REQUEST['pbe_nonce'], $endpoint ) ) {
  236. wp_send_json_error( $error_message );
  237. }
  238. $xml = $this->init_rest_connection();
  239. $xml->query( $endpoint );
  240. if ( $xml->isError() ) {
  241. wp_send_json_error( $error_message );
  242. }
  243. $response = $xml->getResponse();
  244. if ( empty( $response ) ) {
  245. wp_send_json_error( $error_message );
  246. }
  247. // Will be used only in Jetpack_Core_Json_Api_Endpoints::get_remote_value.
  248. update_option( 'post_by_email_address' . get_current_user_id(), $response );
  249. wp_send_json_success( $response );
  250. }
  251. /**
  252. * Calls WPCOM through authenticated request to create, regenerate or delete the Post by Email address.
  253. *
  254. * @since 4.3.0
  255. *
  256. * @param string $endpoint Process to call on WPCOM to create, regenerate or delete the Post by Email address.
  257. * @param string $error Error message to return.
  258. *
  259. * @return array
  260. */
  261. private function process_rest_proxy_request( $endpoint, $error ) {
  262. if ( ! current_user_can( 'edit_posts' ) ) {
  263. return array( 'message' => $error );
  264. }
  265. $xml = $this->init_rest_connection();
  266. $xml->query( $endpoint );
  267. if ( $xml->isError() ) {
  268. return array( 'message' => $error );
  269. }
  270. $response = $xml->getResponse();
  271. if ( empty( $response ) ) {
  272. return array( 'message' => $error );
  273. }
  274. // Used only in Jetpack_Core_Json_Api_Endpoints::get_remote_value.
  275. update_option( 'post_by_email_address' . get_current_user_id(), $response );
  276. return $response;
  277. }
  278. /**
  279. * Initialize the IXR client
  280. *
  281. * @return Jetpack_IXR_Client
  282. */
  283. private function init_rest_connection() {
  284. return new Jetpack_IXR_Client( array( 'user_id' => get_current_user_id() ) );
  285. }
  286. }