Add frontend features with search, shortcodes, widgets, and blocks (v0.6.0)
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>
This commit is contained in:
2026-02-02 14:08:11 +01:00
parent 05f24fdec7
commit 864b8b2869
14 changed files with 5573 additions and 19 deletions

View File

@@ -0,0 +1,465 @@
<?php
/**
* Block registrar.
*
* Handles registration of all Gutenberg blocks.
*
* @package Magdev\WpBnb\Blocks
*/
declare( strict_types=1 );
namespace Magdev\WpBnb\Blocks;
use Magdev\WpBnb\Frontend\Search;
use Magdev\WpBnb\Frontend\Shortcodes;
use Magdev\WpBnb\PostTypes\Building;
use Magdev\WpBnb\PostTypes\Room;
/**
* Block registrar class.
*/
final class BlockRegistrar {
/**
* Initialize block registration.
*
* @return void
*/
public static function init(): void {
add_action( 'init', array( self::class, 'register_blocks' ) );
add_action( 'enqueue_block_editor_assets', array( self::class, 'enqueue_editor_assets' ) );
}
/**
* Register all blocks.
*
* @return void
*/
public static function register_blocks(): void {
// Building block.
register_block_type(
'wp-bnb/building',
array(
'attributes' => array(
'buildingId' => array(
'type' => 'number',
'default' => 0,
),
'showImage' => array(
'type' => 'boolean',
'default' => true,
),
'showAddress' => array(
'type' => 'boolean',
'default' => true,
),
'showRooms' => array(
'type' => 'boolean',
'default' => true,
),
'showContact' => array(
'type' => 'boolean',
'default' => true,
),
),
'render_callback' => array( self::class, 'render_building_block' ),
'editor_script' => 'wp-bnb-blocks-editor',
)
);
// Room block.
register_block_type(
'wp-bnb/room',
array(
'attributes' => array(
'roomId' => array(
'type' => 'number',
'default' => 0,
),
'showImage' => array(
'type' => 'boolean',
'default' => true,
),
'showGallery' => array(
'type' => 'boolean',
'default' => true,
),
'showPrice' => array(
'type' => 'boolean',
'default' => true,
),
'showAmenities' => array(
'type' => 'boolean',
'default' => true,
),
'showAvailability' => array(
'type' => 'boolean',
'default' => true,
),
),
'render_callback' => array( self::class, 'render_room_block' ),
'editor_script' => 'wp-bnb-blocks-editor',
)
);
// Room Search block.
register_block_type(
'wp-bnb/room-search',
array(
'attributes' => array(
'layout' => array(
'type' => 'string',
'default' => 'grid',
),
'columns' => array(
'type' => 'number',
'default' => 3,
),
'showDates' => array(
'type' => 'boolean',
'default' => true,
),
'showGuests' => array(
'type' => 'boolean',
'default' => true,
),
'showRoomType' => array(
'type' => 'boolean',
'default' => true,
),
'showAmenities' => array(
'type' => 'boolean',
'default' => true,
),
'showPriceRange' => array(
'type' => 'boolean',
'default' => true,
),
'showBuilding' => array(
'type' => 'boolean',
'default' => true,
),
'resultsPerPage' => array(
'type' => 'number',
'default' => 12,
),
),
'render_callback' => array( self::class, 'render_room_search_block' ),
'editor_script' => 'wp-bnb-blocks-editor',
)
);
// Buildings List block.
register_block_type(
'wp-bnb/buildings',
array(
'attributes' => array(
'layout' => array(
'type' => 'string',
'default' => 'grid',
),
'columns' => array(
'type' => 'number',
'default' => 3,
),
'limit' => array(
'type' => 'number',
'default' => -1,
),
'showImage' => array(
'type' => 'boolean',
'default' => true,
),
'showAddress' => array(
'type' => 'boolean',
'default' => true,
),
'showRoomsCount' => array(
'type' => 'boolean',
'default' => true,
),
),
'render_callback' => array( self::class, 'render_buildings_block' ),
'editor_script' => 'wp-bnb-blocks-editor',
)
);
// Rooms List block.
register_block_type(
'wp-bnb/rooms',
array(
'attributes' => array(
'layout' => array(
'type' => 'string',
'default' => 'grid',
),
'columns' => array(
'type' => 'number',
'default' => 3,
),
'limit' => array(
'type' => 'number',
'default' => 12,
),
'buildingId' => array(
'type' => 'number',
'default' => 0,
),
'roomType' => array(
'type' => 'string',
'default' => '',
),
'showImage' => array(
'type' => 'boolean',
'default' => true,
),
'showPrice' => array(
'type' => 'boolean',
'default' => true,
),
'showCapacity' => array(
'type' => 'boolean',
'default' => true,
),
'showAmenities' => array(
'type' => 'boolean',
'default' => true,
),
'showBuilding' => array(
'type' => 'boolean',
'default' => true,
),
),
'render_callback' => array( self::class, 'render_rooms_block' ),
'editor_script' => 'wp-bnb-blocks-editor',
)
);
}
/**
* Enqueue editor assets.
*
* @return void
*/
public static function enqueue_editor_assets(): void {
// Register the editor script.
wp_register_script(
'wp-bnb-blocks-editor',
WP_BNB_URL . 'assets/js/blocks-editor.js',
array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-data' ),
WP_BNB_VERSION,
true
);
// Get buildings and rooms for selectors.
$buildings = get_posts(
array(
'post_type' => Building::POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
)
);
$rooms = get_posts(
array(
'post_type' => Room::POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
)
);
$form_data = Search::get_search_form_data();
wp_localize_script(
'wp-bnb-blocks-editor',
'wpBnbBlocks',
array(
'buildings' => array_map(
function ( $building ) {
return array(
'value' => $building->ID,
'label' => $building->post_title,
);
},
$buildings
),
'rooms' => array_map(
function ( $room ) {
$building_id = get_post_meta( $room->ID, '_bnb_room_building_id', true );
$building = $building_id ? get_post( $building_id ) : null;
return array(
'value' => $room->ID,
'label' => $room->post_title,
'building' => $building ? $building->post_title : '',
);
},
$rooms
),
'roomTypes' => $form_data['room_types'],
'amenities' => $form_data['amenities'],
'i18n' => array(
'selectBuilding' => __( 'Select a building', 'wp-bnb' ),
'selectRoom' => __( 'Select a room', 'wp-bnb' ),
'noBuildings' => __( 'No buildings found. Create a building first.', 'wp-bnb' ),
'noRooms' => __( 'No rooms found. Create a room first.', 'wp-bnb' ),
'buildingBlock' => __( 'Building', 'wp-bnb' ),
'roomBlock' => __( 'Room', 'wp-bnb' ),
'roomSearchBlock' => __( 'Room Search', 'wp-bnb' ),
'buildingsBlock' => __( 'Buildings List', 'wp-bnb' ),
'roomsBlock' => __( 'Rooms List', 'wp-bnb' ),
'displaySettings' => __( 'Display Settings', 'wp-bnb' ),
'filterSettings' => __( 'Filter Settings', 'wp-bnb' ),
'layout' => __( 'Layout', 'wp-bnb' ),
'grid' => __( 'Grid', 'wp-bnb' ),
'list' => __( 'List', 'wp-bnb' ),
'columns' => __( 'Columns', 'wp-bnb' ),
'limit' => __( 'Limit', 'wp-bnb' ),
'showImage' => __( 'Show image', 'wp-bnb' ),
'showAddress' => __( 'Show address', 'wp-bnb' ),
'showRooms' => __( 'Show rooms', 'wp-bnb' ),
'showRoomsCount' => __( 'Show rooms count', 'wp-bnb' ),
'showContact' => __( 'Show contact', 'wp-bnb' ),
'showGallery' => __( 'Show gallery', 'wp-bnb' ),
'showPrice' => __( 'Show price', 'wp-bnb' ),
'showAmenities' => __( 'Show amenities', 'wp-bnb' ),
'showAvailability' => __( 'Show availability', 'wp-bnb' ),
'showCapacity' => __( 'Show capacity', 'wp-bnb' ),
'showBuilding' => __( 'Show building', 'wp-bnb' ),
'showDates' => __( 'Show date filter', 'wp-bnb' ),
'showGuests' => __( 'Show guests filter', 'wp-bnb' ),
'showRoomType' => __( 'Show room type filter', 'wp-bnb' ),
'showPriceRange' => __( 'Show price range filter', 'wp-bnb' ),
'resultsPerPage' => __( 'Results per page', 'wp-bnb' ),
'roomType' => __( 'Room Type', 'wp-bnb' ),
'allTypes' => __( 'All Types', 'wp-bnb' ),
'allBuildings' => __( 'All Buildings', 'wp-bnb' ),
'previewPlaceholder' => __( 'Preview will appear here', 'wp-bnb' ),
),
)
);
// Editor styles.
wp_enqueue_style(
'wp-bnb-blocks-editor',
WP_BNB_URL . 'assets/css/blocks-editor.css',
array(),
WP_BNB_VERSION
);
}
/**
* Render building block.
*
* @param array $attributes Block attributes.
* @return string HTML output.
*/
public static function render_building_block( array $attributes ): string {
$building_id = $attributes['buildingId'] ?? 0;
if ( ! $building_id ) {
return '<p class="wp-bnb-block-placeholder">' . esc_html__( 'Please select a building.', 'wp-bnb' ) . '</p>';
}
return Shortcodes::render_single_building(
array(
'id' => $building_id,
'show_rooms' => ( $attributes['showRooms'] ?? true ) ? 'yes' : 'no',
'show_address' => ( $attributes['showAddress'] ?? true ) ? 'yes' : 'no',
'show_contact' => ( $attributes['showContact'] ?? true ) ? 'yes' : 'no',
)
);
}
/**
* Render room block.
*
* @param array $attributes Block attributes.
* @return string HTML output.
*/
public static function render_room_block( array $attributes ): string {
$room_id = $attributes['roomId'] ?? 0;
if ( ! $room_id ) {
return '<p class="wp-bnb-block-placeholder">' . esc_html__( 'Please select a room.', 'wp-bnb' ) . '</p>';
}
return Shortcodes::render_single_room(
array(
'id' => $room_id,
'show_gallery' => ( $attributes['showGallery'] ?? true ) ? 'yes' : 'no',
'show_pricing' => ( $attributes['showPrice'] ?? true ) ? 'yes' : 'no',
'show_amenities' => ( $attributes['showAmenities'] ?? true ) ? 'yes' : 'no',
'show_availability' => ( $attributes['showAvailability'] ?? true ) ? 'yes' : 'no',
)
);
}
/**
* Render room search block.
*
* @param array $attributes Block attributes.
* @return string HTML output.
*/
public static function render_room_search_block( array $attributes ): string {
return Shortcodes::render_room_search(
array(
'layout' => $attributes['layout'] ?? 'grid',
'columns' => $attributes['columns'] ?? 3,
'show_dates' => ( $attributes['showDates'] ?? true ) ? 'yes' : 'no',
'show_guests' => ( $attributes['showGuests'] ?? true ) ? 'yes' : 'no',
'show_room_type' => ( $attributes['showRoomType'] ?? true ) ? 'yes' : 'no',
'show_amenities' => ( $attributes['showAmenities'] ?? true ) ? 'yes' : 'no',
'show_price_range' => ( $attributes['showPriceRange'] ?? true ) ? 'yes' : 'no',
'show_building' => ( $attributes['showBuilding'] ?? true ) ? 'yes' : 'no',
'results_per_page' => $attributes['resultsPerPage'] ?? 12,
)
);
}
/**
* Render buildings list block.
*
* @param array $attributes Block attributes.
* @return string HTML output.
*/
public static function render_buildings_block( array $attributes ): string {
return Shortcodes::render_buildings(
array(
'layout' => $attributes['layout'] ?? 'grid',
'columns' => $attributes['columns'] ?? 3,
'limit' => $attributes['limit'] ?? -1,
'show_image' => ( $attributes['showImage'] ?? true ) ? 'yes' : 'no',
'show_address' => ( $attributes['showAddress'] ?? true ) ? 'yes' : 'no',
'show_rooms_count' => ( $attributes['showRoomsCount'] ?? true ) ? 'yes' : 'no',
)
);
}
/**
* Render rooms list block.
*
* @param array $attributes Block attributes.
* @return string HTML output.
*/
public static function render_rooms_block( array $attributes ): string {
return Shortcodes::render_rooms(
array(
'layout' => $attributes['layout'] ?? 'grid',
'columns' => $attributes['columns'] ?? 3,
'limit' => $attributes['limit'] ?? 12,
'building_id' => $attributes['buildingId'] ?? 0,
'room_type' => $attributes['roomType'] ?? '',
'show_image' => ( $attributes['showImage'] ?? true ) ? 'yes' : 'no',
'show_price' => ( $attributes['showPrice'] ?? true ) ? 'yes' : 'no',
'show_capacity' => ( $attributes['showCapacity'] ?? true ) ? 'yes' : 'no',
'show_amenities' => ( $attributes['showAmenities'] ?? true ) ? 'yes' : 'no',
'show_building' => ( $attributes['showBuilding'] ?? true ) ? 'yes' : 'no',
)
);
}
}