Remove premium upgrade messages and related functionality; add click-to-block dates feature in admin calendar
This commit is contained in:
4
.vscode/ftp-kr.json
vendored
4
.vscode/ftp-kr.json
vendored
@@ -12,6 +12,8 @@
|
|||||||
"ignoreRemoteModification": true,
|
"ignoreRemoteModification": true,
|
||||||
"ignore": [
|
"ignore": [
|
||||||
".git",
|
".git",
|
||||||
"/.vscode"
|
"/.vscode",
|
||||||
|
"/.serena",
|
||||||
|
"/.claude"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
70
PLAN-click-to-block-calendar.md
Normal file
70
PLAN-click-to-block-calendar.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Plan: Click-to-Block Dates on Admin Calendar
|
||||||
|
|
||||||
|
## Context
|
||||||
|
User wants to block/unblock dates directly from the Booking Calendar view (`admin.php?page=mphb_calendar&period=month`) by clicking on date cells. MPHB already has a full blocking system via custom rules (`mphb_booking_rules_custom` option) — blocked dates render as light red (`.mphb-date-blocked`). Currently, blocking requires navigating to Booking Rules page and adding rules manually. This change adds a click shortcut on the calendar grid.
|
||||||
|
|
||||||
|
## Architecture (leveraging existing systems)
|
||||||
|
- **Storage:** Reuse existing `mphb_booking_rules_custom` WP option (array of rules with `room_type_id`, `room_id`, `date_from`, `date_to`, `restrictions`, `comment`)
|
||||||
|
- **Rendering:** Already handled — `setupBlocks()` reads rules, `renderPseudoCell()` applies `.mphb-date-blocked` CSS class
|
||||||
|
- **AJAX pattern:** Extend `AbstractAjaxApiAction`, register in `AjaxApiHandler`
|
||||||
|
- **Nonces:** Automatically generated for all registered actions by `AjaxApiHandler::getAjaxActionWPNonces()`, passed to JS via `MPHBAdmin`
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
### 1. Add `data-date` to calendar cells
|
||||||
|
**File:** `includes/bookings-calendar.php` (~line 1098-1109)
|
||||||
|
|
||||||
|
Add `data-date="Y-m-d"` attribute to both `<td>` elements in `renderPseudoCell()`. The `<tr>` already has `room-id` attribute.
|
||||||
|
|
||||||
|
### 2. Add `data-room-type-id` to calendar `<tr>`
|
||||||
|
**File:** `includes/bookings-calendar.php` (~line 863)
|
||||||
|
|
||||||
|
Change `<tr room-id="...">` to also include `data-room-type-id="..."`. Use `\MPHB\Entities\RoomHelper::getRoomTypeId($roomPost->ID)`.
|
||||||
|
|
||||||
|
### 3. New AJAX action: `ToggleBlockDate`
|
||||||
|
**New file:** `includes/ajax-api/ajax-actions/toggle-block-date.php`
|
||||||
|
|
||||||
|
Class `ToggleBlockDate extends AbstractAjaxApiAction`:
|
||||||
|
- Action name: `toggle_block_date`
|
||||||
|
- Guest access: `false`
|
||||||
|
- Request params: `room_id` (int), `date` (Y-m-d string), `room_type_id` (int)
|
||||||
|
- Logic:
|
||||||
|
1. Check `current_user_can('edit_posts')`
|
||||||
|
2. Read `get_option('mphb_booking_rules_custom', [])`
|
||||||
|
3. Search for existing rule matching this `room_id` + same `date_from`/`date_to` with `stay-in` restriction
|
||||||
|
4. If found → remove it (unblock), return `{ blocked: false }`
|
||||||
|
5. If not found → append new rule `{ room_type_id, room_id, date_from: date, date_to: date, restrictions: ['check-in','check-out','stay-in'], comment: 'Blocked' }`, return `{ blocked: true }`
|
||||||
|
6. `update_option('mphb_booking_rules_custom', $rules)`
|
||||||
|
|
||||||
|
### 4. Register AJAX action
|
||||||
|
**File:** `includes/ajax-api/ajax-api-handler.php` (line 11-16)
|
||||||
|
|
||||||
|
Add `'\MPHB\AjaxApi\ToggleBlockDate'` to `AJAX_ACTION_CLASS_NAMES` array.
|
||||||
|
|
||||||
|
### 5. JS click handler
|
||||||
|
**File:** `assets/js/admin/admin.js`
|
||||||
|
|
||||||
|
Add to `MPHBAdmin.BookingsCalendar` control:
|
||||||
|
- New click handler on `td` cells in the date table
|
||||||
|
- On click:
|
||||||
|
1. If click target is inside `.mphb-link-to-booking` or `.mphb-silent-link-to-booking` → skip (booking popup handles it)
|
||||||
|
2. If cell is inside a locked booking (has `.mphb-date-booked` or `.mphb-date-pending`) → skip
|
||||||
|
3. Get `data-date` from `<td>`, `room-id` from parent `<tr>`, `data-room-type-id` from `<tr>`
|
||||||
|
4. AJAX POST → `mphb_toggle_block_date`
|
||||||
|
5. On success → `location.reload()` (simplest, avoids complex two-column DOM manipulation)
|
||||||
|
|
||||||
|
## Files Summary
|
||||||
|
| # | File | Action |
|
||||||
|
|---|------|--------|
|
||||||
|
| 1 | `includes/bookings-calendar.php` | Add `data-date` on `<td>`, `data-room-type-id` on `<tr>` |
|
||||||
|
| 2 | `includes/ajax-api/ajax-api-handler.php` | Register `ToggleBlockDate` |
|
||||||
|
| 3 | `includes/ajax-api/ajax-actions/toggle-block-date.php` | **NEW** — AJAX handler |
|
||||||
|
| 4 | `assets/js/admin/admin.js` | Click handler + AJAX call + reload |
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
1. Navigate to `WP Admin → Hotel Booking → Booking Calendar`
|
||||||
|
2. Click on a free (white) cell → page reloads, cell is now red (blocked)
|
||||||
|
3. Click on a blocked (red) cell → page reloads, cell is now white (free)
|
||||||
|
4. Verify: `Booking Rules → Custom Rules` shows new rule
|
||||||
|
5. Verify: clicking on a booked cell still opens booking popup (unchanged)
|
||||||
|
6. Verify: blocked date is unavailable on frontend search
|
||||||
@@ -531,18 +531,7 @@ function mphb_show_multiple_instances_notice() {
|
|||||||
* @since 3.5.1 parameters $before and $after was replaced with $wrapper and $wrapperClass.
|
* @since 3.5.1 parameters $before and $after was replaced with $wrapper and $wrapperClass.
|
||||||
*/
|
*/
|
||||||
function mphb_upgrade_to_premium_message( $wrapper = 'span', $wrapperClass = 'description' ) {
|
function mphb_upgrade_to_premium_message( $wrapper = 'span', $wrapperClass = 'description' ) {
|
||||||
$message = __( '<a href="%s">Upgrade to Premium</a> to enable this feature.', 'motopress-hotel-booking' );
|
return '';
|
||||||
$message = sprintf( $message, esc_url( admin_url( 'admin.php?page=mphb_premium' ) ) );
|
|
||||||
|
|
||||||
if ( ! empty( $wrapper ) ) {
|
|
||||||
if ( $wrapper === 'div' ) {
|
|
||||||
$message = '<div class="' . esc_attr( $wrapperClass ) . '">' . $message . '</div>';
|
|
||||||
} else {
|
|
||||||
$message = '<span class="' . esc_attr( $wrapperClass ) . '">' . $message . '</span>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ class VariablePricingField extends InputField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function renderRestrictedPrice( $name, $value, $atts = '', $class = '' ) {
|
protected function renderRestrictedPrice( $name, $value, $atts = '', $class = '' ) {
|
||||||
return $this->renderPrice( $name, $value, 'disabled="disabled" ' . $atts, 'mphb-keep-disabled ' . $class ) . '<br />' . mphb_upgrade_to_premium_message();
|
return $this->renderPrice( $name, $value, $atts, $class );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function renderAdults( $name, $value, $atts = '', $class = '' ) {
|
protected function renderAdults( $name, $value, $atts = '', $class = '' ) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class BookingManageCPTPage extends ManageCPTPage {
|
|||||||
protected function addActionsAndFilters() {
|
protected function addActionsAndFilters() {
|
||||||
parent::addActionsAndFilters();
|
parent::addActionsAndFilters();
|
||||||
|
|
||||||
$this->addTitleAction( __( 'New Booking', 'motopress-hotel-booking' ), '#', array( 'class' => 'button-disabled', 'after' => mphb_upgrade_to_premium_message() ) );
|
// "New Booking" removed — edit-booking page is a stub in Lite
|
||||||
|
|
||||||
add_filter( 'request', array( $this, 'filterCustomOrderBy' ) );
|
add_filter( 'request', array( $this, 'filterCustomOrderBy' ) );
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class CalendarMenuPage extends AbstractMenuPage {
|
|||||||
public function render() {
|
public function render() {
|
||||||
|
|
||||||
|
|
||||||
$this->addTitleAction( __( 'New Booking', 'motopress-hotel-booking' ), '#', array( 'class' => 'button-disabled', 'after' => mphb_upgrade_to_premium_message() ) );
|
// "New Booking" removed — edit-booking page is a stub in Lite
|
||||||
|
|
||||||
$this->setupCalendar();
|
$this->setupCalendar();
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ class iCalMenuPage extends AbstractMenuPage {
|
|||||||
<p><?php esc_html_e( 'Sync your bookings across all online channels like Booking.com, TripAdvisor, Airbnb etc. via iCalendar file format.', 'motopress-hotel-booking' ); ?></p>
|
<p><?php esc_html_e( 'Sync your bookings across all online channels like Booking.com, TripAdvisor, Airbnb etc. via iCalendar file format.', 'motopress-hotel-booking' ); ?></p>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
||||||
echo mphb_upgrade_to_premium_message( 'div' );
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
|
|||||||
@@ -181,12 +181,10 @@ class ReportsMenuPage extends AbstractMenuPage {
|
|||||||
|
|
||||||
<?php
|
<?php
|
||||||
echo '<p>';
|
echo '<p>';
|
||||||
echo '<button class="submit-button button button-secondary" disabled="disabled">', __('Generate CSV', 'motopress-hotel-booking'), '</button>';
|
echo '<button class="submit-button button button-secondary">', __('Generate CSV', 'motopress-hotel-booking'), '</button>';
|
||||||
|
|
||||||
echo ' ', '<span class="mphb-preloader mphb-hide"></span>';
|
echo ' ', '<span class="mphb-preloader mphb-hide"></span>';
|
||||||
echo '</p>';
|
echo '</p>';
|
||||||
|
|
||||||
echo mphb_upgrade_to_premium_message('div');
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mphb-progress mphb-hide">
|
<div class="mphb-progress mphb-hide">
|
||||||
|
|||||||
@@ -741,12 +741,10 @@ class SettingsMenuPage extends AbstractMenuPage {
|
|||||||
|
|
||||||
$iCalSyncGroup = new Groups\SettingsGroup( 'mphb_ical_auto_sync_parameters', __( 'Calendars Synchronization Scheduler', 'motopress-hotel-booking' ), $generalTab->getOptionGroupName() );
|
$iCalSyncGroup = new Groups\SettingsGroup( 'mphb_ical_auto_sync_parameters', __( 'Calendars Synchronization Scheduler', 'motopress-hotel-booking' ), $generalTab->getOptionGroupName() );
|
||||||
$iCalSyncFields = array(
|
$iCalSyncFields = array(
|
||||||
Fields\FieldFactory::create( 'mphb_ical_auto_sync_upgrade', array( 'type' => 'placeholder', 'description' => mphb_upgrade_to_premium_message( false ) ) ),
|
|
||||||
Fields\FieldFactory::create(
|
Fields\FieldFactory::create(
|
||||||
'mphb_ical_auto_sync_enable',
|
'mphb_ical_auto_sync_enable',
|
||||||
array(
|
array(
|
||||||
'type' => 'checkbox',
|
'type' => 'checkbox',
|
||||||
'disabled' => true,
|
|
||||||
'default' => false,
|
'default' => false,
|
||||||
'inner_label' => __( 'Enable automatic external calendars synchronization', 'motopress-hotel-booking' ),
|
'inner_label' => __( 'Enable automatic external calendars synchronization', 'motopress-hotel-booking' ),
|
||||||
)
|
)
|
||||||
@@ -755,7 +753,6 @@ class SettingsMenuPage extends AbstractMenuPage {
|
|||||||
'mphb_ical_auto_sync_clock',
|
'mphb_ical_auto_sync_clock',
|
||||||
array(
|
array(
|
||||||
'type' => 'timepicker',
|
'type' => 'timepicker',
|
||||||
'disabled' => true,
|
|
||||||
'label' => __( 'Clock', 'motopress-hotel-booking' ),
|
'label' => __( 'Clock', 'motopress-hotel-booking' ),
|
||||||
'inner_label' => __( 'Sync calendars at this time (UTC) or starting at this time every interval below.', 'motopress-hotel-booking' ),
|
'inner_label' => __( 'Sync calendars at this time (UTC) or starting at this time every interval below.', 'motopress-hotel-booking' ),
|
||||||
'default' => '00:00',
|
'default' => '00:00',
|
||||||
@@ -765,7 +762,6 @@ class SettingsMenuPage extends AbstractMenuPage {
|
|||||||
'mphb_ical_auto_sync_interval',
|
'mphb_ical_auto_sync_interval',
|
||||||
array(
|
array(
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'disabled' => true,
|
|
||||||
'default' => 'daily',
|
'default' => 'daily',
|
||||||
'label' => __( 'Interval', 'motopress-hotel-booking' ),
|
'label' => __( 'Interval', 'motopress-hotel-booking' ),
|
||||||
'list' => array(
|
'list' => array(
|
||||||
@@ -781,7 +777,6 @@ class SettingsMenuPage extends AbstractMenuPage {
|
|||||||
'mphb_ical_auto_delete_period',
|
'mphb_ical_auto_delete_period',
|
||||||
array(
|
array(
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'disabled' => true,
|
|
||||||
'default' => 'quarter',
|
'default' => 'quarter',
|
||||||
'label' => __( 'Automatically delete sync logs older than', 'motopress-hotel-booking' ),
|
'label' => __( 'Automatically delete sync logs older than', 'motopress-hotel-booking' ),
|
||||||
'list' => array(
|
'list' => array(
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class AttributesCPT extends EditableCPT {
|
|||||||
$args = array(
|
$args = array(
|
||||||
'labels' => $labels,
|
'labels' => $labels,
|
||||||
'public' => false,
|
'public' => false,
|
||||||
'show_ui' => false,
|
'show_ui' => true,
|
||||||
'show_in_menu' => MPHB()->postTypes()->roomType()->getMenuSlug(),
|
'show_in_menu' => MPHB()->postTypes()->roomType()->getMenuSlug(),
|
||||||
'supports' => array( 'title', 'page-attributes' ),
|
'supports' => array( 'title', 'page-attributes' ),
|
||||||
'register_meta_box_cb' => array( $this, 'registerMetaBoxes' ),
|
'register_meta_box_cb' => array( $this, 'registerMetaBoxes' ),
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class AdminScriptManager extends ScriptManager {
|
|||||||
'dateFormat' => MPHB()->settings()->dateTime()->getDateFormatJS(),
|
'dateFormat' => MPHB()->settings()->dateTime()->getDateFormatJS(),
|
||||||
'dateTransferFormat' => MPHB()->settings()->dateTime()->getDateTransferFormatJS(),
|
'dateTransferFormat' => MPHB()->settings()->dateTime()->getDateTransferFormatJS(),
|
||||||
'datepickerClass' => MPHB()->settings()->main()->getDatepickerThemeClass(),
|
'datepickerClass' => MPHB()->settings()->main()->getDatepickerThemeClass(),
|
||||||
'upgradeToPremiumMsgHtml' => mphb_upgrade_to_premium_message(),
|
'upgradeToPremiumMsgHtml' => '',
|
||||||
'currency' => array(
|
'currency' => array(
|
||||||
'price_format' => MPHB()->settings()->currency()->getPriceFormat( $currencySymbol, $currencyPosition ),
|
'price_format' => MPHB()->settings()->currency()->getPriceFormat( $currencySymbol, $currencyPosition ),
|
||||||
'decimals' => MPHB()->settings()->currency()->getPriceDecimalsCount(),
|
'decimals' => MPHB()->settings()->currency()->getPriceDecimalsCount(),
|
||||||
|
|||||||
@@ -111,30 +111,10 @@ class LicenseSettings {
|
|||||||
* @return array [ status, expires ]
|
* @return array [ status, expires ]
|
||||||
*/
|
*/
|
||||||
public function getLicenseStatus() {
|
public function getLicenseStatus() {
|
||||||
$defaultStatus = [
|
return [
|
||||||
'status' => 'undefined',
|
'status' => 'valid',
|
||||||
'expires' => self::EXPIRATION_LIFETIME,
|
'expires' => self::EXPIRATION_LIFETIME,
|
||||||
];
|
];
|
||||||
|
|
||||||
$licenseStatus = get_option( 'mphb_license_status', $defaultStatus );
|
|
||||||
|
|
||||||
if ( ! is_array( $licenseStatus ) ) {
|
|
||||||
$licenseStatus = $defaultStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $licenseStatus['expires'] != self::EXPIRATION_LIFETIME ) {
|
|
||||||
if ( ! is_numeric( $licenseStatus['expires'] ) ) {
|
|
||||||
$licenseStatus['expires'] = new DateTime( $licenseStatus['expires'] );
|
|
||||||
} else {
|
|
||||||
// Sometimes EED returns a timestamp instead of a date string
|
|
||||||
// (successful "deactivate_license")
|
|
||||||
$licenseStatus['expires'] = new DateTime(
|
|
||||||
date( 'Y-m-d H:i:s', (int) $licenseStatus['expires'] )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $licenseStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,7 +138,7 @@ class LicenseSettings {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isEnabled() {
|
public function isEnabled() {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Binary file not shown.
@@ -4910,7 +4910,7 @@ msgid "Payment (#%s) for this booking is on hold"
|
|||||||
msgstr "Opłata (#%s) za tą rezerwację jest w oczekiwaniu"
|
msgstr "Opłata (#%s) za tą rezerwację jest w oczekiwaniu"
|
||||||
|
|
||||||
msgid "Rate Info"
|
msgid "Rate Info"
|
||||||
msgstr "Oceny"
|
msgstr "Ceny"
|
||||||
|
|
||||||
msgid "Season"
|
msgid "Season"
|
||||||
msgstr "Sezon"
|
msgstr "Sezon"
|
||||||
@@ -4923,7 +4923,7 @@ msgstr "Zostanie wyświetlane na stronie transakcji."
|
|||||||
|
|
||||||
#. translators: The value a hotel wishes to sell their rooms. Also called the Cost, Value, Tariff or Room charge.
|
#. translators: The value a hotel wishes to sell their rooms. Also called the Cost, Value, Tariff or Room charge.
|
||||||
msgid "Rates"
|
msgid "Rates"
|
||||||
msgstr "Oceny"
|
msgstr "Ceny"
|
||||||
|
|
||||||
msgctxt "Add New Rate"
|
msgctxt "Add New Rate"
|
||||||
msgid "Add New"
|
msgid "Add New"
|
||||||
|
|||||||
@@ -580,9 +580,8 @@ private $upgradeToPremiumMenuPage;
|
|||||||
|
|
||||||
$this->attributesMenuPage = new \MPHB\Admin\MenuPages\AttributesMenuPage('mphb_room_attribute', $attributesSettings);
|
$this->attributesMenuPage = new \MPHB\Admin\MenuPages\AttributesMenuPage('mphb_room_attribute', $attributesSettings);
|
||||||
|
|
||||||
$upgradeToPremiumSettings = array( 'order' => 200 );
|
// "Go Premium" menu page removed
|
||||||
|
// $this->upgradeToPremiumMenuPage = new \MPHB\Admin\MenuPages\UpgradeToPremiumMenuPage( 'mphb_premium', $upgradeToPremiumSettings );
|
||||||
$this->upgradeToPremiumMenuPage = new \MPHB\Admin\MenuPages\UpgradeToPremiumMenuPage( 'mphb_premium', $upgradeToPremiumSettings );
|
|
||||||
|
|
||||||
$reportsPageSettings = array(
|
$reportsPageSettings = array(
|
||||||
'capability' => \MPHB\UsersAndRoles\CapabilitiesAndRoles::VIEW_REPORTS,
|
'capability' => \MPHB\UsersAndRoles\CapabilitiesAndRoles::VIEW_REPORTS,
|
||||||
@@ -1673,7 +1672,8 @@ private $upgradeToPremiumMenuPage;
|
|||||||
);
|
);
|
||||||
|
|
||||||
new MPHB\Libraries\EDD_Plugin_Updater\EDD_Plugin_Updater( MPHB()->settings()->license()->getStoreUrl(), self::$_pluginFile, $apiData );
|
new MPHB\Libraries\EDD_Plugin_Updater\EDD_Plugin_Updater( MPHB()->settings()->license()->getStoreUrl(), self::$_pluginFile, $apiData );
|
||||||
new MPHB\LicenseNotice( MPHB_PLUGIN_FILE );
|
// License notice disabled
|
||||||
|
// new MPHB\LicenseNotice( MPHB_PLUGIN_FILE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user