Price filters
simpbire_calculated_booking_price Filter
Starting with version 2.0.2, Simple Bike Rental PRO introduces the 'simpbire_calculated_booking_price' filter, which allows developers to change the final price of a booking without having to modify the plugin files.
The filter is applied after the plugin completes all its internal calculations — including hourly and daily rates, quantities, accessories, and multi-day discounts — and before the total is saved in the booking and used for Stripe payment.
If no code uses this filter, the plugin continues to function exactly as it did in previous versions.
Syntax
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
// Use $context to check dates, rental type,
// bicycle rates, quantities, and accessories.
// Apply your custom pricing logic here.
return $total;
},
10,
2
);
The
$totalparameter contains the original total calculated internally by the plugin. The$contextparameter provides access to booking information and configured bicycle rates, such asdaily_rateandhourly_rate.
Informational messages in the price summary
When the filter changes the final total, the price shown in the summary might not match the sum of the individual items.
For example:
To explain to the user why the total has changed, you can use the simpbire_calculated_booking_price_notice filter.
The message appears in the price summary, right before the final total.
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
return 'Promotional rate applied.';
},
10,
4
);
The callback receives four parameters:
| Parameters | Description |
|---|---|
$notice |
Current message. By default, it's an empty string. |
$filtered_total |
Final total after applying the price filter. |
$original_total |
Total calculated internally by the plugin before filtering. |
$context |
The same array of information used by the price filter. |
The message:
- is only displayed in the dynamic price summary on the frontend;
- is not saved in the booking;
- is not sent to Stripe;
- is not added to emails or administrative details;
- is not displayed when the filter returns an empty string.
It's advisable to display the message only when the price has actually been changed:
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if ( abs( $filtered_total - $original_total ) < 0.01 ) {
return '';
}
return 'A custom fee has been applied.';
},
10,
4
);
The $context parameter
The $context parameter contains the main booking details. Among the most useful are:
| Key | Description |
|---|---|
reservation_id |
Booking ID. During the price preview, the booking has not yet been saved, and the value is 0. |
calculation_source |
Indicates which plugin operation requested the price calculation. Especially useful for advanced integrations and debugging. (ajax_preview, frontend_save, admin_save, admin_accessories_update). |
is_preview |
Indicates whether the calculation is a dynamic price preview (true) or a recalculation for a booking (false). Especially useful for advanced integrations and debugging. |
rental_type |
Rental type. |
daily_rate |
Standard daily rate configured for the selected bicycle. |
hourly_rate |
Standard hourly rate configured for the selected bicycle. |
bike_id |
Bicycle ID. |
start_date |
Start date (Y-m-d). |
end_date |
End date (Y-m-d). |
start_time |
Start time. |
end_time |
End time |
quantity |
Number of bicycles reserved. |
original_total |
Original total calculated by the plugin before filtering. |
bike_total_single |
Final total for the single bicycle. |
bike_total_with_quantity |
Total calculated for the bicycles, based on the quantity booked. Accessories are not included. |
accessories_total |
Final total for accessories. |
currency |
Currency configured in the plugin. |
Note: Generally, you don't need to use
calculation_sourceoris_previewin pricing rules. The filter should yield consistent results when previewing and saving the booking.
rental_type values
The plugin currently uses these identifiers:
| Value | Meaning |
|---|---|
orario |
Hourly rental |
giornaliero |
Daily rental |
multiday |
Multi-day rental |
These values can be used to apply different rules based on the type of booking.
Examples
1. Always set a fixed price
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
return 10.00;
},
10,
2
);
// Fixed-price message
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if ( abs( $filtered_total - $original_total ) < 0.01 ) {
return '';
}
return 'Custom fixed price applied.';
},
10,
4
);
2. Apply a change only to daily rentals
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
return $total;
}
return $total * 0.90;
},
10,
2
);
// Message regarding the discount on daily rentals
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if (
'giornaliero' === ( $context['rental_type'] ?? '' )
&& $filtered_total < $original_total
) {
return '10% discount applied to the daily rental.';
}
return $notice;
},
10,
4
);
In this example, a 10% discount is applied only to daily rentals.
3. Special price for a specific date
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
if (
'giornaliero' === ( $context['rental_type'] ?? '' )
&& '2026-08-15' === ( $context['start_date'] ?? '' )
) {
// Special fixed price.
return 45.00;
}
return $total;
},
10,
2
);
// Message regarding the special price for a specific date
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if (
'giornaliero' === ( $context['rental_type'] ?? '' )
&& '2026-08-15' === ( $context['start_date'] ?? '' )
) {
return 'Special rate applied for August 15th.';
}
return $notice;
},
10,
4
);
In this example, a special daily rental price is set for a specific date
To apply a percentage discount, such as 20%, instead of a fixed price, replace
return 45.00;withreturn $total * 0.80;
4. Apply a discount to multiple dates
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
return $total;
}
$discount_dates = array(
'2026-08-15',
'2026-09-10',
'2026-10-05',
);
if ( in_array( $context['start_date'] ?? '', $discount_dates, true ) ) {
return $total * 0.80;
}
return $total;
},
10,
2
);
// Message for the discount applied to multiple dates
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
$discount_dates = array(
'2026-08-15',
'2026-09-10',
'2026-10-05',
);
if (
'giornaliero' === ( $context['rental_type'] ?? '' )
&& in_array( $context['start_date'] ?? '', $discount_dates, true )
&& $filtered_total < $original_total
) {
return '20% promotional discount applied.';
}
return $notice;
},
10,
4
);
In this example, a discount is applied to multiple dates for the daily rental type
5. Different rates on weekdays and weekends
add_filter(
'simpbire_calculated_booking_price',
function ( $total, $context ) {
if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
return $total;
}
$daily_rate = (float) ( $context['daily_rate'] ?? 0 );
if ( $daily_rate <= 0 ) {
return $total;
}
$date = DateTimeImmutable::createFromFormat(
'Y-m-d',
$context['start_date'] ?? ''
);
if ( ! $date ) {
return $total;
}
$quantity = max(
1,
(int) ( $context['quantity'] ?? 1 )
);
$accessories_total = max(
0.0,
(float) ( $context['accessories_total'] ?? 0 )
);
$bike_total = $daily_rate * $quantity;
$is_weekend = (int) $date->format( 'N' ) >= 6;
return $is_weekend
? round( ( $bike_total * 1.10 ) + $accessories_total, 2 )
: round( $bike_total + $accessories_total, 2 );
},
10,
2
);
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if ( 'giornaliero' !== ( $context['rental_type'] ?? '' ) ) {
return $notice;
}
$date = DateTimeImmutable::createFromFormat(
'Y-m-d',
$context['start_date'] ?? ''
);
if ( ! $date || (int) $date->format( 'N' ) < 6 ) {
return $notice;
}
return 'A 10% weekend surcharge has been applied.';
},
10,
4
);
This example uses the daily rate configured for the bicycle and applies a 10% surcharge only on Saturdays and Sundays. On weekdays, the normal daily rate is maintained, and no message is displayed.
On weekends, the message "10% weekend surcharge applied" is displayed.
6. Different rates for each day of a multi-day booking
This is a more advanced example.
The code reconstructs the booking price day by day, applying a different rate on weekends.
/**
* Multi-day pricing:
* - standard daily rate from Monday to Friday;
* - 10% surcharge on Saturdays and Sundays.
*/
add_filter(
'simpbire_calculated_booking_price',
function ( $original_total, $context ) {
if ( 'multiday' !== ( $context['rental_type'] ?? '' ) ) {
return $original_total;
}
$daily_rate = isset( $context['daily_rate'] )
? (float) $context['daily_rate']
: 0.0;
if ( $daily_rate <= 0 ) {
return $original_total;
}
$start_date = $context['start_date'] ?? '';
$end_date = $context['end_date'] ?? '';
if ( ! $start_date || ! $end_date ) {
return $original_total;
}
try {
$current = new DateTimeImmutable( $start_date );
$end = new DateTimeImmutable( $end_date );
} catch ( Exception $e ) {
return $original_total;
}
if ( $end < $current ) {
return $original_total;
}
$bike_total_single = 0.0;
while ( $current <= $end ) {
$day_of_week = (int) $current->format( 'N' );
$day_rate = $daily_rate;
// 6 = Saturday, 7 = Sunday.
if ( $day_of_week >= 6 ) {
$day_rate *= 1.10;
}
$bike_total_single += $day_rate;
$current = $current->modify( '+1 day' );
}
$quantity = max(
1,
(int) ( $context['quantity'] ?? 1 )
);
$accessories_total = max(
0.0,
(float) ( $context['accessories_total'] ?? 0.0 )
);
return round(
( $bike_total_single * $quantity ) + $accessories_total,
2
);
},
10,
2
);
/**
* Message displayed in the price summary on the frontend.
*/
add_filter(
'simpbire_calculated_booking_price_notice',
function ( $notice, $filtered_total, $original_total, $context ) {
if ( 'multiday' !== ( $context['rental_type'] ?? '' ) ) {
return $notice;
}
$start_date = $context['start_date'] ?? '';
$end_date = $context['end_date'] ?? '';
if ( ! $start_date || ! $end_date ) {
return $notice;
}
try {
$current = new DateTimeImmutable( $start_date );
$end = new DateTimeImmutable( $end_date );
} catch ( Exception $e ) {
return $notice;
}
if ( $end < $current ) {
return $notice;
}
while ( $current <= $end ) {
if ( (int) $current->format( 'N' ) >= 6 ) {
return 'A 10% surcharge applies to Saturdays and Sundays included in the booking.';
}
$current = $current->modify( '+1 day' );
}
return $notice;
},
10,
4
);
This approach allows you to implement advanced pricing logic, such as different prices for weekends (Saturdays and Sundays) on multi-day bookings.
This snippet fully reconstructs the price of the bicycle section, day by day. As a result, it replaces the plugin’s standard multi-day calculation and does not automatically apply any multi-day discount configured in the settings. Instead, the accessories are retained using the total already calculated by the plugin.
We recommend not using this filter if you've enabled the multi-day discount in the plugin's general settings.
Best practices
Price filter
- Always return a numeric, non-negative value.
- Return the original total when the custom rule doesn't apply.
- Do not modify the database, send emails, or record coupon usage within the filter.
- The plugin automatically discards non-numeric, negative,
NAN, or infinite values and uses the original total. - Remember that the filter changes the final total, but it doesn't automatically redistribute the difference between the prices of the bike, accessories, and discounts shown in the summary.
Message filter
- Use short, easy-to-understand messages.
- Do not enter HTML: the filter accepts plain text.
- Keep the same conditions as those used in the corresponding price filter.
- The filter can be applied multiple times as the user changes dates, quantities, or accessories.
- Do not perform any permanent operations within the filter.
- Use
$filtered_totaland$original_totalto check if the price has actually changed.