Jetpack_Core_API_Data

Class that manages updating of Jetpack module options and general Jetpack settings or retrieving module data.

Defined (1)

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

/_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php  
  1. class Jetpack_Core_API_Data extends Jetpack_Core_API_XMLRPC_Consumer_Endpoint { 
  2.  
  3. /** 
  4. * Process request by returning the module or updating it. 
  5. * If no module is specified, settings for all modules are assumed. 
  6. * @since 4.3.0 
  7. * @param WP_REST_Request $request 
  8. * @return bool|mixed|void|WP_Error 
  9. */ 
  10. public function process( $request ) { 
  11. if ( 'GET' === $request->get_method() ) { 
  12. if ( isset( $request['slug'] ) ) { 
  13. return $this->get_module( $request ); 
  14.  
  15. return $this->get_all_options(); 
  16. } else { 
  17. return $this->update_data( $request ); 
  18.  
  19. /** 
  20. * Get information about a specific and valid Jetpack module. 
  21. * @since 4.3.0 
  22. * @param WP_REST_Request $request { 
  23. * Array of parameters received by request. 
  24. * @type string $slug Module slug. 
  25. * } 
  26. * @return mixed|void|WP_Error 
  27. */ 
  28. public function get_module( $request ) { 
  29. if ( Jetpack::is_module( $request['slug'] ) ) { 
  30.  
  31. $module = Jetpack::get_module( $request['slug'] ); 
  32.  
  33. $module['options'] = Jetpack_Core_Json_Api_Endpoints::prepare_options_for_response( $request['slug'] ); 
  34.  
  35. if ( 
  36. isset( $module['requires_connection'] ) 
  37. && $module['requires_connection'] 
  38. && Jetpack::is_development_mode() 
  39. ) { 
  40. $module['activated'] = false; 
  41.  
  42. $i18n = jetpack_get_module_i18n( $request['slug'] ); 
  43. if ( isset( $module['name'] ) ) { 
  44. $module['name'] = $i18n['name']; 
  45. if ( isset( $module['description'] ) ) { 
  46. $module['description'] = $i18n['description']; 
  47. $module['short_description'] = $i18n['description']; 
  48.  
  49. return Jetpack_Core_Json_Api_Endpoints::prepare_modules_for_response( $module ); 
  50.  
  51. return new WP_Error( 
  52. 'not_found',  
  53. esc_html__( 'The requested Jetpack module was not found.', 'jetpack' ),  
  54. array( 'status' => 404 ) 
  55. ); 
  56.  
  57. /** 
  58. * Get information about all Jetpack module options and settings. 
  59. * @since 4.6.0 
  60. * @return WP_REST_Response $response 
  61. */ 
  62. public function get_all_options() { 
  63. $response = array(); 
  64.  
  65. $modules = Jetpack::get_available_modules(); 
  66. if ( is_array( $modules ) && ! empty( $modules ) ) { 
  67. foreach ( $modules as $module ) { 
  68. // Add all module options 
  69. $options = Jetpack_Core_Json_Api_Endpoints::prepare_options_for_response( $module ); 
  70. foreach ( $options as $option_name => $option ) { 
  71. $response[ $option_name ] = $option['current_value']; 
  72.  
  73. // Add the module activation state 
  74. $response[ $module ] = Jetpack::is_module_active( $module ); 
  75.  
  76. $settings = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list( 'settings' ); 
  77. $holiday_snow_option_name = Jetpack_Core_Json_Api_Endpoints::holiday_snow_option_name(); 
  78.  
  79. foreach ( $settings as $setting => $properties ) { 
  80. switch ( $setting ) { 
  81. case $holiday_snow_option_name: 
  82. $response[ $setting ] = get_option( $holiday_snow_option_name ) === 'letitsnow'; 
  83. break; 
  84.  
  85. case 'wordpress_api_key': 
  86. // When field is clear, return empty. Otherwise it would return "false". 
  87. if ( '' === get_option( 'wordpress_api_key', '' ) ) { 
  88. $response[ $setting ] = ''; 
  89. } else { 
  90. if ( ! class_exists( 'Akismet' ) ) { 
  91. if ( file_exists( WP_PLUGIN_DIR . '/akismet/class.akismet.php' ) ) { 
  92. require_once WP_PLUGIN_DIR . '/akismet/class.akismet.php'; 
  93. $response[ $setting ] = class_exists( 'Akismet' ) ? Akismet::get_api_key() : ''; 
  94. break; 
  95.  
  96. default: 
  97. $response[ $setting ] = Jetpack_Core_Json_Api_Endpoints::cast_value( get_option( $setting ), $settings[ $setting ] ); 
  98. break; 
  99.  
  100. if ( ! function_exists( 'is_plugin_active' ) ) { 
  101. require_once ABSPATH . 'wp-admin/includes/plugin.php'; 
  102. $response['akismet'] = is_plugin_active( 'akismet/akismet.php' ); 
  103.  
  104. return rest_ensure_response( $response ); 
  105.  
  106. /** 
  107. * If it's a valid Jetpack module and configuration parameters have been sent, update it. 
  108. * @since 4.3.0 
  109. * @param WP_REST_Request $request { 
  110. * Array of parameters received by request. 
  111. * @type string $slug Module slug. 
  112. * } 
  113. * @return bool|WP_Error True if module was updated. Otherwise, a WP_Error instance with the corresponding error. 
  114. */ 
  115. public function update_data( $request ) { 
  116.  
  117. // If it's null, we're trying to update many module options from different modules. 
  118. if ( is_null( $request['slug'] ) ) { 
  119.  
  120. // Value admitted by Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list that will make it return all module options. 
  121. // It will not be passed. It's just checked in this method to pass that method a string or array. 
  122. $request['slug'] = 'any'; 
  123. } else { 
  124. if ( ! Jetpack::is_module( $request['slug'] ) ) { 
  125. return new WP_Error( 'not_found', esc_html__( 'The requested Jetpack module was not found.', 'jetpack' ), array( 'status' => 404 ) ); 
  126.  
  127. if ( ! Jetpack::is_module_active( $request['slug'] ) ) { 
  128. return new WP_Error( 'inactive', esc_html__( 'The requested Jetpack module is inactive.', 'jetpack' ), array( 'status' => 409 ) ); 
  129.  
  130. // Get parameters to update the module. We can not simply use $request->get_params() because when we registered 
  131. // this route, we are adding the entire output of Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list() to 
  132. // the current request object's params. We are interested in body of the actual request. 
  133. // This may be JSON: 
  134. $params = $request->get_json_params(); 
  135. if ( ! is_array( $params ) ) { 
  136. // Or it may be standard POST key-value pairs: 
  137. $params = $request->get_body_params(); 
  138.  
  139. // Exit if no parameters were passed. 
  140. if ( ! is_array( $params ) ) { 
  141. return new WP_Error( 'missing_options', esc_html__( 'Missing options.', 'jetpack' ), array( 'status' => 404 ) ); 
  142.  
  143. // If $params was set via `get_body_params()` there may be some additional variables in the request that can 
  144. // cause validation to fail. This method verifies that each param was in fact updated and will throw a `some_updated` 
  145. // error if unused variables are included in the request. 
  146. foreach ( array_keys( $params ) as $key ) { 
  147. if ( is_int( $key ) || 'slug' === $key || 'context' === $key ) { 
  148. unset( $params[ $key ] ); 
  149.  
  150. // Get available module options. 
  151. $options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list( 'any' === $request['slug'] 
  152. ? $params 
  153. : $request['slug'] 
  154. ); 
  155.  
  156. // Prepare to toggle module if needed 
  157. $toggle_module = new Jetpack_Core_API_Module_Toggle_Endpoint( new Jetpack_IXR_Client() ); 
  158.  
  159. // Options that are invalid or failed to update. 
  160. $invalid = array_keys( array_diff_key( $params, $options ) ); 
  161. $not_updated = array(); 
  162.  
  163. // Remove invalid options 
  164. $params = array_intersect_key( $params, $options ); 
  165.  
  166. // Used if response is successful. The message can be overwritten and additional data can be added here. 
  167. $response = array( 
  168. 'code' => 'success',  
  169. 'message' => esc_html__( 'The requested Jetpack data updates were successful.', 'jetpack' ),  
  170. ); 
  171.  
  172. // If there are modules to activate, activate them first so they're ready when their options are set. 
  173. foreach ( $params as $option => $value ) { 
  174. if ( 'modules' === $options[ $option ]['jp_group'] ) { 
  175.  
  176. // Used if there was an error. Can be overwritten with specific error messages. 
  177. $error = ''; 
  178.  
  179. // Set to true if the module toggling was successful. 
  180. $updated = false; 
  181.  
  182. // Check if user can toggle the module. 
  183. if ( $toggle_module->can_request() ) { 
  184.  
  185. // Activate or deactivate the module according to the value passed. 
  186. $toggle_result = $value 
  187. ? $toggle_module->activate_module( $option ) 
  188. : $toggle_module->deactivate_module( $option ); 
  189.  
  190. if ( 
  191. is_wp_error( $toggle_result ) 
  192. && 'already_inactive' === $toggle_result->get_error_code() 
  193. ) { 
  194.  
  195. // If the module is already inactive, we don't fail 
  196. $updated = true; 
  197. } elseif ( is_wp_error( $toggle_result ) ) { 
  198. $error = $toggle_result->get_error_message(); 
  199. } else { 
  200. $updated = true; 
  201. } else { 
  202. $error = Jetpack_Core_Json_Api_Endpoints::$user_permissions_error_msg; 
  203.  
  204. // The module was not toggled. 
  205. if ( ! $updated ) { 
  206. $not_updated[ $option ] = $error; 
  207.  
  208. // Remove module from list so we don't go through it again. 
  209. unset( $params[ $option ] ); 
  210.  
  211. foreach ( $params as $option => $value ) { 
  212.  
  213. // Used if there was an error. Can be overwritten with specific error messages. 
  214. $error = ''; 
  215.  
  216. // Set to true if the option update was successful. 
  217. $updated = false; 
  218.  
  219. // Get option attributes, including the group it belongs to. 
  220. $option_attrs = $options[ $option ]; 
  221.  
  222. // If this is a module option and the related module isn't active for any reason, continue with the next one. 
  223. if ( 'settings' !== $option_attrs['jp_group'] ) { 
  224. if ( ! Jetpack::is_module( $option_attrs['jp_group'] ) ) { 
  225. $not_updated[ $option ] = esc_html__( 'The requested Jetpack module was not found.', 'jetpack' ); 
  226. continue; 
  227.  
  228. if ( 
  229. 'any' !== $request['slug'] 
  230. && ! Jetpack::is_module_active( $option_attrs['jp_group'] ) 
  231. ) { 
  232.  
  233. // We only take note of skipped options when updating one module 
  234. $not_updated[ $option ] = esc_html__( 'The requested Jetpack module is inactive.', 'jetpack' ); 
  235. continue; 
  236.  
  237. // Properly cast value based on its type defined in endpoint accepted args. 
  238. $value = Jetpack_Core_Json_Api_Endpoints::cast_value( $value, $option_attrs ); 
  239.  
  240. switch ( $option ) { 
  241. case 'monitor_receive_notifications': 
  242. $monitor = new Jetpack_Monitor(); 
  243.  
  244. // If we got true as response, consider it done. 
  245. $updated = true === $monitor->update_option_receive_jetpack_monitor_notification( $value ); 
  246. break; 
  247.  
  248. case 'post_by_email_address': 
  249. if ( 'create' == $value ) { 
  250. $result = $this->_process_post_by_email( 
  251. 'jetpack.createPostByEmailAddress',  
  252. esc_html__( 'Unable to create the Post by Email address. Please try again later.', 'jetpack' ) 
  253. ); 
  254. } elseif ( 'regenerate' == $value ) { 
  255. $result = $this->_process_post_by_email( 
  256. 'jetpack.regeneratePostByEmailAddress',  
  257. esc_html__( 'Unable to regenerate the Post by Email address. Please try again later.', 'jetpack' ) 
  258. ); 
  259. } elseif ( 'delete' == $value ) { 
  260. $result = $this->_process_post_by_email( 
  261. 'jetpack.deletePostByEmailAddress',  
  262. esc_html__( 'Unable to delete the Post by Email address. Please try again later.', 'jetpack' ) 
  263. ); 
  264. } else { 
  265. $result = false; 
  266.  
  267. // If we got an email address (create or regenerate) or 1 (delete), consider it done. 
  268. if ( is_string( $result ) && preg_match( '/[a-z0-9]+@post.wordpress.com/', $result ) ) { 
  269. $response[$option] = $result; 
  270. $updated = true; 
  271. } elseif ( 1 == $result ) { 
  272. $updated = true; 
  273. } elseif ( is_array( $result ) && isset( $result['message'] ) ) { 
  274. $error = $result['message']; 
  275. break; 
  276.  
  277. case 'jetpack_protect_key': 
  278. $protect = Jetpack_Protect_Module::instance(); 
  279. if ( 'create' == $value ) { 
  280. $result = $protect->get_protect_key(); 
  281. } else { 
  282. $result = false; 
  283.  
  284. // If we got one of Protect keys, consider it done. 
  285. if ( preg_match( '/[a-z0-9]{40, }/i', $result ) ) { 
  286. $response[$option] = $result; 
  287. $updated = true; 
  288. break; 
  289.  
  290. case 'jetpack_protect_global_whitelist': 
  291. $updated = jetpack_protect_save_whitelist( explode( PHP_EOL, str_replace( array( ' ', ', ' ), array( '', "\n" ), $value ) ) ); 
  292. if ( is_wp_error( $updated ) ) { 
  293. $error = $updated->get_error_message(); 
  294. break; 
  295.  
  296. case 'show_headline': 
  297. case 'show_thumbnails': 
  298. $grouped_options = $grouped_options_current = (array) Jetpack_Options::get_option( 'relatedposts' ); 
  299. $grouped_options[$option] = $value; 
  300.  
  301. // If option value was the same, consider it done. 
  302. $updated = $grouped_options_current != $grouped_options ? Jetpack_Options::update_option( 'relatedposts', $grouped_options ) : true; 
  303. break; 
  304.  
  305. case 'google': 
  306. case 'bing': 
  307. case 'pinterest': 
  308. case 'yandex': 
  309. $grouped_options = $grouped_options_current = (array) get_option( 'verification_services_codes' ); 
  310. $grouped_options[$option] = $value; 
  311.  
  312. // If option value was the same, consider it done. 
  313. $updated = $grouped_options_current != $grouped_options ? update_option( 'verification_services_codes', $grouped_options ) : true; 
  314. break; 
  315.  
  316. case 'sharing_services': 
  317. if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { 
  318. break; 
  319.  
  320. $sharer = new Sharing_Service(); 
  321.  
  322. // If option value was the same, consider it done. 
  323. $updated = $value != $sharer->get_blog_services() ? $sharer->set_blog_services( $value['visible'], $value['hidden'] ) : true; 
  324. break; 
  325.  
  326. case 'button_style': 
  327. case 'sharing_label': 
  328. case 'show': 
  329. if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { 
  330. break; 
  331.  
  332. $sharer = new Sharing_Service(); 
  333. $grouped_options = $sharer->get_global_options(); 
  334. $grouped_options[ $option ] = $value; 
  335. $updated = $sharer->set_global_options( $grouped_options ); 
  336. break; 
  337.  
  338. case 'custom': 
  339. if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { 
  340. break; 
  341.  
  342. $sharer = new Sharing_Service(); 
  343. $updated = $sharer->new_service( stripslashes( $value['sharing_name'] ), stripslashes( $value['sharing_url'] ), stripslashes( $value['sharing_icon'] ) ); 
  344.  
  345. // Return new custom service 
  346. $response[$option] = $updated; 
  347. break; 
  348.  
  349. case 'sharing_delete_service': 
  350. if ( ! class_exists( 'Sharing_Service' ) && ! include_once( JETPACK__PLUGIN_DIR . 'modules/sharedaddy/sharing-service.php' ) ) { 
  351. break; 
  352.  
  353. $sharer = new Sharing_Service(); 
  354. $updated = $sharer->delete_service( $value ); 
  355. break; 
  356.  
  357. case 'jetpack-twitter-cards-site-tag': 
  358. $value = trim( ltrim( strip_tags( $value ), '@' ) ); 
  359. $updated = get_option( $option ) !== $value ? update_option( $option, $value ) : true; 
  360. break; 
  361.  
  362. case 'onpublish': 
  363. case 'onupdate': 
  364. case 'Bias Language': 
  365. case 'Cliches': 
  366. case 'Complex Expression': 
  367. case 'Diacritical Marks': 
  368. case 'Double Negative': 
  369. case 'Hidden Verbs': 
  370. case 'Jargon Language': 
  371. case 'Passive voice': 
  372. case 'Phrases to Avoid': 
  373. case 'Redundant Expression': 
  374. case 'guess_lang': 
  375. if ( in_array( $option, array( 'onpublish', 'onupdate' ) ) ) { 
  376. $atd_option = 'AtD_check_when'; 
  377. } elseif ( 'guess_lang' == $option ) { 
  378. $atd_option = 'AtD_guess_lang'; 
  379. $option = 'true'; 
  380. } else { 
  381. $atd_option = 'AtD_options'; 
  382. $user_id = get_current_user_id(); 
  383. if ( ! function_exists( 'AtD_get_options' ) ) { 
  384. include_once( JETPACK__PLUGIN_DIR . 'modules/after-the-deadline.php' ); 
  385. $grouped_options_current = AtD_get_options( $user_id, $atd_option ); 
  386. unset( $grouped_options_current['name'] ); 
  387. $grouped_options = $grouped_options_current; 
  388. if ( $value && ! isset( $grouped_options [$option] ) ) { 
  389. $grouped_options [$option] = $value; 
  390. } elseif ( ! $value && isset( $grouped_options [$option] ) ) { 
  391. unset( $grouped_options [$option] ); 
  392. // If option value was the same, consider it done, otherwise try to update it. 
  393. $options_to_save = implode( ', ', array_keys( $grouped_options ) ); 
  394. $updated = $grouped_options != $grouped_options_current ? AtD_update_setting( $user_id, $atd_option, $options_to_save ) : true; 
  395. break; 
  396.  
  397. case 'ignored_phrases': 
  398. case 'unignore_phrase': 
  399. $user_id = get_current_user_id(); 
  400. $atd_option = 'AtD_ignored_phrases'; 
  401. $grouped_options = $grouped_options_current = explode( ', ', AtD_get_setting( $user_id, $atd_option ) ); 
  402. if ( 'ignored_phrases' == $option ) { 
  403. $grouped_options = explode( ', ', $value ); 
  404. } else { 
  405. $index = array_search( $value, $grouped_options ); 
  406. if ( false !== $index ) { 
  407. unset( $grouped_options[$index] ); 
  408. $grouped_options = array_values( $grouped_options ); 
  409. $ignored_phrases = implode( ', ', array_filter( array_map( 'strip_tags', $grouped_options ) ) ); 
  410. $updated = $grouped_options != $grouped_options_current ? AtD_update_setting( $user_id, $atd_option, $ignored_phrases ) : true; 
  411. break; 
  412.  
  413. case 'admin_bar': 
  414. case 'roles': 
  415. case 'count_roles': 
  416. case 'blog_id': 
  417. case 'do_not_track': 
  418. case 'hide_smile': 
  419. case 'version': 
  420. $grouped_options = $grouped_options_current = (array) get_option( 'stats_options' ); 
  421. $grouped_options[$option] = $value; 
  422.  
  423. // If option value was the same, consider it done. 
  424. $updated = $grouped_options_current != $grouped_options ? update_option( 'stats_options', $grouped_options ) : true; 
  425. break; 
  426.  
  427. case Jetpack_Core_Json_Api_Endpoints::holiday_snow_option_name(): 
  428. $updated = get_option( $option ) != $value ? update_option( $option, (bool) $value ? 'letitsnow' : '' ) : true; 
  429. break; 
  430.  
  431. case 'akismet_show_user_comments_approved': 
  432.  
  433. // Save Akismet option '1' or '0' like it's done in akismet/class.akismet-admin.php 
  434. $updated = get_option( $option ) != $value ? update_option( $option, (bool) $value ? '1' : '0' ) : true; 
  435. break; 
  436.  
  437. case 'wordpress_api_key': 
  438.  
  439. if ( ! file_exists( WP_PLUGIN_DIR . '/akismet/class.akismet.php' ) ) { 
  440. $error = esc_html__( 'Please install Akismet.', 'jetpack' ); 
  441. $updated = false; 
  442. break; 
  443.  
  444. if ( ! defined( 'AKISMET_VERSION' ) ) { 
  445. $error = esc_html__( 'Please activate Akismet.', 'jetpack' ); 
  446. $updated = false; 
  447. break; 
  448.  
  449. // Allow to clear the API key field 
  450. if ( '' === $value ) { 
  451. $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true; 
  452. break; 
  453.  
  454. require_once WP_PLUGIN_DIR . '/akismet/class.akismet.php'; 
  455. require_once WP_PLUGIN_DIR . '/akismet/class.akismet-admin.php'; 
  456.  
  457. if ( class_exists( 'Akismet_Admin' ) && method_exists( 'Akismet_Admin', 'save_key' ) ) { 
  458. if ( Akismet::verify_key( $value ) === 'valid' ) { 
  459. $akismet_user = Akismet_Admin::get_akismet_user( $value ); 
  460. if ( $akismet_user ) { 
  461. if ( in_array( $akismet_user->status, array( 'active', 'active-dunning', 'no-sub' ) ) ) { 
  462. $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true; 
  463. break; 
  464. } else { 
  465. $error = esc_html__( "Akismet user status doesn't allow to update the key", 'jetpack' ); 
  466. } else { 
  467. $error = esc_html__( 'Invalid Akismet user', 'jetpack' ); 
  468. } else { 
  469. $error = esc_html__( 'Invalid Akismet key', 'jetpack' ); 
  470. } else { 
  471. $error = esc_html__( 'Akismet is not installed or active', 'jetpack' ); 
  472. $updated = false; 
  473. break; 
  474.  
  475. case 'google_analytics_tracking_id': 
  476. $grouped_options = $grouped_options_current = (array) get_option( 'jetpack_wga' ); 
  477. $grouped_options[ 'code' ] = $value; 
  478.  
  479. // If option value was the same, consider it done. 
  480. $updated = $grouped_options_current != $grouped_options ? update_option( 'jetpack_wga', $grouped_options ) : true; 
  481. break; 
  482.  
  483. case 'dismiss_dash_app_card': 
  484. // If option value was the same, consider it done. 
  485. $updated = get_option( $option ) != $value ? update_option( $option, (bool) $value ) : true; 
  486. break; 
  487.  
  488. default: 
  489. // If option value was the same, consider it done. 
  490. $updated = get_option( $option ) != $value ? update_option( $option, $value ) : true; 
  491. break; 
  492.  
  493. // The option was not updated. 
  494. if ( ! $updated ) { 
  495. $not_updated[ $option ] = $error; 
  496.  
  497. if ( empty( $invalid ) && empty( $not_updated ) ) { 
  498. // The option was updated. 
  499. return rest_ensure_response( $response ); 
  500. } else { 
  501. $invalid_count = count( $invalid ); 
  502. $not_updated_count = count( $not_updated ); 
  503. $error = ''; 
  504. if ( $invalid_count > 0 ) { 
  505. $error = sprintf( 
  506. /** Translators: the plural variable is a comma-separated list. Example: dog, cat, bird. */ 
  507. _n( 'Invalid option: %s.', 'Invalid options: %s.', $invalid_count, 'jetpack' ),  
  508. join( ', ', $invalid ) 
  509. ); 
  510. if ( $not_updated_count > 0 ) { 
  511. $not_updated_messages = array(); 
  512. foreach ( $not_updated as $not_updated_option => $not_updated_message ) { 
  513. if ( ! empty( $not_updated_message ) ) { 
  514. $not_updated_messages[] = sprintf( 
  515. /** Translators: the first variable is a module option or slug, or setting. The second is the error message . */ 
  516. __( '%1$s: %2$s', 'jetpack' ),  
  517. $not_updated_option, $not_updated_message ); 
  518. if ( ! empty( $error ) ) { 
  519. $error .= ' '; 
  520. if ( ! empty( $not_updated_messages ) ) { 
  521. $error .= ' ' . join( '. ', $not_updated_messages ); 
  522.  
  523. // There was an error because some options were updated but others were invalid or failed to update. 
  524. return new WP_Error( 'some_updated', esc_html( $error ), array( 'status' => 400 ) ); 
  525.  
  526.  
  527. /** 
  528. * Calls WPCOM through authenticated request to create, regenerate or delete the Post by Email address. 
  529. * @todo: When all settings are updated to use endpoints, move this to the Post by Email module and replace __process_ajax_proxy_request. 
  530. * @since 4.3.0 
  531. * @param string $endpoint Process to call on WPCOM to create, regenerate or delete the Post by Email address. 
  532. * @param string $error Error message to return. 
  533. * @return array 
  534. */ 
  535. private function _process_post_by_email( $endpoint, $error ) { 
  536. if ( ! current_user_can( 'edit_posts' ) ) { 
  537. return array( 'message' => $error ); 
  538.  
  539. $this->xmlrpc->query( $endpoint ); 
  540.  
  541. if ( $this->xmlrpc->isError() ) { 
  542. return array( 'message' => $error ); 
  543.  
  544. $response = $this->xmlrpc->getResponse(); 
  545. if ( empty( $response ) ) { 
  546. return array( 'message' => $error ); 
  547.  
  548. // Used only in Jetpack_Core_Json_Api_Endpoints::get_remote_value. 
  549. update_option( 'post_by_email_address' . get_current_user_id(), $response ); 
  550.  
  551. return $response; 
  552.  
  553. /** 
  554. * Check if user is allowed to perform the update. 
  555. * @since 4.3.0 
  556. * @param WP_REST_Request $request The request sent to the WP REST API. 
  557. * @return bool 
  558. */ 
  559. public function can_request( $request ) { 
  560. if ( 'GET' === $request->get_method() ) { 
  561. return current_user_can( 'jetpack_admin_page' ); 
  562. } else { 
  563. $module = Jetpack_Core_Json_Api_Endpoints::get_module_requested(); 
  564. if ( empty( $module ) ) { 
  565. $params = $request->get_json_params(); 
  566. if ( ! is_array( $params ) ) { 
  567. $params = $request->get_body_params(); 
  568. $options = Jetpack_Core_Json_Api_Endpoints::get_updateable_data_list( $params ); 
  569. foreach ( $options as $option => $definition ) { 
  570. if ( in_array( $options[ $option ]['jp_group'], array( 'after-the-deadline', 'post-by-email' ) ) ) { 
  571. $module = $options[ $option ]['jp_group']; 
  572. break; 
  573. // User is trying to create, regenerate or delete its PbE || ATD settings. 
  574. if ( 'post-by-email' === $module || 'after-the-deadline' === $module ) { 
  575. return current_user_can( 'edit_posts' ) && current_user_can( 'jetpack_admin_page' ); 
  576. return current_user_can( 'jetpack_configure_modules' );