├── includes
├── arial.ttf
├── class-extending-wp-rest-api-admin-ajax.php
├── class-pn-date-progress-chart.php
└── class-extending-wp-rest-api-controller.php
├── admin
├── admin-hello-world.php
├── admin-hello-world.js
└── class-extending-wp-rest-api-admin.php
├── plugin.php
└── README.md
/includes/arial.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/petenelson/extending-wp-rest-api/HEAD/includes/arial.ttf
--------------------------------------------------------------------------------
/admin/admin-hello-world.php:
--------------------------------------------------------------------------------
1 |
25 |
26 |
--------------------------------------------------------------------------------
/plugin.php:
--------------------------------------------------------------------------------
1 | show_in_rest = is_user_logged_in();```
15 | * Disabled media endpoint: ```rest_dispatch_request``` filter
16 |
17 |
--------------------------------------------------------------------------------
/includes/class-extending-wp-rest-api-admin-ajax.php:
--------------------------------------------------------------------------------
1 | 'post' ) );
20 | wp_send_json( $query->posts );
21 | }
22 |
23 | public function ajax_hello_world() {
24 |
25 | $response = new stdClass();
26 | $response->hello = 'world';
27 | $response->time = current_time( 'mysql' );
28 |
29 | wp_send_json( $response );
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/admin/admin-hello-world.js:
--------------------------------------------------------------------------------
1 | ( function( $ ) {
2 |
3 | 'use strict';
4 |
5 | $.extend( {
6 |
7 | extend_rest_api: {
8 |
9 | bind_events: function() {
10 |
11 | $( '.options-form' ).submit( function ( e ) {
12 | e.preventDefault();
13 | });
14 |
15 | $('.button-get').click( function( e ) {
16 | $.extend_rest_api.send_get();
17 | });
18 |
19 | $('.button-post').click( function( e ) {
20 | $.extend_rest_api.send_post();
21 | });
22 |
23 | $('.button-delete').click( function( e ) {
24 | $.extend_rest_api.send_delete();
25 | });
26 | },
27 |
28 | display_response: function( response ) {
29 | $('.postbox pre code').text( JSON.stringify( response, null, 2 ) ).each( function( i, block ) {
30 | hljs.highlightBlock( block );
31 | });
32 | },
33 |
34 | send_get: function() {
35 | $.get( ExtendingRESTAPI.endpoints.hello_world, {}, function( response ) {
36 | } ).always( function ( response ) {
37 | $.extend_rest_api.display_response( response );
38 | });
39 | },
40 |
41 | send_post: function() {
42 | $.post( ExtendingRESTAPI.endpoints.hello_world, { my_number:$('.extend-my-number').val() }, function() {
43 | } ).always( function ( response ) {
44 | $.extend_rest_api.display_response( response );
45 | });
46 | },
47 |
48 | send_delete: function() {
49 | $.ajax( {
50 | url: ExtendingRESTAPI.endpoints.hello_world,
51 | data: { },
52 | type: 'DELETE',
53 | success: function() {
54 | }
55 | } ).always( function ( response ) {
56 | $.extend_rest_api.display_response( response );
57 | });
58 |
59 | }
60 |
61 |
62 |
63 | }
64 | } );
65 |
66 | // send nonce to the WP API
67 | $( document ).ajaxSend( function( event, xhr ) {
68 | // you can also send _wp_rest_nonce in the GET or POST params
69 | xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
70 | });
71 |
72 | $(document).ready( function() {
73 | $.extend_rest_api.bind_events();
74 | });
75 |
76 |
77 | })( jQuery );
78 |
--------------------------------------------------------------------------------
/includes/class-pn-date-progress-chart.php:
--------------------------------------------------------------------------------
1 | font = plugin_dir_path( __FILE__ ) . $this->font;
27 |
28 | $this->bar_max_width = $this->bar_end - $this->bar_start;
29 |
30 | // create image resource
31 | $this->im = imagecreate($this->width, $this->height);
32 |
33 | //background
34 | $bg = imagecolorallocate($this->im, 246, 246, 247);
35 |
36 | // grey text
37 | $this->textcolor = imagecolorallocate($this->im, 103, 103, 103);
38 |
39 | // blue progress bar
40 | $this->bluebar = imagecolorallocate($this->im, 26, 117, 187);
41 |
42 | // lines and ticks
43 | $this->greyline = imagecolorallocate($this->im, 175, 175, 175);
44 |
45 | }
46 |
47 |
48 | function draw_date($date, $text_center) {
49 | $date_string = date($this->month_year, date_timestamp_get( $date ) );
50 | $box = imagettfbbox($this->font_size, 0, $this->font, $date_string);
51 | $text_width = abs($box[4] - $box[0]);
52 | $text_height = abs($box[5] - $box[1]);
53 | $text_start = $text_center - ($text_width / 2);
54 | imagettftext($this->im, $this->font_size, 0, $text_start, $this->bottom_line_y + $text_height + $this->tick_height + $this->text_top_padding, $this->textcolor, $this->font, $date_string);
55 | }
56 |
57 | function draw_line($from_x, $from_y, $to_x, $to_y) {
58 | imageline($this->im, $from_x, $from_y, $to_x, $to_y, $this->greyline);
59 | }
60 |
61 | function draw_progress_bar($percent_progress) {
62 | $bar_width = ceil($this->bar_max_width * $percent_progress);
63 | imagefilledrectangle($this->im, $this->bar_start, $this->bar_top_x, $this->bar_start + $bar_width, $this->bar_top_x + $this->bar_height, $this->bluebar);
64 | }
65 |
66 |
67 | }
--------------------------------------------------------------------------------
/admin/class-extending-wp-rest-api-admin.php:
--------------------------------------------------------------------------------
1 | register_general_settings();
35 | $this->register_hello_world();
36 | }
37 |
38 |
39 | private function register_general_settings() {
40 | $key = $this->settings_key_general;
41 | $this->plugin_settings_tabs[ $key ] = esc_html__( 'General', 'extending-wp-rest-api' );
42 |
43 | register_setting( $key, $key );
44 |
45 | $section = 'general';
46 |
47 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
48 |
49 | add_settings_field( 'add-revision-count', esc_html__( 'Add Revision Count to Posts', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
50 | array( 'key' => $key, 'name' => 'add-revision-count', ) );
51 |
52 | add_settings_field( 'add-featured-image', esc_html__( 'Add Featured Image to Posts', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
53 | array( 'key' => $key, 'name' => 'add-featured-image', ) );
54 |
55 | add_settings_field( 'determine-current-user', esc_html__( 'Determine Current User Demo', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
56 | array( 'key' => $key, 'name' => 'determine-current-user', ) );
57 |
58 | add_settings_field( 'disallow-non-ssl', esc_html__( 'Disallow non-SSL', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
59 | array( 'key' => $key, 'name' => 'disallow-non-ssl', ) );
60 |
61 | add_settings_field( 'force-ssl-endpoint', esc_html__( 'Force SSL Endpoint in Link Header', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
62 | array( 'key' => $key, 'name' => 'force-ssl-endpoint', ) );
63 |
64 | add_settings_field( 'change-url-prefix', esc_html__( 'Change Endpoint Prefix (/awesome-api)', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
65 | array( 'key' => $key, 'name' => 'change-url-prefix', ) );
66 |
67 | add_settings_field( 'restrict-media-endpoint', esc_html__( 'Hide Media Endpoint from Non-authenticated users', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
68 | array( 'key' => $key, 'name' => 'restrict-media-endpoint', ) );
69 |
70 | add_settings_field( 'disable-media-endpoint', esc_html__( 'Disable Media Endpoint', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
71 | array( 'key' => $key, 'name' => 'disable-media-endpoint', ) );
72 |
73 | add_settings_field( 'remove-wordpess-core', esc_html__( 'Remove WordPress Core', 'extending-wp-rest-api' ), array( $this, 'settings_yes_no' ), $key, $section,
74 | array( 'key' => $key, 'name' => 'remove-wordpress-core', ) );
75 |
76 | }
77 |
78 | private function register_hello_world() {
79 | $key = $this->settings_key_hello_world;
80 | $this->plugin_settings_tabs[ $key ] = esc_html__( 'Hello World', 'extending-wp-rest-api' );
81 |
82 | register_setting( $key, $key );
83 |
84 | $section = 'hello-world';
85 |
86 | add_settings_section( $section, '', array( $this, 'section_header' ), $key );
87 |
88 | }
89 |
90 |
91 | public function setting_is_enabled( $enabled, $key, $setting ) {
92 | return '1' === $this->setting_get( '0', $key, $setting );
93 | }
94 |
95 |
96 | public function setting_get( $value, $key, $setting ) {
97 |
98 | $args = wp_parse_args( get_option( $key ),
99 | array(
100 | $setting => $value,
101 | )
102 | );
103 |
104 | return $args[$setting];
105 | }
106 |
107 |
108 | public function settings_yes_no( $args ) {
109 |
110 | $args = wp_parse_args( $args,
111 | array(
112 | 'name' => '',
113 | 'key' => '',
114 | 'after' => '',
115 | )
116 | );
117 |
118 | $name = $args['name'];
119 | $key = $args['key'];
120 |
121 | $option = get_option( $key );
122 | $value = isset( $option[$name] ) ? esc_attr( $option[$name] ) : '';
123 |
124 | if ( empty( $value ) )
125 | $value = '0';
126 |
127 | $name = esc_attr( $name );
128 | $key = esc_attr( $key );
129 |
130 | echo '';
131 | echo " ";
132 | echo " ";
133 | echo '
';
134 |
135 | if ( !empty( $args['after'] ) )
136 | echo '' . esc_html( $args['after'] ) . '
';
137 | }
138 |
139 |
140 | public function admin_menu() {
141 | add_options_page( esc_html__( 'Extending REST API Settings', 'extending-wp-rest-api' ), esc_html__( 'Extending REST API', 'extending-wp-rest-api' ), 'manage_options', $this->settings_page, array( $this, 'options_page' ), 30 );
142 | }
143 |
144 |
145 | public function options_page() {
146 |
147 | $tab = $this->current_tab(); ?>
148 |
149 | plugin_options_tabs(); ?>
150 |
155 |
156 | settings_key_general : $current_tab;
169 | }
170 |
171 |
172 | private function plugin_options_tabs() {
173 | $current_tab = $this->current_tab();
174 | echo '' . esc_html__( 'Extending WP REST API Settings', 'extending-wp-rest-api' ) . '
';
175 | foreach ( $this->plugin_settings_tabs as $tab_key => $tab_caption ) {
176 | $active = $current_tab == $tab_key ? 'nav-tab-active' : '';
177 |
178 | $url = add_query_arg( array(
179 | 'page' => rawurlencode( $this->settings_page ),
180 | 'tab' => rawurlencode( $tab_key ),
181 | ),
182 | admin_url( 'options-general.php' )
183 | );
184 |
185 | echo '' . esc_html( $tab_caption ) . '';
186 | }
187 | echo '
';
188 | }
189 |
190 |
191 | public function section_header( $args ) {
192 |
193 | switch ( $args['id'] ) {
194 | case 'hello-world';
195 | include_once 'admin-hello-world.php';
196 | wp_enqueue_script( 'extending-wp-rest-api', plugin_dir_url( __FILE__ ) . '/admin-hello-world.js', 'jquery', time(), true );
197 |
198 | // https://highlightjs.org/
199 | wp_enqueue_script( 'extending-highlight-js', '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js' );
200 | wp_enqueue_style( 'extending-highlight-js', '//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css' );
201 |
202 | $data = array(
203 | 'endpoints' => array(
204 | 'hello_world' => rest_url( '/api-extend/v1/hello-world' ),
205 | )
206 | );
207 |
208 | wp_localize_script( 'extending-wp-rest-api', 'ExtendingRESTAPI', $data );
209 |
210 | break;
211 | }
212 | }
213 | }
214 | }
--------------------------------------------------------------------------------
/includes/class-extending-wp-rest-api-controller.php:
--------------------------------------------------------------------------------
1 | register_routes();
12 |
13 | if ( extending_wp_rest_api_setting_enabled( 'add-revision-count' ) ) {
14 | $this->add_revision_count_to_posts();
15 | }
16 | }
17 |
18 |
19 | public function plugins_loaded() {
20 |
21 | // enqueue WP_API_Settings script
22 | add_action( 'wp_print_scripts', function() {
23 | wp_enqueue_script( 'wp-api' );
24 | } );
25 |
26 | if ( extending_wp_rest_api_setting_enabled( 'add-featured-image' ) ) {
27 | add_filter( 'rest_prepare_post', array( $this, 'add_featured_image_link' ), 10, 3 );
28 | }
29 |
30 | if ( extending_wp_rest_api_setting_enabled( 'disallow-non-ssl' ) ) {
31 | add_filter( 'rest_pre_dispatch', array( $this, 'disallow_non_ssl' ) );
32 | }
33 |
34 | if ( extending_wp_rest_api_setting_enabled( 'disable-media-endpoint' ) ) {
35 | add_filter( 'rest_dispatch_request', array( $this, 'disable_media_endpoint' ), 10, 2 );
36 | }
37 |
38 | if ( extending_wp_rest_api_setting_enabled( 'restrict-media-endpoint' ) ) {
39 | add_filter( 'rest_pre_dispatch', array( $this, 'restrict_media_endpoint' ), 10, 3 );
40 | }
41 |
42 | if ( extending_wp_rest_api_setting_enabled( 'remove-wordpress-core' ) ) {
43 | add_filter( 'rest_endpoints', array( $this, 'remove_wordpress_core_endpoints' ), 10, 1 );
44 | }
45 |
46 | if ( extending_wp_rest_api_setting_enabled( 'determine-current-user' ) ) {
47 | add_filter( 'determine_current_user', array( $this, 'determine_current_user' ), 50 );
48 | }
49 |
50 | // You can ignore the extending_wp_rest_api_setting_enabled()
51 | // calls, it's just for the code demo.
52 |
53 | add_filter( 'rest_url_prefix', function( $endpoint ) {
54 |
55 | if ( extending_wp_rest_api_setting_enabled( 'change-url-prefix' ) ) {
56 | // if you're changing the endpoint, you'll also need to call flush_rewrite_rules
57 | // be sure to cache the custom endpoint and only flush the rules if it is changed
58 | $endpoint = 'awesome-api';
59 | }
60 |
61 | if ( $endpoint !== get_option( 'extend_api_endpoint' ) ) {
62 | flush_rewrite_rules();
63 | update_option( 'extend_api_endpoint', $endpoint );
64 | }
65 |
66 | return $endpoint;
67 | } );
68 |
69 | add_filter( 'rest_pre_serve_request', array( $this, 'multiformat_rest_pre_serve_request' ), 10, 4 );
70 |
71 |
72 | if ( extending_wp_rest_api_setting_enabled( 'force-ssl-endpoint' ) ) {
73 | add_filter( 'rest_url', array( $this, 'force_https_rest_url'), 10, 4 );
74 | }
75 | }
76 |
77 |
78 |
79 | public function register_routes() {
80 |
81 | $namespace = 'api-extend'; // base endpoint for our custom API
82 |
83 | // creating a new route for our hello world exaple
84 | register_rest_route( $namespace, '/v1/hello-world', array(
85 | 'methods' => WP_REST_Server::READABLE,
86 | 'callback' => array( $this, 'get_hello_world' ),
87 | 'args' => array(
88 | 'format' => array(
89 | 'sanitize_callback' => 'sanitize_key',
90 | )
91 | ),
92 | ) );
93 |
94 | // creating a new route editable route for our hello world exaple
95 | // the sanitize and validate callback functions are passed the value, the request,
96 | // and the name of the parameter ( $value, $request, $key )
97 | register_rest_route( $namespace, '/v1/hello-world', array(
98 | 'methods' => WP_REST_Server::EDITABLE,
99 | 'callback' => array( $this, 'update_hello_world' ),
100 | 'permission_callback' => array( $this, 'update_hello_world_permission_check' ),
101 | 'args' => array(
102 | 'my_number' => array(
103 | 'required' => true,
104 | 'default' => 10,
105 | 'sanitize_callback' => 'absint',
106 | 'validate_callback' => array( $this, 'number_is_greater_than_10' ),
107 | ),
108 | )
109 | ) );
110 |
111 |
112 | // creating a new route for our hello world exaple
113 | // versioning example
114 | register_rest_route( $namespace, '/v2/hello-world', array(
115 | 'methods' => WP_REST_Server::READABLE,
116 | 'callback' => array( $this, 'get_hello_world_v2' ),
117 | 'args' => array(
118 | 'format' => array(
119 | 'required' => false,
120 | 'default' => 'json',
121 | 'sanitize_callback' => 'sanitize_key',
122 | )
123 | ),
124 | ) );
125 |
126 |
127 | // creating a new route editable route for our hello world exaple
128 | // the sanitize and validate callbacks are passed the value, the request, and the name of the parameter ( $value, $request, $key )
129 | register_rest_route( $namespace, '/v1/hello-world', array(
130 | 'methods' => WP_REST_Server::DELETABLE,
131 | 'callback' => array( $this, 'delete_hello_world' ),
132 | 'permission_callback' => array( $this, 'update_hello_world_permission_check' ),
133 | ) );
134 |
135 |
136 | // creating a new route for our custom authentication exaple
137 | register_rest_route( $namespace, '/whoami', array(
138 | 'methods' => array( WP_REST_Server::READABLE ),
139 | 'callback' => array( $this, 'get_whoami' ),
140 | ) );
141 |
142 |
143 | // creating a new route for our custom authentication exaple
144 | register_rest_route( 'wp/v2', '/cron', array(
145 | 'methods' => array( WP_REST_Server::READABLE ),
146 | 'callback' => array( $this, 'get_crons' ),
147 | ) );
148 |
149 |
150 | register_rest_route( $namespace, '/itsec-lockout', array(
151 | 'methods' => array( WP_REST_Server::READABLE ),
152 | 'callback' => array( $this, 'get_itsec_lockouts' ),
153 | ) );
154 |
155 | register_rest_route( $namespace, '/itsec-lockout/(?P[\d]+)', array(
156 | 'methods' => array( WP_REST_Server::READABLE ),
157 | 'callback' => array( $this, 'get_itsec_lockouts' ),
158 | 'args' => array(
159 | 'id' => array(
160 | 'default' => 0,
161 | 'sanitize_callback' => 'absint',
162 | ),
163 | ),
164 | ) );
165 |
166 |
167 | // sample for dynamically generating an image and returning it via the REST API
168 | register_rest_route( $namespace, '/billing-period-chart', array(
169 | 'methods' => array( WP_REST_Server::READABLE ),
170 | 'callback' => array( $this, 'get_chart' ),
171 | 'args' => array(
172 | 'start' => array(
173 | 'required' => true,
174 | 'sanitize_callback' => array( $this, 'to_date_time' ),
175 | ),
176 | 'end' => array(
177 | 'required' => true,
178 | 'sanitize_callback' => array( $this, 'to_date_time' ),
179 | ),
180 | 'current' => array(
181 | 'required' => true,
182 | 'sanitize_callback' => array( $this, 'to_date_time' ),
183 | ),
184 | )
185 | ) );
186 |
187 | register_rest_route( $namespace, '/remote-sizes', array(
188 | 'methods' => array( WP_REST_Server::READABLE ),
189 | 'callback' => array( $this, 'get_remote_sizes' ),
190 | )
191 | );
192 |
193 | }
194 |
195 |
196 | public function disallow_non_ssl( $response ) {
197 |
198 | if ( ! is_ssl() ) {
199 | $response = new WP_Error( 'rest_forbidden', __( "SSL is required to access the REST API." ), array( 'status' => 403 ) );
200 | }
201 |
202 | return $response;
203 | }
204 |
205 | public function restrict_media_endpoint( $response, $server, $request ) {
206 |
207 | // See if this is the media endpoint and the user is logged in.
208 | if ( false !== stripos( $request->get_route(), '/wp/v2/media' ) && ! is_user_logged_in() ) {
209 | $response = new WP_Error(
210 | 'rest_forbidden',
211 | __( "Authentication is required to access the media endpoint." ),
212 | array( 'status' => 403 )
213 | );
214 | }
215 |
216 | return $response;
217 | }
218 |
219 |
220 | public function force_https_rest_url( $url, $path, $blog_id, $scheme ) {
221 | return set_url_scheme( $url, 'https' ); // force the Link header to be https
222 | }
223 |
224 |
225 | public function disable_media_endpoint( $response, $request ) {
226 |
227 | if ( false !== stripos( $request->get_route(), 'wp/v2/media' ) ) {
228 | $response = new WP_Error( 'rest_forbidden', __( "Sorry, the media endpoint is temporarily disabled." ),
229 | array( 'status' => 403 ) );
230 | }
231 |
232 | return $response;
233 | }
234 |
235 |
236 | public function get_hello_world( WP_REST_Request $request ) {
237 |
238 | $response = new stdClass();
239 | $response->hello = 'world';
240 | $response->time = current_time( 'mysql' );
241 | $response->my_number = absint( get_option( '_extending_my_number' ) );
242 |
243 | $response->some_html = 'Hello World';
244 |
245 | return rest_ensure_response( $response );
246 | }
247 |
248 |
249 | public function get_hello_world_v2( WP_REST_Request $request ) {
250 |
251 | $response = new stdClass();
252 | $response->hello = 'This is the new and improved endpoint!';
253 | $response->my_number = absint( get_option( '_extending_my_number' ) );
254 |
255 | return rest_ensure_response( $response );
256 | }
257 |
258 |
259 | public function update_hello_world_permission_check( WP_REST_Request $request ) {
260 | $cap = 'manage_options';
261 | if ( ! current_user_can( $cap ) ) {
262 | // can return false or a custom WP_Error
263 | return new WP_Error( 'rest_forbidden',
264 | sprintf( 'current user must have %s permissions', $cap ), array( 'status' => 403 ) );
265 | } else {
266 | return true;
267 | }
268 | }
269 |
270 |
271 | public function number_is_greater_than_10( $value, $request, $key ) {
272 | if ( $value <= 10 ) {
273 | // can return false or a custom WP_Error
274 | return new WP_Error( 'rest_invalid_param',
275 | sprintf( '%s %d must be greater than 10', $key, $value ), array( 'status' => 400 ) );
276 | } else {
277 | return true;
278 | }
279 | }
280 |
281 |
282 | public function update_hello_world( WP_REST_Request $request ) {
283 |
284 | // because permissions, sanitation, and validation have already been taken care of,
285 | // we can start working with our data right away
286 |
287 | // update our example with whatever was passed by the user
288 | update_option( '_extending_my_number', $request['my_number'] );
289 |
290 | // return the updated object
291 | return $this->get_hello_world( $request );
292 |
293 | }
294 |
295 |
296 | public function delete_hello_world( WP_REST_Request $request ) {
297 |
298 | delete_option( '_extending_my_number' );
299 |
300 | // return the updated object
301 | return $this->get_hello_world( $request );
302 |
303 | }
304 |
305 |
306 | public function add_revision_count_to_posts() {
307 |
308 | $schema = array(
309 | 'type' => 'integer',
310 | 'description' => 'number of revisions',
311 | 'context' => array( 'view' ),
312 | );
313 |
314 | register_rest_field( 'post', 'number_of_revisions', array(
315 | 'schema' => $schema,
316 | 'get_callback' => array( $this, 'get_number_of_revisions' ),
317 | ) );
318 | }
319 |
320 |
321 | public function get_number_of_revisions( $post ) {
322 | return absint( count( wp_get_post_revisions( $post->ID ) ) );
323 | }
324 |
325 |
326 | public function add_featured_image_link( $result, $post, $request ) {
327 |
328 | if ( has_post_thumbnail( $post->ID ) ) {
329 | $featured_image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
330 |
331 | if ( is_array( $featured_image ) && ! empty( $featured_image ) ) {
332 | $result->add_link( 'featured_image',
333 | $featured_image[0],
334 | array(
335 | 'width' => absint( $featured_image[1] ),
336 | 'height' => absint( $featured_image[2] )
337 | )
338 | );
339 | }
340 | }
341 |
342 | return $result;
343 | }
344 |
345 |
346 | public function get_whoami( WP_REST_Request $request ) {
347 |
348 | $response = new stdClass();
349 | $response->current_user = null;
350 |
351 | // Runs the determine_current_user filter.
352 | $user = wp_get_current_user();
353 | if ( ! empty( $user ) ) {
354 | $response->current_user = new stdClass();
355 | $response->current_user->ID = $user->ID;
356 | $response->current_user->login = $user->user_login;
357 | $response->current_user->email = $user->user_email;
358 | $response->current_user->capabilities = $user->allcaps;
359 | }
360 |
361 | return rest_ensure_response( $response );
362 | }
363 |
364 |
365 | public function determine_current_user( $user_id ) {
366 |
367 | $uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING );
368 | $api_key = filter_input( INPUT_GET, 'api-key', FILTER_SANITIZE_STRING );
369 | $login = filter_input( INPUT_GET, 'login', FILTER_SANITIZE_STRING );
370 |
371 | // Make sure this is only for our whoami demo.
372 | // Only for a specific API key.
373 | // Verify login was passed.
374 | if ( false !== stripos( $uri, '/api-extend/whoami' ) && 'helloworld' === $api_key && ! empty( $login ) ) {
375 |
376 | // this request is allowed to impersonate anyone
377 | $user = get_user_by( 'login', $login );
378 | if ( ! empty( $user ) ) {
379 | $user_id = $user->ID;
380 | }
381 | }
382 |
383 | return $user_id;
384 | }
385 |
386 |
387 | public function get_crons( WP_REST_Request $request ) {
388 | $response = new stdClass();
389 | $response->cron_jobs = _get_cron_array();
390 | $response->schedules = wp_get_schedules();
391 | return rest_ensure_response( $response );
392 | }
393 |
394 |
395 | public function get_itsec_lockouts( WP_REST_Request $request ) {
396 |
397 | // itsec_lockouts
398 | global $wpdb;
399 |
400 | $sql = "select * from {$wpdb->prefix}itsec_lockouts where 1";
401 |
402 | if ( ! empty( $request['id'] ) ) {
403 | $sql .= $wpdb->prepare( ' and lockout_id = %d' , $request['id'] );
404 | }
405 |
406 | $response = new stdClass();
407 | $response->lockouts = array();
408 |
409 | $lockouts = $wpdb->get_results( $sql );
410 |
411 | foreach ( $lockouts as $lockout ) {
412 |
413 | // add a link to the individual entry
414 | $lockout->_links = array( 'self' => array( 'href' => rest_url( '/api-extend/itsec-lockout/' . absint( $lockout->lockout_id ) ) ) );
415 | $response->lockouts[] = $lockout;
416 |
417 | }
418 |
419 | return rest_ensure_response( $response );
420 |
421 | }
422 |
423 |
424 | public function multiformat_rest_pre_serve_request( $served, $result, $request, $server ) {
425 |
426 | if ( in_array( $request->get_route(), array( '/api-extend/v1/hello-world', '/api-extend/v2/hello-world' ) ) ) {
427 |
428 | // this coud also be accomplished with an Accepts header
429 | switch ( $request['format'] ) {
430 |
431 | case 'text':
432 | // if you needed a CSV, this is where you'd do it
433 | header( 'Content-Type: text/plain; charset=' . get_option( 'blog_charset' ) );
434 | echo $result->data->hello . ' ';
435 | echo $result->data->time . ' ';
436 | echo $result->data->my_number;
437 | $served = true; // tells the WP-API that we sent the response already
438 | break;
439 |
440 | case 'xml': // I guess if you really need to
441 | header( 'Content-Type: application/xml; charset=' . get_option( 'blog_charset' ) );
442 |
443 | $xmlDoc = new DOMDocument();
444 | $response = $xmlDoc->appendChild( $xmlDoc->createElement( 'Response' ) );
445 | $response->appendChild( $xmlDoc->createElement( 'Hello', $result->data->hello ) );
446 | $response->appendChild( $xmlDoc->createElement( 'Time', $result->data->time ) );
447 | $response->appendChild( $xmlDoc->createElement( 'My_Number', $result->data->my_number ) );
448 |
449 | echo $xmlDoc->saveXML();
450 | $served = true;
451 | break;
452 |
453 | }
454 |
455 | }
456 |
457 |
458 | if ( '/api-extend/billing-period-chart' === $request->get_route() ) {
459 |
460 | // because we returned the image generator class to the API, we can access the
461 | // image it generated and return it to the browser
462 | header('Content-type: image/png');
463 | imagepng($result->data->im);
464 | imagedestroy($result->data->im);
465 |
466 | $served = true;
467 |
468 | }
469 |
470 |
471 | return $served;
472 | }
473 |
474 |
475 | public function to_date_time( $value ) {
476 | return new DateTime( $value );
477 | }
478 |
479 |
480 | public function get_chart( WP_REST_Request $request ) {
481 |
482 | // https://www.greenmountainenergy.com/api/?api-action=billing-period-chart&s=2014-11-13&e=2014-12-15&c=2014-11-25
483 | // http://local.baconipsum.dev/wp-json/api-extend/chart?start=2015-02-01&end=2015-04-25¤t=2015-03-09
484 |
485 | require_once 'class-pn-date-progress-chart.php';
486 |
487 | $start = $request['start'];
488 | $end = $request['end'];
489 | $current = $request['current'];
490 |
491 | $dateChart = new pn_date_progress_chart();
492 | $dateChart->init();
493 |
494 |
495 | // vertical grey line to the left of the blue bar
496 | $dateChart->draw_line($dateChart->bar_start-1, 1, $dateChart->bar_start-1, $dateChart->bottom_line_y);
497 |
498 | // horizontal grey line to the bottom of the blue bar
499 | $dateChart->draw_line($dateChart->bar_start-1, $dateChart->bottom_line_y, $dateChart->bar_end, $dateChart->bottom_line_y);
500 |
501 | // start date tick
502 | $dateChart->draw_line($dateChart->bar_start-1, $dateChart->bottom_line_y, $dateChart->bar_start-1, $dateChart->bottom_line_y + $dateChart->tick_height);
503 |
504 |
505 | // end date tick
506 | $dateChart->draw_line($dateChart->bar_end, $dateChart->bottom_line_y, $dateChart->bar_end, $dateChart->bottom_line_y + $dateChart->tick_height);
507 |
508 |
509 | // draw start date
510 | $dateChart->draw_date($start, $dateChart->bar_start-1);
511 |
512 | // draw end date
513 | $dateChart->draw_date($end, $dateChart->bar_end);
514 |
515 | // figure out how far into the date range we are and draw a progress bar accordingly
516 | $total_days = date_diff($start, $end)->days;
517 | $days_into_range = date_diff($start, $current)->days;
518 | $percent_into_range = $days_into_range / $total_days;
519 |
520 | // draw ticks at 25%, 50%, 75%
521 | $percent_ticks_x = [];
522 | for ($i = .25; $i <= .75 ; $i += .25)
523 | $percent_ticks_x[] = $dateChart->bar_start + floor($dateChart->bar_max_width * $i);
524 |
525 |
526 |
527 | foreach ($percent_ticks_x as $p)
528 | $dateChart->draw_line($p, $dateChart->bottom_line_y, $p, $dateChart->bottom_line_y + $dateChart->tick_height);
529 |
530 |
531 | // create dates for 25%, 50% and 75%
532 | $percent_date = [];
533 | for ($i = .25; $i <= .75 ; $i += .25) {
534 | $percent_date[] = date_add(clone $start, new DateInterval('P' . floor($total_days * $i) . 'D'));
535 | }
536 |
537 |
538 | // draw dates at 25%, 50%, 75%
539 | for ($i=0; $i < 3; $i++)
540 | $dateChart->draw_date($percent_date[$i], $percent_ticks_x[$i]);
541 |
542 | $dateChart->draw_progress_bar($percent_into_range);
543 |
544 | return $dateChart;
545 |
546 |
547 | }
548 |
549 |
550 | /**
551 | * Unsets all core WP endpoints registered by the WordPress REST API (via rest_endpoints filter)
552 | * @param array $endpoints registered endpoints
553 | * @return array
554 | */
555 | public function remove_wordpress_core_endpoints( $endpoints ) {
556 |
557 | foreach ( array_keys( $endpoints ) as $endpoint ) {
558 | if ( stripos( $endpoint, '/wp/v2' ) === 0 ) {
559 | unset( $endpoints[ $endpoint ] );
560 | }
561 | }
562 |
563 | return $endpoints;
564 | }
565 |
566 | public function get_remote_sizes() {
567 |
568 | // a basic example of logging results from API requests to other servers
569 |
570 | $args = array(
571 | 'time' => current_time( 'mysql' ),
572 | 'ip_address' => filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_SANITIZE_STRING ),
573 | 'route' => '/wp-json/dashboard-directory-size/v1/sizes',
574 | 'source' => 'petenelson.io REST API',
575 | 'method' => 'GET',
576 | 'status' => 0,
577 | 'request' => array(
578 | 'body' => '',
579 | ),
580 | 'response' => array(
581 | 'body' => '',
582 | ),
583 | 'milliseconds' => 0,
584 | );
585 |
586 | $remote_results = wp_remote_get( 'https://petenelson.io/wp-json/dashboard-directory-size/v1/sizes' );
587 |
588 | $args['response']['headers'] = wp_remote_retrieve_headers( $remote_results );
589 | $args['status'] = wp_remote_retrieve_response_code( $remote_results );
590 |
591 | $data = json_decode( wp_remote_retrieve_body( $remote_results ) );
592 |
593 | $args['response']['body'] = $data;
594 |
595 | do_action( 'wp-rest-api-log-insert', $args );
596 |
597 | $data = wp_list_pluck( $data, 'path' );
598 |
599 | return rest_ensure_response( $data );
600 |
601 | }
602 |
603 | }
604 |
605 |
606 | }
607 |
--------------------------------------------------------------------------------