true, 'strategy' => 'defer', ) ); add_shortcode( 'medivot_booking', array( __CLASS__, 'booking_shortcode' ) ); add_shortcode( 'medivot_form', array( __CLASS__, 'form_shortcode' ) ); register_block_type( MEDIVOT_PLUGIN_DIR . 'blocks/booking', array( 'render_callback' => array( __CLASS__, 'render_booking_block' ) ) ); register_block_type( MEDIVOT_PLUGIN_DIR . 'blocks/form', array( 'render_callback' => array( __CLASS__, 'render_form_block' ) ) ); } /** * [medivot_booking event="intro-call" text="Book a call" workspace="" new_tab="yes" align="" style="button"] * * @param array|string $atts Shortcode attributes. * @return string */ public static function booking_shortcode( $atts ) { $atts = shortcode_atts( array( 'event' => '', 'workspace' => '', 'text' => '', 'new_tab' => 'yes', 'align' => '', 'style' => 'button', ), $atts, 'medivot_booking' ); $classes = array( 'medivot-booking' ); if ( in_array( $atts['align'], array( 'left', 'center', 'right' ), true ) ) { $classes[] = 'medivot-align-' . $atts['align']; } return self::booking_markup( array( 'event' => $atts['event'], 'workspace' => $atts['workspace'], 'text' => $atts['text'], 'new_tab' => self::truthy( $atts['new_tab'] ), 'appearance' => $atts['style'], ), 'class="' . esc_attr( implode( ' ', $classes ) ) . '"' ); } /** * Block render callback for medivot/booking-button. * * @param array $attributes Block attributes. * @return string */ public static function render_booking_block( $attributes ) { $attributes = is_array( $attributes ) ? $attributes : array(); $alignment = isset( $attributes['alignment'] ) ? (string) $attributes['alignment'] : ''; $extra = array( 'class' => 'medivot-booking' ); if ( in_array( $alignment, array( 'left', 'center', 'right' ), true ) ) { $extra['class'] .= ' medivot-align-' . $alignment; } return self::booking_markup( array( 'event' => isset( $attributes['eventSlug'] ) ? $attributes['eventSlug'] : '', 'workspace' => isset( $attributes['workspace'] ) ? $attributes['workspace'] : '', 'text' => isset( $attributes['label'] ) ? $attributes['label'] : '', 'new_tab' => ! isset( $attributes['newTab'] ) || (bool) $attributes['newTab'], 'appearance' => isset( $attributes['appearance'] ) ? $attributes['appearance'] : 'button', ), get_block_wrapper_attributes( $extra ) ); } /** * Booking button HTML. * * @param array $args event, workspace, text, new_tab, appearance. * @param string $wrapper_attrs Escaped attributes for the wrapping div. * @return string */ public static function booking_markup( $args, $wrapper_attrs ) { // "event" may be an event slug, "handle/event", or a booking link // (https://medivot.com/book/handle or .../book/handle/event). $raw_event = is_scalar( $args['event'] ) ? (string) $args['event'] : ''; $event_parts = Medivot_Plugin::slugs_from( $raw_event, 'book' ); $workspace = Medivot_Plugin::slugs_from( $args['workspace'], 'book' ); $handle = isset( $workspace[0] ) ? $workspace[0] : ''; $event = ''; if ( preg_match( '#(^|/)book/#', $raw_event ) || count( $event_parts ) >= 2 ) { if ( '' === $handle && isset( $event_parts[0] ) ) { $handle = $event_parts[0]; } $event = isset( $event_parts[1] ) ? $event_parts[1] : ''; } elseif ( isset( $event_parts[0] ) ) { $event = $event_parts[0]; } if ( '' === $handle ) { $handle = Medivot_Plugin::booking_handle(); } if ( '' === $handle ) { return self::editor_hint( __( 'Medivot booking button: add your booking page handle under Settings > Medivot.', 'medivot' ) ); } $url = Medivot_Plugin::app_url() . '/book/' . rawurlencode( $handle ); if ( '' !== $event ) { $url .= '/' . rawurlencode( $event ); } $text = is_scalar( $args['text'] ) ? trim( wp_strip_all_tags( (string) $args['text'] ) ) : ''; if ( '' === $text ) { $text = __( 'Book a meeting', 'medivot' ); } $link_class = 'link' === $args['appearance'] ? 'medivot-booking__link' : 'medivot-booking__button wp-element-button'; $target = ''; $new_tab_sr = ''; if ( $args['new_tab'] ) { $target = ' target="_blank" rel="noopener"'; $new_tab_sr = ' ' . esc_html__( '(opens in a new tab)', 'medivot' ) . ''; } wp_enqueue_style( self::STYLE ); return sprintf( '
%5$s%6$s
', $wrapper_attrs, esc_attr( $link_class ), esc_url( $url ), $target, esc_html( $text ), $new_tab_sr ); } /** * [medivot_form form="contact-us" height="650" title="Contact us" fallback="yes"] * Aliases for form: slug, id, url. * * @param array|string $atts Shortcode attributes. * @return string */ public static function form_shortcode( $atts ) { $atts = shortcode_atts( array( 'form' => '', 'slug' => '', 'id' => '', 'url' => '', 'height' => '650', 'title' => '', 'fallback' => 'yes', ), $atts, 'medivot_form' ); $form = ''; foreach ( array( 'form', 'slug', 'id', 'url' ) as $key ) { if ( '' !== trim( (string) $atts[ $key ] ) ) { $form = $atts[ $key ]; break; } } return self::form_markup( array( 'form' => $form, 'height' => $atts['height'], 'title' => $atts['title'], 'fallback' => self::truthy( $atts['fallback'] ), ), 'class="medivot-form"' ); } /** * Block render callback for medivot/form. * * @param array $attributes Block attributes. * @return string */ public static function render_form_block( $attributes ) { $attributes = is_array( $attributes ) ? $attributes : array(); return self::form_markup( array( 'form' => isset( $attributes['form'] ) ? $attributes['form'] : '', 'height' => isset( $attributes['height'] ) ? $attributes['height'] : 650, 'title' => isset( $attributes['title'] ) ? $attributes['title'] : '', 'fallback' => ! isset( $attributes['showFallback'] ) || (bool) $attributes['showFallback'], ), get_block_wrapper_attributes( array( 'class' => 'medivot-form' ) ) ); } /** * Webform iframe HTML. * * @param array $args form, height, title, fallback. * @param string $wrapper_attrs Escaped attributes for the wrapping div. * @return string */ public static function form_markup( $args, $wrapper_attrs ) { // Accept a slug, a form ID or the public link (https://medivot.com/forms/{slug}). $parts = Medivot_Plugin::slugs_from( $args['form'], 'forms' ); $form = isset( $parts[0] ) ? $parts[0] : ''; if ( '' === $form ) { return self::editor_hint( __( 'Medivot form: choose which form to show (its slug, ID or public link).', 'medivot' ) ); } $height = is_numeric( $args['height'] ) ? (int) $args['height'] : 650; $height = max( 200, min( 3000, $height ) ); $title = is_scalar( $args['title'] ) ? trim( wp_strip_all_tags( (string) $args['title'] ) ) : ''; if ( '' === $title ) { $title = __( 'Contact form', 'medivot' ); } $url = Medivot_Plugin::app_url() . '/forms/' . rawurlencode( $form ); wp_enqueue_style( self::STYLE ); wp_enqueue_script( self::FORMS_SCRIPT ); $html = '
'; $html .= sprintf( '', esc_url( $url ), esc_attr( $title ), $height ); if ( $args['fallback'] ) { $html .= sprintf( '

%2$s %3$s

', esc_url( $url ), esc_html__( 'Open the form in a new tab', 'medivot' ), esc_html__( '(opens in a new tab)', 'medivot' ) ); } $html .= '
'; return $html; } /** * REST route the block editor uses to list event types. */ public static function register_rest_routes() { register_rest_route( 'medivot/v1', '/event-types', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( __CLASS__, 'rest_event_types' ), 'permission_callback' => array( __CLASS__, 'can_edit' ), ) ); } /** * Only people who can edit posts may read the editor data. * * @return bool */ public static function can_edit() { return current_user_can( 'edit_posts' ); } /** * GET /wp-json/medivot/v1/event-types * * @return WP_REST_Response */ public static function rest_event_types() { $data = array( 'connected' => false, 'handle' => Medivot_Plugin::booking_handle(), 'items' => array(), 'message' => '', ); $api_key = (string) Medivot_Plugin::get( 'api_key' ); if ( '' === $api_key ) { return rest_ensure_response( $data ); } $data['connected'] = true; $items = get_transient( Medivot_Plugin::EVENT_TYPES_TRANSIENT ); if ( ! is_array( $items ) ) { $items = Medivot_Api::event_types( $api_key ); if ( is_wp_error( $items ) ) { $data['message'] = $items->get_error_message(); return rest_ensure_response( $data ); } set_transient( Medivot_Plugin::EVENT_TYPES_TRANSIENT, $items, 5 * MINUTE_IN_SECONDS ); } $data['items'] = $items; return rest_ensure_response( $data ); } /** * A setup hint shown only to people who can edit the page; visitors see nothing. * * @param string $message Hint text. * @return string */ private static function editor_hint( $message ) { if ( ! current_user_can( 'edit_posts' ) ) { return ''; } wp_enqueue_style( self::STYLE ); return '

' . esc_html( $message ) . '

'; } /** * Interpret yes/no style shortcode values. * * @param mixed $value Attribute value. * @return bool */ private static function truthy( $value ) { return in_array( strtolower( trim( (string) $value ) ), array( '1', 'yes', 'true', 'on' ), true ); } }