From d310a24bca63c4ae0b221983f27428a9f6439033 Mon Sep 17 00:00:00 2001 From: Adroit Date: Mon, 23 Feb 2026 12:44:09 -0600 Subject: [PATCH 01/17] Implement dynamic REST API route discovery - Added get_api_routes() to dynamically fetch all public collection endpoints from /wp-json/. - Replaced hardcoded routes ('posts', 'pages', 'media') with discovered routes. - Switched to wp_remote_get() for improved HTTP handling and access checking. - Updated README.md and bumped version to 0.3.0. --- README.md | 8 +++++ wp-serverless-api.php | 83 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2647d25..819492a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Explore WordPress data via the WP REST API as a JSON file for static WordPress Hosting on [Shifter](https://getshifter.io). +This plugin dynamically discovers all publicly available REST API collections (posts, pages, media, custom post types, etc.) and compiles them into a single JSON file. + 1. Install as a WordPress Plugin 2. Activate and save or create a new post or page 3. Create a new static Artifact on Shifter @@ -9,6 +11,12 @@ Explore WordPress data via the WP REST API as a JSON file for static WordPress H ## CHANGELOG +### 0.3.0 + +- Added dynamic discovery of all public REST API collection routes. +- Added support for Custom Post Types (CPT) and plugin-provided endpoints (Pods, Elementor, etc.) without manual configuration. +- Switched to WordPress HTTP API (`wp_remote_get`) for better reliability and access checking. + ### 0.2.1 - Removed environment determination to generate db.json even in local environment [#2](https://github.com/getshifter/wp-serverless-api/pull/2) diff --git a/wp-serverless-api.php b/wp-serverless-api.php index 2f07564..041833a 100644 --- a/wp-serverless-api.php +++ b/wp-serverless-api.php @@ -4,7 +4,7 @@ Plugin Name: WP Serverless API Plugin URI: https://github.com/getshifter/wp-serverless-api Description: WordPress REST API to JSON File -Version: 0.2.1 +Version: 0.3.0 Author: Shifter Author URI: https://getshifter.io */ @@ -21,21 +21,80 @@ function enable_permalinks_notice() { add_action( 'admin_notices', 'enable_permalinks_notice' ); } -function compile_db( - $routes = array( - 'posts', - 'pages', - 'media' - ) -) { +/** + * Get available REST API routes dynamically + */ +function get_api_routes() { + $url = esc_url( home_url( '/' ) ) . 'wp-json/'; + $response = wp_remote_get( $url ); + + if ( is_wp_error( $response ) ) { + return array( 'wp/v2/posts', 'wp/v2/pages', 'wp/v2/media' ); + } + + $body = wp_remote_retrieve_body( $response ); + $data = json_decode( $body, true ); + + if ( ! isset( $data['routes'] ) ) { + return array( 'wp/v2/posts', 'wp/v2/pages', 'wp/v2/media' ); + } + + $found_routes = array(); + foreach ( $data['routes'] as $path => $details ) { + // Skip root and namespace roots + if ( $path === '/' || ( isset( $details['namespace'] ) && $path === '/' . $details['namespace'] ) ) { + continue; + } + + // Skip routes with regex parameters (individual items or sub-resources) + if ( strpos( $path, '(?P<' ) !== false ) { + continue; + } + + // Skip schema endpoints + if ( substr( $path, -7 ) === '/schema' ) { + continue; + } + + // Only include routes that support GET + $methods = isset( $details['methods'] ) ? $details['methods'] : array(); + if ( ! in_array( 'GET', $methods ) ) { + continue; + } + + $found_routes[] = ltrim( $path, '/' ); + } + + return array_unique( $found_routes ); +} + +function compile_db( $routes = array() ) { + + if ( empty( $routes ) ) { + $routes = get_api_routes(); + } $db_array = array(); - foreach ($routes as $route) { - $url = esc_url( home_url( '/' ) ) . 'wp-json/wp/v2/' . $route; - $jsonData = json_decode( file_get_contents($url) ); + foreach ( $routes as $route ) { + $url = esc_url( home_url( '/' ) ) . 'wp-json/' . $route; + + $response = wp_remote_get( $url ); + if ( is_wp_error( $response ) ) { + continue; + } + + $code = wp_remote_retrieve_response_code( $response ); + if ( $code !== 200 ) { + continue; + } + + $body = wp_remote_retrieve_body( $response ); + $jsonData = json_decode( $body, true ); - $db_array[$route] = (array) $jsonData; + if ( is_array( $jsonData ) ) { + $db_array[$route] = $jsonData; + } } $db = json_encode($db_array); From 7a5a18e3782d982e0dd8c65631105bb29329095d Mon Sep 17 00:00:00 2001 From: Adroit Date: Mon, 23 Feb 2026 12:50:32 -0600 Subject: [PATCH 02/17] Offload build process to background task - Replaced synchronous build_db on save_post with a scheduled WP-Cron event. - Added schedule_build_db() to prevent blocking the post-save UI. - Use wp_next_scheduled to avoid redundant overlapping builds. --- wp-serverless-api.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wp-serverless-api.php b/wp-serverless-api.php index 041833a..da71011 100644 --- a/wp-serverless-api.php +++ b/wp-serverless-api.php @@ -125,8 +125,16 @@ function build_db() $db = compile_db(); save_db($db); } +add_action( 'wp_serverless_api_build_db_worker', 'build_db' ); + +function schedule_build_db() +{ + if ( ! wp_next_scheduled( 'wp_serverless_api_build_db_worker' ) ) { + wp_schedule_single_event( time(), 'wp_serverless_api_build_db_worker' ); + } +} /** * Build on Post Save */ -add_action( 'save_post', 'build_db' ); +add_action( 'save_post', 'schedule_build_db' ); From 103477df4bca29e8ca4400320923c87636207290 Mon Sep 17 00:00:00 2001 From: Adroit Date: Mon, 23 Feb 2026 13:05:40 -0600 Subject: [PATCH 03/17] Refine route filtering and simplify JSON keys - Restricted dynamic discovery to /wp/v2/ namespace only. - Simplified JSON keys to use the final endpoint name (e.g., 'posts' instead of 'wp/v2/posts'). - Excluded empty collections from the resulting database output. --- wp-serverless-api.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wp-serverless-api.php b/wp-serverless-api.php index da71011..aa82e7d 100644 --- a/wp-serverless-api.php +++ b/wp-serverless-api.php @@ -41,8 +41,8 @@ function get_api_routes() { $found_routes = array(); foreach ( $data['routes'] as $path => $details ) { - // Skip root and namespace roots - if ( $path === '/' || ( isset( $details['namespace'] ) && $path === '/' . $details['namespace'] ) ) { + // Only include standard wp/v2 routes + if ( strpos( $path, '/wp/v2/' ) !== 0 ) { continue; } @@ -92,8 +92,10 @@ function compile_db( $routes = array() ) { $body = wp_remote_retrieve_body( $response ); $jsonData = json_decode( $body, true ); - if ( is_array( $jsonData ) ) { - $db_array[$route] = $jsonData; + // Only include non-empty collections and simplify the key + if ( is_array( $jsonData ) && ! empty( $jsonData ) ) { + $key = basename( $route ); + $db_array[$key] = $jsonData; } } From e3c259c024005d44e4f3563cdcc20af2d01d7a74 Mon Sep 17 00:00:00 2001 From: Adroit Date: Mon, 23 Feb 2026 13:39:46 -0600 Subject: [PATCH 04/17] Add settings page for excluding paths and fields - Added an admin settings page under Settings > WP Serverless API. - Re-implemented discovery cache to limit network queries. - Discovered paths have checkboxes, unchecking them adds to exclusion list. - Greyed out checkboxes for endpoints that are inaccessible. - Paths matching a REST base are checked by default, excluding nav_menu_item and ones starting with wp_, e-, elementor_. - Extracted and display all available fields, allowing field-level exclusions. - Excluded 'guid' and '_links/curies' fields by default. --- wp-serverless-api.php | 297 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 264 insertions(+), 33 deletions(-) diff --git a/wp-serverless-api.php b/wp-serverless-api.php index aa82e7d..8b1f028 100644 --- a/wp-serverless-api.php +++ b/wp-serverless-api.php @@ -21,57 +21,158 @@ function enable_permalinks_notice() { add_action( 'admin_notices', 'enable_permalinks_notice' ); } -/** - * Get available REST API routes dynamically - */ -function get_api_routes() { +function wp_sls_api_discover_all() { $url = esc_url( home_url( '/' ) ) . 'wp-json/'; $response = wp_remote_get( $url ); + $data = array(); + if ( ! is_wp_error( $response ) ) { + $body = wp_remote_retrieve_body( $response ); + $data = json_decode( $body, true ); + } - if ( is_wp_error( $response ) ) { - return array( 'wp/v2/posts', 'wp/v2/pages', 'wp/v2/media' ); + $types_url = esc_url( home_url( '/' ) ) . 'wp-json/wp/v2/types/'; + $types_response = wp_remote_get( $types_url ); + $types = array(); + if ( ! is_wp_error( $types_response ) && wp_remote_retrieve_response_code($types_response) === 200 ) { + $types_body = wp_remote_retrieve_body( $types_response ); + $types = json_decode( $types_body, true ); + } + + $rest_bases = array(); + if ( is_array($types) ) { + foreach ( $types as $type_slug => $type_info ) { + if ( isset( $type_info['rest_base'] ) ) { + $rest_bases[$type_info['rest_base']] = array( + 'name' => isset($type_info['name']) ? $type_info['name'] : $type_slug, + 'slug' => $type_slug, + ); + } + } } - $body = wp_remote_retrieve_body( $response ); - $data = json_decode( $body, true ); + $paths = array(); + $all_fields = array(); - if ( ! isset( $data['routes'] ) ) { - return array( 'wp/v2/posts', 'wp/v2/pages', 'wp/v2/media' ); - } + if ( isset( $data['routes'] ) ) { + foreach ( $data['routes'] as $path => $details ) { + // Only include standard wp/v2 routes + if ( strpos( $path, '/wp/v2/' ) !== 0 ) continue; + // Skip routes with regex parameters + if ( strpos( $path, '(?P<' ) !== false ) continue; + // Skip schema endpoints + if ( substr( $path, -7 ) === '/schema' ) continue; - $found_routes = array(); - foreach ( $data['routes'] as $path => $details ) { - // Only include standard wp/v2 routes - if ( strpos( $path, '/wp/v2/' ) !== 0 ) { - continue; - } + $methods = isset( $details['methods'] ) ? $details['methods'] : array(); + if ( ! in_array( 'GET', $methods ) ) continue; - // Skip routes with regex parameters (individual items or sub-resources) - if ( strpos( $path, '(?P<' ) !== false ) { - continue; - } + $clean_path = ltrim( $path, '/' ); + $base_name = basename( $clean_path ); + + $endpoint_url = esc_url( home_url( '/' ) ) . 'wp-json/' . $clean_path . '?per_page=1'; + $endpoint_response = wp_remote_get( $endpoint_url ); + $is_accessible = false; + + if ( ! is_wp_error( $endpoint_response ) && wp_remote_retrieve_response_code( $endpoint_response ) === 200 ) { + $is_accessible = true; + $sample_body = wp_remote_retrieve_body($endpoint_response); + $sample_data = json_decode($sample_body, true); + if ( is_array($sample_data) && !empty($sample_data) ) { + $first_item = array(); + if ( isset($sample_data[0]) ) { + $first_item = $sample_data[0]; + } else if ( array_keys($sample_data) !== range(0, count($sample_data) - 1) ) { + $first_item = $sample_data; + } - // Skip schema endpoints - if ( substr( $path, -7 ) === '/schema' ) { - continue; - } + if ( is_array($first_item) ) { + foreach ($first_item as $field_key => $field_val) { + $all_fields[$field_key] = true; + if ( is_array($field_val) && $field_key === '_links' ) { + foreach ($field_val as $sub_key => $sub_val) { + $all_fields[$field_key . '/' . $sub_key] = true; + } + } + } + } + } + } - // Only include routes that support GET - $methods = isset( $details['methods'] ) ? $details['methods'] : array(); - if ( ! in_array( 'GET', $methods ) ) { - continue; + $is_default_checked = false; + $type_slug = ''; + if ( isset( $rest_bases[$base_name] ) ) { + $is_default_checked = true; + $type_slug = $rest_bases[$base_name]['slug']; + } + + if ( $type_slug === 'nav_menu_item' || + $base_name === 'nav_menu_item' || + strpos($base_name, 'wp_') === 0 || + strpos($base_name, 'e-') === 0 || + strpos($base_name, 'elementor_') === 0 ) { + $is_default_checked = false; + } + + $paths[$clean_path] = array( + 'accessible' => $is_accessible, + 'name' => isset($rest_bases[$base_name]['name']) ? $rest_bases[$base_name]['name'] : '', + 'default_checked' => $is_default_checked, + 'url' => esc_url( home_url( '/' ) ) . 'wp-json/' . $clean_path + ); } + } + + return array( + 'paths' => $paths, + 'fields' => array_keys($all_fields) + ); +} - $found_routes[] = ltrim( $path, '/' ); +function wp_sls_api_get_discovery() { + $cache = get_transient('wp_sls_api_discovery'); + if ( $cache !== false ) { + return $cache; } + $discovery = wp_sls_api_discover_all(); + set_transient('wp_sls_api_discovery', $discovery, HOUR_IN_SECONDS); + return $discovery; +} - return array_unique( $found_routes ); +function wp_sls_api_filter_fields($item, $excluded_fields) { + if ( !is_array($item) ) return $item; + foreach ($excluded_fields as $field) { + if ( strpos($field, '/') !== false ) { + $parts = explode('/', $field, 2); + $parent = $parts[0]; + $child = $parts[1]; + if ( isset($item[$parent]) && is_array($item[$parent]) ) { + unset($item[$parent][$child]); + if ( empty($item[$parent]) ) { + unset($item[$parent]); + } + } + } else { + unset($item[$field]); + } + } + return $item; } function compile_db( $routes = array() ) { + $has_saved_paths = get_option('wp_sls_api_excluded_paths') !== false; + $excluded_paths = get_option('wp_sls_api_excluded_paths', array()); + $excluded_fields = get_option('wp_sls_api_excluded_fields', array('guid', '_links/curies')); if ( empty( $routes ) ) { - $routes = get_api_routes(); + $discovery = wp_sls_api_get_discovery(); + $routes = array(); + foreach ( $discovery['paths'] as $path => $info ) { + if ( ! $info['accessible'] ) continue; + + $is_checked = $has_saved_paths ? !in_array($path, $excluded_paths) : $info['default_checked']; + if ( $is_checked ) { + $routes[] = $path; + } + } } $db_array = array(); @@ -94,6 +195,12 @@ function compile_db( $routes = array() ) { // Only include non-empty collections and simplify the key if ( is_array( $jsonData ) && ! empty( $jsonData ) ) { + if ( !empty($excluded_fields) ) { + foreach ( $jsonData as &$item ) { + $item = wp_sls_api_filter_fields($item, $excluded_fields); + } + } + $key = basename( $route ); $db_array[$key] = $jsonData; } @@ -102,7 +209,6 @@ function compile_db( $routes = array() ) { $db = json_encode($db_array); return $db; - } function save_db( @@ -140,3 +246,128 @@ function schedule_build_db() * Build on Post Save */ add_action( 'save_post', 'schedule_build_db' ); + +// --- Admin Settings Page --- + +add_action( 'admin_menu', 'wp_sls_api_admin_menu' ); + +function wp_sls_api_admin_menu() { + add_options_page( 'WP Serverless API Settings', 'WP Serverless API', 'manage_options', 'wp-sls-api', 'wp_sls_api_settings_page' ); +} + +function wp_sls_api_settings_page() { + if ( isset( $_POST['wp_sls_api_save'] ) && check_admin_referer( 'wp_sls_api_save_action' ) ) { + if ( isset($_POST['wp_sls_api_refresh_cache']) ) { + delete_transient('wp_sls_api_discovery'); + } + + $discovery = wp_sls_api_get_discovery(); + $paths = $discovery['paths']; + $fields = $discovery['fields']; + + $submitted_included_paths = isset($_POST['included_paths']) ? array_map('sanitize_text_field', $_POST['included_paths']) : array(); + $submitted_included_fields = isset($_POST['included_fields']) ? array_map('sanitize_text_field', $_POST['included_fields']) : array(); + + $excluded_paths = array(); + foreach ( $paths as $path => $info ) { + if ( !in_array($path, $submitted_included_paths) ) { + $excluded_paths[] = $path; + } + } + + $excluded_fields = array(); + foreach ( $fields as $field ) { + if ( !in_array($field, $submitted_included_fields) ) { + $excluded_fields[] = $field; + } + } + + update_option( 'wp_sls_api_excluded_paths', $excluded_paths ); + update_option( 'wp_sls_api_excluded_fields', $excluded_fields ); + + echo '

Settings saved.

'; + } + + $discovery = wp_sls_api_get_discovery(); + $paths = $discovery['paths']; + $fields = $discovery['fields']; + sort($fields); + + $has_saved_paths = get_option('wp_sls_api_excluded_paths') !== false; + $saved_excluded_paths = get_option('wp_sls_api_excluded_paths', array()); + $saved_excluded_fields = get_option('wp_sls_api_excluded_fields', array('guid', '_links/curies')); + + ?> +
+

WP Serverless API Settings

+
+ + +

Discovered Paths (/wp/v2/)

+

Uncheck paths to exclude them from the generated JSON.

+ + + + + + + + + + + $info ): + $is_checked = $has_saved_paths ? !in_array($path, $saved_excluded_paths) : $info['default_checked']; + $disabled = ! $info['accessible'] ? 'disabled' : ''; + if ( $disabled ) $is_checked = false; + ?> + + + + + + + + +
PathFriendly NamePreview
+ /> + > + + Preview + + Not accessible + +
+ +

Discovered Fields

+

Uncheck fields to exclude them from all endpoint responses.

+
+ +
+ +
+ +
+ +

+ + +

+
+
+ + Date: Mon, 23 Feb 2026 14:03:14 -0600 Subject: [PATCH 05/17] Enhance settings UI and extend path discovery - Added 'Output Path' column with editable text boxes for custom JSON keys. - Show all API paths, with non-wp/v2 paths unchecked by default. - Updated Preview column to show item counts (e.g., 'View 10 items'). - Inaccessible paths now still provide a link to preview the error. - Implemented visual indentation for nested fields in the Discovered Fields section. - Added 'total_items' and 'base_name' to discovery metadata. --- wp-serverless-api.php | 124 ++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 47 deletions(-) diff --git a/wp-serverless-api.php b/wp-serverless-api.php index 8b1f028..15d4efd 100644 --- a/wp-serverless-api.php +++ b/wp-serverless-api.php @@ -55,8 +55,10 @@ function wp_sls_api_discover_all() { if ( isset( $data['routes'] ) ) { foreach ( $data['routes'] as $path => $details ) { - // Only include standard wp/v2 routes - if ( strpos( $path, '/wp/v2/' ) !== 0 ) continue; + // Skip root + if ( $path === '/' ) continue; + // Skip namespace roots + if ( isset( $details['namespace'] ) && $path === '/' . $details['namespace'] ) continue; // Skip routes with regex parameters if ( strpos( $path, '(?P<' ) !== false ) continue; // Skip schema endpoints @@ -71,25 +73,30 @@ function wp_sls_api_discover_all() { $endpoint_url = esc_url( home_url( '/' ) ) . 'wp-json/' . $clean_path . '?per_page=1'; $endpoint_response = wp_remote_get( $endpoint_url ); $is_accessible = false; + $total_items = 0; - if ( ! is_wp_error( $endpoint_response ) && wp_remote_retrieve_response_code( $endpoint_response ) === 200 ) { - $is_accessible = true; - $sample_body = wp_remote_retrieve_body($endpoint_response); - $sample_data = json_decode($sample_body, true); - if ( is_array($sample_data) && !empty($sample_data) ) { - $first_item = array(); - if ( isset($sample_data[0]) ) { - $first_item = $sample_data[0]; - } else if ( array_keys($sample_data) !== range(0, count($sample_data) - 1) ) { - $first_item = $sample_data; - } + if ( ! is_wp_error( $endpoint_response ) ) { + if ( wp_remote_retrieve_response_code( $endpoint_response ) === 200 ) { + $is_accessible = true; + $total_items = (int) wp_remote_retrieve_header( $endpoint_response, 'x-wp-total' ); + + $sample_body = wp_remote_retrieve_body($endpoint_response); + $sample_data = json_decode($sample_body, true); + if ( is_array($sample_data) && !empty($sample_data) ) { + $first_item = array(); + if ( isset($sample_data[0]) ) { + $first_item = $sample_data[0]; + } else if ( array_keys($sample_data) !== range(0, count($sample_data) - 1) ) { + $first_item = $sample_data; + } - if ( is_array($first_item) ) { - foreach ($first_item as $field_key => $field_val) { - $all_fields[$field_key] = true; - if ( is_array($field_val) && $field_key === '_links' ) { - foreach ($field_val as $sub_key => $sub_val) { - $all_fields[$field_key . '/' . $sub_key] = true; + if ( is_array($first_item) ) { + foreach ($first_item as $field_key => $field_val) { + $all_fields[$field_key] = true; + if ( is_array($field_val) && $field_key === '_links' ) { + foreach ($field_val as $sub_key => $sub_val) { + $all_fields[$field_key . '/' . $sub_key] = true; + } } } } @@ -98,25 +105,29 @@ function wp_sls_api_discover_all() { } $is_default_checked = false; - $type_slug = ''; - if ( isset( $rest_bases[$base_name] ) ) { - $is_default_checked = true; - $type_slug = $rest_bases[$base_name]['slug']; - } - - if ( $type_slug === 'nav_menu_item' || - $base_name === 'nav_menu_item' || - strpos($base_name, 'wp_') === 0 || - strpos($base_name, 'e-') === 0 || - strpos($base_name, 'elementor_') === 0 ) { - $is_default_checked = false; + if ( strpos( $path, '/wp/v2/' ) === 0 ) { + $type_slug = ''; + if ( isset( $rest_bases[$base_name] ) ) { + $is_default_checked = true; + $type_slug = $rest_bases[$base_name]['slug']; + } + + if ( $type_slug === 'nav_menu_item' || + $base_name === 'nav_menu_item' || + strpos($base_name, 'wp_') === 0 || + strpos($base_name, 'e-') === 0 || + strpos($base_name, 'elementor_') === 0 ) { + $is_default_checked = false; + } } $paths[$clean_path] = array( 'accessible' => $is_accessible, 'name' => isset($rest_bases[$base_name]['name']) ? $rest_bases[$base_name]['name'] : '', 'default_checked' => $is_default_checked, - 'url' => esc_url( home_url( '/' ) ) . 'wp-json/' . $clean_path + 'url' => esc_url( home_url( '/' ) ) . 'wp-json/' . $clean_path, + 'total_items' => $total_items, + 'base_name' => $base_name ); } } @@ -160,6 +171,7 @@ function wp_sls_api_filter_fields($item, $excluded_fields) { function compile_db( $routes = array() ) { $has_saved_paths = get_option('wp_sls_api_excluded_paths') !== false; $excluded_paths = get_option('wp_sls_api_excluded_paths', array()); + $custom_output_paths = get_option('wp_sls_api_output_paths', array()); $excluded_fields = get_option('wp_sls_api_excluded_fields', array('guid', '_links/curies')); if ( empty( $routes ) ) { @@ -201,7 +213,7 @@ function compile_db( $routes = array() ) { } } - $key = basename( $route ); + $key = isset($custom_output_paths[$route]) && !empty($custom_output_paths[$route]) ? $custom_output_paths[$route] : basename( $route ); $db_array[$key] = $jsonData; } } @@ -267,6 +279,7 @@ function wp_sls_api_settings_page() { $submitted_included_paths = isset($_POST['included_paths']) ? array_map('sanitize_text_field', $_POST['included_paths']) : array(); $submitted_included_fields = isset($_POST['included_fields']) ? array_map('sanitize_text_field', $_POST['included_fields']) : array(); + $submitted_output_paths = isset($_POST['output_paths']) ? $_POST['output_paths'] : array(); $excluded_paths = array(); foreach ( $paths as $path => $info ) { @@ -282,8 +295,14 @@ function wp_sls_api_settings_page() { } } + $output_paths = array(); + foreach ( $submitted_output_paths as $path => $val ) { + $output_paths[sanitize_text_field($path)] = sanitize_text_field($val); + } + update_option( 'wp_sls_api_excluded_paths', $excluded_paths ); update_option( 'wp_sls_api_excluded_fields', $excluded_fields ); + update_option( 'wp_sls_api_output_paths', $output_paths ); echo '

Settings saved.

'; } @@ -296,6 +315,7 @@ function wp_sls_api_settings_page() { $has_saved_paths = get_option('wp_sls_api_excluded_paths') !== false; $saved_excluded_paths = get_option('wp_sls_api_excluded_paths', array()); $saved_excluded_fields = get_option('wp_sls_api_excluded_fields', array('guid', '_links/curies')); + $saved_output_paths = get_option('wp_sls_api_output_paths', array()); ?>
@@ -303,13 +323,14 @@ function wp_sls_api_settings_page() {
-

Discovered Paths (/wp/v2/)

-

Uncheck paths to exclude them from the generated JSON.

+

Discovered Paths

+

Uncheck paths to exclude them from the generated JSON. Non-wp/v2 paths are unchecked by default.

- + + @@ -317,21 +338,28 @@ function wp_sls_api_settings_page() { $info ): $is_checked = $has_saved_paths ? !in_array($path, $saved_excluded_paths) : $info['default_checked']; - $disabled = ! $info['accessible'] ? 'disabled' : ''; - if ( $disabled ) $is_checked = false; + $accessible = $info['accessible']; + $disabled_attr = ! $accessible ? 'disabled' : ''; + if ( ! $accessible ) $is_checked = false; + $out_val = isset($saved_output_paths[$path]) ? $saved_output_paths[$path] : $info['base_name']; ?> - + + @@ -339,12 +367,14 @@ function wp_sls_api_settings_page() {
PathInput PathOutput Path Friendly Name Preview
- /> + /> >> + + - - Preview - - Not accessible - + + + View items + + View Error + +

Discovered Fields

-

Uncheck fields to exclude them from all endpoint responses.

+

Uncheck fields to exclude them from all endpoint responses. Nested fields are indented.

-
+