# booking-manager/2.0.2/core/wpbc/wpbm-bc-export.php

Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar, version 2.0.2. 382 lines.

- Page: https://pluginprobe.com/plugins/booking-manager/2.0.2/code/core/wpbc/wpbm-bc-export.php
- Raw: https://pluginprobe.com/plugins/booking-manager/2.0.2/raw/core/wpbc/wpbm-bc-export.php
- Modified: 2017-11-05T08:51:02+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/booking-manager/2.0.2/code/core/wpbc/wpbm-bc-export.php#L10-L20`.

```php
<?php 
/**
 * @version 1.0
 * @description Booking Calendar integration - Export
 * 
 * @author wpdevelop
 * @link http://oplugins.com/
 * @email info@oplugins.com
 *
 * @modified 2017-06-28
 */

if ( ! defined( 'ABSPATH' ) ) exit;                                             // Exit if accessed directly



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////				
// E X P O R T
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////	

/** Define ICS Feeds names
 * 
 *   wpbm-ics - Example of Feed Name.
 * 
 *   Have to  work  correctly immediately:		http://beta/?feed=wpbm-ics
 *   Nice looking link:							http://beta/feed/wpbm-ics		-- require to update permalink  structure at WordPress > Settings > Permalink Settings page by clicking  on "Save changes" button.
 *   Finally, to display your feed, you’ll first need to flush your WordPress rewrite rules. 
 *   The easiest way to do this is by logging in to the WordPress admin, and clicking Settings -> Permalinks. 
 *   Once here, just click Save Changes, which will flush the rewrite rules.
 *   
 *   Otherwsie need to run ONLY once this:
 * 
 *   global $wp_rewrite;
 *   $wp_rewrite->flush_rules();
 * 
 */
function wpbm_make_export_ics_feeds(){

	if ( function_exists( 'wp_parse_url' ) )
		$my_parsed_url = wp_parse_url( $_SERVER[ 'REQUEST_URI' ] );
	else
		$my_parsed_url = @parse_url( $_SERVER[ 'REQUEST_URI' ] );
	
	if ( false === $my_parsed_url ) {		// seriously malformed URLs, parse_url() may return FALSE. 
		return;
	}
	
	$my_parsed_url_path	 = trim( $my_parsed_url[ 'path' ] );
	$my_parsed_url_path	 = trim( $my_parsed_url_path, '/' );

	// Get booking resources and Export Feed URLS
	$is_continue = false;
	if ( function_exists( 'wpbc_br_cache' ) ) {
		
		$resources_cache = wpbc_br_cache();                                         // Get booking resources from  cache        
	    $resource_list = $resources_cache->get_resources();
		
		foreach ( $resource_list as $res_id => $res_arr) {
			
			if ( ! empty( $res_arr[ 'export' ] ) ) {
				$resource_feed_url = $res_arr[ 'export' ];
			} else {
				$resource_feed_url = '';
			}
			
			$resource_feed_url = trim( $resource_feed_url, '/' );
			if ( ! empty( $resource_feed_url ) ) {
				// if ( 0 === strpos( $my_parsed_url_path, $resource_feed_url ) ) {	// First coocurence of  $download_url_path in URL, like 'wpbm-ics-export' in 'http://beta/wpbm-ics-export/my-feed/'
				if ( $my_parsed_url_path === $resource_feed_url ) {
					$is_continue = true;
					break;
				}
			}
		}
	} else if ( function_exists( 'get_bk_option' ) ) {	

		//TODO: cehck  for Free version.		
		$res_id = 1;
		$resource_feed_url = get_bk_option( 'booking_resource_export_ics_url' );
		
		$resource_feed_url = trim( $resource_feed_url, '/' );
		
		if ( ! empty( $resource_feed_url ) ) {			
			if ( $my_parsed_url_path === $resource_feed_url ) {
				$is_continue = true;
			}
		}
		
	} else {
		return;	// No Booking Calendar active,  so  ust opening some other page
	}
	
	
	if ( true === $is_continue) {	

		$download_url_path = $resource_feed_url;

		$ics_export = wpbm_export_ics_feed__wpbm_ics( array( 'wh_booking_type' => $res_id ) );

		if ( headers_sent() ){
			die( 'headers_sent_before_download' );
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Prepare system before downloading set time limits, server output options 
		////////////////////////////////////////////////////////////////////////////////////////////////////////////
		$disabled = explode( ',', ini_get( 'disable_functions' ) );
		$is_func_disabled = in_array( 'set_time_limit', $disabled );
		if ( ! $is_func_disabled && ! ini_get( 'safe_mode' ) ) {
			@set_time_limit( 0 );
		}

		if ( function_exists( 'get_magic_quotes_runtime' ) && get_magic_quotes_runtime() && version_compare( phpversion(), '5.4', '<' ) ) {
			set_magic_quotes_runtime( 0 );
		}

		@session_write_close();
		if ( function_exists( 'apache_setenv' ) ) {
			@apache_setenv( 'no-gzip', 1 );
		}
		@ini_set( 'zlib.output_compression', 'Off' );

		@ob_end_clean();	// In case,  if somewhere opeded output buffer, may be  required for working fpassthru with  large files 


		////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Set Headers before file download 
		////////////////////////////////////////////////////////////////////////////////////////////////////////////
		$file = array();
		$file['content_type'] = 'text/calendar';
		$file['name'] = 'wpbm.ics';
		
		$text_encoding = mb_detect_encoding( $ics_export );
		
//debuge( mb_detect_encoding( $ics_export ) );die;		
		
		if (    ( is_array(  $text_encoding ) ) 
			 && ( ! in_array( 'UTF-8', $text_encoding ) )  
		){
			$file['size'] = wpbm_get_bytes_from_str( $ics_export );
		} else {
			$file['size'] = 0;	// UTF-8 encoding,  so  size alculated incorrectly, probabaly
		}

		nocache_headers();		
		header( "Robots: none" . "\n" );
		@header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 200 OK' . "\n" );
		header( "Content-Type: " . $file['content_type'] . "\n" );
		header( "Content-Description: File Transfer" . "\n" );
		header( "Content-Disposition: attachment; filename=\"" . $file['name'] . "\"" . "\n" );
		header( "Content-Transfer-Encoding: binary" . "\n" );

		if ( (int) $file['size'] > 0 )
			header( "Content-Length: " . $file['size'] . "\n" );


		echo $ics_export;

		exit;	
	}
	// Unknown error, or just opening some other page


}
add_action( 'template_redirect', 'wpbm_make_export_ics_feeds' );



/** Define export ICS here  
 *  For testing: http://beta/?feed=wpbm-ics
 */
function wpbm_export_ics_feed__wpbm_ics( $param = array( 'wh_booking_type' => '1', 'wh_trash' => '' ) ) {               //FixIn: 2.0.2.3

	if ( ! function_exists( 'wpbc_api_get_bookings_arr' ) )
		return '';
	
	// Get array of bookings.
	$bookings_arr = wpbc_api_get_bookings_arr( $param );


	ob_start();
			
	// create the ical object
	$icalobj = new ZCiCal();
	
	
	foreach ( $bookings_arr['bookings'] as $bk_id => $bk_arr ) {

		// create the event within the ical object
		$eventobj = new ZCiCalNode( 'VEVENT', $icalobj->curnode );

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// SUMMARY  [Title]
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
						
		if ( function_exists( 'get_title_for_showing_in_day' ) ) {	// Get title  of booking pipiline in "Calendar Overview" page
			
			if ( true ) {																									// admin
				$what_show_in_day_template = get_bk_option( 'booking_default_title_in_day_for_calendar_view_mode' );
			} else {																										// front-end
				$what_show_in_day_template = get_bk_option( 'booking_default_title_in_day_for_timeline_front_end' );
			}
			//$title = esc_textarea( get_title_for_showing_in_day( $bk_id, $bookings_arr['bookings'], $what_show_in_day_template ) );
			$title = get_title_for_showing_in_day( $bk_id, $bookings_arr['bookings'], $what_show_in_day_template );     //FixIn: 2.0.1.6.1
			
		} else {
			
			$title =   ( ( isset( $bk_arr->form_data['name'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['name'] ) : '' )
					.  ( ( isset( $bk_arr->form_data['firstname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['firstname'] ) : '' )
					.  ( ( isset( $bk_arr->form_data['secondname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['secondname'] ) : '' )
					.  ( ( isset( $bk_arr->form_data['lastname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['lastname'] ) : '' );			
		}

		$title = wpbm_esc_to_plain_text( $title );                                                                      //FixIn: 2.0.1.6.1

//$title = substr($title, 0, 5);
		$eventobj->addNode( new ZCiCalDataNode( 'SUMMARY:' . trim( $title ) ) );

		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// DESCRIPTION
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		$description = $bk_arr->form_show;
		//$description = html_entity_decode( sanitize_text_field( $description ) ); 
		//$description =  trim( wp_specialchars_decode( esc_html( stripslashes( $description ) ), ENT_QUOTES ) );

		$description = wpbm_esc_to_plain_text(  $description );
//debuge($description . '!');die;
//$description = substr($description, 0, 1);
		$description = preg_replace( array( "/\n/" ), array( '' ), $description );
//debuge( ZCiCal::formatContent( $description ) );die;
		$eventobj->addNode( new ZCiCalDataNode( 'DESCRIPTION:' . ZCiCal::formatContent( $description ) ) );
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// START & END DATES
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		$event_start =  $bk_arr->dates_short[ 0 ];
		if ( ( count($bk_arr->dates_short) > 1 ) && ( '-' === $bk_arr->dates_short[ 1 ] ) ) {
			
			$event_end   = $bk_arr->dates_short[ 2 ];
				
			$event_end = wpbm_get_next_date_if_it_full_date( $event_end );
				
			$period_start_index = 3;
		} else {											// comma
			$event_end   = $bk_arr->dates_short[ 0 ];
			
			$event_end = wpbm_get_next_date_if_it_full_date( $event_end );

			$period_start_index = 1;
		}
		
		// add start date
		$eventobj->addNode( new ZCiCalDataNode( "DTSTART:" . ZCiCal::fromSqlDateTime( $event_start ) ) );

		// add end date
		$eventobj->addNode( new ZCiCalDataNode( "DTEND:" . ZCiCal::fromSqlDateTime( $event_end ) ) );
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// RDATE   -  Rule for other different dates.
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//
		//		RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,
        //		19960404T010000Z/PT3H		
		//
		$rdate = array();
		$previos_value = '';
		foreach ( $bk_arr->dates_short as $short_ind => $bk_date ) {
			
			if ( $short_ind < $period_start_index )
				continue;
			
			if (   ( $bk_date !== ',' ) && ( $bk_date !== '-' )   ) {

				if ( $previos_value == '-' ) {
					$bk_date = wpbm_get_next_date_if_it_full_date( $bk_date );
				} else {
					$bk_date = wpbm_get_only_date_if_it_full_date( $bk_date );
				}
				
				$rdate[]= ZCiCal::fromSqlDateTime( $bk_date );

			} else if ( ( $bk_date === '-' ) && ( count($rdate) > 0 ) ) {
				
				$rdate[] = '/';				// PERIOD
				
			} else if ( ( $bk_date === ',' ) && ( count($rdate) > 0 ) ) {
				
				$rdate[] = ',';				// Other date
				
			}
			$previos_value = $bk_date;
		}
		if ( ! empty( $rdate ) ) {
			$rdate = implode( '', $rdate );
			// add RDATE
			$eventobj->addNode( new ZCiCalDataNode( "RDATE;VALUE=PERIOD:" . $rdate ) );
			
		}

		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// UID
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		$uid = $event_start . '_' . $bk_id . "@demo.icalendar.org";
		$eventobj->addNode( new ZCiCalDataNode( "UID:" . $uid ) );
		
		// DTSTAMP is a required item in VEVENT
		$eventobj->addNode( new ZCiCalDataNode( "DTSTAMP:" . ZCiCal::fromSqlDateTime() ) );

		$eventobj->addNode( new ZCiCalDataNode( "CREATED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
		$eventobj->addNode( new ZCiCalDataNode( "LAST-MODIFIED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
		
		
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// STATUS:CONFIRMED		( "TENTATIVE" / "CONFIRMED" / "CANCELLED" )												// This property defines the overall status for EVENT
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		$ics_status = 'TENTATIVE';
		if ( ! ( empty( $bk_arr->trash ) ) ) {
			$ics_status = 'CANCELLED';
		} elseif ( ! ( empty( $bk_arr->dates[0]->approved ) ) ) {
			$ics_status = 'CONFIRMED';
		}
		$eventobj->addNode( new ZCiCalDataNode( "STATUS:" . $ics_status ) );
				
		
		// RRULE:FREQ=WEEKLY;COUNT=3;BYDAY=WE,SA
		// LOCATION:South Australia\, Australia
		// SEQUENCE:1									// defines the revision sequence number of the calendar component within a sequence of revisions 
		// TRANSP:OPAQUE								// This property defines whether or not an event is transparent to busy time searches	;Default value is OPAQUE
		//		  OPAQUE		-  Blocks or opaque on busy time searches.
		//		  TRANSPARENT 	-  Transparent on busy time searches.
		
	}

	echo $icalobj->export();			// write iCalendar feed to stdout

	$ics_export = ob_get_contents();

	ob_end_clean();

	return $ics_export;
}


/** Get Next day in MySQL format without time,  if current day  its Full day - ending with 00:00:00
 * 
 * @param string $mysql_date	- 2017-07-12 00:00:00
 * @return string				- 2017-07-13
 */
function wpbm_get_next_date_if_it_full_date( $mysql_date ) {
	
	// Check if this date ending with 00:00:00 its means that it full  day,  
	// so we need to add 24 hours for ending at 23:59:59 (basically  00:00:00 of next  day) instead of at  start  of current day 00:00:00
	if (   ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
		&& ( substr( $mysql_date, 11 ) == '00:00:00' ) 
	) {

		$mysql_date = date_i18n( "Y-m-d 00:00:00",  strtotime( $mysql_date ) );
		$mysql_date = strtotime( $mysql_date );
		$mysql_date = date_i18n( "Y-m-d",  strtotime( '+1 day', $mysql_date ) );											
	} 

	return $mysql_date;	
}


/** Get day in MySQL format without time,  if current day  its Full day - ending with 00:00:00
 * 
 * @param string $mysql_date	- 2017-07-12 00:00:00
 * @return string				- 2017-07-12
 */
function wpbm_get_only_date_if_it_full_date( $mysql_date ) {

	if (   ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
		&& ( substr( $mysql_date, 11) == '00:00:00' ) 
	) {					
		$mysql_date = substr( $mysql_date, 0, 10 );
	}

	return $mysql_date;
}
```
