Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.82% covered (warning)
81.82%
36 / 44
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Notices_Controller
81.82% covered (warning)
81.82%
36 / 44
50.00% covered (danger)
50.00%
3 / 6
7.29
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 register
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 register_routes
100.00% covered (success)
100.00%
34 / 34
100.00% covered (success)
100.00%
1 / 1
1
 check_permission
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 get_notices
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 update_notice
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * REST controller for the dashboard notices, which need local processing the data proxy can't do.
4 *
5 * @package automattic/jetpack-premium-analytics
6 */
7
8namespace Automattic\Jetpack\PremiumAnalytics\REST;
9
10use Automattic\Jetpack\PremiumAnalytics\Notices;
11use WP_REST_Request;
12use WP_REST_Server;
13
14/**
15 * Exposes `jetpack-premium-analytics/v1/notices` (GET + POST).
16 *
17 * Unlike the transparent endpoints served by {@see Api_Proxy_Controller}, the notices GET augments
18 * the WPCOM dismissal state with locally-derived flags (opt-in/opt-out/feedback/GDPR), so it lives
19 * on its own route outside `proxy/` and delegates to the {@see Notices} class.
20 */
21class Notices_Controller {
22
23    /**
24     * Package slug, used as the REST namespace root.
25     *
26     * @var string
27     */
28    private const SLUG = 'jetpack-premium-analytics';
29
30    /**
31     * REST namespace.
32     *
33     * @var string
34     */
35    private $namespace;
36
37    /**
38     * Constructor.
39     */
40    public function __construct() {
41        $this->namespace = self::SLUG . '/v1';
42    }
43
44    /**
45     * Hook the controller's routes onto rest_api_init.
46     *
47     * @return void
48     */
49    public static function register(): void {
50        $controller = new self();
51        add_action( 'rest_api_init', array( $controller, 'register_routes' ) );
52    }
53
54    /**
55     * Register the notices route.
56     *
57     * @return void
58     */
59    public function register_routes(): void {
60        register_rest_route(
61            $this->namespace,
62            '/notices',
63            array(
64                array(
65                    'methods'             => WP_REST_Server::READABLE,
66                    'callback'            => array( $this, 'get_notices' ),
67                    'permission_callback' => array( $this, 'check_permission' ),
68                ),
69                array(
70                    'methods'             => WP_REST_Server::EDITABLE,
71                    'callback'            => array( $this, 'update_notice' ),
72                    'permission_callback' => array( $this, 'check_permission' ),
73                    'args'                => array(
74                        'id'            => array(
75                            'required'    => true,
76                            'type'        => 'string',
77                            'description' => __( 'ID of the notice.', 'jetpack-premium-analytics' ),
78                        ),
79                        'status'        => array(
80                            'required'    => true,
81                            'type'        => 'string',
82                            'description' => __( 'Status of the notice.', 'jetpack-premium-analytics' ),
83                        ),
84                        'postponed_for' => array(
85                            'type'        => 'number',
86                            'default'     => 0,
87                            'description' => __( 'Postponed for (in seconds).', 'jetpack-premium-analytics' ),
88                            'minimum'     => 0,
89                        ),
90                    ),
91                ),
92            )
93        );
94    }
95
96    /**
97     * Whether the current user may read or change the dashboard notices.
98     *
99     * @return bool
100     */
101    public function check_permission(): bool {
102        return current_user_can( 'manage_options' ) || current_user_can( 'view_stats' );
103    }
104
105    /**
106     * Get the notices to show, with locally-derived flags merged in.
107     *
108     * @param WP_REST_Request $request Request object.
109     *
110     * @return array
111     */
112    public function get_notices( WP_REST_Request $request ): array {
113        return ( new Notices() )->get_notices_to_show( null !== $request->get_param( 'force_refresh' ) );
114    }
115
116    /**
117     * Dismiss or delay a notice.
118     *
119     * @param WP_REST_Request $request Request object.
120     *
121     * @return array|\WP_Error
122     */
123    public function update_notice( WP_REST_Request $request ) {
124        return ( new Notices() )->update_notice(
125            $request->get_param( 'id' ),
126            $request->get_param( 'status' ),
127            $request->get_param( 'postponed_for' )
128        );
129    }
130}