All checks were successful
Create Release Package / build-release (push) Successful in 1m20s
- Room search with availability, capacity, room type, amenity, price range, and building filters - AJAX-powered search with pagination and load more - Shortcodes: [bnb_buildings], [bnb_rooms], [bnb_room_search], [bnb_building], [bnb_room] - Widgets: Similar Rooms, Building Rooms, Availability Calendar - Gutenberg blocks: Building, Room, Room Search, Buildings List, Rooms List - Frontend CSS with responsive design and CSS custom properties - Frontend JavaScript with SearchForm, CalendarWidget, AvailabilityForm, PriceCalculator Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
262 lines
9.2 KiB
PHP
262 lines
9.2 KiB
PHP
<?php
|
|
/**
|
|
* Building Rooms widget.
|
|
*
|
|
* Displays all rooms in a specific building.
|
|
*
|
|
* @package Magdev\WpBnb\Frontend\Widgets
|
|
*/
|
|
|
|
declare( strict_types=1 );
|
|
|
|
namespace Magdev\WpBnb\Frontend\Widgets;
|
|
|
|
use Magdev\WpBnb\Frontend\Search;
|
|
use Magdev\WpBnb\PostTypes\Building;
|
|
use Magdev\WpBnb\PostTypes\Room;
|
|
|
|
/**
|
|
* Building Rooms widget class.
|
|
*/
|
|
class BuildingRooms extends \WP_Widget {
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct() {
|
|
parent::__construct(
|
|
'wp_bnb_building_rooms',
|
|
__( 'WP BnB: Building Rooms', 'wp-bnb' ),
|
|
array(
|
|
'classname' => 'wp-bnb-widget-building-rooms',
|
|
'description' => __( 'Display all rooms in a building.', 'wp-bnb' ),
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Output the widget content.
|
|
*
|
|
* @param array $args Widget arguments.
|
|
* @param array $instance Widget instance settings.
|
|
* @return void
|
|
*/
|
|
public function widget( $args, $instance ): void {
|
|
$title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Rooms', 'wp-bnb' );
|
|
$building_id = ! empty( $instance['building_id'] ) ? (int) $instance['building_id'] : 0;
|
|
$count = ! empty( $instance['count'] ) ? (int) $instance['count'] : -1;
|
|
$show_availability = ! empty( $instance['show_availability'] );
|
|
$show_price = ! empty( $instance['show_price'] );
|
|
$layout = ! empty( $instance['layout'] ) ? $instance['layout'] : 'list';
|
|
|
|
// Auto-detect building from single building page.
|
|
if ( ! $building_id && is_singular( Building::POST_TYPE ) ) {
|
|
$building_id = get_the_ID();
|
|
}
|
|
|
|
if ( ! $building_id ) {
|
|
return;
|
|
}
|
|
|
|
// Get rooms for building.
|
|
$search_args = array(
|
|
'building_id' => $building_id,
|
|
'limit' => $count,
|
|
'orderby' => 'title',
|
|
'order' => 'ASC',
|
|
);
|
|
|
|
$rooms = Search::search( $search_args );
|
|
|
|
if ( empty( $rooms ) ) {
|
|
return;
|
|
}
|
|
|
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
|
|
if ( $title ) {
|
|
echo $args['before_title'] . esc_html( apply_filters( 'widget_title', $title ) ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
$list_class = 'compact' === $layout ? 'wp-bnb-building-rooms-compact' : 'wp-bnb-building-rooms-list';
|
|
echo '<ul class="' . esc_attr( $list_class ) . '">';
|
|
|
|
foreach ( $rooms as $room ) {
|
|
$status = get_post_meta( $room['id'], '_bnb_room_status', true ) ?: 'available';
|
|
?>
|
|
<li class="wp-bnb-building-room">
|
|
<a href="<?php echo esc_url( $room['permalink'] ); ?>" class="wp-bnb-building-room-link">
|
|
<span class="wp-bnb-building-room-title"><?php echo esc_html( $room['title'] ); ?></span>
|
|
|
|
<?php if ( ! empty( $room['room_number'] ) ) : ?>
|
|
<span class="wp-bnb-building-room-number">#<?php echo esc_html( $room['room_number'] ); ?></span>
|
|
<?php endif; ?>
|
|
|
|
<?php if ( $show_availability ) : ?>
|
|
<span class="wp-bnb-building-room-status wp-bnb-status-<?php echo esc_attr( $status ); ?>">
|
|
<?php
|
|
$statuses = Room::get_room_statuses();
|
|
echo esc_html( $statuses[ $status ] ?? $status );
|
|
?>
|
|
</span>
|
|
<?php endif; ?>
|
|
|
|
<?php if ( $show_price && ! empty( $room['price_formatted'] ) ) : ?>
|
|
<span class="wp-bnb-building-room-price">
|
|
<?php echo esc_html( $room['price_formatted'] ); ?>
|
|
</span>
|
|
<?php endif; ?>
|
|
</a>
|
|
|
|
<?php if ( 'list' === $layout ) : ?>
|
|
<div class="wp-bnb-building-room-meta">
|
|
<?php if ( ! empty( $room['capacity'] ) ) : ?>
|
|
<span class="wp-bnb-meta-item">
|
|
<span class="dashicons dashicons-groups"></span>
|
|
<?php echo esc_html( $room['capacity'] ); ?>
|
|
</span>
|
|
<?php endif; ?>
|
|
|
|
<?php if ( ! empty( $room['room_types'] ) ) : ?>
|
|
<span class="wp-bnb-meta-item">
|
|
<?php echo esc_html( $room['room_types'][0] ); ?>
|
|
</span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</li>
|
|
<?php
|
|
}
|
|
|
|
echo '</ul>';
|
|
|
|
// Show view all link if there are more rooms.
|
|
$building = get_post( $building_id );
|
|
if ( $building && $count > 0 && count( $rooms ) >= $count ) {
|
|
$all_rooms = Room::get_rooms_for_building( $building_id );
|
|
if ( count( $all_rooms ) > $count ) {
|
|
printf(
|
|
'<a href="%s" class="wp-bnb-view-all-rooms">%s</a>',
|
|
esc_url( get_permalink( $building_id ) ),
|
|
esc_html__( 'View all rooms', 'wp-bnb' )
|
|
);
|
|
}
|
|
}
|
|
|
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
/**
|
|
* Output the widget settings form.
|
|
*
|
|
* @param array $instance Current widget instance settings.
|
|
* @return void
|
|
*/
|
|
public function form( $instance ): void {
|
|
$title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Rooms', 'wp-bnb' );
|
|
$building_id = ! empty( $instance['building_id'] ) ? (int) $instance['building_id'] : 0;
|
|
$count = ! empty( $instance['count'] ) ? (int) $instance['count'] : -1;
|
|
$show_availability = ! empty( $instance['show_availability'] );
|
|
$show_price = ! empty( $instance['show_price'] );
|
|
$layout = ! empty( $instance['layout'] ) ? $instance['layout'] : 'list';
|
|
|
|
// Get all buildings.
|
|
$buildings = get_posts(
|
|
array(
|
|
'post_type' => Building::POST_TYPE,
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'orderby' => 'title',
|
|
'order' => 'ASC',
|
|
)
|
|
);
|
|
?>
|
|
<p>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
|
|
<?php esc_html_e( 'Title:', 'wp-bnb' ); ?>
|
|
</label>
|
|
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
|
|
type="text" value="<?php echo esc_attr( $title ); ?>">
|
|
</p>
|
|
|
|
<p>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'building_id' ) ); ?>">
|
|
<?php esc_html_e( 'Building:', 'wp-bnb' ); ?>
|
|
</label>
|
|
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'building_id' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'building_id' ) ); ?>">
|
|
<option value="0"><?php esc_html_e( '— Auto-detect from page —', 'wp-bnb' ); ?></option>
|
|
<?php foreach ( $buildings as $building ) : ?>
|
|
<option value="<?php echo esc_attr( $building->ID ); ?>" <?php selected( $building_id, $building->ID ); ?>>
|
|
<?php echo esc_html( $building->post_title ); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<small><?php esc_html_e( 'Leave as auto-detect to show rooms of the current building page.', 'wp-bnb' ); ?></small>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>">
|
|
<?php esc_html_e( 'Number of rooms:', 'wp-bnb' ); ?>
|
|
</label>
|
|
<input class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'count' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'count' ) ); ?>"
|
|
type="number" min="-1" max="50" value="<?php echo esc_attr( $count ); ?>">
|
|
<small><?php esc_html_e( '-1 for all rooms', 'wp-bnb' ); ?></small>
|
|
</p>
|
|
|
|
<p>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>">
|
|
<?php esc_html_e( 'Layout:', 'wp-bnb' ); ?>
|
|
</label>
|
|
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'layout' ) ); ?>">
|
|
<option value="list" <?php selected( $layout, 'list' ); ?>>
|
|
<?php esc_html_e( 'List (with details)', 'wp-bnb' ); ?>
|
|
</option>
|
|
<option value="compact" <?php selected( $layout, 'compact' ); ?>>
|
|
<?php esc_html_e( 'Compact', 'wp-bnb' ); ?>
|
|
</option>
|
|
</select>
|
|
</p>
|
|
|
|
<p>
|
|
<input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_availability' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'show_availability' ) ); ?>"
|
|
<?php checked( $show_availability ); ?>>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'show_availability' ) ); ?>">
|
|
<?php esc_html_e( 'Show availability status', 'wp-bnb' ); ?>
|
|
</label>
|
|
</p>
|
|
|
|
<p>
|
|
<input class="checkbox" type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_price' ) ); ?>"
|
|
name="<?php echo esc_attr( $this->get_field_name( 'show_price' ) ); ?>"
|
|
<?php checked( $show_price ); ?>>
|
|
<label for="<?php echo esc_attr( $this->get_field_id( 'show_price' ) ); ?>">
|
|
<?php esc_html_e( 'Show price', 'wp-bnb' ); ?>
|
|
</label>
|
|
</p>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Update widget settings.
|
|
*
|
|
* @param array $new_instance New settings.
|
|
* @param array $old_instance Old settings.
|
|
* @return array Updated settings.
|
|
*/
|
|
public function update( $new_instance, $old_instance ): array {
|
|
$instance = array();
|
|
$instance['title'] = ! empty( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '';
|
|
$instance['building_id'] = ! empty( $new_instance['building_id'] ) ? absint( $new_instance['building_id'] ) : 0;
|
|
$instance['count'] = isset( $new_instance['count'] ) ? (int) $new_instance['count'] : -1;
|
|
$instance['show_availability'] = ! empty( $new_instance['show_availability'] );
|
|
$instance['show_price'] = ! empty( $new_instance['show_price'] );
|
|
$instance['layout'] = ! empty( $new_instance['layout'] ) ? sanitize_text_field( $new_instance['layout'] ) : 'list';
|
|
return $instance;
|
|
}
|
|
}
|