PluginProbe
Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar / 2.0
Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar v2.0
2.1.21 2.1.20 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 trunk 1.1 2.0 2.0.1 2.0.10.2 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.17 2.0.18 2.0.2 2.0.20 2.0.21 2.0.22 All 55 releases
booking-manager / core / wpbc / wpbm-bc-export.php

wpbm-bc-export.php in Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar 2.0, at core/wpbc/wpbm-bc-export.php

377 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @description Booking Calendar integration - Export
5 *
6 * @author wpdevelop
7 * @link http://oplugins.com/
8 * @email info@oplugins.com
9 *
10 * @modified 2017-06-28
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
14
15
16
17 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 // E X P O R T
19 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20
21 /** Define ICS Feeds names
22 *
23 * wpbm-ics - Example of Feed Name.
24 *
25 * Have to work correctly immediately: http://beta/?feed=wpbm-ics
26 * 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.
27 * Finally, to display your feed, you’ll first need to flush your WordPress rewrite rules.
28 * The easiest way to do this is by logging in to the WordPress admin, and clicking Settings -> Permalinks.
29 * Once here, just click Save Changes, which will flush the rewrite rules.
30 *
31 * Otherwsie need to run ONLY once this:
32 *
33 * global $wp_rewrite;
34 * $wp_rewrite->flush_rules();
35 *
36 */
37 function wpbm_make_export_ics_feeds(){
38
39 if ( function_exists( 'wp_parse_url' ) )
40 $my_parsed_url = wp_parse_url( $_SERVER[ 'REQUEST_URI' ] );
41 else
42 $my_parsed_url = @parse_url( $_SERVER[ 'REQUEST_URI' ] );
43
44 if ( false === $my_parsed_url ) { // seriously malformed URLs, parse_url() may return FALSE.
45 return;
46 }
47
48 $my_parsed_url_path = trim( $my_parsed_url[ 'path' ] );
49 $my_parsed_url_path = trim( $my_parsed_url_path, '/' );
50
51 // Get booking resources and Export Feed URLS
52 $is_continue = false;
53 if ( function_exists( 'wpbc_br_cache' ) ) {
54
55 $resources_cache = wpbc_br_cache(); // Get booking resources from cache
56 $resource_list = $resources_cache->get_resources();
57
58 foreach ( $resource_list as $res_id => $res_arr) {
59
60 if ( ! empty( $res_arr[ 'export' ] ) ) {
61 $resource_feed_url = $res_arr[ 'export' ];
62 } else {
63 $resource_feed_url = '';
64 }
65
66 $resource_feed_url = trim( $resource_feed_url, '/' );
67 if ( ! empty( $resource_feed_url ) ) {
68 // 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/'
69 if ( $my_parsed_url_path === $resource_feed_url ) {
70 $is_continue = true;
71 break;
72 }
73 }
74 }
75 } else if ( function_exists( 'get_bk_option' ) ) {
76
77 //TODO: cehck for Free version.
78 $res_id = 1;
79 $resource_feed_url = get_bk_option( 'booking_resource_export_ics_url' );
80
81 $resource_feed_url = trim( $resource_feed_url, '/' );
82
83 if ( ! empty( $resource_feed_url ) ) {
84 if ( $my_parsed_url_path === $resource_feed_url ) {
85 $is_continue = true;
86 }
87 }
88
89 } else {
90 return; // No Booking Calendar active, so ust opening some other page
91 }
92
93
94 if ( true === $is_continue) {
95
96 $download_url_path = $resource_feed_url;
97
98 $ics_export = wpbm_export_ics_feed__wpbm_ics( array( 'wh_booking_type' => $res_id ) );
99
100 if ( headers_sent() ){
101 die( 'headers_sent_before_download' );
102 }
103
104 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 // Prepare system before downloading set time limits, server output options
106 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
107 $disabled = explode( ',', ini_get( 'disable_functions' ) );
108 $is_func_disabled = in_array( 'set_time_limit', $disabled );
109 if ( ! $is_func_disabled && ! ini_get( 'safe_mode' ) ) {
110 @set_time_limit( 0 );
111 }
112
113 if ( function_exists( 'get_magic_quotes_runtime' ) && get_magic_quotes_runtime() && version_compare( phpversion(), '5.4', '<' ) ) {
114 set_magic_quotes_runtime( 0 );
115 }
116
117 @session_write_close();
118 if ( function_exists( 'apache_setenv' ) ) {
119 @apache_setenv( 'no-gzip', 1 );
120 }
121 @ini_set( 'zlib.output_compression', 'Off' );
122
123 @ob_end_clean(); // In case, if somewhere opeded output buffer, may be required for working fpassthru with large files
124
125
126 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
127 // Set Headers before file download
128 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
129 $file = array();
130 $file['content_type'] = 'text/calendar';
131 $file['name'] = 'wpbm.ics';
132
133 $text_encoding = mb_detect_encoding( $ics_export );
134
135 //debuge( mb_detect_encoding( $ics_export ) );die;
136
137 if ( ( is_array( $text_encoding ) )
138 && ( ! in_array( 'UTF-8', $text_encoding ) )
139 ){
140 $file['size'] = wpbm_get_bytes_from_str( $ics_export );
141 } else {
142 $file['size'] = 0; // UTF-8 encoding, so size alculated incorrectly, probabaly
143 }
144
145 nocache_headers();
146 header( "Robots: none" . "\n" );
147 @header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 200 OK' . "\n" );
148 header( "Content-Type: " . $file['content_type'] . "\n" );
149 header( "Content-Description: File Transfer" . "\n" );
150 header( "Content-Disposition: attachment; filename=\"" . $file['name'] . "\"" . "\n" );
151 header( "Content-Transfer-Encoding: binary" . "\n" );
152
153 if ( (int) $file['size'] > 0 )
154 header( "Content-Length: " . $file['size'] . "\n" );
155
156
157 echo $ics_export;
158
159 exit;
160 }
161 // Unknown error, or just opening some other page
162
163
164 }
165 add_action( 'template_redirect', 'wpbm_make_export_ics_feeds' );
166
167
168
169 /** Define export ICS here
170 * For testing: http://beta/?feed=wpbm-ics
171 */
172 function wpbm_export_ics_feed__wpbm_ics( $param = array( 'wh_booking_type' => '1' ) ) {
173
174 if ( ! function_exists( 'wpbc_api_get_bookings_arr' ) )
175 return '';
176
177 // Get array of bookings.
178 $bookings_arr = wpbc_api_get_bookings_arr( $param );
179
180
181 ob_start();
182
183 // create the ical object
184 $icalobj = new ZCiCal();
185
186
187 foreach ( $bookings_arr['bookings'] as $bk_id => $bk_arr ) {
188
189 // create the event within the ical object
190 $eventobj = new ZCiCalNode( 'VEVENT', $icalobj->curnode );
191
192 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
193 // SUMMARY [Title]
194 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
195
196 if ( function_exists( 'get_title_for_showing_in_day' ) ) { // Get title of booking pipiline in "Calendar Overview" page
197
198 if ( true ) { // admin
199 $what_show_in_day_template = get_bk_option( 'booking_default_title_in_day_for_calendar_view_mode' );
200 } else { // front-end
201 $what_show_in_day_template = get_bk_option( 'booking_default_title_in_day_for_timeline_front_end' );
202 }
203 $title = esc_textarea( get_title_for_showing_in_day( $bk_id, $bookings_arr['bookings'], $what_show_in_day_template ) );
204
205 } else {
206
207 $title = ( ( isset( $bk_arr->form_data['name'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['name'] ) : '' )
208 . ( ( isset( $bk_arr->form_data['firstname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['firstname'] ) : '' )
209 . ( ( isset( $bk_arr->form_data['secondname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['secondname'] ) : '' )
210 . ( ( isset( $bk_arr->form_data['lastname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['lastname'] ) : '' );
211 }
212
213 //$title = substr($title, 0, 5);
214 $eventobj->addNode( new ZCiCalDataNode( 'SUMMARY:' . trim( $title ) ) );
215
216 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217 // DESCRIPTION
218 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219 $description = $bk_arr->form_show;
220 //$description = html_entity_decode( sanitize_text_field( $description ) );
221 //$description = trim( wp_specialchars_decode( esc_html( stripslashes( $description ) ), ENT_QUOTES ) );
222
223 $description = wpbm_esc_to_plain_text( $description );
224 //$description = substr($description, 0, 1);
225 $description = preg_replace( array( "/\n/" ), array( '' ), $description );
226 $eventobj->addNode( new ZCiCalDataNode( 'DESCRIPTION:' . ZCiCal::formatContent( $description ) ) );
227
228 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
229 // START & END DATES
230 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
231 $event_start = $bk_arr->dates_short[ 0 ];
232 if ( ( count($bk_arr->dates_short) > 1 ) && ( '-' === $bk_arr->dates_short[ 1 ] ) ) {
233
234 $event_end = $bk_arr->dates_short[ 2 ];
235
236 $event_end = wpbm_get_next_date_if_it_full_date( $event_end );
237
238 $period_start_index = 3;
239 } else { // comma
240 $event_end = $bk_arr->dates_short[ 0 ];
241
242 $event_end = wpbm_get_next_date_if_it_full_date( $event_end );
243
244 $period_start_index = 1;
245 }
246
247 // add start date
248 $eventobj->addNode( new ZCiCalDataNode( "DTSTART:" . ZCiCal::fromSqlDateTime( $event_start ) ) );
249
250 // add end date
251 $eventobj->addNode( new ZCiCalDataNode( "DTEND:" . ZCiCal::fromSqlDateTime( $event_end ) ) );
252
253 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
254 // RDATE - Rule for other different dates.
255 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
256 //
257 // RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,
258 // 19960404T010000Z/PT3H
259 //
260 $rdate = array();
261 $previos_value = '';
262 foreach ( $bk_arr->dates_short as $short_ind => $bk_date ) {
263
264 if ( $short_ind < $period_start_index )
265 continue;
266
267 if ( ( $bk_date !== ',' ) && ( $bk_date !== '-' ) ) {
268
269 if ( $previos_value == '-' ) {
270 $bk_date = wpbm_get_next_date_if_it_full_date( $bk_date );
271 } else {
272 $bk_date = wpbm_get_only_date_if_it_full_date( $bk_date );
273 }
274
275 $rdate[]= ZCiCal::fromSqlDateTime( $bk_date );
276
277 } else if ( ( $bk_date === '-' ) && ( count($rdate) > 0 ) ) {
278
279 $rdate[] = '/'; // PERIOD
280
281 } else if ( ( $bk_date === ',' ) && ( count($rdate) > 0 ) ) {
282
283 $rdate[] = ','; // Other date
284
285 }
286 $previos_value = $bk_date;
287 }
288 if ( ! empty( $rdate ) ) {
289 $rdate = implode( '', $rdate );
290 // add RDATE
291 $eventobj->addNode( new ZCiCalDataNode( "RDATE;VALUE=PERIOD:" . $rdate ) );
292
293 }
294
295
296 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297 // UID
298 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 $uid = $event_start . '_' . $bk_id . "@demo.icalendar.org";
300 $eventobj->addNode( new ZCiCalDataNode( "UID:" . $uid ) );
301
302 // DTSTAMP is a required item in VEVENT
303 $eventobj->addNode( new ZCiCalDataNode( "DTSTAMP:" . ZCiCal::fromSqlDateTime() ) );
304
305 $eventobj->addNode( new ZCiCalDataNode( "CREATED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
306 $eventobj->addNode( new ZCiCalDataNode( "LAST-MODIFIED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
307
308
309 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
310 // STATUS:CONFIRMED ( "TENTATIVE" / "CONFIRMED" / "CANCELLED" ) // This property defines the overall status for EVENT
311 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312
313 $ics_status = 'TENTATIVE';
314 if ( ! ( empty( $bk_arr->trash ) ) ) {
315 $ics_status = 'CANCELLED';
316 } elseif ( ! ( empty( $bk_arr->dates[0]->approved ) ) ) {
317 $ics_status = 'CONFIRMED';
318 }
319 $eventobj->addNode( new ZCiCalDataNode( "STATUS:" . $ics_status ) );
320
321
322 // RRULE:FREQ=WEEKLY;COUNT=3;BYDAY=WE,SA
323 // LOCATION:South Australia\, Australia
324 // SEQUENCE:1 // defines the revision sequence number of the calendar component within a sequence of revisions
325 // TRANSP:OPAQUE // This property defines whether or not an event is transparent to busy time searches ;Default value is OPAQUE
326 // OPAQUE - Blocks or opaque on busy time searches.
327 // TRANSPARENT - Transparent on busy time searches.
328
329 }
330
331 echo $icalobj->export(); // write iCalendar feed to stdout
332
333 $ics_export = ob_get_contents();
334
335 ob_end_clean();
336
337 return $ics_export;
338 }
339
340
341 /** Get Next day in MySQL format without time, if current day its Full day - ending with 00:00:00
342 *
343 * @param string $mysql_date - 2017-07-12 00:00:00
344 * @return string - 2017-07-13
345 */
346 function wpbm_get_next_date_if_it_full_date( $mysql_date ) {
347
348 // Check if this date ending with 00:00:00 its means that it full day,
349 // 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
350 if ( ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
351 && ( substr( $mysql_date, 11 ) == '00:00:00' )
352 ) {
353
354 $mysql_date = date_i18n( "Y-m-d 00:00:00", strtotime( $mysql_date ) );
355 $mysql_date = strtotime( $mysql_date );
356 $mysql_date = date_i18n( "Y-m-d", strtotime( '+1 day', $mysql_date ) );
357 }
358
359 return $mysql_date;
360 }
361
362
363 /** Get day in MySQL format without time, if current day its Full day - ending with 00:00:00
364 *
365 * @param string $mysql_date - 2017-07-12 00:00:00
366 * @return string - 2017-07-12
367 */
368 function wpbm_get_only_date_if_it_full_date( $mysql_date ) {
369
370 if ( ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
371 && ( substr( $mysql_date, 11) == '00:00:00' )
372 ) {
373 $mysql_date = substr( $mysql_date, 0, 10 );
374 }
375
376 return $mysql_date;
377 }