WPCOM_JSON_API_Site_Settings_Endpoint

The Jetpack by WordPress.com WPCOM JSON API Site Settings Endpoint class.

Defined (1)

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

/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php  
  1. class WPCOM_JSON_API_Site_Settings_Endpoint extends WPCOM_JSON_API_Endpoint { 
  2.  
  3. public static $site_format = array( 
  4. 'ID' => '(int) Site ID',  
  5. 'name' => '(string) Title of site',  
  6. 'description' => '(string) Tagline or description of site',  
  7. 'URL' => '(string) Full URL to the site',  
  8. 'lang' => '(string) Primary language code of the site',  
  9. 'settings' => '(array) An array of options/settings for the blog. Only viewable by users with post editing rights to the site.',  
  10. ); 
  11.  
  12. // GET /sites/%s/settings 
  13. // POST /sites/%s/settings 
  14. function callback( $path = '', $blog_id = 0 ) { 
  15. $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) ); 
  16. if ( is_wp_error( $blog_id ) ) { 
  17. return $blog_id; 
  18.  
  19. if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { 
  20. $this->load_theme_functions(); 
  21.  
  22. if ( ! is_user_logged_in() ) { 
  23. return new WP_Error( 'Unauthorized', 'You must be logged-in to manage settings.', 401 ); 
  24. } else if ( ! current_user_can( 'manage_options' ) ) { 
  25. return new WP_Error( 'Forbidden', 'You do not have the capability to manage settings for this site.', 403 ); 
  26.  
  27. if ( 'GET' === $this->api->method ) { 
  28. /** 
  29. * Fires on each GET request to a specific endpoint. 
  30. * @module json-api 
  31. * @since 3.2.0 
  32. * @param string sites. 
  33. */ 
  34. do_action( 'wpcom_json_api_objects', 'sites' ); 
  35. return $this->get_settings_response(); 
  36. } else if ( 'POST' === $this->api->method ) { 
  37. return $this->update_settings(); 
  38. } else { 
  39. return new WP_Error( 'bad_request', 'An unsupported request method was used.' ); 
  40.  
  41.  
  42. /** 
  43. * Determines whether jetpack_relatedposts is supported 
  44. * @return (bool) 
  45. */ 
  46. public function jetpack_relatedposts_supported() { 
  47. $wpcom_related_posts_theme_blacklist = array( 
  48. 'Expound',  
  49. 'Traveler',  
  50. 'Opti',  
  51. 'Currents',  
  52. ); 
  53. return ( ! in_array( wp_get_theme()->get( 'Name' ), $wpcom_related_posts_theme_blacklist ) ); 
  54.  
  55. /** 
  56. * Returns category details 
  57. * @return (array) 
  58. */ 
  59. public function get_category_details( $category ) { 
  60. return array( 
  61. 'value' => $category->term_id,  
  62. 'name' => $category->name 
  63. ); 
  64.  
  65. /** 
  66. * Collects the necessary information to return for a get settings response. 
  67. * @return (array) 
  68. */ 
  69. public function get_settings_response() { 
  70.  
  71. $response_format = self::$site_format; 
  72. $blog_id = (int) $this->api->get_blog_id_for_output(); 
  73. /** This filter is documented in class.json-api-endpoints.php */ 
  74. $is_jetpack = true === apply_filters( 'is_jetpack_site', false, $blog_id ); 
  75.  
  76. foreach ( array_keys( $response_format ) as $key ) { 
  77. switch ( $key ) { 
  78. case 'ID' : 
  79. $response[$key] = $blog_id; 
  80. break; 
  81. case 'name' : 
  82. $response[$key] = (string) htmlspecialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ); 
  83. break; 
  84. case 'description' : 
  85. $response[$key] = (string) htmlspecialchars_decode( get_bloginfo( 'description' ), ENT_QUOTES ); 
  86. break; 
  87. case 'URL' : 
  88. $response[$key] = (string) home_url(); 
  89. break; 
  90. case 'lang' : 
  91. $response[$key] = (string) get_bloginfo( 'language' ); 
  92. break; 
  93. case 'settings': 
  94.  
  95. $jetpack_relatedposts_options = Jetpack_Options::get_option( 'relatedposts' ); 
  96.  
  97. if ( method_exists( 'Jetpack', 'is_module_active' ) ) { 
  98. $jetpack_relatedposts_options[ 'enabled' ] = Jetpack::is_module_active( 'related-posts' ); 
  99.  
  100. // array_values() is necessary to ensure the array starts at index 0. 
  101. $post_categories = array_values( 
  102. array_map( 
  103. array( $this, 'get_category_details' ),  
  104. get_categories( array( 'hide_empty' => false ) ) 
  105. ); 
  106.  
  107. $eventbrite_api_token = (int) get_option( 'eventbrite_api_token' ); 
  108. if ( 0 === $eventbrite_api_token ) { 
  109. $eventbrite_api_token = null; 
  110.  
  111. $response[$key] = array( 
  112.  
  113. // also exists as "options" 
  114. 'admin_url' => get_admin_url(),  
  115. 'default_ping_status' => (bool) ( 'closed' != get_option( 'default_ping_status' ) ),  
  116. 'default_comment_status' => (bool) ( 'closed' != get_option( 'default_comment_status' ) ),  
  117.  
  118. // new stuff starts here 
  119. 'blog_public' => (int) get_option( 'blog_public' ),  
  120. 'jetpack_sync_non_public_post_stati' => (bool) Jetpack_Options::get_option( 'sync_non_public_post_stati' ),  
  121. 'jetpack_relatedposts_allowed' => (bool) $this->jetpack_relatedposts_supported(),  
  122. 'jetpack_relatedposts_enabled' => (bool) $jetpack_relatedposts_options[ 'enabled' ],  
  123. 'jetpack_relatedposts_show_headline' => (bool) $jetpack_relatedposts_options[ 'show_headline' ],  
  124. 'jetpack_relatedposts_show_thumbnails' => (bool) $jetpack_relatedposts_options[ 'show_thumbnails' ],  
  125. 'default_category' => (int) get_option('default_category'),  
  126. 'post_categories' => (array) $post_categories,  
  127. 'default_post_format' => get_option( 'default_post_format' ),  
  128. 'default_pingback_flag' => (bool) get_option( 'default_pingback_flag' ),  
  129. 'require_name_email' => (bool) get_option( 'require_name_email' ),  
  130. 'comment_registration' => (bool) get_option( 'comment_registration' ),  
  131. 'close_comments_for_old_posts' => (bool) get_option( 'close_comments_for_old_posts' ),  
  132. 'close_comments_days_old' => (int) get_option( 'close_comments_days_old' ),  
  133. 'thread_comments' => (bool) get_option( 'thread_comments' ),  
  134. 'thread_comments_depth' => (int) get_option( 'thread_comments_depth' ),  
  135. 'page_comments' => (bool) get_option( 'page_comments' ),  
  136. 'comments_per_page' => (int) get_option( 'comments_per_page' ),  
  137. 'default_comments_page' => get_option( 'default_comments_page' ),  
  138. 'comment_order' => get_option( 'comment_order' ),  
  139. 'comments_notify' => (bool) get_option( 'comments_notify' ),  
  140. 'moderation_notify' => (bool) get_option( 'moderation_notify' ),  
  141. 'social_notifications_like' => ( "on" == get_option( 'social_notifications_like' ) ),  
  142. 'social_notifications_reblog' => ( "on" == get_option( 'social_notifications_reblog' ) ),  
  143. 'social_notifications_subscribe' => ( "on" == get_option( 'social_notifications_subscribe' ) ),  
  144. 'comment_moderation' => (bool) get_option( 'comment_moderation' ),  
  145. 'comment_whitelist' => (bool) get_option( 'comment_whitelist' ),  
  146. 'comment_max_links' => (int) get_option( 'comment_max_links' ),  
  147. 'moderation_keys' => get_option( 'moderation_keys' ),  
  148. 'blacklist_keys' => get_option( 'blacklist_keys' ),  
  149. 'lang_id' => get_option( 'lang_id' ),  
  150. 'wga' => get_option( 'wga' ),  
  151. 'disabled_likes' => (bool) get_option( 'disabled_likes' ),  
  152. 'disabled_reblogs' => (bool) get_option( 'disabled_reblogs' ),  
  153. 'jetpack_comment_likes_enabled' => (bool) get_option( 'jetpack_comment_likes_enabled', false ),  
  154. 'twitter_via' => (string) get_option( 'twitter_via' ),  
  155. 'jetpack-twitter-cards-site-tag' => (string) get_option( 'jetpack-twitter-cards-site-tag' ),  
  156. 'eventbrite_api_token' => $eventbrite_api_token,  
  157. ); 
  158.  
  159. if ( class_exists( 'Sharing_Service' ) ) { 
  160. $ss = new Sharing_Service(); 
  161. $sharing = $ss->get_global_options(); 
  162. $response[ $key ]['sharing_button_style'] = (string) $sharing['button_style']; 
  163. $response[ $key ]['sharing_label'] = (string) $sharing['sharing_label']; 
  164. $response[ $key ]['sharing_show'] = (array) $sharing['show']; 
  165. $response[ $key ]['sharing_open_links'] = (string) $sharing['open_links']; 
  166.  
  167. if ( function_exists( 'jetpack_protect_format_whitelist' ) ) { 
  168. $response[ $key ]['jetpack_protect_whitelist'] = jetpack_protect_format_whitelist(); 
  169.  
  170. if ( ! current_user_can( 'edit_posts' ) ) 
  171. unset( $response[$key] ); 
  172. break; 
  173.  
  174. return $response; 
  175.  
  176.  
  177. /** 
  178. * Updates site settings for authorized users 
  179. * @return (array) 
  180. */ 
  181. public function update_settings() { 
  182.  
  183. // $this->input() retrieves posted arguments whitelisted and casted to the $request_format 
  184. // specs that get passed in when this class is instantiated 
  185. /** 
  186. * Filters the settings to be updated on the site. 
  187. * @module json-api 
  188. * @since 3.6.0 
  189. * @param array $input Associative array of site settings to be updated. 
  190. */ 
  191. $input = apply_filters( 'rest_api_update_site_settings', $this->input() ); 
  192.  
  193. $jetpack_relatedposts_options = array(); 
  194. $sharing_options = array(); 
  195. $updated = array(); 
  196.  
  197. foreach ( $input as $key => $value ) { 
  198.  
  199. if ( ! is_array( $value ) ) { 
  200. $value = trim( $value ); 
  201. $value = wp_unslash( $value ); 
  202.  
  203. switch ( $key ) { 
  204.  
  205. case 'default_ping_status': 
  206. case 'default_comment_status': 
  207. // settings are stored as closed|open 
  208. $coerce_value = ( $value ) ? 'open' : 'closed'; 
  209. if ( update_option( $key, $coerce_value ) ) { 
  210. $updated[ $key ] = $value; 
  211. }; 
  212. break; 
  213. case 'jetpack_protect_whitelist': 
  214. if ( function_exists( 'jetpack_protect_save_whitelist' ) ) { 
  215. $result = jetpack_protect_save_whitelist( $value ); 
  216. if ( is_wp_error( $result ) ) { 
  217. return $result; 
  218. $updated[ $key ] = jetpack_protect_format_whitelist(); 
  219. break; 
  220. case 'jetpack_sync_non_public_post_stati': 
  221. Jetpack_Options::update_option( 'sync_non_public_post_stati', $value ); 
  222. break; 
  223. case 'jetpack_relatedposts_enabled': 
  224. case 'jetpack_relatedposts_show_thumbnails': 
  225. case 'jetpack_relatedposts_show_headline': 
  226. if ( ! $this->jetpack_relatedposts_supported() ) { 
  227. break; 
  228. if ( 'jetpack_relatedposts_enabled' === $key && method_exists( 'Jetpack', 'is_module_active' ) && $this->jetpack_relatedposts_supported() ) { 
  229. $before_action = Jetpack::is_module_active('related-posts'); 
  230. if ( $value ) { 
  231. Jetpack::activate_module( 'related-posts', false, false ); 
  232. } else { 
  233. Jetpack::deactivate_module( 'related-posts' ); 
  234. $after_action = Jetpack::is_module_active('related-posts'); 
  235. if ( $after_action == $before_action ) { 
  236. break; 
  237. $just_the_key = substr( $key, 21 ); 
  238. $jetpack_relatedposts_options[ $just_the_key ] = $value; 
  239. break; 
  240.  
  241. case 'social_notifications_like': 
  242. case 'social_notifications_reblog': 
  243. case 'social_notifications_subscribe': 
  244. // settings are stored as on|off 
  245. $coerce_value = ( $value ) ? 'on' : 'off'; 
  246. if ( update_option( $key, $coerce_value ) ) { 
  247. $updated[ $key ] = $value; 
  248. break; 
  249. case 'wga': 
  250. if ( ! isset( $value['code'] ) || ! preg_match( '/^$|^UA-[\d-]+$/i', $value['code'] ) ) { 
  251. return new WP_Error( 'invalid_code', 'Invalid UA ID' ); 
  252. $wga = get_option( 'wga', array() ); 
  253. $wga['code'] = $value['code']; // maintain compatibility with wp-google-analytics 
  254. if ( update_option( 'wga', $wga ) ) { 
  255. $updated[ $key ] = $value; 
  256.  
  257. $enabled_or_disabled = $wga['code'] ? 'enabled' : 'disabled'; 
  258.  
  259. /** This action is documented in modules/widgets/social-media-icons.php */ 
  260. do_action( 'jetpack_bump_stats_extras', 'google-analytics', $enabled_or_disabled ); 
  261.  
  262. $business_plugins = WPCOM_Business_Plugins::instance(); 
  263. $business_plugins->activate_plugin( 'wp-google-analytics' ); 
  264. break; 
  265.  
  266. case 'jetpack_comment_likes_enabled': 
  267. // settings are stored as 1|0 
  268. $coerce_value = (int) $value; 
  269. if ( update_option( $key, $coerce_value ) ) { 
  270. $updated[ $key ] = $value; 
  271. break; 
  272.  
  273. // Sharing options 
  274. case 'sharing_button_style': 
  275. case 'sharing_show': 
  276. case 'sharing_open_links': 
  277. $sharing_options[ preg_replace( '/^sharing_/', '', $key ) ] = $value; 
  278. break; 
  279. case 'sharing_label': 
  280. $sharing_options[ $key ] = $value; 
  281. break; 
  282.  
  283. // Keyring token option 
  284. case 'eventbrite_api_token': 
  285. // These options can only be updated for sites hosted on WordPress.com 
  286. if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { 
  287. if ( empty( $value ) || WPCOM_JSON_API::is_falsy( $value ) ) { 
  288. if ( delete_option( $key ) ) { 
  289. $updated[ $key ] = null; 
  290. } else if ( update_option( $key, $value ) ) { 
  291. $updated[ $key ] = (int) $value; 
  292. break; 
  293.  
  294. // no worries, we've already whitelisted and casted arguments above 
  295. default: 
  296. if ( update_option( $key, $value ) ) { 
  297. $updated[ $key ] = $value; 
  298.  
  299.  
  300. if ( count( $jetpack_relatedposts_options ) ) { 
  301. // track new jetpack_relatedposts options against old 
  302. $old_relatedposts_options = Jetpack_Options::get_option( 'relatedposts' ); 
  303. if ( Jetpack_Options::update_option( 'relatedposts', $jetpack_relatedposts_options ) ) { 
  304. foreach( $jetpack_relatedposts_options as $key => $value ) { 
  305. if ( $value !== $old_relatedposts_options[ $key ] ) { 
  306. $updated[ 'jetpack_relatedposts_' . $key ] = $value; 
  307.  
  308. if ( ! empty( $sharing_options ) && class_exists( 'Sharing_Service' ) ) { 
  309. $ss = new Sharing_Service(); 
  310.  
  311. // Merge current values with updated, since Sharing_Service expects 
  312. // all values to be included when updating 
  313. $current_sharing_options = $ss->get_global_options(); 
  314. foreach ( $current_sharing_options as $key => $val ) { 
  315. if ( ! isset( $sharing_options[ $key ] ) ) { 
  316. $sharing_options[ $key ] = $val; 
  317.  
  318. $updated_social_options = $ss->set_global_options( $sharing_options ); 
  319.  
  320. if ( isset( $input['sharing_button_style'] ) ) { 
  321. $updated['sharing_button_style'] = (string) $updated_social_options['button_style']; 
  322. if ( isset( $input['sharing_label'] ) ) { 
  323. // Sharing_Service won't report label as updated if set to default 
  324. $updated['sharing_label'] = (string) $sharing_options['sharing_label']; 
  325. if ( isset( $input['sharing_show'] ) ) { 
  326. $updated['sharing_show'] = (array) $updated_social_options['show']; 
  327. if ( isset( $input['sharing_open_links'] ) ) { 
  328. $updated['sharing_open_links'] = (string) $updated_social_options['open_links']; 
  329.  
  330. return array( 
  331. 'updated' => $updated 
  332. ); 
  333.