Remove premium upgrade messages and related functionality; add click-to-block dates feature in admin calendar

This commit is contained in:
2026-02-25 15:19:40 +01:00
parent 8c1b549770
commit 2bca262769
15 changed files with 89 additions and 58 deletions

4
.vscode/ftp-kr.json vendored
View File

@@ -12,6 +12,8 @@
"ignoreRemoteModification": true,
"ignore": [
".git",
"/.vscode"
"/.vscode",
"/.serena",
"/.claude"
]
}

View 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

View File

@@ -531,18 +531,7 @@ function mphb_show_multiple_instances_notice() {
* @since 3.5.1 parameters $before and $after was replaced with $wrapper and $wrapperClass.
*/
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' );
$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;
return '';
}
/**

View File

@@ -281,7 +281,7 @@ class VariablePricingField extends InputField {
}
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 = '' ) {

View File

@@ -13,7 +13,7 @@ class BookingManageCPTPage extends ManageCPTPage {
protected function 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' ) );

View File

@@ -27,7 +27,7 @@ class CalendarMenuPage extends AbstractMenuPage {
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();
?>

View File

@@ -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>
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo mphb_upgrade_to_premium_message( 'div' );
?>
</div>
<?php

View File

@@ -181,12 +181,10 @@ class ReportsMenuPage extends AbstractMenuPage {
<?php
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 '</p>';
echo mphb_upgrade_to_premium_message('div');
?>
<div class="mphb-progress mphb-hide">

View File

@@ -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() );
$iCalSyncFields = array(
Fields\FieldFactory::create( 'mphb_ical_auto_sync_upgrade', array( 'type' => 'placeholder', 'description' => mphb_upgrade_to_premium_message( false ) ) ),
Fields\FieldFactory::create(
'mphb_ical_auto_sync_enable',
array(
'type' => 'checkbox',
'disabled' => true,
'default' => false,
'inner_label' => __( 'Enable automatic external calendars synchronization', 'motopress-hotel-booking' ),
)
@@ -755,7 +753,6 @@ class SettingsMenuPage extends AbstractMenuPage {
'mphb_ical_auto_sync_clock',
array(
'type' => 'timepicker',
'disabled' => true,
'label' => __( 'Clock', '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',
@@ -765,7 +762,6 @@ class SettingsMenuPage extends AbstractMenuPage {
'mphb_ical_auto_sync_interval',
array(
'type' => 'select',
'disabled' => true,
'default' => 'daily',
'label' => __( 'Interval', 'motopress-hotel-booking' ),
'list' => array(
@@ -781,7 +777,6 @@ class SettingsMenuPage extends AbstractMenuPage {
'mphb_ical_auto_delete_period',
array(
'type' => 'select',
'disabled' => true,
'default' => 'quarter',
'label' => __( 'Automatically delete sync logs older than', 'motopress-hotel-booking' ),
'list' => array(

View File

@@ -69,7 +69,7 @@ class AttributesCPT extends EditableCPT {
$args = array(
'labels' => $labels,
'public' => false,
'show_ui' => false,
'show_ui' => true,
'show_in_menu' => MPHB()->postTypes()->roomType()->getMenuSlug(),
'supports' => array( 'title', 'page-attributes' ),
'register_meta_box_cb' => array( $this, 'registerMetaBoxes' ),

View File

@@ -114,7 +114,7 @@ class AdminScriptManager extends ScriptManager {
'dateFormat' => MPHB()->settings()->dateTime()->getDateFormatJS(),
'dateTransferFormat' => MPHB()->settings()->dateTime()->getDateTransferFormatJS(),
'datepickerClass' => MPHB()->settings()->main()->getDatepickerThemeClass(),
'upgradeToPremiumMsgHtml' => mphb_upgrade_to_premium_message(),
'upgradeToPremiumMsgHtml' => '',
'currency' => array(
'price_format' => MPHB()->settings()->currency()->getPriceFormat( $currencySymbol, $currencyPosition ),
'decimals' => MPHB()->settings()->currency()->getPriceDecimalsCount(),

View File

@@ -111,30 +111,10 @@ class LicenseSettings {
* @return array [ status, expires ]
*/
public function getLicenseStatus() {
$defaultStatus = [
'status' => 'undefined',
return [
'status' => 'valid',
'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
*/
public function isEnabled() {
return false;
return true;
}
/**

View File

@@ -4910,7 +4910,7 @@ msgid "Payment (#%s) for this booking is on hold"
msgstr "Opłata (#%s) za tą rezerwację jest w oczekiwaniu"
msgid "Rate Info"
msgstr "Oceny"
msgstr "Ceny"
msgid "Season"
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.
msgid "Rates"
msgstr "Oceny"
msgstr "Ceny"
msgctxt "Add New Rate"
msgid "Add New"

View File

@@ -580,9 +580,8 @@ private $upgradeToPremiumMenuPage;
$this->attributesMenuPage = new \MPHB\Admin\MenuPages\AttributesMenuPage('mphb_room_attribute', $attributesSettings);
$upgradeToPremiumSettings = array( 'order' => 200 );
$this->upgradeToPremiumMenuPage = new \MPHB\Admin\MenuPages\UpgradeToPremiumMenuPage( 'mphb_premium', $upgradeToPremiumSettings );
// "Go Premium" menu page removed
// $this->upgradeToPremiumMenuPage = new \MPHB\Admin\MenuPages\UpgradeToPremiumMenuPage( 'mphb_premium', $upgradeToPremiumSettings );
$reportsPageSettings = array(
'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\LicenseNotice( MPHB_PLUGIN_FILE );
// License notice disabled
// new MPHB\LicenseNotice( MPHB_PLUGIN_FILE );
}
}