Implement Phase 10: REST API Endpoints (v0.10.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m10s

- Add complete REST API infrastructure under src/Api/
- ResponseFormatter for standardized responses
- RateLimiter with tiered limits (public 60/min, availability 30/min, booking 10/min, admin 120/min)
- AbstractController base class with common functionality
- BuildingsController: list, get, rooms endpoints
- RoomsController: list, get, availability, calendar, search endpoints
- BookingsController: CRUD + confirm/check-in/check-out status transitions
- GuestsController: list, get, search, booking history (admin only)
- ServicesController: list, get, calculate endpoints
- PricingController: calculate, seasons endpoints
- API settings tab with enable/disable toggles
- Comprehensive API documentation in README

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 21:24:40 +01:00
parent 87aa89b1a6
commit 81c97c31d7
15 changed files with 4447 additions and 7 deletions

View File

@@ -18,6 +18,7 @@ use Magdev\WpBnb\Booking\Availability;
use Magdev\WpBnb\Booking\EmailNotifier;
use Magdev\WpBnb\Frontend\Search;
use Magdev\WpBnb\Frontend\Shortcodes;
use Magdev\WpBnb\Api\RestApi;
use Magdev\WpBnb\Integration\CF7;
use Magdev\WpBnb\Integration\Prometheus;
use Magdev\WpBnb\Frontend\Widgets\AvailabilityCalendar;
@@ -146,6 +147,9 @@ final class Plugin {
// Initialize Prometheus metrics integration.
Prometheus::init();
// Initialize REST API.
$this->init_rest_api();
// Initialize admin components.
if ( is_admin() ) {
$this->init_admin();
@@ -170,6 +174,16 @@ final class Plugin {
$updater->init();
}
/**
* Initialize the REST API.
*
* @return void
*/
private function init_rest_api(): void {
$api = new RestApi();
$api->init();
}
/**
* Initialize admin components.
*
@@ -618,6 +632,10 @@ final class Plugin {
class="nav-tab <?php echo 'metrics' === $active_tab ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e( 'Metrics', 'wp-bnb' ); ?>
</a>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-bnb-settings&tab=api' ) ); ?>"
class="nav-tab <?php echo 'api' === $active_tab ? 'nav-tab-active' : ''; ?>">
<?php esc_html_e( 'API', 'wp-bnb' ); ?>
</a>
</nav>
<div class="tab-content">
@@ -635,6 +653,9 @@ final class Plugin {
case 'metrics':
$this->render_metrics_settings();
break;
case 'api':
$this->render_api_settings();
break;
default:
$this->render_general_settings();
break;
@@ -1433,6 +1454,157 @@ final class Plugin {
<?php
}
/**
* Render API settings tab.
*
* @return void
*/
private function render_api_settings(): void {
$api_enabled = get_option( 'wp_bnb_api_enabled', 'yes' );
$rate_limiting = get_option( 'wp_bnb_api_rate_limiting', 'yes' );
$api_base_url = rest_url( RestApi::NAMESPACE );
?>
<form method="post" action="">
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
<h2><?php esc_html_e( 'REST API Settings', 'wp-bnb' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Enable API', 'wp-bnb' ); ?></th>
<td>
<label>
<input type="checkbox" name="wp_bnb_api_enabled" value="yes" <?php checked( $api_enabled, 'yes' ); ?>>
<?php esc_html_e( 'Enable the REST API endpoints', 'wp-bnb' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'When enabled, external applications can access room, availability, and booking data via the API.', 'wp-bnb' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Rate Limiting', 'wp-bnb' ); ?></th>
<td>
<label>
<input type="checkbox" name="wp_bnb_api_rate_limiting" value="yes" <?php checked( $rate_limiting, 'yes' ); ?>>
<?php esc_html_e( 'Enable rate limiting', 'wp-bnb' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Limits API requests to prevent abuse. Recommended for production sites.', 'wp-bnb' ); ?>
</p>
</td>
</tr>
</table>
<h2 style="margin-top: 30px;"><?php esc_html_e( 'API Information', 'wp-bnb' ); ?></h2>
<table class="form-table">
<tr>
<th scope="row"><?php esc_html_e( 'Base URL', 'wp-bnb' ); ?></th>
<td>
<code><?php echo esc_html( $api_base_url ); ?></code>
<p class="description">
<?php esc_html_e( 'All API endpoints are prefixed with this URL.', 'wp-bnb' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'API Version', 'wp-bnb' ); ?></th>
<td>
<code><?php echo esc_html( RestApi::VERSION ); ?></code>
</td>
</tr>
<tr>
<th scope="row"><?php esc_html_e( 'Info Endpoint', 'wp-bnb' ); ?></th>
<td>
<code><?php echo esc_html( $api_base_url . '/info' ); ?></code>
<p class="description">
<?php esc_html_e( 'Returns API information and available endpoints.', 'wp-bnb' ); ?>
</p>
</td>
</tr>
</table>
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Available Endpoints', 'wp-bnb' ); ?></h2>
<h3><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></h3>
<table class="widefat" style="margin-bottom: 20px;">
<thead>
<tr>
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
</tr>
</thead>
<tbody>
<tr><td>GET</td><td><code>/buildings</code></td><td><?php esc_html_e( 'List all buildings', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/buildings/{id}</code></td><td><?php esc_html_e( 'Get building details', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/buildings/{id}/rooms</code></td><td><?php esc_html_e( 'List rooms in building', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/rooms</code></td><td><?php esc_html_e( 'List/search rooms', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/rooms/{id}</code></td><td><?php esc_html_e( 'Get room details', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/rooms/{id}/availability</code></td><td><?php esc_html_e( 'Check room availability', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/rooms/{id}/calendar</code></td><td><?php esc_html_e( 'Get room calendar', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/availability/search</code></td><td><?php esc_html_e( 'Search available rooms', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/services</code></td><td><?php esc_html_e( 'List services', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/pricing/calculate</code></td><td><?php esc_html_e( 'Calculate booking price', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/bookings</code></td><td><?php esc_html_e( 'Create booking (pending status)', 'wp-bnb' ); ?></td></tr>
</tbody>
</table>
<h3><?php esc_html_e( 'Admin Endpoints (Requires Authentication)', 'wp-bnb' ); ?></h3>
<table class="widefat" style="margin-bottom: 20px;">
<thead>
<tr>
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
</tr>
</thead>
<tbody>
<tr><td>GET</td><td><code>/bookings</code></td><td><?php esc_html_e( 'List all bookings', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Get booking details', 'wp-bnb' ); ?></td></tr>
<tr><td>PATCH</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Update booking', 'wp-bnb' ); ?></td></tr>
<tr><td>DELETE</td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Cancel booking', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/bookings/{id}/confirm</code></td><td><?php esc_html_e( 'Confirm booking', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/bookings/{id}/check-in</code></td><td><?php esc_html_e( 'Check in guest', 'wp-bnb' ); ?></td></tr>
<tr><td>POST</td><td><code>/bookings/{id}/check-out</code></td><td><?php esc_html_e( 'Check out guest', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/guests</code></td><td><?php esc_html_e( 'List guests', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/guests/{id}</code></td><td><?php esc_html_e( 'Get guest details', 'wp-bnb' ); ?></td></tr>
<tr><td>GET</td><td><code>/guests/search</code></td><td><?php esc_html_e( 'Search guests', 'wp-bnb' ); ?></td></tr>
</tbody>
</table>
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Authentication', 'wp-bnb' ); ?></h2>
<p><?php esc_html_e( 'Admin endpoints require authentication. Use one of the following methods:', 'wp-bnb' ); ?></p>
<ul style="list-style: disc; margin-left: 20px;">
<li><strong><?php esc_html_e( 'Application Passwords:', 'wp-bnb' ); ?></strong> <?php esc_html_e( 'Create one in Users > Your Profile. Use Basic Auth with username and app password.', 'wp-bnb' ); ?></li>
<li><strong><?php esc_html_e( 'Cookie + Nonce:', 'wp-bnb' ); ?></strong> <?php esc_html_e( 'For same-domain requests. Pass nonce in X-WP-Nonce header.', 'wp-bnb' ); ?></li>
</ul>
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Rate Limits', 'wp-bnb' ); ?></h2>
<table class="widefat" style="margin-bottom: 20px;">
<thead>
<tr>
<th><?php esc_html_e( 'Type', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Limit', 'wp-bnb' ); ?></th>
<th><?php esc_html_e( 'Applies To', 'wp-bnb' ); ?></th>
</tr>
</thead>
<tbody>
<tr><td><?php esc_html_e( 'Public', 'wp-bnb' ); ?></td><td>60/min</td><td><?php esc_html_e( 'GET rooms, buildings, services', 'wp-bnb' ); ?></td></tr>
<tr><td><?php esc_html_e( 'Availability', 'wp-bnb' ); ?></td><td>30/min</td><td><?php esc_html_e( 'Availability checks, calendar', 'wp-bnb' ); ?></td></tr>
<tr><td><?php esc_html_e( 'Booking', 'wp-bnb' ); ?></td><td>10/min</td><td><?php esc_html_e( 'Booking creation', 'wp-bnb' ); ?></td></tr>
<tr><td><?php esc_html_e( 'Admin', 'wp-bnb' ); ?></td><td>120/min</td><td><?php esc_html_e( 'All admin endpoints', 'wp-bnb' ); ?></td></tr>
</tbody>
</table>
<p class="submit">
<?php submit_button( __( 'Save API Settings', 'wp-bnb' ), 'primary', 'submit', false ); ?>
</p>
</form>
<?php
}
/**
* Render license status badge.
*
@@ -1507,6 +1679,9 @@ final class Plugin {
case 'metrics':
$this->save_metrics_settings();
break;
case 'api':
$this->save_api_settings();
break;
default:
$this->save_general_settings();
break;
@@ -1649,6 +1824,22 @@ final class Plugin {
settings_errors( 'wp_bnb_settings' );
}
/**
* Save API settings.
*
* @return void
*/
private function save_api_settings(): void {
$api_enabled = isset( $_POST['wp_bnb_api_enabled'] ) ? 'yes' : 'no';
$rate_limiting = isset( $_POST['wp_bnb_api_rate_limiting'] ) ? 'yes' : 'no';
update_option( 'wp_bnb_api_enabled', $api_enabled );
update_option( 'wp_bnb_api_rate_limiting', $rate_limiting );
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'API settings saved.', 'wp-bnb' ), 'success' );
settings_errors( 'wp_bnb_settings' );
}
/**
* AJAX handler for checking room availability.
*