Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
REST_Onboarding
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
3 / 3
8
100.00% covered (success)
100.00%
1 / 1
 register_rest_routes
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 permissions_callback
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 settle
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2/**
3 * Records how someone left My Jetpack's setup flow.
4 *
5 * @package automattic/my-jetpack
6 */
7
8namespace Automattic\Jetpack\My_Jetpack;
9
10use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11
12/**
13 * Registers the REST route that settles the setup flow.
14 *
15 * @phan-constructor-used-for-side-effects
16 */
17class REST_Onboarding {
18    /**
19     * Register the routes.
20     */
21    public function register_rest_routes() {
22        register_rest_route(
23            'my-jetpack/v1',
24            '/site/onboarding/settled',
25            array(
26                array(
27                    'methods'             => \WP_REST_Server::EDITABLE,
28                    'callback'            => __CLASS__ . '::settle',
29                    'permission_callback' => __CLASS__ . '::permissions_callback',
30                    'args'                => array(
31                        'outcome' => array(
32                            'description' => __( 'How the user left setup.', 'jetpack-my-jetpack' ),
33                            'type'        => 'string',
34                            'required'    => true,
35                            'enum'        => array( 'completed', 'skipped' ),
36                        ),
37                    ),
38                ),
39            )
40        );
41    }
42
43    /**
44     * Who may settle setup.
45     *
46     * The same capability the takeover itself is gated on, since this is the record
47     * of a decision only someone who was shown it can have made.
48     *
49     * @return bool
50     */
51    public static function permissions_callback() {
52        // Checked here rather than at registration, so it runs only when the route is hit.
53        return Initializer::is_onboarding_wizard_enabled() && current_user_can( 'jetpack_connect' );
54    }
55
56    /**
57     * Record that setup has been settled, and how.
58     *
59     * Finishing is site-wide: the flow connects the site and switches modules on, so
60     * once it is done nobody needs the takeover again. Skipping is one person saying
61     * "not now" and is kept on that person, or the first admin to skip would answer
62     * for everyone else on a site nobody has set up.
63     *
64     * @param \WP_REST_Request $request The request.
65     * @return \WP_REST_Response|\WP_Error
66     */
67    public static function settle( $request ) {
68        $outcome    = $request->get_param( 'outcome' );
69        $connection = new Connection_Manager();
70
71        // Accepting the terms registers the site, and My Jetpack requires at least that much.
72        if ( ! $connection->is_connected() ) {
73            return new \WP_Error(
74                'site_not_connected',
75                __( 'Connect this site before leaving setup.', 'jetpack-my-jetpack' ),
76                array( 'status' => 409 )
77            );
78        }
79
80        // A saved run can resume on a site that has since lost its owner, so a finish
81        // without one is downgraded rather than refused: the user did leave the screen,
82        // and erroring would lose that and interrupt them again.
83        if ( 'completed' === $outcome && ! $connection->has_connected_owner() ) {
84            $outcome = 'skipped';
85        }
86
87        if ( 'completed' === $outcome ) {
88            update_option( Initializer::ONBOARDING_COMPLETED_OPTION, true, false );
89        }
90
91        // Recorded for a skip as well as a finish: someone who has been all the way
92        // through should not be offered it again on their next visit either.
93        update_user_option( get_current_user_id(), Initializer::ONBOARDING_DISMISSED_USER_OPTION, true );
94
95        return rest_ensure_response(
96            array(
97                'completed' => (bool) get_option( Initializer::ONBOARDING_COMPLETED_OPTION, false ),
98                'outcome'   => $outcome,
99                'settled'   => true,
100            )
101        );
102    }
103}