_x( 'Guests', 'post type general name', 'wp-bnb' ), 'singular_name' => _x( 'Guest', 'post type singular name', 'wp-bnb' ), 'menu_name' => _x( 'Guests', 'admin menu', 'wp-bnb' ), 'name_admin_bar' => _x( 'Guest', 'add new on admin bar', 'wp-bnb' ), 'add_new' => _x( 'Add New', 'guest', 'wp-bnb' ), 'add_new_item' => __( 'Add New Guest', 'wp-bnb' ), 'new_item' => __( 'New Guest', 'wp-bnb' ), 'edit_item' => __( 'Edit Guest', 'wp-bnb' ), 'view_item' => __( 'View Guest', 'wp-bnb' ), 'all_items' => __( 'Guests', 'wp-bnb' ), 'search_items' => __( 'Search Guests', 'wp-bnb' ), 'parent_item_colon' => __( 'Parent Guests:', 'wp-bnb' ), 'not_found' => __( 'No guests found.', 'wp-bnb' ), 'not_found_in_trash' => __( 'No guests found in Trash.', 'wp-bnb' ), 'archives' => __( 'Guest archives', 'wp-bnb' ), 'insert_into_item' => __( 'Insert into guest', 'wp-bnb' ), 'uploaded_to_this_item' => __( 'Uploaded to this guest', 'wp-bnb' ), 'filter_items_list' => __( 'Filter guests list', 'wp-bnb' ), 'items_list_navigation' => __( 'Guests list navigation', 'wp-bnb' ), 'items_list' => __( 'Guests list', 'wp-bnb' ), ); $args = array( 'labels' => $labels, 'public' => false, 'publicly_queryable' => false, 'show_ui' => true, 'show_in_menu' => 'wp-bnb', 'query_var' => false, 'rewrite' => false, 'capability_type' => 'post', 'has_archive' => false, 'hierarchical' => false, 'menu_position' => null, 'menu_icon' => 'dashicons-groups', 'supports' => array( 'title', 'revisions', ), 'show_in_rest' => true, 'rest_base' => 'guests', 'rest_controller_class' => 'WP_REST_Posts_Controller', ); register_post_type( self::POST_TYPE, $args ); } /** * Add meta boxes. * * @return void */ public static function add_meta_boxes(): void { add_meta_box( 'bnb_guest_personal', __( 'Personal Information', 'wp-bnb' ), array( self::class, 'render_personal_meta_box' ), self::POST_TYPE, 'normal', 'high' ); add_meta_box( 'bnb_guest_address', __( 'Address', 'wp-bnb' ), array( self::class, 'render_address_meta_box' ), self::POST_TYPE, 'normal', 'high' ); add_meta_box( 'bnb_guest_identification', __( 'Identification', 'wp-bnb' ), array( self::class, 'render_identification_meta_box' ), self::POST_TYPE, 'normal', 'default' ); add_meta_box( 'bnb_guest_consent', __( 'Consent & Privacy', 'wp-bnb' ), array( self::class, 'render_consent_meta_box' ), self::POST_TYPE, 'side', 'high' ); add_meta_box( 'bnb_guest_bookings', __( 'Booking History', 'wp-bnb' ), array( self::class, 'render_bookings_meta_box' ), self::POST_TYPE, 'normal', 'default' ); add_meta_box( 'bnb_guest_status', __( 'Status & Notes', 'wp-bnb' ), array( self::class, 'render_status_meta_box' ), self::POST_TYPE, 'side', 'default' ); } /** * Render personal information meta box. * * @param \WP_Post $post Current post object. * @return void */ public static function render_personal_meta_box( \WP_Post $post ): void { wp_nonce_field( 'bnb_guest_meta', 'bnb_guest_meta_nonce' ); $first_name = get_post_meta( $post->ID, self::META_PREFIX . 'first_name', true ); $last_name = get_post_meta( $post->ID, self::META_PREFIX . 'last_name', true ); $email = get_post_meta( $post->ID, self::META_PREFIX . 'email', true ); $phone = get_post_meta( $post->ID, self::META_PREFIX . 'phone', true ); $date_of_birth = get_post_meta( $post->ID, self::META_PREFIX . 'date_of_birth', true ); $nationality = get_post_meta( $post->ID, self::META_PREFIX . 'nationality', true ); ?>
' . esc_html__( 'No bookings found for this guest.', 'wp-bnb' ) . '
'; return; } ?>| ID ); ?> | post_title : '—' ); ?> |
post_title !== $full_name ) { remove_action( 'save_post_' . self::POST_TYPE, array( self::class, 'save_meta' ), 10 ); wp_update_post( array( 'ID' => $post_id, 'post_title' => $full_name, ) ); add_action( 'save_post_' . self::POST_TYPE, array( self::class, 'save_meta' ), 10, 2 ); } } } /** * Add custom columns to the post list. * * @param array $columns Existing columns. * @return array */ public static function add_columns( array $columns ): array { $new_columns = array(); foreach ( $columns as $key => $value ) { $new_columns[ $key ] = $value; if ( 'title' === $key ) { $new_columns['email'] = __( 'Email', 'wp-bnb' ); $new_columns['phone'] = __( 'Phone', 'wp-bnb' ); $new_columns['country'] = __( 'Country', 'wp-bnb' ); $new_columns['bookings'] = __( 'Bookings', 'wp-bnb' ); $new_columns['status'] = __( 'Status', 'wp-bnb' ); } } // Remove default date column. unset( $new_columns['date'] ); return $new_columns; } /** * Render custom column content. * * @param string $column Column name. * @param int $post_id Post ID. * @return void */ public static function render_column( string $column, int $post_id ): void { switch ( $column ) { case 'email': $email = get_post_meta( $post_id, self::META_PREFIX . 'email', true ); if ( $email ) { printf( '%s', esc_attr( $email ), esc_html( $email ) ); } else { echo '—'; } break; case 'phone': $phone = get_post_meta( $post_id, self::META_PREFIX . 'phone', true ); echo esc_html( $phone ?: '—' ); break; case 'country': $country = get_post_meta( $post_id, self::META_PREFIX . 'country', true ); if ( $country ) { $countries = Building::get_countries(); echo esc_html( $countries[ $country ] ?? $country ); } else { echo '—'; } break; case 'bookings': $count = self::get_booking_count( $post_id ); if ( $count > 0 ) { printf( '%s', esc_url( admin_url( 'edit.php?post_type=' . Booking::POST_TYPE . '&guest_id=' . $post_id ) ), esc_html( sprintf( /* translators: %d: Number of bookings */ _n( '%d booking', '%d bookings', $count, 'wp-bnb' ), $count ) ) ); } else { echo '—'; } break; case 'status': $status = get_post_meta( $post_id, self::META_PREFIX . 'status', true ) ?: 'active'; $colors = self::get_status_colors(); $statuses = self::get_statuses(); printf( '%s', esc_attr( $colors[ $status ] ?? '#999' ), esc_html( $statuses[ $status ] ?? $status ) ); break; } } /** * Add sortable columns. * * @param array $columns Existing sortable columns. * @return array */ public static function sortable_columns( array $columns ): array { $columns['email'] = 'email'; $columns['country'] = 'country'; $columns['status'] = 'status'; return $columns; } /** * Add filter dropdowns to admin list. * * @param string $post_type Current post type. * @return void */ public static function add_filters( string $post_type ): void { if ( self::POST_TYPE !== $post_type ) { return; } // Status filter. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter display only. $selected_status = isset( $_GET['guest_status'] ) ? sanitize_text_field( wp_unslash( $_GET['guest_status'] ) ) : ''; ?> is_main_query() ) { return; } if ( self::POST_TYPE !== $query->get( 'post_type' ) ) { return; } $meta_query = array(); // Status filter. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter query only. if ( ! empty( $_GET['guest_status'] ) ) { $meta_query[] = array( 'key' => self::META_PREFIX . 'status', 'value' => sanitize_text_field( wp_unslash( $_GET['guest_status'] ) ), ); } // Country filter. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Filter query only. if ( ! empty( $_GET['guest_country'] ) ) { $meta_query[] = array( 'key' => self::META_PREFIX . 'country', 'value' => sanitize_text_field( wp_unslash( $_GET['guest_country'] ) ), ); } if ( ! empty( $meta_query ) ) { $meta_query['relation'] = 'AND'; $query->set( 'meta_query', $meta_query ); } // Handle orderby for custom columns. $orderby = $query->get( 'orderby' ); if ( 'email' === $orderby ) { $query->set( 'meta_key', self::META_PREFIX . 'email' ); $query->set( 'orderby', 'meta_value' ); } elseif ( 'country' === $orderby ) { $query->set( 'meta_key', self::META_PREFIX . 'country' ); $query->set( 'orderby', 'meta_value' ); } elseif ( 'status' === $orderby ) { $query->set( 'meta_key', self::META_PREFIX . 'status' ); $query->set( 'orderby', 'meta_value' ); } } /** * Change title placeholder. * * @param string $placeholder Default placeholder. * @param \WP_Post $post Current post. * @return string */ public static function change_title_placeholder( string $placeholder, \WP_Post $post ): string { if ( self::POST_TYPE === $post->post_type ) { return __( 'Guest name (auto-generated from first/last name)', 'wp-bnb' ); } return $placeholder; } /** * Get guest statuses. * * @return array