- Deruan Rimba Campsite, Jalan Sungai Gabai, 43100 Hulu Langat, Selangor
- deruanrimbaofficial@gmail.com
- +60196552630
welcome to
Deruan Rimba Campsite
Check Availability
Select a product, dates and guests
Available Bookings
One-Time Setup Required
- Go to your WordPress admin dashboard
- Install the free Code Snippets plugin (or edit functions.php)
- Add a new PHP snippet with the code below and activate it
- Reload this page — the widget will auto-connect!
/* WooCommerce Booking Filter — REST API */
add_action( 'rest_api_init', function () {
/* ── List all bookable products (with resources) ── */
register_rest_route( 'wcbf/v1', '/products', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function () {
$q = new WP_Query([
'post_type' => 'product',
'posts_per_page' => 200,
'post_status' => 'publish',
'tax_query' => [[
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => 'booking',
]],
]);
$out = [];
foreach ( $q->posts as $p ) {
$prod = wc_get_product( $p->ID );
if ( ! $prod ) continue;
$img = wp_get_attachment_url( $prod->get_image_id() );
$item = [
'id' => $p->ID,
'name' => $prod->get_name(),
'price' => $prod->get_price(),
'price_html' => strip_tags( $prod->get_price_html() ),
'permalink' => get_permalink( $p->ID ),
'image' => $img ? $img : '',
// Full product short description (no trimming)
'description_html' => wp_kses_post( (string) $prod->get_short_description() ),
'description' => wp_strip_all_tags( (string) $prod->get_short_description() ),
// Nonce for wc-ajax=wc_bookings_calculate_cost
'cost_nonce' => function_exists('wp_create_nonce') ? wp_create_nonce( 'wc_bookings_calculate_cost' ) : '',
];
if ( $prod instanceof WC_Product_Booking ) {
$item['has_persons'] = $prod->has_persons();
$item['min_persons'] = $prod->get_min_persons();
$item['max_persons'] = $prod->get_max_persons();
$item['duration'] = $prod->get_duration();
$item['dur_unit'] = $prod->get_duration_unit();
$item['duration_type'] = method_exists( $prod, 'get_duration_type' ) ? $prod->get_duration_type() : '';
$item['has_resources'] = $prod->has_resources();
$item['resources'] = [];
$item['resources_label'] = '';
if ( $prod->has_resources() ) {
$item['resources_label'] = $prod->get_resource_label() ? $prod->get_resource_label() : 'Resource Type';
foreach ( $prod->get_resources() as $res ) {
$item['resources'][] = [
'id' => $res->get_id(),
'name' => $res->get_name(),
];
}
}
}
$out[] = $item;
}
return $out;
},
]);
/* ── Check availability (uses WC Bookings engine; strict per-resource across whole stay) ── */
register_rest_route( 'wcbf/v1', '/availability', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function ( $req ) {
$pid = absint( $req->get_param('product_id') );
$start = sanitize_text_field( $req->get_param('start_date') );
$end = sanitize_text_field( $req->get_param('end_date') );
$qty = absint( $req->get_param('persons') ) ?: 1;
$resource_id = absint( $req->get_param('resource_id') );
if ( ! $pid || ! $start || ! $end ) {
return new WP_Error( 'bad', 'Missing params', [ 'status' => 400 ] );
}
$prod = wc_get_product( $pid );
if ( ! $prod || ! ( $prod instanceof WC_Product_Booking ) ) {
return new WP_Error( 'bad', 'Not bookable', [ 'status' => 400 ] );
}
/* Persons validation (per booking) */
if ( $prod->has_persons() ) {
if ( $qty < $prod->get_min_persons() || $qty > $prod->get_max_persons() ) {
return [ 'available' => false, 'reason' => 'persons', 'product_id' => $pid, 'resource_id' => 0 ];
}
}
$start_ts = strtotime( $start . ' 00:00:00' );
$end_ts = strtotime( $end . ' 00:00:00' );
if ( ! $start_ts || ! $end_ts || $end_ts <= $start_ts ) {
return new WP_Error( 'bad', 'Invalid date range', [ 'status' => 400 ] );
}
$next_day = function( $ts ) { return strtotime( '+1 day', $ts ); };
$day_is_available = function( $rid, $cur, $day_end ) use ( $prod, $qty ) {
$check = $prod->get_available_bookings( $cur, $day_end, (int) $rid, (int) $qty );
if ( is_wp_error( $check ) ) return false;
return ! empty( $check );
};
$range_is_available_for_resource = function( $rid ) use ( $start_ts, $end_ts, $next_day, $day_is_available ) {
for ( $cur = $start_ts; $cur < $end_ts; $cur = $next_day( $cur ) ) {
$day_end = $next_day( $cur );
if ( ! $day_is_available( $rid, $cur, $day_end ) ) return false;
}
return true;
};
/* Products WITH resources */
if ( $prod->has_resources() ) {
$resources = $prod->get_resources();
/* Validate an explicitly requested resource */
if ( $resource_id ) {
$ok = $range_is_available_for_resource( $resource_id );
return [
'available' => (bool) $ok,
'product_id' => $pid,
'resource_id' => (int) $resource_id,
];
}
/* Otherwise, pick a SINGLE resource that works for ALL days */
foreach ( $resources as $res ) {
$rid = (int) $res->get_id();
if ( ! $rid ) continue;
if ( $range_is_available_for_resource( $rid ) ) {
return [ 'available' => true, 'product_id' => $pid, 'resource_id' => $rid ];
}
}
return [ 'available' => false, 'product_id' => $pid, 'resource_id' => 0 ];
}
/* Products WITHOUT resources */
$ok = $range_is_available_for_resource( 0 );
return [ 'available' => (bool) $ok, 'product_id' => $pid, 'resource_id' => 0 ];
},
]);
/* ── Calculate exact booking cost (server-side proxy to WC Bookings calculator) ── */
register_rest_route( 'wcbf/v1', '/cost', [
'methods' => 'GET',
'permission_callback' => '__return_true',
'callback' => function( $req ) {
$pid = absint( $req->get_param('product_id') );
$start = sanitize_text_field( $req->get_param('start_date') );
$end = sanitize_text_field( $req->get_param('end_date') );
$persons = absint( $req->get_param('persons') ) ?: 0;
$quantity = absint( $req->get_param('quantity') ) ?: 0;
$resource_id = absint( $req->get_param('resource_id') );
if ( ! $pid || ! $start || ! $end ) {
return new WP_Error( 'bad', 'Missing params', [ 'status' => 400 ] );
}
if ( ! function_exists('wc_get_product') ) {
return new WP_Error( 'bad', 'WooCommerce not available', [ 'status' => 400 ] );
}
$prod = wc_get_product( $pid );
if ( ! $prod || ! ( $prod instanceof WC_Product_Booking ) ) {
return new WP_Error( 'bad', 'Not bookable', [ 'status' => 400 ] );
}
$start_ts = strtotime( $start . ' 00:00:00' );
$end_ts = strtotime( $end . ' 00:00:00' );
if ( ! $start_ts || ! $end_ts || $end_ts <= $start_ts ) {
return new WP_Error( 'bad', 'Invalid date range', [ 'status' => 400 ] );
}
$duration = (int) ceil( ( $end_ts - $start_ts ) / DAY_IN_SECONDS );
if ( $duration < 1 ) $duration = 1;
$fields = [
'add-to-cart' => $pid,
'product_id' => $pid,
'wc_bookings_field_start_date_year' => (int) gmdate( 'Y', $start_ts ),
'wc_bookings_field_start_date_month' => (int) gmdate( 'n', $start_ts ),
'wc_bookings_field_start_date_day' => (int) gmdate( 'j', $start_ts ),
// Accommodation-style end date fields
'wc_bookings_field_start_date_to_year' => (int) gmdate( 'Y', $end_ts ),
'wc_bookings_field_start_date_to_month' => (int) gmdate( 'n', $end_ts ),
'wc_bookings_field_start_date_to_day' => (int) gmdate( 'j', $end_ts ),
// Alternate end date fields
'wc_bookings_field_end_date_year' => (int) gmdate( 'Y', $end_ts ),
'wc_bookings_field_end_date_month' => (int) gmdate( 'n', $end_ts ),
'wc_bookings_field_end_date_day' => (int) gmdate( 'j', $end_ts ),
'wc_bookings_field_duration' => $duration,
];
if ( $persons > 0 ) {
$fields['wc_bookings_field_persons'] = $persons;
}
if ( $quantity > 0 ) {
$fields['quantity'] = $quantity;
}
if ( $resource_id > 0 ) {
$fields['wc_bookings_field_resource'] = $resource_id;
}
$nonce = function_exists('wp_create_nonce') ? wp_create_nonce( 'wc_bookings_calculate_cost' ) : '';
$endpoint = home_url( '/?wc-ajax=wc_bookings_calculate_cost' );
$payload = [
'security' => $nonce,
'form' => http_build_query( $fields ),
];
$resp = wp_remote_post( $endpoint, [
'timeout' => 15,
'redirection' => 3,
'sslverify' => true,
'headers' => [
'Accept' => 'application/json, text/plain, */*',
'X-Requested-With' => 'XMLHttpRequest',
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
],
'body' => $payload,
] );
if ( is_wp_error( $resp ) ) {
return [ 'ok' => false, 'error' => $resp->get_error_message() ];
}
$body = wp_remote_retrieve_body( $resp );
$data = json_decode( $body, true );
// Return JSON if we got JSON
if ( is_array( $data ) ) {
// The calculator usually returns { cost: "123" } or fragments.
if ( isset( $data['cost'] ) ) {
return [ 'ok' => true, 'cost' => (float) preg_replace('/[^0-9.]/', '', (string) $data['cost'] ) ];
}
if ( isset( $data['cost_html'] ) ) {
return [ 'ok' => true, 'cost_html' => (string) $data['cost_html'] ];
}
return [ 'ok' => false, 'error' => 'No cost returned', 'raw' => $data ];
}
// Fallback: try to parse a number from HTML/text
$plain = trim( preg_replace( '/\s+/', ' ', wp_strip_all_tags( (string) $body ) ) );
if ( preg_match( '/([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]+)?|[0-9]+(?:\.[0-9]+)?)/', $plain, $m ) ) {
$num = (float) str_replace( ',', '', $m[1] );
return [ 'ok' => true, 'cost' => $num ];
}
return [ 'ok' => false, 'error' => 'Unable to parse cost' ];
},
]);
});
Featured
Lari sekejap dari kesibukan kota dan rasai pengalaman camping santai dan menenangkan tepi sungai di Deruan Rimba Campsite (DRC)!*
Terletak bersebelahan Air Terjun Sungai Gabai, Hulu Langat, DRC menawarkan suasana alam semula jadi yang sukar ditandingi hanya sekitar 30 minit dari Kuala Lumpur, tetapi rasa seperti berada jauh di pedalaman hutan yang tenang.
Bangun pagi dengan udara sejuk tanah tinggi, bunyi deruan air sungai yang menenangkan dan kabus nipis yang menyelubungi kawasan campsite. Nikmati pemandangan matahari terbit yang memukau berlatarbelakangkan kehijauan Banjaran Titiwangsa.
Campsite ini turut dikelilingi dusun buah-buahan seperti Durian, Manggis dan banyak lagi! Pada musim buah, pengunjung berpeluang menikmati durian dan hasil segar terus dari kebun.
•Lokasi strategik & mudah diakses
•Suasana sejuk, nyaman & privasi terjaga
•Sesuai untuk family day, gathering, picnic
Slot hujung minggu cepat penuh! Tempah sekarang dan rasai sendiri pengalaman camping yang santai di Deruan Rimba Campsite.
Facilities
Amenities
Everything you need for a comfortable stay.
Outside: free
Subcribe now to receive offers
Contact Us
Deruan Rimba Campsite, Jalan Sungai Gabai, 43100 Hulu Langat, Selangor
Phone : +60196552630
Email : deruanrimbaofficial@gmail.com