PluginProbe
Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar / 2.0.2
Booking Manager – Sync WP Booking Calendar – Import Events, Export Bookings to ICS Calendar v2.0.2
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.2, at core/wpbc/wpbm-bc-export.php

382 lines 14.0 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', 'wh_trash' => '' ) ) { //FixIn: 2.0.2.3
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 $title = get_title_for_showing_in_day( $bk_id, $bookings_arr['bookings'], $what_show_in_day_template ); //FixIn: 2.0.1.6.1
205
206 } else {
207
208 $title = ( ( isset( $bk_arr->form_data['name'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['name'] ) : '' )
209 . ( ( isset( $bk_arr->form_data['firstname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['firstname'] ) : '' )
210 . ( ( isset( $bk_arr->form_data['secondname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['secondname'] ) : '' )
211 . ( ( isset( $bk_arr->form_data['lastname'] ) ) ? ' ' . esc_textarea( $bk_arr->form_data['lastname'] ) : '' );
212 }
213
214 $title = wpbm_esc_to_plain_text( $title ); //FixIn: 2.0.1.6.1
215
216 //$title = substr($title, 0, 5);
217 $eventobj->addNode( new ZCiCalDataNode( 'SUMMARY:' . trim( $title ) ) );
218
219 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
220 // DESCRIPTION
221 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222 $description = $bk_arr->form_show;
223 //$description = html_entity_decode( sanitize_text_field( $description ) );
224 //$description = trim( wp_specialchars_decode( esc_html( stripslashes( $description ) ), ENT_QUOTES ) );
225
226 $description = wpbm_esc_to_plain_text( $description );
227 //debuge($description . '!');die;
228 //$description = substr($description, 0, 1);
229 $description = preg_replace( array( "/\n/" ), array( '' ), $description );
230 //debuge( ZCiCal::formatContent( $description ) );die;
231 $eventobj->addNode( new ZCiCalDataNode( 'DESCRIPTION:' . ZCiCal::formatContent( $description ) ) );
232
233 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
234 // START & END DATES
235 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
236 $event_start = $bk_arr->dates_short[ 0 ];
237 if ( ( count($bk_arr->dates_short) > 1 ) && ( '-' === $bk_arr->dates_short[ 1 ] ) ) {
238
239 $event_end = $bk_arr->dates_short[ 2 ];
240
241 $event_end = wpbm_get_next_date_if_it_full_date( $event_end );
242
243 $period_start_index = 3;
244 } else { // comma
245 $event_end = $bk_arr->dates_short[ 0 ];
246
247 $event_end = wpbm_get_next_date_if_it_full_date( $event_end );
248
249 $period_start_index = 1;
250 }
251
252 // add start date
253 $eventobj->addNode( new ZCiCalDataNode( "DTSTART:" . ZCiCal::fromSqlDateTime( $event_start ) ) );
254
255 // add end date
256 $eventobj->addNode( new ZCiCalDataNode( "DTEND:" . ZCiCal::fromSqlDateTime( $event_end ) ) );
257
258 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
259 // RDATE - Rule for other different dates.
260 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
261 //
262 // RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,
263 // 19960404T010000Z/PT3H
264 //
265 $rdate = array();
266 $previos_value = '';
267 foreach ( $bk_arr->dates_short as $short_ind => $bk_date ) {
268
269 if ( $short_ind < $period_start_index )
270 continue;
271
272 if ( ( $bk_date !== ',' ) && ( $bk_date !== '-' ) ) {
273
274 if ( $previos_value == '-' ) {
275 $bk_date = wpbm_get_next_date_if_it_full_date( $bk_date );
276 } else {
277 $bk_date = wpbm_get_only_date_if_it_full_date( $bk_date );
278 }
279
280 $rdate[]= ZCiCal::fromSqlDateTime( $bk_date );
281
282 } else if ( ( $bk_date === '-' ) && ( count($rdate) > 0 ) ) {
283
284 $rdate[] = '/'; // PERIOD
285
286 } else if ( ( $bk_date === ',' ) && ( count($rdate) > 0 ) ) {
287
288 $rdate[] = ','; // Other date
289
290 }
291 $previos_value = $bk_date;
292 }
293 if ( ! empty( $rdate ) ) {
294 $rdate = implode( '', $rdate );
295 // add RDATE
296 $eventobj->addNode( new ZCiCalDataNode( "RDATE;VALUE=PERIOD:" . $rdate ) );
297
298 }
299
300
301 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
302 // UID
303 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
304 $uid = $event_start . '_' . $bk_id . "@demo.icalendar.org";
305 $eventobj->addNode( new ZCiCalDataNode( "UID:" . $uid ) );
306
307 // DTSTAMP is a required item in VEVENT
308 $eventobj->addNode( new ZCiCalDataNode( "DTSTAMP:" . ZCiCal::fromSqlDateTime() ) );
309
310 $eventobj->addNode( new ZCiCalDataNode( "CREATED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
311 $eventobj->addNode( new ZCiCalDataNode( "LAST-MODIFIED:" . ZCiCal::fromSqlDateTime( $bk_arr->modification_date ) ) );
312
313
314 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
315 // STATUS:CONFIRMED ( "TENTATIVE" / "CONFIRMED" / "CANCELLED" ) // This property defines the overall status for EVENT
316 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317
318 $ics_status = 'TENTATIVE';
319 if ( ! ( empty( $bk_arr->trash ) ) ) {
320 $ics_status = 'CANCELLED';
321 } elseif ( ! ( empty( $bk_arr->dates[0]->approved ) ) ) {
322 $ics_status = 'CONFIRMED';
323 }
324 $eventobj->addNode( new ZCiCalDataNode( "STATUS:" . $ics_status ) );
325
326
327 // RRULE:FREQ=WEEKLY;COUNT=3;BYDAY=WE,SA
328 // LOCATION:South Australia\, Australia
329 // SEQUENCE:1 // defines the revision sequence number of the calendar component within a sequence of revisions
330 // TRANSP:OPAQUE // This property defines whether or not an event is transparent to busy time searches ;Default value is OPAQUE
331 // OPAQUE - Blocks or opaque on busy time searches.
332 // TRANSPARENT - Transparent on busy time searches.
333
334 }
335
336 echo $icalobj->export(); // write iCalendar feed to stdout
337
338 $ics_export = ob_get_contents();
339
340 ob_end_clean();
341
342 return $ics_export;
343 }
344
345
346 /** Get Next day in MySQL format without time, if current day its Full day - ending with 00:00:00
347 *
348 * @param string $mysql_date - 2017-07-12 00:00:00
349 * @return string - 2017-07-13
350 */
351 function wpbm_get_next_date_if_it_full_date( $mysql_date ) {
352
353 // Check if this date ending with 00:00:00 its means that it full day,
354 // 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
355 if ( ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
356 && ( substr( $mysql_date, 11 ) == '00:00:00' )
357 ) {
358
359 $mysql_date = date_i18n( "Y-m-d 00:00:00", strtotime( $mysql_date ) );
360 $mysql_date = strtotime( $mysql_date );
361 $mysql_date = date_i18n( "Y-m-d", strtotime( '+1 day', $mysql_date ) );
362 }
363
364 return $mysql_date;
365 }
366
367
368 /** Get day in MySQL format without time, if current day its Full day - ending with 00:00:00
369 *
370 * @param string $mysql_date - 2017-07-12 00:00:00
371 * @return string - 2017-07-12
372 */
373 function wpbm_get_only_date_if_it_full_date( $mysql_date ) {
374
375 if ( ( strlen( $mysql_date ) > 10 ) // , like 2017-07-12 00:00:00
376 && ( substr( $mysql_date, 11) == '00:00:00' )
377 ) {
378 $mysql_date = substr( $mysql_date, 0, 10 );
379 }
380
381 return $mysql_date;
382 }