Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
Registry
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 12
342
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 sanitize_key
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 sanitize_url_key
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 register
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 register_action
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 get_action_names_for_entry
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_action_nonce
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 all
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_endpoint
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_entry
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_namespace
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_namespace_http
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * The Registry class is a singleton that stores references to all Data_Sync_Entry instances.
4 * It also stores references to all Endpoint instances.
5 * It is namespaced to allow for multiple registries.
6 *
7 * @package automattic/jetpack-wp-js-data-sync
8 */
9
10namespace Automattic\Jetpack\WP_JS_Data_Sync;
11
12use Automattic\Jetpack\Schema\Schema_Parser;
13use Automattic\Jetpack\WP_JS_Data_Sync\Contracts\Data_Sync_Entry;
14use Automattic\Jetpack\WP_JS_Data_Sync\Endpoints\Action_Endpoint;
15use Automattic\Jetpack\WP_JS_Data_Sync\Endpoints\Endpoint;
16
17class Registry {
18
19    /**
20     * Registry instances are namespaced to allow for multiple registries.
21     *
22     * @var string
23     */
24    private $namespace;
25
26    /**
27     * Store a references for every Data_Sync_Entry instance.
28     *
29     * @var Data_Sync_Entry[]
30     */
31    private $entries = array();
32
33    private $action_endpoints = array();
34
35    /**
36     * Store references for every Endpoint instance.
37     *
38     * @var Endpoint[]
39     */
40    private $endpoints = array();
41
42    /**
43     * There can be multiple registries, reference them by namepsace.
44     * For example "jetpack_boost".
45     *
46     * @param string $namespace The namespace for this registry instance.
47     */
48    public function __construct( $namespace ) {
49        $this->namespace = $namespace;
50    }
51
52    /**
53     * Sanitize a key.
54     *
55     * @param string $key - Keys should only include alphanumeric characters and underscores.
56     *
57     * @return string
58     * @throws \Exception In debug mode, if the key is invalid.
59     */
60    private function sanitize_key( $key ) {
61        $sanitized_key = sanitize_key( $key );
62        $sanitized_key = str_replace( '-', '_', $sanitized_key );
63        if ( DS_Utils::is_debug() && $sanitized_key !== $key ) {
64            // If the key is invalid,
65            // Log an error during development
66            // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
67            error_log( "Invalid key '$key'. Keys should only include alphanumeric characters and underscores." );
68        }
69        return $sanitized_key;
70    }
71
72    /**
73     * Sanitize a key for use in a URL.
74     *
75     * @param string $key - Keys should only include alphanumeric characters and underscores.
76     *
77     * @return string
78     */
79    private function sanitize_url_key( $key ) {
80        return str_replace( '_', '-', sanitize_key( $key ) );
81    }
82
83    /**
84     * Register a new entry and add it to the registry.
85     *
86     * @param string          $key - The name of the entry. For example `widget_status`.
87     * @param Data_Sync_Entry $entry
88     *
89     * @return Data_Sync_Entry
90     */
91    public function register( $key, $entry ) {
92
93        $key = $this->sanitize_key( $key );
94
95        $this->entries[ $key ]   = $entry;
96        $endpoint                = new Endpoint( $this->get_namespace_http(), $this->sanitize_url_key( $key ), $entry );
97        $this->endpoints[ $key ] = $endpoint;
98
99        add_action( 'rest_api_init', array( $endpoint, 'register_rest_routes' ) );
100
101        return $entry;
102    }
103
104    /**
105     * Register an action endpoint.
106     *
107     * @param string        $key            The base key for the endpoint.
108     * @param string        $action_name    The name of the action.
109     * @param Schema_Parser $request_schema The schema for the action's request body.
110     * @param mixed         $action_class   The class handling the action logic.
111     */
112    public function register_action( $key, $action_name, $request_schema, $action_class ) {
113        // Create and store the action endpoint instance
114        $action_endpoint = new Action_Endpoint(
115            $this->get_namespace_http(),
116            $this->sanitize_url_key( $key ),
117            $this->sanitize_url_key( $action_name ),
118            $request_schema,
119            $action_class
120        );
121
122        // Store the action endpoint instance for nonce retrieval
123        $this->action_endpoints[ $key ][ $action_name ] = $action_endpoint;
124
125        // Register the REST route for the action endpoint
126        add_action( 'rest_api_init', array( $action_endpoint, 'register_rest_routes' ) );
127    }
128
129    /**
130     * Retrieve all action names for a given entry.
131     *
132     * @param string $entry_key The key for the entry.
133     *
134     * @return array An array of action names.
135     */
136    public function get_action_names_for_entry( $entry_key ) {
137        if ( isset( $this->action_endpoints[ $entry_key ] ) ) {
138            return array_keys( $this->action_endpoints[ $entry_key ] );
139
140        }
141        return array();
142    }
143
144    /**
145     * Get the nonce for a specific action endpoint.
146     *
147     * @param string $key         The base key for the endpoint.
148     * @param string $action_name The name of the action.
149     *
150     * @return false|string The nonce or false if not found.
151     */
152    public function get_action_nonce( $key, $action_name ) {
153        if ( isset( $this->action_endpoints[ $key ][ $action_name ] ) ) {
154            return $this->action_endpoints[ $key ][ $action_name ]->create_nonce();
155        }
156        return false;
157    }
158
159    /**
160     * Get all registered entries.
161     *
162     * @return Data_Sync_Entry[]
163     */
164    public function all() {
165        return $this->entries;
166    }
167
168    /**
169     * Get the endpoint for a given key.
170     *
171     * @param string $key - The key for the endpoint.
172     *
173     * @return Endpoint|false
174     */
175    public function get_endpoint( $key ) {
176        if ( ! isset( $this->endpoints[ $key ] ) ) {
177            return false;
178        }
179        return $this->endpoints[ $key ];
180    }
181
182    /**
183     * Get the entry for a given key.
184     *
185     * @param string $key - The key for the entry.
186     *
187     * @return Data_Sync_Entry|false
188     */
189    public function get_entry( $key ) {
190        if ( ! isset( $this->entries[ $key ] ) ) {
191            return false;
192        }
193        return $this->entries[ $key ];
194    }
195
196    /**
197     * Get the namespace for use in a filter.
198     *
199     * @return string The namespace key of this registry instance.
200     */
201    public function get_namespace() {
202        return $this->namespace;
203    }
204
205    /**
206     * Get the namespace for use in a URL.
207     *
208     * @return string The namespace key of this registry instance.
209     */
210    public function get_namespace_http() {
211        return $this->sanitize_url_key( $this->namespace );
212    }
213}