PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/blog/wp-content/plugins/jetpack/json-endpoints/class.wpcom-json-api-site-settings-endpoint.php

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