__( 'Booking', 'abogo-booking' ),
'target' => 'abfw_product_data',
'class' => array(),
'priority' => 65,
);
return $tabs;
}
/**
* Print the panel.
*
* @since 1.0.0
*/
public function render_panel() {
global $post;
$product_id = $post ? (int) $post->ID : 0;
echo '
';
woocommerce_wp_checkbox(
array(
'id' => '_abfw_bookable',
'label' => __( 'Bookable', 'abogo-booking' ),
'description' => __( 'Customers choose their dates before adding this product to the cart.', 'abogo-booking' ),
'desc_tip' => true,
'value' => Settings::is_bookable( $product_id ) ? 'yes' : 'no',
)
);
woocommerce_wp_select(
array(
'id' => '_abfw_dates',
'label' => __( 'Dates to choose', 'abogo-booking' ),
'options' => array(
'' => __( 'Same as the shop', 'abogo-booking' ),
'one' => __( 'One date', 'abogo-booking' ),
'two' => __( 'Arrival and departure', 'abogo-booking' ),
),
'value' => get_post_meta( $product_id, '_abfw_dates', true ),
)
);
woocommerce_wp_select(
array(
'id' => '_abfw_mode',
'label' => __( 'Charged by', 'abogo-booking' ),
'options' => array(
'' => __( 'Same as the shop', 'abogo-booking' ),
'nights' => __( 'Night', 'abogo-booking' ),
'days' => __( 'Day', 'abogo-booking' ),
),
'value' => get_post_meta( $product_id, '_abfw_mode', true ),
)
);
$this->number_field( '_abfw_duration', __( 'Booking duration', 'abogo-booking' ), __( 'Nights or days booked together, for example 7 for a week.', 'abogo-booking' ), $product_id );
$this->number_field( '_abfw_min', __( 'Minimum duration', 'abogo-booking' ), __( 'Fewest booking durations a customer can take. 0 for no minimum.', 'abogo-booking' ), $product_id );
$this->number_field( '_abfw_max', __( 'Maximum duration', 'abogo-booking' ), __( 'Most booking durations a customer can take. 0 for no maximum.', 'abogo-booking' ), $product_id );
$this->number_field( '_abfw_first', __( 'First available date', 'abogo-booking' ), __( 'Days from today. 0 for today.', 'abogo-booking' ), $product_id );
$this->number_field( '_abfw_last', __( 'Last available date', 'abogo-booking' ), __( 'Days from today. 0 for no limit.', 'abogo-booking' ), $product_id );
/**
* Fires at the end of the Booking tab of a product, so an extension can add its rules.
*
* @since 1.1.0
* @param int $product_id Product being edited.
*/
do_action( 'abfw_product_panel', $product_id );
echo '
';
}
/**
* Save the panel.
*
* @since 1.0.0
* @param int $product_id Product being saved.
*/
public function save( $product_id ) {
// WooCommerce checked the nonce of the product screen before firing this.
// phpcs:disable WordPress.Security.NonceVerification.Missing
update_post_meta( $product_id, '_abfw_bookable', isset( $_POST['_abfw_bookable'] ) ? 'yes' : 'no' );
foreach ( array( '_abfw_dates', '_abfw_mode' ) as $key ) {
$value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
update_post_meta( $product_id, $key, $value );
}
foreach ( array( '_abfw_duration', '_abfw_min', '_abfw_max', '_abfw_first', '_abfw_last' ) as $key ) {
$raw = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';
$value = '' === $raw ? '' : max( 0, (int) $raw );
update_post_meta( $product_id, $key, $value );
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
}
/**
* Print one whole-number field that falls back to the shop when left empty.
*
* @since 1.0.0
* @param string $id Meta key.
* @param string $label Visible label.
* @param string $description Help text.
* @param int $product_id Product being edited.
*/
private function number_field( $id, $label, $description, $product_id ) {
woocommerce_wp_text_input(
array(
'id' => $id,
'label' => $label,
'description' => $description,
'desc_tip' => true,
'type' => 'number',
'placeholder' => __( 'Same as the shop', 'abogo-booking' ),
'custom_attributes' => array( 'min' => '0', 'step' => '1' ),
'value' => get_post_meta( $product_id, $id, true ),
)
);
}
}