← All changes
|
jetpack_vendor/automattic/jetpack-stats-admin/src/class-rest-controller.php
+160
-4
16.2
→
16.3-a.7
View file →
| @@ -8,8 +8,9 @@ | ||
| 8 | 8 | |
| 9 | 9 | namespace Automattic\Jetpack\Stats_Admin; |
| 10 | 10 | |
| 11 | 11 | use Automattic\Jetpack\Constants; |
| 12 | +use Automattic\Jetpack\Stats\Settings as Stats_Settings; | |
| 12 | 13 | use Automattic\Jetpack\Stats\WPCOM_Stats; |
| 13 | 14 | use Jetpack_Options; |
| 14 | 15 | use WP_Error; |
| 15 | 16 | use WP_REST_Request; |
| @@ -165,8 +166,47 @@ | ||
| 165 | 166 | 'permission_callback' => array( $this, 'can_user_view_general_stats_callback' ), |
| 166 | 167 | ) |
| 167 | 168 | ); |
| 168 | 169 | |
| 170 | + // Stats settings. | |
| 171 | + register_rest_route( | |
| 172 | + static::$namespace, | |
| 173 | + sprintf( '/sites/%d/jetpack-stats/settings', Jetpack_Options::get_option( 'id' ) ), | |
| 174 | + array( | |
| 175 | + array( | |
| 176 | + 'methods' => WP_REST_Server::READABLE, | |
| 177 | + 'callback' => array( $this, 'get_stats_settings' ), | |
| 178 | + 'permission_callback' => array( $this, 'can_user_manage_stats_settings_callback' ), | |
| 179 | + ), | |
| 180 | + array( | |
| 181 | + 'methods' => WP_REST_Server::EDITABLE, | |
| 182 | + 'callback' => array( $this, 'update_stats_settings' ), | |
| 183 | + 'permission_callback' => array( $this, 'can_user_manage_stats_settings_callback' ), | |
| 184 | + 'args' => array( | |
| 185 | + 'admin_bar' => array( | |
| 186 | + 'description' => 'Show a chart of the last 48 hours of views in the admin bar', | |
| 187 | + 'type' => 'boolean', | |
| 188 | + ), | |
| 189 | + 'roles' => array( | |
| 190 | + 'description' => 'Roles that can view Stats. `administrator` is always kept.', | |
| 191 | + 'type' => 'array', | |
| 192 | + 'items' => array( 'type' => 'string' ), | |
| 193 | + 'minItems' => 1, | |
| 194 | + ), | |
| 195 | + 'count_roles' => array( | |
| 196 | + 'description' => 'Roles whose logged-in page views are counted', | |
| 197 | + 'type' => 'array', | |
| 198 | + 'items' => array( 'type' => 'string' ), | |
| 199 | + ), | |
| 200 | + 'wpcom_reader_views_enabled' => array( | |
| 201 | + 'description' => 'Show post views in the WordPress.com Reader', | |
| 202 | + 'type' => 'boolean', | |
| 203 | + ), | |
| 204 | + ), | |
| 205 | + ), | |
| 206 | + ) | |
| 207 | + ); | |
| 208 | + | |
| 169 | 209 | // User feedback endpoint. |
| 170 | 210 | register_rest_route( |
| 171 | 211 | static::$namespace, |
| 172 | 212 | sprintf( '/sites/%d/jetpack-stats/user-feedback', Jetpack_Options::get_option( 'id' ) ), |
| @@ -220,9 +260,9 @@ | ||
| 220 | 260 | 'description' => 'Status of the notice', |
| 221 | 261 | ), |
| 222 | 262 | 'postponed_for' => array( |
| 223 | 263 | 'type' => 'number', |
| 224 | - 'default' => null, | |
| 264 | + 'default' => 0, | |
| 225 | 265 | 'description' => 'Postponed for (in seconds)', |
| 226 | 266 | 'minimum' => 0, |
| 227 | 267 | ), |
| 228 | 268 | ), |
| @@ -249,9 +289,10 @@ | ||
| 249 | 289 | 'description' => 'Status of the notice', |
| 250 | 290 | ), |
| 251 | 291 | 'postponed_for' => array( |
| 252 | 292 | 'type' => 'number', |
| 253 | - 'default' => null, | |
| 293 | + // Forwarded to WPCOM as-is, whose schema rejects the null an omitted param would carry. | |
| 294 | + 'default' => 0, | |
| 254 | 295 | 'description' => 'Postponed for (in seconds)', |
| 255 | 296 | 'minimum' => 0, |
| 256 | 297 | ), |
| 257 | 298 | ), |
| @@ -265,8 +306,15 @@ | ||
| 265 | 306 | array( |
| 266 | 307 | 'methods' => WP_REST_Server::READABLE, |
| 267 | 308 | 'callback' => array( $this, 'get_notice_status' ), |
| 268 | 309 | 'permission_callback' => array( $this, 'can_user_view_general_stats_callback' ), |
| 310 | + 'args' => array( | |
| 311 | + 'include_details' => array( | |
| 312 | + 'type' => 'boolean', | |
| 313 | + 'default' => false, | |
| 314 | + 'description' => 'Return a detail record per notice instead of a flat boolean map', | |
| 315 | + ), | |
| 316 | + ), | |
| 269 | 317 | ) |
| 270 | 318 | ); |
| 271 | 319 | |
| 272 | 320 | // Get referrer spam list. |
| @@ -475,8 +523,21 @@ | ||
| 475 | 523 | return $this->get_forbidden_error(); |
| 476 | 524 | } |
| 477 | 525 | |
| 478 | 526 | /** |
| 527 | + * Only administrators can read or change the Stats settings, because `roles` decides who else can view Stats. | |
| 528 | + * | |
| 529 | + * @return bool|WP_Error | |
| 530 | + */ | |
| 531 | + public function can_user_manage_stats_settings_callback() { | |
| 532 | + if ( current_user_can( 'manage_options' ) ) { | |
| 533 | + return true; | |
| 534 | + } | |
| 535 | + | |
| 536 | + return $this->get_forbidden_error(); | |
| 537 | + } | |
| 538 | + | |
| 539 | + /** | |
| 479 | 540 | * Only administrators or users with capability `activate_wordads` can access the API. |
| 480 | 541 | */ |
| 481 | 542 | public function can_user_view_wordads_stats_callback() { |
| 482 | 543 | // phpcs:ignore WordPress.WP.Capabilities.Unknown |
| @@ -753,8 +814,102 @@ | ||
| 753 | 814 | ); |
| 754 | 815 | } |
| 755 | 816 | |
| 756 | 817 | /** |
| 818 | + * Get the Stats settings and the site's roles. | |
| 819 | + * | |
| 820 | + * @return array | |
| 821 | + */ | |
| 822 | + public function get_stats_settings() { | |
| 823 | + return $this->get_stats_settings_response(); | |
| 824 | + } | |
| 825 | + | |
| 826 | + /** | |
| 827 | + * Save the Stats settings in the request. | |
| 828 | + * | |
| 829 | + * @param WP_REST_Request $req The request object. | |
| 830 | + * | |
| 831 | + * @return array|WP_Error The settings after the save, or why the values were refused. | |
| 832 | + */ | |
| 833 | + public function update_stats_settings( $req ) { | |
| 834 | + $params = $req->get_params(); | |
| 835 | + $keys = self::get_stats_settings_keys(); | |
| 836 | + | |
| 837 | + $stats_values = array_intersect_key( $params, array_flip( $keys ) ); | |
| 838 | + if ( empty( $stats_values ) && ! isset( $params['wpcom_reader_views_enabled'] ) ) { | |
| 839 | + return new WP_Error( | |
| 840 | + 'jetpack_stats_missing_setting_field', | |
| 841 | + sprintf( | |
| 842 | + /* translators: %s: comma-separated list of the settings that can be changed. */ | |
| 843 | + __( 'Provide at least one of: %s.', 'jetpack-stats-admin' ), | |
| 844 | + implode( ', ', array_merge( $keys, array( 'wpcom_reader_views_enabled' ) ) ) | |
| 845 | + ), | |
| 846 | + array( 'status' => 400 ) | |
| 847 | + ); | |
| 848 | + } | |
| 849 | + | |
| 850 | + if ( ! empty( $stats_values ) ) { | |
| 851 | + $result = Stats_Settings::update( $stats_values, $keys ); | |
| 852 | + if ( is_wp_error( $result ) ) { | |
| 853 | + $result->add_data( array( 'status' => 400 ) ); | |
| 854 | + return $result; | |
| 855 | + } | |
| 856 | + } | |
| 857 | + | |
| 858 | + if ( isset( $params['wpcom_reader_views_enabled'] ) ) { | |
| 859 | + $reader_views = (int) $params['wpcom_reader_views_enabled']; | |
| 860 | + update_option( 'wpcom_reader_views_enabled', $reader_views ); | |
| 861 | + // update_option() also returns false for an unchanged value, so read the option back. | |
| 862 | + if ( (int) get_option( 'wpcom_reader_views_enabled', 1 ) !== $reader_views ) { | |
| 863 | + return new WP_Error( | |
| 864 | + 'jetpack_stats_save_failed', | |
| 865 | + __( 'The Stats settings could not be saved.', 'jetpack-stats-admin' ), | |
| 866 | + array( 'status' => 400 ) | |
| 867 | + ); | |
| 868 | + } | |
| 869 | + } | |
| 870 | + | |
| 871 | + return $this->get_stats_settings_response(); | |
| 872 | + } | |
| 873 | + | |
| 874 | + /** | |
| 875 | + * The Stats settings the Settings screen offers. | |
| 876 | + * | |
| 877 | + * @return string[] | |
| 878 | + */ | |
| 879 | + private static function get_stats_settings_keys() { | |
| 880 | + // Nothing reads `do_not_track`, so the screen does not offer it. | |
| 881 | + return array_values( array_diff( Stats_Settings::KEYS, array( 'do_not_track' ) ) ); | |
| 882 | + } | |
| 883 | + | |
| 884 | + /** | |
| 885 | + * Build the settings response: the current values and the roles the toggles list. | |
| 886 | + * | |
| 887 | + * @return array | |
| 888 | + */ | |
| 889 | + private function get_stats_settings_response() { | |
| 890 | + if ( ! function_exists( 'get_editable_roles' ) ) { | |
| 891 | + require_once ABSPATH . 'wp-admin/includes/user.php'; | |
| 892 | + } | |
| 893 | + | |
| 894 | + $roles = array(); | |
| 895 | + foreach ( get_editable_roles() as $slug => $role ) { | |
| 896 | + $roles[] = array( | |
| 897 | + 'slug' => $slug, | |
| 898 | + 'name' => translate_user_role( $role['name'] ), | |
| 899 | + ); | |
| 900 | + } | |
| 901 | + | |
| 902 | + return array( | |
| 903 | + 'settings' => array_merge( | |
| 904 | + Stats_Settings::get( self::get_stats_settings_keys() ), | |
| 905 | + array( 'wpcom_reader_views_enabled' => (bool) get_option( 'wpcom_reader_views_enabled', true ) ) | |
| 906 | + ), | |
| 907 | + 'roles' => $roles, | |
| 908 | + ); | |
| 909 | + } | |
| 910 | + | |
| 911 | + /** | |
| 757 | 912 | * Post user feedback for Jetpack Stats. |
| 758 | 913 | * |
| 759 | 914 | * @param WP_REST_Request $req The request object. |
| 760 | 915 | * |
| @@ -1039,12 +1194,13 @@ | ||
| 1039 | 1194 | |
| 1040 | 1195 | /** |
| 1041 | 1196 | * Get stats notices. |
| 1042 | 1197 | * |
| 1198 | + * @param WP_REST_Request $req The request object. | |
| 1043 | 1199 | * @return array |
| 1044 | 1200 | */ |
| 1045 | - public function get_notice_status() { | |
| 1046 | - return ( new Notices() )->get_notices_to_show(); | |
| 1201 | + public function get_notice_status( $req ) { | |
| 1202 | + return ( new Notices() )->get_notices_to_show( (bool) $req->get_param( 'include_details' ) ); | |
| 1047 | 1203 | } |
| 1048 | 1204 | |
| 1049 | 1205 | /** |
| 1050 | 1206 | * Get the list of spam referrers. |