Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f5adfb04e | |||
| b701d127f8 | |||
| 481495805b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ wp-plugins
|
|||||||
wp-core
|
wp-core
|
||||||
vendor/
|
vendor/
|
||||||
releases/*
|
releases/*
|
||||||
|
MARKETING.md
|
||||||
|
|||||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.10.1] - 2026-02-03
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- API Settings subtabs for better organization:
|
||||||
|
- General subtab: Enable/disable REST API, rate limiting toggle, API information
|
||||||
|
- Rate Limits subtab: Configurable time window and endpoint-specific limits
|
||||||
|
- Endpoints subtab: Full endpoint documentation with HTTP method badges
|
||||||
|
- Configurable rate limiting:
|
||||||
|
- Time window setting (10-300 seconds, default 60)
|
||||||
|
- Per-endpoint-type limits (public, availability, booking, admin)
|
||||||
|
- Settings stored in WordPress options with fallback defaults
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- RateLimiter class now loads limits from WordPress options
|
||||||
|
- README updated with configurable rate limiting documentation
|
||||||
|
|
||||||
## [0.10.0] - 2026-02-03
|
## [0.10.0] - 2026-02-03
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -451,8 +451,10 @@ The plugin provides a comprehensive REST API for integration with external appli
|
|||||||
### Enabling the API
|
### Enabling the API
|
||||||
|
|
||||||
1. Navigate to **WP BnB → Settings → API**
|
1. Navigate to **WP BnB → Settings → API**
|
||||||
2. Enable "Enable REST API"
|
2. In the **General** subtab, enable "Enable REST API"
|
||||||
3. Optionally enable rate limiting for protection against abuse
|
3. Optionally enable rate limiting for protection against abuse
|
||||||
|
4. Configure rate limits in the **Rate Limits** subtab
|
||||||
|
5. View all available endpoints in the **Endpoints** subtab
|
||||||
|
|
||||||
### Base URL
|
### Base URL
|
||||||
|
|
||||||
@@ -517,15 +519,23 @@ curl -u "username:app-password" https://site.com/wp-json/wp-bnb/v1/bookings
|
|||||||
|
|
||||||
### Rate Limiting
|
### Rate Limiting
|
||||||
|
|
||||||
When enabled, rate limits are applied per client (by user ID or IP address):
|
When enabled, rate limits are applied per client (by user ID or IP address). Configure limits in **Settings → API → Rate Limits**.
|
||||||
|
|
||||||
| Type | Limit | Applies To |
|
**Default Limits:**
|
||||||
| ---- | ----- | ---------- |
|
|
||||||
|
| Type | Default | Applies To |
|
||||||
|
| ---- | ------- | ---------- |
|
||||||
| Public | 60/min | Room/building listings |
|
| Public | 60/min | Room/building listings |
|
||||||
| Availability | 30/min | Availability and calendar endpoints |
|
| Availability | 30/min | Availability and calendar endpoints |
|
||||||
| Booking | 10/min | Booking creation |
|
| Booking | 10/min | Booking creation |
|
||||||
| Admin | 120/min | All admin endpoints |
|
| Admin | 120/min | All admin endpoints |
|
||||||
|
|
||||||
|
**Configuration Options:**
|
||||||
|
|
||||||
|
- **Time Window**: 10-300 seconds (default: 60 seconds)
|
||||||
|
- **Per-endpoint limits**: Customize for each endpoint type
|
||||||
|
- **Rate limiting toggle**: Enable/disable without losing settings
|
||||||
|
|
||||||
Rate limit headers are included in responses:
|
Rate limit headers are included in responses:
|
||||||
|
|
||||||
- `X-RateLimit-Limit`: Maximum requests allowed
|
- `X-RateLimit-Limit`: Maximum requests allowed
|
||||||
|
|||||||
@@ -491,6 +491,37 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* API Method Badges */
|
||||||
|
.wp-bnb-method {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.get {
|
||||||
|
background: #e7f5e7;
|
||||||
|
color: #1e7e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.post {
|
||||||
|
background: #e7f0f5;
|
||||||
|
color: #1e5f7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.patch {
|
||||||
|
background: #f5f0e7;
|
||||||
|
color: #7e5f1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-bnb-method.delete {
|
||||||
|
background: #f5e7e7;
|
||||||
|
color: #7e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
/* Form Tables */
|
/* Form Tables */
|
||||||
.form-table th {
|
.form-table th {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
|||||||
@@ -22,23 +22,61 @@ final class RateLimiter {
|
|||||||
private const TRANSIENT_PREFIX = 'wp_bnb_rate_';
|
private const TRANSIENT_PREFIX = 'wp_bnb_rate_';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rate limits per minute by endpoint type.
|
* Default rate limits per minute by endpoint type.
|
||||||
*
|
*
|
||||||
* @var array<string, int>
|
* @var array<string, int>
|
||||||
*/
|
*/
|
||||||
private array $limits = array(
|
private const DEFAULT_LIMITS = array(
|
||||||
'public' => 60, // Public read endpoints.
|
'public' => 60, // Public read endpoints.
|
||||||
'availability' => 30, // Availability checks.
|
'availability' => 30, // Availability checks.
|
||||||
'booking' => 10, // Booking creation.
|
'booking' => 10, // Booking creation.
|
||||||
'admin' => 120, // Admin endpoints.
|
'admin' => 120, // Admin endpoints.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rate limits per minute by endpoint type.
|
||||||
|
*
|
||||||
|
* @var array<string, int>
|
||||||
|
*/
|
||||||
|
private array $limits;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time window in seconds.
|
* Time window in seconds.
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private int $window = 60;
|
private int $window;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->load_limits_from_options();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load rate limits from WordPress options.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function load_limits_from_options(): void {
|
||||||
|
$this->limits = array(
|
||||||
|
'public' => (int) get_option( 'wp_bnb_rate_limit_public', self::DEFAULT_LIMITS['public'] ),
|
||||||
|
'availability' => (int) get_option( 'wp_bnb_rate_limit_availability', self::DEFAULT_LIMITS['availability'] ),
|
||||||
|
'booking' => (int) get_option( 'wp_bnb_rate_limit_booking', self::DEFAULT_LIMITS['booking'] ),
|
||||||
|
'admin' => (int) get_option( 'wp_bnb_rate_limit_admin', self::DEFAULT_LIMITS['admin'] ),
|
||||||
|
);
|
||||||
|
$this->window = (int) get_option( 'wp_bnb_rate_limit_window', 60 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default rate limits.
|
||||||
|
*
|
||||||
|
* @return array<string, int>
|
||||||
|
*/
|
||||||
|
public static function get_default_limits(): array {
|
||||||
|
return self::DEFAULT_LIMITS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if request is within rate limit.
|
* Check if request is within rate limit.
|
||||||
|
|||||||
451
src/Plugin.php
451
src/Plugin.php
@@ -1460,147 +1460,319 @@ final class Plugin {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function render_api_settings(): void {
|
private function render_api_settings(): void {
|
||||||
$api_enabled = get_option( 'wp_bnb_api_enabled', 'yes' );
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Subtab switching only.
|
||||||
$rate_limiting = get_option( 'wp_bnb_api_rate_limiting', 'yes' );
|
$active_subtab = isset( $_GET['subtab'] ) ? sanitize_key( $_GET['subtab'] ) : 'general';
|
||||||
$api_base_url = rest_url( RestApi::NAMESPACE );
|
|
||||||
|
$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 );
|
||||||
|
|
||||||
|
// Rate limit values.
|
||||||
|
$defaults = \Magdev\WpBnb\Api\RateLimiter::get_default_limits();
|
||||||
|
$limit_public = get_option( 'wp_bnb_rate_limit_public', $defaults['public'] );
|
||||||
|
$limit_avail = get_option( 'wp_bnb_rate_limit_availability', $defaults['availability'] );
|
||||||
|
$limit_booking = get_option( 'wp_bnb_rate_limit_booking', $defaults['booking'] );
|
||||||
|
$limit_admin = get_option( 'wp_bnb_rate_limit_admin', $defaults['admin'] );
|
||||||
|
$limit_window = get_option( 'wp_bnb_rate_limit_window', 60 );
|
||||||
|
|
||||||
|
$base_url = admin_url( 'admin.php?page=wp-bnb-settings&tab=api' );
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<!-- API Subtabs -->
|
||||||
|
<div class="wp-bnb-subtabs">
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=general' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'general' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-admin-generic"></span>
|
||||||
|
<?php esc_html_e( 'General', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=rate-limits' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'rate-limits' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-dashboard"></span>
|
||||||
|
<?php esc_html_e( 'Rate Limits', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=endpoints' ); ?>"
|
||||||
|
class="wp-bnb-subtab <?php echo 'endpoints' === $active_subtab ? 'active' : ''; ?>">
|
||||||
|
<span class="dashicons dashicons-rest-api"></span>
|
||||||
|
<?php esc_html_e( 'Endpoints', 'wp-bnb' ); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post" action="">
|
<form method="post" action="">
|
||||||
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
<?php wp_nonce_field( 'wp_bnb_save_settings', 'wp_bnb_settings_nonce' ); ?>
|
||||||
|
|
||||||
<h2><?php esc_html_e( 'REST API Settings', 'wp-bnb' ); ?></h2>
|
<?php if ( 'general' === $active_subtab ) : ?>
|
||||||
|
<!-- General Subtab -->
|
||||||
|
<h2><?php esc_html_e( 'REST API Settings', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
<table class="form-table">
|
<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>
|
<tr>
|
||||||
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
<th scope="row"><?php esc_html_e( 'Enable API', 'wp-bnb' ); ?></th>
|
||||||
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
<td>
|
||||||
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
<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>
|
||||||
</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>
|
<tr>
|
||||||
<th><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
<th scope="row"><?php esc_html_e( 'Rate Limiting', 'wp-bnb' ); ?></th>
|
||||||
<th><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
<td>
|
||||||
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
<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' ); ?>
|
||||||
|
<?php if ( 'yes' === $rate_limiting ) : ?>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=rate-limits' ); ?>"><?php esc_html_e( 'Configure limits', 'wp-bnb' ); ?> →</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</table>
|
||||||
<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>
|
<h2 style="margin-top: 30px;"><?php esc_html_e( 'API Information', '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="form-table">
|
||||||
<table class="widefat" style="margin-bottom: 20px;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th><?php esc_html_e( 'Type', 'wp-bnb' ); ?></th>
|
<th scope="row"><?php esc_html_e( 'Base URL', 'wp-bnb' ); ?></th>
|
||||||
<th><?php esc_html_e( 'Limit', 'wp-bnb' ); ?></th>
|
<td>
|
||||||
<th><?php esc_html_e( 'Applies To', 'wp-bnb' ); ?></th>
|
<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>
|
||||||
</thead>
|
<tr>
|
||||||
<tbody>
|
<th scope="row"><?php esc_html_e( 'API Version', 'wp-bnb' ); ?></th>
|
||||||
<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>
|
<td>
|
||||||
<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>
|
<code><?php echo esc_html( RestApi::VERSION ); ?></code>
|
||||||
<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>
|
</td>
|
||||||
<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>
|
</tr>
|
||||||
</tbody>
|
<tr>
|
||||||
</table>
|
<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>
|
||||||
|
|
||||||
<p class="submit">
|
<?php submit_button( __( 'Save Settings', 'wp-bnb' ) ); ?>
|
||||||
<?php submit_button( __( 'Save API Settings', 'wp-bnb' ), 'primary', 'submit', false ); ?>
|
|
||||||
</p>
|
<?php elseif ( 'rate-limits' === $active_subtab ) : ?>
|
||||||
|
<!-- Rate Limits Subtab -->
|
||||||
|
<h2><?php esc_html_e( 'Rate Limit Configuration', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
|
<?php if ( 'yes' !== $rate_limiting ) : ?>
|
||||||
|
<div class="notice notice-warning inline" style="margin: 15px 0;">
|
||||||
|
<p>
|
||||||
|
<?php esc_html_e( 'Rate limiting is currently disabled.', 'wp-bnb' ); ?>
|
||||||
|
<a href="<?php echo esc_url( $base_url . '&subtab=general' ); ?>"><?php esc_html_e( 'Enable it in General settings', 'wp-bnb' ); ?></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<p class="description"><?php esc_html_e( 'Configure the number of requests allowed per time window for each endpoint type.', 'wp-bnb' ); ?></p>
|
||||||
|
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Time Window', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_window" value="<?php echo esc_attr( $limit_window ); ?>" min="10" max="300" step="10" class="small-text">
|
||||||
|
<?php esc_html_e( 'seconds', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php esc_html_e( 'The time window for rate limit counting. Default: 60 seconds.', 'wp-bnb' ); ?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_public" value="<?php echo esc_attr( $limit_public ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for public read endpoints (rooms, buildings, services). Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['public']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Availability Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_availability" value="<?php echo esc_attr( $limit_avail ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for availability checks and calendar requests. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['availability']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Booking Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_booking" value="<?php echo esc_attr( $limit_booking ); ?>" min="1" max="100" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for booking creation. Keep low to prevent abuse. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['booking']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Admin Endpoints', 'wp-bnb' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<input type="number" name="wp_bnb_rate_limit_admin" value="<?php echo esc_attr( $limit_admin ); ?>" min="1" max="1000" class="small-text">
|
||||||
|
<?php esc_html_e( 'requests per window', 'wp-bnb' ); ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php
|
||||||
|
printf(
|
||||||
|
/* translators: %d: default limit */
|
||||||
|
esc_html__( 'Limit for authenticated admin endpoints. Default: %d', 'wp-bnb' ),
|
||||||
|
$defaults['admin']
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2 style="margin-top: 30px;"><?php esc_html_e( 'Current Rate Limits Summary', 'wp-bnb' ); ?></h2>
|
||||||
|
<table class="widefat striped" style="max-width: 600px;">
|
||||||
|
<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><strong><?php echo esc_html( $limit_public . '/' . $limit_window . 's' ); ?></strong></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><strong><?php echo esc_html( $limit_avail . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'Availability checks, calendar', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Booking', 'wp-bnb' ); ?></td>
|
||||||
|
<td><strong><?php echo esc_html( $limit_booking . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'Booking creation', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Admin', 'wp-bnb' ); ?></td>
|
||||||
|
<td><strong><?php echo esc_html( $limit_admin . '/' . $limit_window . 's' ); ?></strong></td>
|
||||||
|
<td><?php esc_html_e( 'All admin endpoints', 'wp-bnb' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php submit_button( __( 'Save Rate Limits', 'wp-bnb' ) ); ?>
|
||||||
|
|
||||||
|
<?php else : ?>
|
||||||
|
<!-- Endpoints Subtab -->
|
||||||
|
<h2><?php esc_html_e( 'Available Endpoints', 'wp-bnb' ); ?></h2>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'Public Endpoints', 'wp-bnb' ); ?></h3>
|
||||||
|
<p class="description"><?php esc_html_e( 'These endpoints are accessible without authentication.', 'wp-bnb' ); ?></p>
|
||||||
|
<table class="widefat striped" style="margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 80px;"><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
||||||
|
<th style="width: 250px;"><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings</code></td><td><?php esc_html_e( 'List all buildings', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings/{id}</code></td><td><?php esc_html_e( 'Get building details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/buildings/{id}/rooms</code></td><td><?php esc_html_e( 'List rooms in building', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms</code></td><td><?php esc_html_e( 'List/search rooms', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}</code></td><td><?php esc_html_e( 'Get room details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}/availability</code></td><td><?php esc_html_e( 'Check room availability', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/rooms/{id}/calendar</code></td><td><?php esc_html_e( 'Get room calendar', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/availability/search</code></td><td><?php esc_html_e( 'Search available rooms', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/services</code></td><td><?php esc_html_e( 'List services', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/pricing/calculate</code></td><td><?php esc_html_e( 'Calculate booking price', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></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', 'wp-bnb' ); ?></h3>
|
||||||
|
<p class="description"><?php esc_html_e( 'These endpoints require authentication (Application Password or Cookie + Nonce).', 'wp-bnb' ); ?></p>
|
||||||
|
<table class="widefat striped" style="margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 80px;"><?php esc_html_e( 'Method', 'wp-bnb' ); ?></th>
|
||||||
|
<th style="width: 250px;"><?php esc_html_e( 'Endpoint', 'wp-bnb' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Description', 'wp-bnb' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/bookings</code></td><td><?php esc_html_e( 'List all bookings', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Get booking details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method patch">PATCH</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Update booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method delete">DELETE</span></td><td><code>/bookings/{id}</code></td><td><?php esc_html_e( 'Cancel booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/confirm</code></td><td><?php esc_html_e( 'Confirm booking', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/check-in</code></td><td><?php esc_html_e( 'Check in guest', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method post">POST</span></td><td><code>/bookings/{id}/check-out</code></td><td><?php esc_html_e( 'Check out guest', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/guests</code></td><td><?php esc_html_e( 'List guests', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></td><td><code>/guests/{id}</code></td><td><?php esc_html_e( 'Get guest details', 'wp-bnb' ); ?></td></tr>
|
||||||
|
<tr><td><span class="wp-bnb-method get">GET</span></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>
|
||||||
|
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<span class="dashicons dashicons-admin-network" style="color: #2271b1;"></span>
|
||||||
|
<?php esc_html_e( 'Application Passwords', 'wp-bnb' ); ?>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<p><?php esc_html_e( 'Create an Application Password in Users > Your Profile.', 'wp-bnb' ); ?></p>
|
||||||
|
<p><code>Authorization: Basic base64(username:app-password)</code></p>
|
||||||
|
<p class="description"><?php esc_html_e( 'Recommended for external applications and integrations.', 'wp-bnb' ); ?></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<span class="dashicons dashicons-lock" style="color: #2271b1;"></span>
|
||||||
|
<?php esc_html_e( 'Cookie + Nonce', 'wp-bnb' ); ?>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<p><?php esc_html_e( 'For same-domain JavaScript requests when user is logged in.', 'wp-bnb' ); ?></p>
|
||||||
|
<p><code>X-WP-Nonce: <?php echo esc_html( wp_create_nonce( 'wp_rest' ) ); ?></code></p>
|
||||||
|
<p class="description"><?php esc_html_e( 'Best for frontend JavaScript that interacts with the API.', 'wp-bnb' ); ?></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
</form>
|
</form>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
@@ -1836,6 +2008,31 @@ final class Plugin {
|
|||||||
update_option( 'wp_bnb_api_enabled', $api_enabled );
|
update_option( 'wp_bnb_api_enabled', $api_enabled );
|
||||||
update_option( 'wp_bnb_api_rate_limiting', $rate_limiting );
|
update_option( 'wp_bnb_api_rate_limiting', $rate_limiting );
|
||||||
|
|
||||||
|
// Save rate limit configuration.
|
||||||
|
$defaults = \Magdev\WpBnb\Api\RateLimiter::get_default_limits();
|
||||||
|
|
||||||
|
$limit_window = isset( $_POST['wp_bnb_rate_limit_window'] )
|
||||||
|
? max( 10, min( 300, absint( $_POST['wp_bnb_rate_limit_window'] ) ) )
|
||||||
|
: 60;
|
||||||
|
$limit_public = isset( $_POST['wp_bnb_rate_limit_public'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_public'] ) ) )
|
||||||
|
: $defaults['public'];
|
||||||
|
$limit_avail = isset( $_POST['wp_bnb_rate_limit_availability'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_availability'] ) ) )
|
||||||
|
: $defaults['availability'];
|
||||||
|
$limit_booking = isset( $_POST['wp_bnb_rate_limit_booking'] )
|
||||||
|
? max( 1, min( 100, absint( $_POST['wp_bnb_rate_limit_booking'] ) ) )
|
||||||
|
: $defaults['booking'];
|
||||||
|
$limit_admin = isset( $_POST['wp_bnb_rate_limit_admin'] )
|
||||||
|
? max( 1, min( 1000, absint( $_POST['wp_bnb_rate_limit_admin'] ) ) )
|
||||||
|
: $defaults['admin'];
|
||||||
|
|
||||||
|
update_option( 'wp_bnb_rate_limit_window', $limit_window );
|
||||||
|
update_option( 'wp_bnb_rate_limit_public', $limit_public );
|
||||||
|
update_option( 'wp_bnb_rate_limit_availability', $limit_avail );
|
||||||
|
update_option( 'wp_bnb_rate_limit_booking', $limit_booking );
|
||||||
|
update_option( 'wp_bnb_rate_limit_admin', $limit_admin );
|
||||||
|
|
||||||
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'API settings saved.', 'wp-bnb' ), 'success' );
|
add_settings_error( 'wp_bnb_settings', 'settings_saved', __( 'API settings saved.', 'wp-bnb' ), 'success' );
|
||||||
settings_errors( 'wp_bnb_settings' );
|
settings_errors( 'wp_bnb_settings' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Plugin Name: WP BnB Management
|
* Plugin Name: WP BnB Management
|
||||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wp-bnb
|
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wp-bnb
|
||||||
* Description: A comprehensive Bed & Breakfast management system for WordPress. Manage buildings, rooms, bookings, and guests.
|
* Description: A comprehensive Bed & Breakfast management system for WordPress. Manage buildings, rooms, bookings, and guests.
|
||||||
* Version: 0.10.0
|
* Version: 0.10.1
|
||||||
* Requires at least: 6.0
|
* Requires at least: 6.0
|
||||||
* Requires PHP: 8.3
|
* Requires PHP: 8.3
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
@@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Plugin version constant - MUST match Version in header above.
|
// Plugin version constant - MUST match Version in header above.
|
||||||
define( 'WP_BNB_VERSION', '0.10.0' );
|
define( 'WP_BNB_VERSION', '0.10.1' );
|
||||||
|
|
||||||
// Plugin path constants.
|
// Plugin path constants.
|
||||||
define( 'WP_BNB_PATH', plugin_dir_path( __FILE__ ) );
|
define( 'WP_BNB_PATH', plugin_dir_path( __FILE__ ) );
|
||||||
|
|||||||
Reference in New Issue
Block a user