Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
Capabilities
100.00% covered (success)
100.00%
54 / 54
100.00% covered (success)
100.00%
4 / 4
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 register_routes
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
 check_permission
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 update
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2/**
3 * REST API endpoint, `wp-json/newfold-data/v1/capabilities`, for pushing capabilities from Hiive.
4 *
5 * @see \NewfoldLabs\WP\Module\Data\SiteCapabilities
6 */
7
8namespace NewfoldLabs\WP\Module\Data\API;
9
10use NewfoldLabs\WP\Module\Data\SiteCapabilities;
11use WP_Error;
12use WP_REST_Controller;
13use WP_REST_Request;
14use WP_REST_Server;
15use WP_REST_Response;
16
17/**
18 * REST API controller endpoint to push capabilities from Hiive.
19 */
20class Capabilities extends WP_REST_Controller {
21
22    /** @var SiteCapabilities $site_capabilities */
23    protected $site_capabilities;
24
25    /**
26     * Constructor
27     *
28     * @param SiteCapabilities $site_capabilities The class that loads and saves the capabilities.
29     */
30    public function __construct( SiteCapabilities $site_capabilities ) {
31        $this->site_capabilities = $site_capabilities;
32
33        $this->namespace = 'newfold-data/v1';
34        $this->rest_base = 'capabilities';
35    }
36
37    /**
38     * Registers the routes for the objects of the controller.
39     *
40     * @hooked rest_api_init
41     *
42     * @see register_rest_route()
43     */
44    public function register_routes() {
45        register_rest_route(
46            $this->namespace,
47            '/' . $this->rest_base,
48            array(
49                'args' => array(),
50                array(
51                    'methods'             => WP_REST_Server::EDITABLE,
52                    'callback'            => array( $this, 'update' ),
53                    'permission_callback' => array( $this, 'check_permission' ),
54                ),
55            )
56        );
57    }
58
59    /**
60     * Check permissions for routes.
61     *
62     * The Hiive request is authenticated in {@see Data::authenticate()} and sets the current user to an administrator.
63     *
64     * @see \NewfoldLabs\WP\Module\Data\Data::authenticate()
65     *
66     * @return bool|WP_Error
67     */
68    public function check_permission() {
69
70        if ( ! current_user_can( 'manage_options' ) ) {
71            return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to access this endpoint.' ), array( 'status' => rest_authorization_required_code() ) );
72        }
73
74        return true;
75    }
76
77    /**
78     * POST or PUT to set, discarding existing capabilities, PATCH to update, preserving existing capabilities that are
79     * not in the request.
80     *
81     * @param WP_REST_Request $request Full details about the request.
82     * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
83     */
84    public function update( $request ) {
85
86        $existing_capabilities = $this->site_capabilities->all( false );
87        $new_capabilities      = $request->get_json_params();
88
89        'PATCH' === $request->get_method()
90            ? $this->site_capabilities->update( $new_capabilities ) // PATCH – update existing list.
91            : $this->site_capabilities->set( $new_capabilities ); // POST or PUT – replace list.
92
93        $added_capabilities     = array();
94        $updated_capabilities   = array();
95        $unchanged_capabilities = array();
96
97        foreach ( $new_capabilities as $capability_name => $capability_value ) {
98            if ( ! isset( $existing_capabilities[ $capability_name ] ) ) {
99                $added_capabilities[ $capability_name ] = $capability_value;
100                continue;
101            }
102            if ( $existing_capabilities[ $capability_name ] !== $capability_value ) {
103                $updated_capabilities[ $capability_name ] = $capability_value;
104            } else {
105                $unchanged_capabilities[ $capability_name ] = $capability_value;
106            }
107            unset( $existing_capabilities[ $capability_name ] );
108        }
109
110        $removed_capabilities = array_diff_key( $existing_capabilities, $this->site_capabilities->all( false ) );
111
112        $unchanged_capabilities = array_diff(
113            array_merge(
114                $unchanged_capabilities,
115                $existing_capabilities
116            ),
117            $removed_capabilities
118        );
119
120        $status = empty( $added_capabilities ) && empty( $updated_capabilities ) && empty( $removed_capabilities )
121            ? 200 // No changes.
122            : 201; // Changes.
123
124        return new WP_REST_Response(
125            array(
126                'added'     => $added_capabilities,
127                'updated'   => $updated_capabilities,
128                'removed'   => $removed_capabilities,
129                'unchanged' => $unchanged_capabilities,
130            ),
131            $status
132        );
133    }
134}