Events Manager - Version 5.7

Version Description

  • added em_events_admin_args filter allowing modification of event search arguments
  • removed jQuery UI localize files for the datepicker in favor of WP 4.6 native localization
  • fixed potential bug where modified ticket spaces aren't saving correctly when editing a booking
  • added is_user_attendee, not_user_attendee and variations of both proceeding with _0 or another number representing booking status
  • added edit/view shortcut links for each event location in events list admin area
  • fixed conflict with BuddyPress Group Extras and potentially other plugins when one or more of our list pages aren't assigned a page (e.g. locations page) resulting in a blank page
  • fixed ical feed not serving wrapped content lines,
  • added EM_ICAL_APPLE_STRUCT constant to allow ommitting of X-APPLE-STRUCTURED-LOCATION lines in the ical file
  • fixed formatting issues with ical X-APPLE-STRUCTURED-LOCATION line
  • fixed instances where locations or events automatically creating a post slug if needed when published
  • fixed location image display issues on other blogs when in MultiSite Global mode
  • corrected and updated docs
  • fixed switch_to_blog() being used instead of restore_current_blog() in buddypress/bp-em-core.php (props @mikegillihan)
  • fixed search form CSS inconsistencies for Twenty Seventeen theme
  • fixed locations map breaking when provided with object versions of JSON response (such as with WPML compat add-on)
  • updated maps google library to always use most stable version
  • fixed issues when creating MS Global Events programmatically
  • moved some logic out of the EM_Event->output() function into their own function for easier future use in templates
  • fixed google calendar links not including full location address
  • added an import/export settings option in settings page
  • added ability to use post_id in calendar shortcode and PHP functions
  • added has_location and no_location to event search attributes
  • added [events_map] shortcode which searches by event rather than location
  • changed behaviour of zooming when mouse is over a map so a click is required first to avoid catching whilst scrolling the page
  • fixed all errors and warnings for PHP 7 and others highlighted by PHP Compatibility Checker plugin
  • added decimal parameter to get_tax_rate functions which allows fixing of minor PHP warning when tax is set to 0
  • fixed filter typos and get_sql positions in EM_Bookings::get() and EMLocations::get()
  • removed unnecessary storage of _post_id in postmeta for recurring events
  • fixed bug where tickets aren't deleted with event
  • fixed incompatibility with WP Fastest Cache for bookings on cached pages
  • fixed EM_Categories not removing categories if none are selected when resaving an event
  • added em_get_events_admin_url() function
  • added major improvements to recurring events including ability to duplicate templates and also make changes without deleting previous recurrences,
  • changed various event editor templates to accommodate new recurring event changes
  • changed no-user bookings feature to not require a dummy user
  • changed no-user bookings so previous bookings appear correctly regardless of whether NU bookings is enabled or disabled
  • tweaked PHP Mail sending method to go through WP PHPMailer class for better encoding
  • fixed overly aggressive filtering of get_the_date and get_the_time filters (kudos @boonebgorges)
  • fixed missing map markers array variable to be supplied in JS hook em_maps_locations_hook (kudos @raruto)
  • changed booking discount php functions into price adjustment functions which will now allow for surcharges to be implemented
  • fixed guest submissions with bookings enabled producing false permission errors instead of a confirmation
  • fixed/updated media uploader JS interface for category image
  • added more booking price filters to individual functions
  • fixed minor nuance where upcoming events scope filter not selectable on mobile view
  • fixed JS not being loaded automatically on events list when JS performance loading enabled
  • fixed regex matching preventing use of a #_LATT attribute within an #_ATT default value bracket
  • fixed confirmation message not showing for event duplication
  • added duplicate shortcut link on dashboard edit event page
  • fixed issues with selection of Sunday on monthly recurrences and the generated pattern summary
  • changed/fixed events_list_grouped using date format for sub-section titles from settings page if no date_format supplied regardless of grouping mode
  • added em_scripts_and_styles_public_enqueue_pages filter for custom pages to automatically include EM script/styles when limiting for performance is enabled
  • fixed PHP non-object notices on certain non-EM dashboard pages
  • changed booking form scrolling JS to scroll to booking message feedback element and added EM_BOOKING_MSG_JS_OFFSET constant to allow adjusting the offset in wp-config.php
  • fixed redirect link on booking form login not taking into account SSL pages
  • added #_EVENTEXCERPTCUT to allow cutting of both excerpts and post content
  • changed event all day times to start at 00:00:00 and end at 23:59:59 when saved (kudos @cliffpaulick)
  • changed default search form settings behaviour to ignore country filtering if search option is not enabled
  • fixed scheduled recurring events not publishing recurrences
  • improved google maps JS for multiple events/locations maps and auto-zooming of included locations (kudos @benklocek)
  • fixed minor php warning on user profile page
  • tweaked booking JS to allow a redirect variable passed on with a successful response
  • fixed 'Bookings' header not being translated when formats are disabled and booking form is added just after content
  • fixed ticket availability status indicator showing false to admins when ticket is restricted to guests
  • added get_total_paid function (mainly for hooking purposes in Pro add-ons)
  • added support for Google Maps styles via services like the Google Maps Style Wizard or Snazzy Maps
Download this release

Release Info

Developer netweblogic
Plugin Icon 128x128 Events Manager
Version 5.7
Comparing to
See all releases

Code changes from version 5.6.6.1 to 5.7

Files changed (60) hide show
  1. admin/bookings/em-events.php +1 -1
  2. admin/em-admin.php +1 -1
  3. admin/em-bookings.php +34 -17
  4. admin/em-docs.php +4 -4
  5. admin/em-ms-options.php +4 -4
  6. admin/em-options.php +91 -0
  7. admin/settings/tabs/bookings.php +1 -11
  8. admin/settings/tabs/emails.php +1 -1
  9. admin/settings/tabs/formats.php +3 -2
  10. buddypress/bp-em-core.php +280 -275
  11. buddypress/bp-em-notifications.php +1 -1
  12. classes/em-booking.php +133 -53
  13. classes/em-bookings-table.php +1 -1
  14. classes/em-bookings.php +4 -3
  15. classes/em-calendar.php +2 -1
  16. classes/em-categories-taxonomy.php +13 -13
  17. classes/em-categories.php +10 -12
  18. classes/em-event-post-admin.php +21 -12
  19. classes/em-event-post.php +12 -10
  20. classes/em-event-posts-admin.php +55 -5
  21. classes/em-event.php +429 -202
  22. classes/em-events.php +9 -2
  23. classes/em-location-post-admin.php +3 -5
  24. classes/em-location.php +38 -12
  25. classes/em-locations.php +3 -3
  26. classes/em-mailer.php +3 -19
  27. classes/em-object.php +11 -21
  28. classes/em-people.php +23 -14
  29. classes/em-permalinks.php +16 -0
  30. classes/em-person.php +5 -6
  31. classes/em-ticket.php +10 -10
  32. classes/em-tickets.php +6 -2
  33. em-actions.php +20 -4
  34. em-events.php +2 -1
  35. em-functions.php +2 -2
  36. em-ical.php +48 -2
  37. em-install.php +103 -87
  38. em-shortcode.php +46 -4
  39. em-template-tags.php +18 -7
  40. events-manager.php +95 -126
  41. includes/css/events_manager.css +10 -3
  42. includes/css/events_manager_admin.css +7 -0
  43. includes/js/bookingsform.js +4 -1
  44. includes/js/categories-admin.js +61 -60
  45. includes/js/events-manager.js +72 -34
  46. readme.txt +70 -3
  47. templates/buddypress/group-events.php +1 -1
  48. templates/emails/bookingsummary.php +18 -0
  49. templates/forms/bookingform/login.php +1 -1
  50. templates/forms/event-editor.php +1 -1
  51. templates/forms/event/bookings.php +139 -101
  52. templates/forms/event/recurring-when.php +63 -50
  53. templates/forms/event/when-with-recurring.php +0 -1
  54. templates/placeholders/attendees.php +2 -4
  55. templates/placeholders/attendeeslist.php +2 -4
  56. templates/placeholders/attendeespendinglist.php +1 -3
  57. templates/tables/events.php +5 -3
  58. templates/tables/locations.php +3 -1
  59. templates/templates/ical.php +31 -22
  60. templates/templates/map-global.php +8 -0
admin/bookings/em-events.php CHANGED
@@ -80,7 +80,7 @@ function em_bookings_events_table() {
80
  }
81
  ?>
82
  </div>
83
-
84
  <?php
85
  if (empty ( $events )) {
86
  // TODO localize
80
  }
81
  ?>
82
  </div>
83
+ <div class="clear"></div>
84
  <?php
85
  if (empty ( $events )) {
86
  // TODO localize
admin/em-admin.php CHANGED
@@ -101,7 +101,7 @@ function em_admin_dashicon(){
101
  font-style: normal;
102
  }
103
  .menu-icon-event .dashicons-calendar:before, #toplevel_page_events-manager-options .dashicons-calendar:before {
104
- font-family: 'em_dashicons' !important;
105
  content: '\e600';
106
  }
107
  </style>
101
  font-style: normal;
102
  }
103
  .menu-icon-event .dashicons-calendar:before, #toplevel_page_events-manager-options .dashicons-calendar:before {
104
+ font-family: 'em_dashicons';
105
  content: '\e600';
106
  }
107
  </style>
admin/em-bookings.php CHANGED
@@ -222,14 +222,13 @@ function em_bookings_single(){
222
  <?php esc_html_e( 'Personal Details', 'events-manager'); ?>
223
  </h3>
224
  <div class="inside">
225
- <?php $no_user = get_option('dbem_bookings_registration_disable') && $EM_Booking->get_person()->ID == get_option('dbem_bookings_registration_user'); ?>
226
  <div class="em-booking-person-details">
227
  <?php echo $EM_Booking->get_person()->display_summary(); ?>
228
- <?php if( $no_user ): ?>
229
- <input type="button" id="em-booking-person-modify" value="<?php esc_attr_e('Edit Details','events-manager'); ?>" />
230
  <?php endif; ?>
231
  </div>
232
- <?php if( $no_user ): ?>
233
  <form action="" method="post" class="em-booking-person-form">
234
  <div class="em-booking-person-editor" style="display:none;">
235
  <?php echo $EM_Booking->get_person_editor(); ?>
@@ -237,8 +236,8 @@ function em_bookings_single(){
237
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
238
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
239
  <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_modify_person_'.$EM_Booking->booking_id); ?>'/>
240
- <input type="submit" class="em-booking-person-modify-submit" id="em-booking-person-modify-submit" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
241
- <input type="button" id="em-booking-person-modify-cancel" value="<?php esc_attr_e('Cancel','events-manager'); ?>" />
242
  </div>
243
  </form>
244
  <script type="text/javascript">
@@ -272,8 +271,8 @@ function em_bookings_single(){
272
  <form action="" method="post" class="em-booking-single-status-info">
273
  <strong><?php esc_html_e('Status','events-manager'); ?> : </strong>
274
  <?php echo $EM_Booking->get_status(); ?>
275
- <input type="button" class="em-booking-submit-status-modify" id="em-booking-submit-status-modify" value="<?php esc_attr_e('Change', 'events-manager'); ?>" />
276
- <input type="submit" class="em-booking-resend-email" id="em-booking-resend-email" value="<?php esc_attr_e('Resend Email', 'events-manager'); ?>" />
277
  <input type='hidden' name='action' value='booking_resend_email'/>
278
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
279
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
@@ -288,8 +287,8 @@ function em_bookings_single(){
288
  </select>
289
  <input type="checkbox" checked="checked" name="send_email" value="1" />
290
  <?php esc_html_e('Send Email','events-manager'); ?>
291
- <input type="submit" class="em-booking-submit-status" id="em-booking-submit-status" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
292
- <input type="button" class="em-booking-submit-status-cancel" id="em-booking-submit-status-cancel" value="<?php esc_attr_e('Cancel', 'events-manager'); ?>" />
293
  <input type='hidden' name='action' value='booking_set_status'/>
294
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
295
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
@@ -328,7 +327,7 @@ function em_bookings_single(){
328
  <td class="ticket-type"><a class="row-title" href="<?php echo em_add_get_params($EM_Event->get_bookings_url(), array('ticket_id'=>$EM_Ticket->ticket_id)); ?>"><?php echo $EM_Ticket->ticket_name ?></a></td>
329
  <td>
330
  <span class="em-booking-single-info">0</span>
331
- <div class="em-booking-single-edit"><input name="em_tickets[<?php echo $EM_Ticket->ticket_id; ?>][spaces]" class="em-ticket-select" id="em-ticket-spaces-<?php echo $EM_Ticket_Booking->ticket_id; ?>" value="0" /></div>
332
  </td>
333
  <td><?php echo em_get_currency_symbol() ?>0.00</td>
334
  </tr>
@@ -352,11 +351,20 @@ function em_bookings_single(){
352
  <?php foreach( $price_summary['discounts_pre_tax'] as $discount_summary ): ?>
353
  <tr>
354
  <th><?php echo $discount_summary['name']; ?></th>
355
- <th><?php echo $discount_summary['discount']; ?></th>
356
  <th>- <?php echo $discount_summary['amount']; ?></th>
357
  </tr>
358
  <?php endforeach; ?>
359
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
360
  <?php if( !empty($price_summary['taxes']['amount']) ): ?>
361
  <tr>
362
  <th><?php esc_html_e('Tax','events-manager'); ?></th>
@@ -371,11 +379,20 @@ function em_bookings_single(){
371
  <?php foreach( $price_summary['discounts_post_tax'] as $discount_summary ): ?>
372
  <tr>
373
  <th><?php echo $discount_summary['name']; ?></th>
374
- <th><?php echo $discount_summary['discount']; ?></th>
375
  <th>- <?php echo $discount_summary['amount']; ?></th>
376
  </tr>
377
  <?php endforeach; ?>
378
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
379
  <tr>
380
  <th><?php esc_html_e('Total Price','events-manager'); ?></th>
381
  <th>&nbsp;</th>
@@ -397,13 +414,13 @@ function em_bookings_single(){
397
  <?php endif; ?>
398
  </table>
399
  <p class="em-booking-single-info">
400
- <input type="button" class="em-booking-submit-modify" id="em-booking-submit-modify" value="<?php esc_attr_e('Modify Booking', 'events-manager'); ?>" />
401
  </p>
402
  <p class="em-booking-single-edit">
403
  <em><?php _e('<strong>Notes:</strong> Ticket availability not taken into account (i.e. you can overbook). Emails are not resent automatically.','events-manager'); ?></em>
404
  <br /><br />
405
- <input type="submit" class="em-booking-submit" id="em-booking-submit" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
406
- <input type="button" class="em-booking-submit-cancel" id="em-booking-submit-cancel" value="<?php esc_attr_e('Cancel', 'events-manager'); ?>" />
407
  <input type='hidden' name='action' value='booking_save'/>
408
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
409
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
@@ -455,7 +472,7 @@ function em_bookings_single(){
455
  <textarea class="widefat" rows="5" name="booking_note"></textarea>
456
  <input type="hidden" name="action" value="bookings_add_note" />
457
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('bookings_add_note'); ?>" />
458
- <input type="submit" value="Add Note" />
459
  </form>
460
  </div>
461
  </div>
222
  <?php esc_html_e( 'Personal Details', 'events-manager'); ?>
223
  </h3>
224
  <div class="inside">
 
225
  <div class="em-booking-person-details">
226
  <?php echo $EM_Booking->get_person()->display_summary(); ?>
227
+ <?php if( $EM_Booking->is_no_user() ): ?>
228
+ <input type="button" class="button-secondary" id="em-booking-person-modify" value="<?php esc_attr_e('Edit Details','events-manager'); ?>" />
229
  <?php endif; ?>
230
  </div>
231
+ <?php if( $EM_Booking->is_no_user() ): ?>
232
  <form action="" method="post" class="em-booking-person-form">
233
  <div class="em-booking-person-editor" style="display:none;">
234
  <?php echo $EM_Booking->get_person_editor(); ?>
236
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
237
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
238
  <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_modify_person_'.$EM_Booking->booking_id); ?>'/>
239
+ <input type="submit" class="button-primary em-button em-booking-person-modify-submit" id="em-booking-person-modify-submit" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
240
+ <input type="button" id="em-booking-person-modify-cancel" class="button-secondary em-button" value="<?php esc_attr_e('Cancel','events-manager'); ?>" />
241
  </div>
242
  </form>
243
  <script type="text/javascript">
271
  <form action="" method="post" class="em-booking-single-status-info">
272
  <strong><?php esc_html_e('Status','events-manager'); ?> : </strong>
273
  <?php echo $EM_Booking->get_status(); ?>
274
+ <input type="button" class="button-secondary em-button em-booking-submit-status-modify" id="em-booking-submit-status-modify" value="<?php esc_attr_e('Change', 'events-manager'); ?>" />
275
+ <input type="submit" class="button-primary em-button em-booking-resend-email" id="em-booking-resend-email" value="<?php esc_attr_e('Resend Email', 'events-manager'); ?>" />
276
  <input type='hidden' name='action' value='booking_resend_email'/>
277
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
278
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
287
  </select>
288
  <input type="checkbox" checked="checked" name="send_email" value="1" />
289
  <?php esc_html_e('Send Email','events-manager'); ?>
290
+ <input type="submit" class="button-primary em-button em-booking-submit-status" id="em-booking-submit-status" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
291
+ <input type="button" class="button-secondary em-button em-booking-submit-status-cancel" id="em-booking-submit-status-cancel" value="<?php esc_attr_e('Cancel', 'events-manager'); ?>" />
292
  <input type='hidden' name='action' value='booking_set_status'/>
293
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
294
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
327
  <td class="ticket-type"><a class="row-title" href="<?php echo em_add_get_params($EM_Event->get_bookings_url(), array('ticket_id'=>$EM_Ticket->ticket_id)); ?>"><?php echo $EM_Ticket->ticket_name ?></a></td>
328
  <td>
329
  <span class="em-booking-single-info">0</span>
330
+ <div class="em-booking-single-edit"><input name="em_tickets[<?php echo $EM_Ticket->ticket_id; ?>][spaces]" class="em-ticket-select" id="em-ticket-spaces-<?php echo $EM_Ticket->ticket_id; ?>" value="0" /></div>
331
  </td>
332
  <td><?php echo em_get_currency_symbol() ?>0.00</td>
333
  </tr>
351
  <?php foreach( $price_summary['discounts_pre_tax'] as $discount_summary ): ?>
352
  <tr>
353
  <th><?php echo $discount_summary['name']; ?></th>
354
+ <th><?php echo $discount_summary['adjustment']; ?></th>
355
  <th>- <?php echo $discount_summary['amount']; ?></th>
356
  </tr>
357
  <?php endforeach; ?>
358
  <?php endif; ?>
359
+ <?php if( count($price_summary['surcharges_pre_tax']) > 0 ): ?>
360
+ <?php foreach( $price_summary['surcharges_pre_tax'] as $surcharge_summary ): ?>
361
+ <tr>
362
+ <th><?php echo $surcharge_summary['name']; ?></th>
363
+ <th><?php echo $surcharge_summary['adjustment']; ?></th>
364
+ <th><?php echo $surcharge_summary['amount']; ?></th>
365
+ </tr>
366
+ <?php endforeach; ?>
367
+ <?php endif; ?>
368
  <?php if( !empty($price_summary['taxes']['amount']) ): ?>
369
  <tr>
370
  <th><?php esc_html_e('Tax','events-manager'); ?></th>
379
  <?php foreach( $price_summary['discounts_post_tax'] as $discount_summary ): ?>
380
  <tr>
381
  <th><?php echo $discount_summary['name']; ?></th>
382
+ <th><?php echo $discount_summary['adjustment']; ?></th>
383
  <th>- <?php echo $discount_summary['amount']; ?></th>
384
  </tr>
385
  <?php endforeach; ?>
386
  <?php endif; ?>
387
+ <?php if( count($price_summary['surcharges_post_tax']) > 0 ): ?>
388
+ <?php foreach( $price_summary['surcharges_post_tax'] as $surcharge_summary ): ?>
389
+ <tr>
390
+ <th><?php echo $surcharge_summary['name']; ?></th>
391
+ <th><?php echo $surcharge_summary['adjustment']; ?></th>
392
+ <th><?php echo $surcharge_summary['amount']; ?></th>
393
+ </tr>
394
+ <?php endforeach; ?>
395
+ <?php endif; ?>
396
  <tr>
397
  <th><?php esc_html_e('Total Price','events-manager'); ?></th>
398
  <th>&nbsp;</th>
414
  <?php endif; ?>
415
  </table>
416
  <p class="em-booking-single-info">
417
+ <input type="button" class="button-secondary em-button em-booking-submit-modify" id="em-booking-submit-modify" value="<?php esc_attr_e('Modify Booking', 'events-manager'); ?>" />
418
  </p>
419
  <p class="em-booking-single-edit">
420
  <em><?php _e('<strong>Notes:</strong> Ticket availability not taken into account (i.e. you can overbook). Emails are not resent automatically.','events-manager'); ?></em>
421
  <br /><br />
422
+ <input type="submit" class="button-primary em-button em-booking-submit" id="em-booking-submit" value="<?php esc_attr_e('Submit Changes', 'events-manager'); ?>" />
423
+ <input type="button" class="button-secondary em-button em-booking-submit-cancel" id="em-booking-submit-cancel" value="<?php esc_attr_e('Cancel', 'events-manager'); ?>" />
424
  <input type='hidden' name='action' value='booking_save'/>
425
  <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
426
  <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
472
  <textarea class="widefat" rows="5" name="booking_note"></textarea>
473
  <input type="hidden" name="action" value="bookings_add_note" />
474
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('bookings_add_note'); ?>" />
475
+ <input type="submit" class="em-button button-primary" value="Add Note" />
476
  </form>
477
  </div>
478
  </div>
admin/em-docs.php CHANGED
@@ -31,7 +31,9 @@ function em_docs_init($force_init = false){
31
  'search' => array( 'desc'=> 'Do a search for this string within event name, details and location address.' ),
32
  'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','events'), 'default'=>1),
33
  'tag' => array( 'desc'=> str_replace('%s', 'tags', 'Supply a single id, slug or comma-separated ids or slugs (e.g. "1,%s-slug,3") to limit the search to events in any of these %s. You can also use negative numbers and slugs to exclude specific %s (e.g. -1,-exclude-%s,-3). If you mix inclusions and exclusions, all events with included %s AND without excluded %s will be shown. You can also use &amp; to separate ids and slugs, in which case events must contain (or not contain) both %s to be shown.'), 'default'=>0),
34
- 'year' => array( 'desc'=> 'If set to a year (e.g. 2010) only events that start or end during this year/month will be returned. Does not work as intended if used with scope.', 'default'=>'')
 
 
35
  ),
36
  'locations' => array(
37
  'blog' => array( 'desc' => sprintf('Limit search to %s created in a specific blog id (MultiSite only)','locations')),
@@ -88,6 +90,7 @@ function em_docs_init($force_init = false){
88
  '#_EVENTNOTES' => array( 'desc' => 'Shows the description of the event.' ),
89
  '#_EVENTEXCERPT' => array( 'desc' => 'If an excerpt has been added to the event, it will be used. If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your event description, only the content before this tag will show.' ),
90
  '#_EVENTEXCERPT{words,...}' => array( 'desc' => 'If an excerpt has not been added to the event you can use this format <code>#_EVENTEXCERPT{10,...}</code>, where 10 is the number of words to show and ... is what is used at the cut-off point.' ),
 
91
  '#_EVENTIMAGE' => array( 'desc' => 'Shows the event image, if available.' ),
92
  '#_EVENTIMAGE{x,y}' => array( 'desc' => 'Shows the event image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_EVENTIMAGE{100,100}</code>. If 0 is used for either width or height, the corresponding dimension will be proportionally sized' ),
93
  '#_EVENTCATEGORIES' => array( 'desc' => 'Shows a list of category links this event belongs to.' ),
@@ -213,9 +216,6 @@ function em_docs_init($force_init = false){
213
  '#_TAGNAME' => array( 'desc' => 'Shows the tag name.' ),
214
  '#_TAGID' => array( 'desc' => 'Shows the tag ID.' ),
215
  '#_TAGSLUG' => array( 'desc' => 'Shows the tag slug.' ),
216
- '#_TAGIMAGE' => array( 'desc' => 'Shows the tag image, if available.' ),
217
- '#_TAGIMAGE{x,y}' => array( 'desc' => 'Shows the tag image thumbnail if available, x and y are width and height respectively, both being numbers e.g. <code>#_TAGIMAGE{100,100}</code>. If 0 is used for either width or height, the corresponding dimension will be proportionally sized.' ),
218
- '#_TAGIMAGEURL' => array( 'desc' => 'Shows the tag image url, if available.' ),
219
  '#_TAGNOTES' => array( 'desc' => 'Shows the tag description.' )
220
  )
221
  ),
31
  'search' => array( 'desc'=> 'Do a search for this string within event name, details and location address.' ),
32
  'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','events'), 'default'=>1),
33
  'tag' => array( 'desc'=> str_replace('%s', 'tags', 'Supply a single id, slug or comma-separated ids or slugs (e.g. "1,%s-slug,3") to limit the search to events in any of these %s. You can also use negative numbers and slugs to exclude specific %s (e.g. -1,-exclude-%s,-3). If you mix inclusions and exclusions, all events with included %s AND without excluded %s will be shown. You can also use &amp; to separate ids and slugs, in which case events must contain (or not contain) both %s to be shown.'), 'default'=>0),
34
+ 'year' => array( 'desc'=> 'If set to a year (e.g. 2010) only events that start or end during this year/month will be returned. Does not work as intended if used with scope.', 'default'=>''),
35
+ 'has_location' => array( 'desc'=> 'When set to true, only events WITH an assigned location will be shown, has priority over no_location.', 'default'=>''),
36
+ 'no_location' => array( 'desc'=> 'When set to true, only events WITHOUT an assigned location will be shown.', 'default'=>'')
37
  ),
38
  'locations' => array(
39
  'blog' => array( 'desc' => sprintf('Limit search to %s created in a specific blog id (MultiSite only)','locations')),
90
  '#_EVENTNOTES' => array( 'desc' => 'Shows the description of the event.' ),
91
  '#_EVENTEXCERPT' => array( 'desc' => 'If an excerpt has been added to the event, it will be used. If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your event description, only the content before this tag will show.' ),
92
  '#_EVENTEXCERPT{words,...}' => array( 'desc' => 'If an excerpt has not been added to the event you can use this format <code>#_EVENTEXCERPT{10,...}</code>, where 10 is the number of words to show and ... is what is used at the cut-off point.' ),
93
+ '#_EVENTEXCERPTCUT' => array( 'desc' => 'Same as <code>#_EVENTEXCERPT</code> (and also accepts the <code>{words,...}</code> arguments) but will also cut excerpts as well as post content. Default word limit is 55 and cut-off is <code>[...]</code>' ),
94
  '#_EVENTIMAGE' => array( 'desc' => 'Shows the event image, if available.' ),
95
  '#_EVENTIMAGE{x,y}' => array( 'desc' => 'Shows the event image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_EVENTIMAGE{100,100}</code>. If 0 is used for either width or height, the corresponding dimension will be proportionally sized' ),
96
  '#_EVENTCATEGORIES' => array( 'desc' => 'Shows a list of category links this event belongs to.' ),
216
  '#_TAGNAME' => array( 'desc' => 'Shows the tag name.' ),
217
  '#_TAGID' => array( 'desc' => 'Shows the tag ID.' ),
218
  '#_TAGSLUG' => array( 'desc' => 'Shows the tag slug.' ),
 
 
 
219
  '#_TAGNOTES' => array( 'desc' => 'Shows the tag description.' )
220
  )
221
  ),
admin/em-ms-options.php CHANGED
@@ -1,4 +1,4 @@
1
- <?php
2
  function em_ms_upgrade( $blog_id ){
3
  ?>
4
  <div class="wrap">
@@ -31,8 +31,8 @@ function em_ms_upgrade( $blog_id ){
31
  <p><?php esc_html_e('To update your network blogs with the latest Events Manager automatically, click the update button below.','events-manager'); ?></p>
32
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('em_ms_ugrade_'.get_current_user_id()); ?>" />
33
  <input type="hidden" name="action" value="upgrade" />
34
- <input type="submit" value="<?php esc_attr_e('Update','events-manager'); ?>" />
35
- </form>
36
  <?php
37
  }
38
  ?>
@@ -151,7 +151,7 @@ function em_ms_admin_options_page() {
151
  $global_link_tip = __( 'When displaying global %s on the main site you have the option of users viewing the %s details on the main site or being directed to the sub-site.','events-manager');
152
  $global_post_tip = __( 'Displays %s from all sites on the network by default. You can still restrict %s by blog using shortcodes and template tags coupled with the <code>blog</code> attribute. Requires global tables to be turned on.','events-manager');
153
  $global_link_tip2 = __('You <strong>must</strong> have assigned a %s page in your <a href="%s">main blog settings</a> for this to work.','events-manager');
154
- $options_page_link = get_admin_url($current_site->blog_id, 'edit.php?post_type=event&page=events-manager-options#pages');
155
  ?><tr class="em-header"><td><h4><?php echo sprintf(__('%s Options','events-manager'),__('Event','events-manager')); ?></h4></td></tr><?php
156
  em_options_radio_binary ( sprintf(__( 'Display global events on main blog?', 'events-manager'), __('events','events-manager')), 'dbem_ms_global_events', sprintf($global_post_tip, __('events','events-manager'), __('events','events-manager')) );
157
  em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'events-manager'), __('events','events-manager')), 'dbem_ms_global_events_links', sprintf($global_link_tip, __('events','events-manager'), __('event','events-manager')).sprintf($global_link_tip2, __('event','events-manager'), $options_page_link) );
1
+ <?php
2
  function em_ms_upgrade( $blog_id ){
3
  ?>
4
  <div class="wrap">
31
  <p><?php esc_html_e('To update your network blogs with the latest Events Manager automatically, click the update button below.','events-manager'); ?></p>
32
  <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('em_ms_ugrade_'.get_current_user_id()); ?>" />
33
  <input type="hidden" name="action" value="upgrade" />
34
+ <input type="submit" value="<?php esc_attr_e('Update','events-manager'); ?>" />
35
+ </form>
36
  <?php
37
  }
38
  ?>
151
  $global_link_tip = __( 'When displaying global %s on the main site you have the option of users viewing the %s details on the main site or being directed to the sub-site.','events-manager');
152
  $global_post_tip = __( 'Displays %s from all sites on the network by default. You can still restrict %s by blog using shortcodes and template tags coupled with the <code>blog</code> attribute. Requires global tables to be turned on.','events-manager');
153
  $global_link_tip2 = __('You <strong>must</strong> have assigned a %s page in your <a href="%s">main blog settings</a> for this to work.','events-manager');
154
+ $options_page_link = get_admin_url($current_site->blog_id, 'edit.php?post_type='.EM_POST_TYPE_EVENT.'&page=events-manager-options#pages');
155
  ?><tr class="em-header"><td><h4><?php echo sprintf(__('%s Options','events-manager'),__('Event','events-manager')); ?></h4></td></tr><?php
156
  em_options_radio_binary ( sprintf(__( 'Display global events on main blog?', 'events-manager'), __('events','events-manager')), 'dbem_ms_global_events', sprintf($global_post_tip, __('events','events-manager'), __('events','events-manager')) );
157
  em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'events-manager'), __('events','events-manager')), 'dbem_ms_global_events_links', sprintf($global_link_tip, __('events','events-manager'), __('event','events-manager')).sprintf($global_link_tip2, __('event','events-manager'), $options_page_link) );
admin/em-options.php CHANGED
@@ -162,6 +162,57 @@ function em_options_save(){
162
  wp_redirect(em_wp_get_referer());
163
  exit();
164
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
  }
167
  add_action('admin_init', 'em_options_save');
@@ -567,16 +618,21 @@ function em_admin_option_box_uninstall(){
567
  $reset_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
568
  $recheck_updates_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=recheck_updates&amp;_wpnonce='.wp_create_nonce('em_recheck_updates_'.get_current_user_id().'_wpnonce');
569
  $check_devs = admin_url().'network/admin.php?page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
 
 
570
  }else{
571
  $uninstall_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
572
  $reset_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
573
  $recheck_updates_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=recheck_updates&amp;_wpnonce='.wp_create_nonce('em_recheck_updates_'.get_current_user_id().'_wpnonce');
574
  $check_devs = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
 
 
575
  }
576
  ?>
577
  <div class="postbox" id="em-opt-admin-tools" >
578
  <div class="handlediv" title="<?php __('Click to toggle', 'events-manager'); ?>"><br /></div><h3><span><?php _e ( 'Admin Tools', 'events-manager'); ?> (<?php _e ( 'Advanced', 'events-manager'); ?>)</span></h3>
579
  <div class="inside">
 
580
  <table class="form-table">
581
  <tr class="em-header"><td colspan="2">
582
  <h4><?php _e ( 'Development Versions &amp; Updates', 'events-manager'); ?></h4>
@@ -593,6 +649,41 @@ function em_admin_option_box_uninstall(){
593
  </tr>
594
  </table>
595
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
596
  <table class="form-table">
597
  <tr class="em-header"><td colspan="2">
598
  <h4><?php _e ( 'Uninstall/Reset', 'events-manager'); ?></h4>
162
  wp_redirect(em_wp_get_referer());
163
  exit();
164
  }
165
+ //import EM settings
166
+ if( !empty($_REQUEST['action']) && ($_REQUEST['action'] == 'import_em_settings' && check_admin_referer('import_em_settings')) || (is_multisite() && $_REQUEST['action'] == 'import_em_ms_settings' && check_admin_referer('import_em_ms_settings')) && is_super_admin() ){
167
+ //upload uniquely named file to system for usage later
168
+ if( !empty($_FILES['import_settings_file']['size']) && is_uploaded_file($_FILES['import_settings_file']['tmp_name']) ){
169
+ $settings = file_get_contents($_FILES['import_settings_file']['tmp_name']);
170
+ $settings = json_decode($settings, true);
171
+ if( is_array($settings) ){
172
+ if( is_multisite() && $_REQUEST['action'] == 'import_em_ms_settings' ){
173
+ global $EM_MS_Globals, $wpdb;
174
+ $sitewide_options = $EM_MS_Globals->get_globals();
175
+ foreach( $settings as $k => $v ){
176
+ if( in_array($k, $sitewide_options) ) update_site_option($k, $v);
177
+ }
178
+ }else{
179
+ foreach( $settings as $k => $v ){
180
+ if( preg_match('/^(?:db)emp?_/', $k) ){
181
+ update_option($k, $v);
182
+ }
183
+ }
184
+ }
185
+ $EM_Notices->add_confirm(__('Settings imported.','events-manager'), true);
186
+ wp_redirect(em_wp_get_referer());
187
+ exit();
188
+ }
189
+ }
190
+ $EM_Notices->add_error(__('Please upload a valid txt file containing Events Manager import settings.','events-manager'), true);
191
+ wp_redirect(em_wp_get_referer());
192
+ exit();
193
+ }
194
+ //export EM settings
195
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'export_em_settings' && check_admin_referer('export_em_settings') && is_super_admin() ){
196
+ global $wpdb;
197
+ $results = $wpdb->get_results('SELECT option_name, option_value FROM '.$wpdb->options ." WHERE option_name LIKE 'dbem_%' OR option_name LIKE 'emp_%' OR option_name LIKE 'em_%'", ARRAY_A);
198
+ $options = array();
199
+ foreach( $results as $result ) $options[$result['option_name']] = $result['option_value'];
200
+ header('Content-Type: text/plain; charset=utf-8');
201
+ header('Content-Disposition: attachment; filename="events-manager-settings.txt"');
202
+ echo json_encode($options);
203
+ exit();
204
+ }
205
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'export_ms_em_settings' && check_admin_referer('export_ms_em_settings') && is_multisite() && is_super_admin() ){
206
+ //delete transients, and add a flag to recheck dev version next time round
207
+ global $EM_MS_Globals, $wpdb;
208
+ $options = array();
209
+ $sitewide_options = $EM_MS_Globals->get_globals();
210
+ foreach( $sitewide_options as $option ) $options[$option] = get_site_option($option);
211
+ header('Content-Type: text/plain; charset=utf-8');
212
+ header('Content-Disposition: attachment; filename="events-manager-settings.txt"');
213
+ echo json_encode($options);
214
+ exit();
215
+ }
216
 
217
  }
218
  add_action('admin_init', 'em_options_save');
618
  $reset_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
619
  $recheck_updates_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=recheck_updates&amp;_wpnonce='.wp_create_nonce('em_recheck_updates_'.get_current_user_id().'_wpnonce');
620
  $check_devs = admin_url().'network/admin.php?page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
621
+ $export_settings_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=export_em_ms_settings&amp;_wpnonce='.wp_create_nonce('export_em_ms_settings');
622
+ $import_nonce = wp_create_nonce('import_em_ms_settings');
623
  }else{
624
  $uninstall_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
625
  $reset_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
626
  $recheck_updates_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=recheck_updates&amp;_wpnonce='.wp_create_nonce('em_recheck_updates_'.get_current_user_id().'_wpnonce');
627
  $check_devs = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
628
+ $export_settings_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=export_em_settings&amp;_wpnonce='.wp_create_nonce('export_em_settings');
629
+ $import_nonce = wp_create_nonce('import_em_settings');
630
  }
631
  ?>
632
  <div class="postbox" id="em-opt-admin-tools" >
633
  <div class="handlediv" title="<?php __('Click to toggle', 'events-manager'); ?>"><br /></div><h3><span><?php _e ( 'Admin Tools', 'events-manager'); ?> (<?php _e ( 'Advanced', 'events-manager'); ?>)</span></h3>
634
  <div class="inside">
635
+
636
  <table class="form-table">
637
  <tr class="em-header"><td colspan="2">
638
  <h4><?php _e ( 'Development Versions &amp; Updates', 'events-manager'); ?></h4>
649
  </tr>
650
  </table>
651
 
652
+ <table class="form-table">
653
+ <tr class="em-header"><td colspan="2">
654
+ <h4><?php esc_html_e( 'Import/Export Settings', 'events-manager'); ?></h4>
655
+ <?php if( is_multisite() && is_network_admin() ): ?>
656
+ <p><?php esc_html_e("Within the network admin area, only network-specific settings will be exported or imported. For individual site settings please visit the relevant site within your network.", 'events-manager'); ?></p>
657
+ <?php endif; ?>
658
+ </td></tr>
659
+ <tr>
660
+ <th style="text-align:right;">
661
+ <a href="#" class="button-secondary" id="em-admin-import-settings"><?php esc_html_e('Import Settings','events-manager'); ?></a>
662
+ </th>
663
+ <td>
664
+ <input type="file" name="import_settings_file" id="em-admin-import-settings-file" />
665
+ <p><em><?php echo esc_html(sprintf(__('Choose a settings file saved from a backup or another Events Manager installation and click the \'%s\' button.','events-manager'), __('Import Settings','events-manager'))); ?></em></p>
666
+ </td>
667
+ <script type="text/javascript" charset="utf-8">
668
+ jQuery(document).ready(function($){
669
+ $('a#em-admin-import-settings').click(function(e,el){
670
+ var thisform = $(this).closest('form');
671
+ thisform.find('input[type=text], textarea, select, input[type=radio], input[type=hidden]').prop('disabled', true);
672
+ thisform.find('input[name=_wpnonce]').val('<?php echo esc_attr($import_nonce); ?>').prop('disabled', false);
673
+ thisform.append($('<input type="hidden" name="action" value="<?php echo is_multisite() ? 'import_em_ms_settings':'import_em_settings'; ?>" />'));
674
+ thisform.attr('enctype', 'multipart/form-data').submit();
675
+ });
676
+ });
677
+ </script>
678
+ </tr>
679
+ <tr>
680
+ <th style="text-align:right;">
681
+ <a href="<?php echo $export_settings_url; ?>" class="button-secondary"><?php esc_html_e('Export Settings','events-manager'); ?></a>
682
+ </th>
683
+ <td><?php esc_html_e('Export your Events Manager settings and restore them here or on another website running this plugin.','events-manager'); ?></td>
684
+ </tr>
685
+ </table>
686
+
687
  <table class="form-table">
688
  <tr class="em-header"><td colspan="2">
689
  <h4><?php _e ( 'Uninstall/Reset', 'events-manager'); ?></h4>
admin/settings/tabs/bookings.php CHANGED
@@ -133,24 +133,14 @@
133
  <div class="inside">
134
  <table class='form-table'>
135
  <tr><td colspan='2'>
 
136
  <p><?php _e('By default, when a booking is made by a user, this booking is tied to a user account, if the user is not registered nor logged in and guest bookings are enabled, an account will be created for them.','events-manager'); ?></p>
137
- <p><?php _e('The option below allows you to disable user accounts and assign all bookings to a parent user, yet you will still see the supplied booking personal information for each booking. When this mode is enabled, extra booking information about the person is stored alongside the booking record rather than as a WordPress user.','events-manager'); ?></p>
138
  <p><?php _e('Users with accounts (which would be created by other means when this mode is enabled) will still be able to log in and make bookings linked to their account as normal.','events-manager'); ?></p>
139
  <p><?php _e('<strong>Warning : </strong> Various features afforded to users with an account will not be available, e.g. viewing bookings. Once you enable this and select a user, modifying these values will prevent older non-user bookings from displaying the correct information.','events-manager'); ?></p>
140
  </td></tr>
141
  <?php
142
  em_options_radio_binary ( __( 'Enable No-User Booking Mode?', 'events-manager'), 'dbem_bookings_registration_disable', __( 'This disables user registrations for bookings.', 'events-manager') );
143
  em_options_radio_binary ( __( 'Allow bookings with registered emails?', 'events-manager'), 'dbem_bookings_registration_disable_user_emails', __( 'By default, if a guest tries to book an event using the email of a user account on your site they will be asked to log in, selecting yes will bypass this security measure.', 'events-manager').'<br />'.__('<strong>Warning : </strong> By enabling this, registered users will not be able to see bookings they make as guests in their "My Bookings" page.','events-manager') );
144
- $current_user = array();
145
- if( get_option('dbem_bookings_registration_user') ){
146
- $user = get_user_by('id',get_option('dbem_bookings_registration_user'));
147
- $current_user[$user->ID] = $user->display_name;
148
- }
149
- if( defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') && EM_OPTIMIZE_SETTINGS_PAGE_USERS ){
150
- em_options_input_text ( __( 'Assign bookings to', 'events-manager'), 'dbem_bookings_registration_user', __('Please add a User ID.','events-manager').' '.__( 'Choose a parent user to assign bookings to. People making their booking will be unaware of this and will never have access to those user details. This should be a subscriber user you do not use to log in with yourself.', 'events-manager') );
151
- }else{
152
- em_options_select ( __( 'Assign bookings to', 'events-manager'), 'dbem_bookings_registration_user', em_get_wp_users(array('role' => 'subscriber'), $current_user), __( 'Choose a parent user to assign bookings to. People making their booking will be unaware of this and will never have access to those user details. This should be a subscriber user you do not use to log in with yourself.', 'events-manager') );
153
- }
154
  echo $save_button;
155
  ?>
156
  </table>
133
  <div class="inside">
134
  <table class='form-table'>
135
  <tr><td colspan='2'>
136
+ <p><?php _e('The option below allows you to disable user accounts, yet you will still see the supplied personal information for each booking.','events-manager'); ?></p>
137
  <p><?php _e('By default, when a booking is made by a user, this booking is tied to a user account, if the user is not registered nor logged in and guest bookings are enabled, an account will be created for them.','events-manager'); ?></p>
 
138
  <p><?php _e('Users with accounts (which would be created by other means when this mode is enabled) will still be able to log in and make bookings linked to their account as normal.','events-manager'); ?></p>
139
  <p><?php _e('<strong>Warning : </strong> Various features afforded to users with an account will not be available, e.g. viewing bookings. Once you enable this and select a user, modifying these values will prevent older non-user bookings from displaying the correct information.','events-manager'); ?></p>
140
  </td></tr>
141
  <?php
142
  em_options_radio_binary ( __( 'Enable No-User Booking Mode?', 'events-manager'), 'dbem_bookings_registration_disable', __( 'This disables user registrations for bookings.', 'events-manager') );
143
  em_options_radio_binary ( __( 'Allow bookings with registered emails?', 'events-manager'), 'dbem_bookings_registration_disable_user_emails', __( 'By default, if a guest tries to book an event using the email of a user account on your site they will be asked to log in, selecting yes will bypass this security measure.', 'events-manager').'<br />'.__('<strong>Warning : </strong> By enabling this, registered users will not be able to see bookings they make as guests in their "My Bookings" page.','events-manager') );
 
 
 
 
 
 
 
 
 
 
144
  echo $save_button;
145
  ?>
146
  </table>
admin/settings/tabs/emails.php CHANGED
@@ -105,7 +105,7 @@
105
  em_options_radio_binary ( __( 'Disable new registration email?', 'events-manager'), 'dbem_email_disable_registration', __( 'Check this option if you want to prevent the WordPress registration email from going out when a user anonymously books an event.', 'events-manager') );
106
 
107
  em_options_input_text ( __( 'Registration email subject', 'events-manager'), 'dbem_bookings_email_registration_subject' );
108
- em_options_textarea ( __( 'Registration email', 'events-manager'), 'dbem_bookings_email_registration_body', sprintf(__('%s is replaced by username and %s is replaced by the user password.','events-manager'),'<code>%username%</code>','<code>%password%</code>') );
109
  echo $save_button;
110
  ?>
111
  </table>
105
  em_options_radio_binary ( __( 'Disable new registration email?', 'events-manager'), 'dbem_email_disable_registration', __( 'Check this option if you want to prevent the WordPress registration email from going out when a user anonymously books an event.', 'events-manager') );
106
 
107
  em_options_input_text ( __( 'Registration email subject', 'events-manager'), 'dbem_bookings_email_registration_subject' );
108
+ em_options_textarea ( __( 'Registration email', 'events-manager'), 'dbem_bookings_email_registration_body', sprintf(__('%s is replaced by username, %s is replaced by the user password and %s is replaced by a link to create a password.','events-manager'),'<code>%username%</code>','<code>%password%</code>','<code>%passwordurl%</code>') );
109
  echo $save_button;
110
  ?>
111
  </table>
admin/settings/tabs/formats.php CHANGED
@@ -103,8 +103,8 @@
103
  ?>
104
  <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Country', 'events-manager'); ?></h5></td></tr>
105
  <?php
106
- em_options_radio_binary ( __( 'Show countries?', 'events-manager'), 'dbem_search_form_countries', '', '', '#dbem_search_form_country_label_row, #dbem_search_form_countries_label_row' );
107
- em_options_select ( __( 'Default Country', 'events-manager'), 'dbem_search_form_default_country', em_get_countries(__('no default country', 'events-manager')), __('Search form will be pre-selected with this country, if searching by country is disabled above, only search results from this country will be returned.','events-manager') );
108
  em_options_input_text ( __( 'Label', 'events-manager'), 'dbem_search_form_country_label', __('Appears as the label for this search option.','events-manager') );
109
  em_options_input_text ( __( 'All countries text', 'events-manager'), 'dbem_search_form_countries_label', __('Appears as the first default search option.','events-manager') );
110
  ?>
@@ -445,6 +445,7 @@
445
  <?php em_options_input_text(__('Google Maps API Browser Key','events-manager'), 'dbem_google_maps_browser_key', sprintf(__('Google Maps require an API key, please see our %s page for instructions on obtaining one.', 'events-manager'), sprintf('<a href="http://wp-events-plugin.com/documentation/google-maps/api-key/">%s</a>', __('documentation','events-manager')))); ?>
446
  <?php em_options_input_text(__('Default map width','events-manager'), 'dbem_map_default_width', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'events-manager'), '<code>100%</code>', '<code>100px</code>')); ?>
447
  <?php em_options_input_text(__('Default map height','events-manager'), 'dbem_map_default_height', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'events-manager'), '<code>100%</code>', '<code>100px</code>')); ?>
 
448
  </tr>
449
  <tr class="em-header"><td colspan="2">
450
  <h4><?php _e('Global Map Format','events-manager'); ?></h4>
103
  ?>
104
  <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Country', 'events-manager'); ?></h5></td></tr>
105
  <?php
106
+ em_options_radio_binary ( __( 'Show countries?', 'events-manager'), 'dbem_search_form_countries', '', '', '#dbem_search_form_default_country_row, #dbem_search_form_country_label_row, #dbem_search_form_countries_label_row' );
107
+ em_options_select ( __( 'Default Country', 'events-manager'), 'dbem_search_form_default_country', em_get_countries(__('no default country', 'events-manager')), __('Search form will be pre-selected with this country.','events-manager') );
108
  em_options_input_text ( __( 'Label', 'events-manager'), 'dbem_search_form_country_label', __('Appears as the label for this search option.','events-manager') );
109
  em_options_input_text ( __( 'All countries text', 'events-manager'), 'dbem_search_form_countries_label', __('Appears as the first default search option.','events-manager') );
110
  ?>
445
  <?php em_options_input_text(__('Google Maps API Browser Key','events-manager'), 'dbem_google_maps_browser_key', sprintf(__('Google Maps require an API key, please see our %s page for instructions on obtaining one.', 'events-manager'), sprintf('<a href="http://wp-events-plugin.com/documentation/google-maps/api-key/">%s</a>', __('documentation','events-manager')))); ?>
446
  <?php em_options_input_text(__('Default map width','events-manager'), 'dbem_map_default_width', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'events-manager'), '<code>100%</code>', '<code>100px</code>')); ?>
447
  <?php em_options_input_text(__('Default map height','events-manager'), 'dbem_map_default_height', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'events-manager'), '<code>100%</code>', '<code>100px</code>')); ?>
448
+ <?php em_options_textarea(__('Google Maps Style', 'events-manager'), 'dbem_google_maps_styles', sprintf(__('You can add styles to your maps to give them a unique look. Build one using the %s or choose from the many free templates on %s paste the generated JSON code here.', 'events-manager'), '<a href="https://mapstyle.withgoogle.com/" target="_blank">'.__('Google Maps Styling Wizard', 'events-manager').'</a>', '<a href="https://snazzymaps.com/explore" target="_blank">Snazzy Maps</a>')); ?>
449
  </tr>
450
  <tr class="em-header"><td colspan="2">
451
  <h4><?php _e('Global Map Format','events-manager'); ?></h4>
buddypress/bp-em-core.php CHANGED
@@ -1,165 +1,165 @@
1
- <?php
2
- //Main loader for buddypress
3
- /**
4
- * Events Manager component for BuddyPress
5
- * @author marcus
6
- * @since 5.0
7
- */
8
- class BP_EM_Component extends BP_Component {
9
-
10
- function __construct() {
11
- global $bp;
12
- parent::start('events', __('Events', 'events-manager'), EM_DIR);
13
- $this->includes();
14
- //TODO make BP component optional
15
- $bp->active_components[$this->id] = '1';
16
- }
17
-
18
- function includes( $includes = array() ) {
19
- // Files to include
20
- $includes = array(
21
- 'buddypress/bp-em-activity.php',
22
- 'buddypress/bp-em-templatetags.php',
23
- 'buddypress/bp-em-notifications.php',
24
- 'buddypress/screens/profile.php',
25
- 'buddypress/screens/my-events.php',
26
- 'buddypress/screens/my-locations.php',
27
- 'buddypress/screens/attending.php',
28
- 'buddypress/screens/my-bookings.php',
29
- 'buddypress/screens/my-group-events.php'
30
- );
31
- if( bp_is_active('groups') ){
32
- $includes[] = 'buddypress/screens/group-events.php';
33
- $includes[] = 'buddypress/bp-em-groups.php';
34
- }
35
- parent::includes( $includes );
36
- //TODO add admin pages for extra BP specific settings
37
- }
38
-
39
- /**
40
- * Sets up the global Events Manager BuddyPress Components
41
- */
42
- function setup_globals( $args = array() ) {
43
- global $bp, $wpdb;
44
- // Define a slug constant that will be used to view this components pages
45
- if ( !defined( 'BP_EM_SLUG' ) )
46
- define ( 'BP_EM_SLUG', str_replace('/','-', EM_POST_TYPE_EVENT_SLUG) );
47
-
48
- // Set up the $globals array to be passed along to parent::setup_globals()
49
- $globals = array(
50
- 'slug' => BP_EM_SLUG,
51
- 'has_directory' => false, //already done by EM
52
- 'notification_callback' => 'bp_em_format_notifications',
53
- 'search_string' => sprintf(__( 'Search %s...', 'events-manager'),__('Events','events-manager')),
54
- );
55
-
56
- // Let BP_Component::setup_globals() do its work.
57
- parent::setup_globals( $globals );
58
-
59
- //quick link shortcut - may need to revisit this
60
- $bp->{$this->id}->link = trailingslashit($bp->loggedin_user->domain).BP_EM_SLUG.'/';
61
- }
62
-
63
- public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
64
- global $blog_id;
65
- //check multisite or normal mode for correct permission checking
66
- if(is_multisite() && $blog_id != BP_ROOT_BLOG){
67
- //FIXME MS mode doesn't seem to recognize cross subsite caps, using the proper functions, for now we use switch_blog.
68
- $current_blog = $blog_id;
69
- switch_to_blog(BP_ROOT_BLOG);
70
- $can_manage_events = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_events');
71
- $can_manage_locations = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_locations');
72
- $can_manage_bookings = current_user_can_for_blog(BP_ROOT_BLOG, 'manage_bookings');
73
- switch_to_blog($current_blog);
74
- }else{
75
- $can_manage_events = current_user_can('edit_events');
76
- $can_manage_locations = current_user_can('edit_locations');
77
- $can_manage_bookings = current_user_can('manage_bookings');
78
- }
79
- /* Add 'Events' to the main user profile navigation */
80
- $main_nav = array(
81
- 'name' => __( 'Events', 'events-manager'),
82
- 'slug' => em_bp_get_slug(),
83
- 'position' => 80,
84
- 'screen_function' => 'bp_em_events',
85
- 'default_subnav_slug' => 'profile'
86
- );
87
-
88
- $em_link = trailingslashit( bp_displayed_user_domain() . em_bp_get_slug() );
89
-
90
- /* Create SubNav Items */
91
- $sub_nav[] = array(
92
- 'name' => __( 'My Profile', 'events-manager'),
93
- 'slug' => 'profile',
94
- 'parent_slug' => em_bp_get_slug(),
95
- 'parent_url' => $em_link,
96
- 'screen_function' => 'bp_em_events',
97
- 'position' => 10
98
- );
99
-
100
- $sub_nav[] = array(
101
- 'name' => __( 'Events I\'m Attending', 'events-manager'),
102
- 'slug' => 'attending',
103
- 'parent_slug' => em_bp_get_slug(),
104
- 'parent_url' => $em_link,
105
- 'screen_function' => 'bp_em_attending',
106
- 'position' => 20,
107
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
108
- );
109
-
110
- if( $can_manage_events ){
111
- $sub_nav[] = array(
112
- 'name' => __( 'My Events', 'events-manager'),
113
- 'slug' => 'my-events',
114
- 'parent_slug' => em_bp_get_slug(),
115
- 'parent_url' => $em_link,
116
- 'screen_function' => 'bp_em_my_events',
117
- 'position' => 30,
118
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
119
- );
120
- }
121
-
122
- if( $can_manage_locations && get_option('dbem_locations_enabled') ){
123
- $sub_nav[] = array(
124
- 'name' => __( 'My Locations', 'events-manager'),
125
- 'slug' => 'my-locations',
126
- 'parent_slug' => em_bp_get_slug(),
127
- 'parent_url' => $em_link,
128
- 'screen_function' => 'bp_em_my_locations',
129
- 'position' => 40,
130
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
131
- );
132
- }
133
-
134
- if( $can_manage_bookings && get_option('dbem_rsvp_enabled') ){
135
- $sub_nav[] = array(
136
- 'name' => __( 'My Event Bookings', 'events-manager'),
137
- 'slug' => 'my-bookings',
138
- 'parent_slug' => em_bp_get_slug(),
139
- 'parent_url' => $em_link,
140
- 'screen_function' => 'bp_em_my_bookings',
141
- 'position' => 50,
142
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
143
- );
144
- }
145
-
146
- if( bp_is_active('groups') ){
147
- /* Create Profile Group Sub-Nav */
148
- $sub_nav[] = array(
149
- 'name' => __( 'Events', 'events-manager'),
150
- 'slug' => 'group-events',
151
- 'parent_slug' => bp_get_groups_slug(),
152
- 'parent_url' =>trailingslashit( bp_displayed_user_domain() . bp_get_groups_slug() ),
153
- 'screen_function' => 'bp_em_my_group_events',
154
- 'position' => 60,
155
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
156
- );
157
- }
158
-
159
- parent::setup_nav( $main_nav, $sub_nav );
160
- add_action( 'bp_init', array(&$this, 'setup_group_nav') );
161
- }
162
-
163
  public function setup_admin_bar( $wp_admin_nav = array() ) {
164
  global $bp, $blog_id;
165
 
@@ -167,7 +167,7 @@ class BP_EM_Component extends BP_Component {
167
  $wp_admin_nav = array();
168
 
169
  // Menus for logged in user
170
- if ( is_user_logged_in() ) {
171
  //check multisite or normal mode for correct permission checking
172
  if(is_multisite() && $blog_id != BP_ROOT_BLOG){
173
  //FIXME MS mode doesn't seem to recognize cross subsite caps, using the proper functions, for now we use switch_blog.
@@ -176,20 +176,20 @@ class BP_EM_Component extends BP_Component {
176
  $can_manage_events = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_events');
177
  $can_manage_locations = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_locations');
178
  $can_manage_bookings = current_user_can_for_blog(BP_ROOT_BLOG, 'manage_bookings');
179
- switch_to_blog($current_blog);
180
  }else{
181
  $can_manage_events = current_user_can('edit_events');
182
  $can_manage_locations = current_user_can('edit_locations');
183
  $can_manage_bookings = current_user_can('manage_bookings');
184
- }
185
 
186
- $em_link = trailingslashit( bp_loggedin_user_domain() . em_bp_get_slug() );
187
 
188
  /* Add 'Events' to the main user profile navigation */
189
- $wp_admin_nav[] = array(
190
- 'parent' => $bp->my_account_menu_id,
191
- 'id' => 'my-em-' . $this->id,
192
- 'title' => __( 'Events', 'events-manager'),
193
  'href' => $em_link
194
  );
195
 
@@ -201,10 +201,10 @@ class BP_EM_Component extends BP_Component {
201
  'href' => $em_link.'profile/'
202
  );
203
 
204
- $wp_admin_nav[] = array(
205
- 'parent' => 'my-em-' . $this->id,
206
- 'id' => 'my-em-' . $this->id .'-attending',
207
- 'title' => __( 'Events I\'m Attending', 'events-manager'),
208
  'href' => $em_link.'attending/'
209
  );
210
 
@@ -218,123 +218,128 @@ class BP_EM_Component extends BP_Component {
218
  }
219
 
220
  if( $can_manage_locations && get_option('dbem_locations_enabled') ){
221
- $wp_admin_nav[] = array(
222
- 'parent' => 'my-em-' . $this->id,
223
- 'id' => 'my-em-' . $this->id .'-my-locations',
224
- 'title' => __( 'My Locations', 'events-manager'),
225
  'href' => $em_link.'my-locations/'
226
  );
227
  }
228
 
229
  if( $can_manage_bookings && get_option('dbem_rsvp_enabled') ){
230
- $wp_admin_nav[] = array(
231
- 'parent' => 'my-em-' . $this->id,
232
- 'id' => 'my-em-' . $this->id .'-my-bookings',
233
- 'title' => __( 'My Event Bookings', 'events-manager'),
234
  'href' => $em_link.'my-bookings/'
235
  );
236
  }
237
 
238
  if( bp_is_active('groups') ){
239
  /* Create Profile Group Sub-Nav */
240
- $wp_admin_nav[] = array(
241
- 'parent' => 'my-account-groups',
242
- 'id' => 'my-account-groups-' . $this->id ,
243
- 'title' => __( 'Events', 'events-manager'),
244
  'href' => trailingslashit( bp_loggedin_user_domain() . bp_get_groups_slug() ) . 'group-events/'
245
  );
246
  }
247
  }
248
 
249
  parent::setup_admin_bar( $wp_admin_nav );
250
- }
251
-
252
- function setup_group_nav(){
253
- global $bp;
254
- /* Add some group subnav items */
255
- $user_access = false;
256
- $group_link = '';
257
- if( bp_is_active('groups') && !empty($bp->groups->current_group) ){
258
- $group_link = $bp->root_domain . '/' . bp_get_groups_root_slug() . '/' . $bp->groups->current_group->slug . '/';
259
- $user_access = $bp->groups->current_group->user_has_access;
260
- if( !empty($bp->current_component) && $bp->current_component == 'groups' ){
261
- $count = EM_Events::count(array('group'=>$bp->groups->current_group->id));
262
- if( empty($count) ) $count = 0;
263
- }
264
- bp_core_new_subnav_item( array(
265
- 'name' => __( 'Events', 'events-manager') . " <span>$count</span>",
266
- 'slug' => 'events',
267
- 'parent_url' => $group_link,
268
- 'parent_slug' => $bp->groups->current_group->slug,
269
- 'screen_function' => 'bp_em_group_events',
270
- 'position' => 50,
271
- 'user_has_access' => $user_access,
272
- 'item_css_id' => 'events'
273
- ));
274
- }
275
- }
276
- }
277
- function bp_em_load_core_component() {
278
- global $bp;
279
- $bp->events = new BP_EM_Component();
280
- }
281
- add_action( 'bp_loaded', 'bp_em_load_core_component' );
282
-
283
- if( !is_admin() || ( defined('DOING_AJAX') && !empty($_REQUEST['is_public'])) ){
284
- /*
285
- * Links and URL Rewriting
286
- */
287
- function em_bp_rewrite_edit_url($url, $EM_Event){
288
- global $bp;
289
- return $bp->events->link.'my-events/?action=edit&event_id='.$EM_Event->event_id;
290
- }
291
- if( !get_option('dbem_edit_events_page') ){
292
- add_filter('em_event_get_edit_url','em_bp_rewrite_edit_url',10,2);
293
- }
294
-
295
- function em_bp_rewrite_bookings_url($url, $EM_Event){
296
- global $bp;
297
- return $bp->events->link.'my-bookings/?event_id='.$EM_Event->event_id;
298
- }
299
- if( !get_option('dbem_edit_bookings_page') ){
300
- add_filter('em_event_get_bookings_url','em_bp_rewrite_bookings_url',10,2);
301
- }
302
-
303
- function em_bp_rewrite_edit_location_url($url, $EM_Location){
304
- global $bp;
305
- return $bp->events->link.'my-locations/?action=edit&location_id='.$EM_Location->location_id;
306
- }
307
- if( !get_option('dbem_edit_locations_page') ){
308
- add_filter('em_location_get_edit_url','em_bp_rewrite_edit_location_url',10,2);
309
- }
310
- }
311
-
312
- //CSS and JS Loading
 
 
 
 
 
313
  function bp_em_enqueue_scripts( ){
314
- if( bp_is_current_component('events') || (bp_is_current_component('groups') && bp_is_current_action('group-events')) ){
315
- add_filter('option_dbem_js_limit', create_function('$args','return false;'));
316
- add_filter('option_dbem_css_limit', create_function('$args','return false;'));
317
- }
318
-
319
- }
320
- add_action('wp_enqueue_scripts','bp_em_enqueue_scripts',1);
321
-
322
- function bp_em_messages_js_compat() {
323
- if(bp_is_messages_compose_screen()){
324
- wp_deregister_script( 'events-manager' );
325
- }
326
- }
327
- add_action( 'wp_print_scripts', 'bp_em_messages_js_compat', 100 );
328
-
329
- /**
330
- * Delete events when you delete a user.
331
- */
332
- function bp_em_remove_data( $user_id ) {
333
- $EM_Events = EM_Events::get(array('scope'=>'all','owner'=>$user_id, 'status'=>false));
334
- EM_Events::delete($EM_Events);
335
- }
336
- add_action( 'wpmu_delete_user', 'bp_em_remove_data', 1 );
337
- add_action( 'delete_user', 'bp_em_remove_data', 1 );
338
-
339
- define('EM_BP_LOADED',true); //so we know
340
  ?>
1
+ <?php
2
+ //Main loader for buddypress
3
+ /**
4
+ * Events Manager component for BuddyPress
5
+ * @author marcus
6
+ * @since 5.0
7
+ */
8
+ class BP_EM_Component extends BP_Component {
9
+
10
+ function __construct() {
11
+ global $bp;
12
+ parent::start('events', __('Events', 'events-manager'), EM_DIR);
13
+ $this->includes();
14
+ //TODO make BP component optional
15
+ $bp->active_components[$this->id] = '1';
16
+ }
17
+
18
+ function includes( $includes = array() ) {
19
+ // Files to include
20
+ $includes = array(
21
+ 'buddypress/bp-em-activity.php',
22
+ 'buddypress/bp-em-templatetags.php',
23
+ 'buddypress/bp-em-notifications.php',
24
+ 'buddypress/screens/profile.php',
25
+ 'buddypress/screens/my-events.php',
26
+ 'buddypress/screens/my-locations.php',
27
+ 'buddypress/screens/attending.php',
28
+ 'buddypress/screens/my-bookings.php',
29
+ 'buddypress/screens/my-group-events.php'
30
+ );
31
+ if( bp_is_active('groups') ){
32
+ $includes[] = 'buddypress/screens/group-events.php';
33
+ $includes[] = 'buddypress/bp-em-groups.php';
34
+ }
35
+ parent::includes( $includes );
36
+ //TODO add admin pages for extra BP specific settings
37
+ }
38
+
39
+ /**
40
+ * Sets up the global Events Manager BuddyPress Components
41
+ */
42
+ function setup_globals( $args = array() ) {
43
+ global $bp, $wpdb;
44
+ // Define a slug constant that will be used to view this components pages
45
+ if ( !defined( 'BP_EM_SLUG' ) )
46
+ define ( 'BP_EM_SLUG', str_replace('/','-', EM_POST_TYPE_EVENT_SLUG) );
47
+
48
+ // Set up the $globals array to be passed along to parent::setup_globals()
49
+ $globals = array(
50
+ 'slug' => BP_EM_SLUG,
51
+ 'has_directory' => false, //already done by EM
52
+ 'notification_callback' => 'bp_em_format_notifications',
53
+ 'search_string' => sprintf(__( 'Search %s...', 'events-manager'),__('Events','events-manager')),
54
+ );
55
+
56
+ // Let BP_Component::setup_globals() do its work.
57
+ parent::setup_globals( $globals );
58
+
59
+ //quick link shortcut - may need to revisit this
60
+ $bp->{$this->id}->link = trailingslashit($bp->loggedin_user->domain).BP_EM_SLUG.'/';
61
+ }
62
+
63
+ public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
64
+ global $blog_id;
65
+ //check multisite or normal mode for correct permission checking
66
+ if(is_multisite() && $blog_id != BP_ROOT_BLOG){
67
+ //FIXME MS mode doesn't seem to recognize cross subsite caps, using the proper functions, for now we use switch_blog.
68
+ $current_blog = $blog_id;
69
+ switch_to_blog(BP_ROOT_BLOG);
70
+ $can_manage_events = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_events');
71
+ $can_manage_locations = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_locations');
72
+ $can_manage_bookings = current_user_can_for_blog(BP_ROOT_BLOG, 'manage_bookings');
73
+ restore_current_blog();
74
+ }else{
75
+ $can_manage_events = current_user_can('edit_events');
76
+ $can_manage_locations = current_user_can('edit_locations');
77
+ $can_manage_bookings = current_user_can('manage_bookings');
78
+ }
79
+ /* Add 'Events' to the main user profile navigation */
80
+ $main_nav = array(
81
+ 'name' => __( 'Events', 'events-manager'),
82
+ 'slug' => em_bp_get_slug(),
83
+ 'position' => 80,
84
+ 'screen_function' => 'bp_em_events',
85
+ 'default_subnav_slug' => 'profile'
86
+ );
87
+
88
+ $em_link = trailingslashit( bp_displayed_user_domain() . em_bp_get_slug() );
89
+
90
+ /* Create SubNav Items */
91
+ $sub_nav[] = array(
92
+ 'name' => __( 'My Profile', 'events-manager'),
93
+ 'slug' => 'profile',
94
+ 'parent_slug' => em_bp_get_slug(),
95
+ 'parent_url' => $em_link,
96
+ 'screen_function' => 'bp_em_events',
97
+ 'position' => 10
98
+ );
99
+
100
+ $sub_nav[] = array(
101
+ 'name' => __( 'Events I\'m Attending', 'events-manager'),
102
+ 'slug' => 'attending',
103
+ 'parent_slug' => em_bp_get_slug(),
104
+ 'parent_url' => $em_link,
105
+ 'screen_function' => 'bp_em_attending',
106
+ 'position' => 20,
107
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
108
+ );
109
+
110
+ if( $can_manage_events ){
111
+ $sub_nav[] = array(
112
+ 'name' => __( 'My Events', 'events-manager'),
113
+ 'slug' => 'my-events',
114
+ 'parent_slug' => em_bp_get_slug(),
115
+ 'parent_url' => $em_link,
116
+ 'screen_function' => 'bp_em_my_events',
117
+ 'position' => 30,
118
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
119
+ );
120
+ }
121
+
122
+ if( $can_manage_locations && get_option('dbem_locations_enabled') ){
123
+ $sub_nav[] = array(
124
+ 'name' => __( 'My Locations', 'events-manager'),
125
+ 'slug' => 'my-locations',
126
+ 'parent_slug' => em_bp_get_slug(),
127
+ 'parent_url' => $em_link,
128
+ 'screen_function' => 'bp_em_my_locations',
129
+ 'position' => 40,
130
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
131
+ );
132
+ }
133
+
134
+ if( $can_manage_bookings && get_option('dbem_rsvp_enabled') ){
135
+ $sub_nav[] = array(
136
+ 'name' => __( 'My Event Bookings', 'events-manager'),
137
+ 'slug' => 'my-bookings',
138
+ 'parent_slug' => em_bp_get_slug(),
139
+ 'parent_url' => $em_link,
140
+ 'screen_function' => 'bp_em_my_bookings',
141
+ 'position' => 50,
142
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
143
+ );
144
+ }
145
+
146
+ if( bp_is_active('groups') ){
147
+ /* Create Profile Group Sub-Nav */
148
+ $sub_nav[] = array(
149
+ 'name' => __( 'Events', 'events-manager'),
150
+ 'slug' => 'group-events',
151
+ 'parent_slug' => bp_get_groups_slug(),
152
+ 'parent_url' =>trailingslashit( bp_displayed_user_domain() . bp_get_groups_slug() ),
153
+ 'screen_function' => 'bp_em_my_group_events',
154
+ 'position' => 60,
155
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
156
+ );
157
+ }
158
+
159
+ parent::setup_nav( $main_nav, $sub_nav );
160
+ add_action( 'bp_init', array(&$this, 'setup_group_nav') );
161
+ }
162
+
163
  public function setup_admin_bar( $wp_admin_nav = array() ) {
164
  global $bp, $blog_id;
165
 
167
  $wp_admin_nav = array();
168
 
169
  // Menus for logged in user
170
+ if ( is_user_logged_in() ) {
171
  //check multisite or normal mode for correct permission checking
172
  if(is_multisite() && $blog_id != BP_ROOT_BLOG){
173
  //FIXME MS mode doesn't seem to recognize cross subsite caps, using the proper functions, for now we use switch_blog.
176
  $can_manage_events = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_events');
177
  $can_manage_locations = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_locations');
178
  $can_manage_bookings = current_user_can_for_blog(BP_ROOT_BLOG, 'manage_bookings');
179
+ restore_current_blog();
180
  }else{
181
  $can_manage_events = current_user_can('edit_events');
182
  $can_manage_locations = current_user_can('edit_locations');
183
  $can_manage_bookings = current_user_can('manage_bookings');
184
+ }
185
 
186
+ $em_link = trailingslashit( bp_loggedin_user_domain() . em_bp_get_slug() );
187
 
188
  /* Add 'Events' to the main user profile navigation */
189
+ $wp_admin_nav[] = array(
190
+ 'parent' => $bp->my_account_menu_id,
191
+ 'id' => 'my-em-' . $this->id,
192
+ 'title' => __( 'Events', 'events-manager'),
193
  'href' => $em_link
194
  );
195
 
201
  'href' => $em_link.'profile/'
202
  );
203
 
204
+ $wp_admin_nav[] = array(
205
+ 'parent' => 'my-em-' . $this->id,
206
+ 'id' => 'my-em-' . $this->id .'-attending',
207
+ 'title' => __( 'Events I\'m Attending', 'events-manager'),
208
  'href' => $em_link.'attending/'
209
  );
210
 
218
  }
219
 
220
  if( $can_manage_locations && get_option('dbem_locations_enabled') ){
221
+ $wp_admin_nav[] = array(
222
+ 'parent' => 'my-em-' . $this->id,
223
+ 'id' => 'my-em-' . $this->id .'-my-locations',
224
+ 'title' => __( 'My Locations', 'events-manager'),
225
  'href' => $em_link.'my-locations/'
226
  );
227
  }
228
 
229
  if( $can_manage_bookings && get_option('dbem_rsvp_enabled') ){
230
+ $wp_admin_nav[] = array(
231
+ 'parent' => 'my-em-' . $this->id,
232
+ 'id' => 'my-em-' . $this->id .'-my-bookings',
233
+ 'title' => __( 'My Event Bookings', 'events-manager'),
234
  'href' => $em_link.'my-bookings/'
235
  );
236
  }
237
 
238
  if( bp_is_active('groups') ){
239
  /* Create Profile Group Sub-Nav */
240
+ $wp_admin_nav[] = array(
241
+ 'parent' => 'my-account-groups',
242
+ 'id' => 'my-account-groups-' . $this->id ,
243
+ 'title' => __( 'Events', 'events-manager'),
244
  'href' => trailingslashit( bp_loggedin_user_domain() . bp_get_groups_slug() ) . 'group-events/'
245
  );
246
  }
247
  }
248
 
249
  parent::setup_admin_bar( $wp_admin_nav );
250
+ }
251
+
252
+ function setup_group_nav(){
253
+ global $bp;
254
+ /* Add some group subnav items */
255
+ $user_access = false;
256
+ $group_link = '';
257
+ if( bp_is_active('groups') && !empty($bp->groups->current_group) ){
258
+ $group_link = $bp->root_domain . '/' . bp_get_groups_root_slug() . '/' . $bp->groups->current_group->slug . '/';
259
+ $user_access = $bp->groups->current_group->user_has_access;
260
+ if( !empty($bp->current_component) && $bp->current_component == 'groups' ){
261
+ $count = EM_Events::count(array('group'=>$bp->groups->current_group->id));
262
+ if( empty($count) ) $count = 0;
263
+ }
264
+ bp_core_new_subnav_item( array(
265
+ 'name' => __( 'Events', 'events-manager') . " <span>$count</span>",
266
+ 'slug' => 'events',
267
+ 'parent_url' => $group_link,
268
+ 'parent_slug' => $bp->groups->current_group->slug,
269
+ 'screen_function' => 'bp_em_group_events',
270
+ 'position' => 50,
271
+ 'user_has_access' => $user_access,
272
+ 'item_css_id' => 'events'
273
+ ));
274
+ }
275
+ }
276
+ }
277
+ function bp_em_load_core_component() {
278
+ global $bp;
279
+ $bp->events = new BP_EM_Component();
280
+ }
281
+ add_action( 'bp_loaded', 'bp_em_load_core_component' );
282
+
283
+ if( !is_admin() || ( defined('DOING_AJAX') && !empty($_REQUEST['is_public'])) ){
284
+ /*
285
+ * Links and URL Rewriting
286
+ */
287
+ function em_bp_rewrite_edit_url($url, $EM_Event){
288
+ global $bp;
289
+ return $bp->events->link.'my-events/?action=edit&event_id='.$EM_Event->event_id;
290
+ }
291
+ function em_bp_rewrite_events_admin_url( $url ){
292
+ global $bp;
293
+ return $bp->events->link.'my-events/';
294
+ }
295
+ if( !get_option('dbem_edit_events_page') ){
296
+ add_filter('em_event_get_edit_url','em_bp_rewrite_edit_url',10,2);
297
+ add_filter('em_get_events_admin_url','em_bp_rewrite_edit_url',10,2);
298
+ }
299
+
300
+ function em_bp_rewrite_bookings_url($url, $EM_Event){
301
+ global $bp;
302
+ return $bp->events->link.'my-bookings/?event_id='.$EM_Event->event_id;
303
+ }
304
+ if( !get_option('dbem_edit_bookings_page') ){
305
+ add_filter('em_event_get_bookings_url','em_bp_rewrite_bookings_url',10,2);
306
+ }
307
+
308
+ function em_bp_rewrite_edit_location_url($url, $EM_Location){
309
+ global $bp;
310
+ return $bp->events->link.'my-locations/?action=edit&location_id='.$EM_Location->location_id;
311
+ }
312
+ if( !get_option('dbem_edit_locations_page') ){
313
+ add_filter('em_location_get_edit_url','em_bp_rewrite_edit_location_url',10,2);
314
+ }
315
+ }
316
+
317
+ //CSS and JS Loading
318
  function bp_em_enqueue_scripts( ){
319
+ if( bp_is_current_component('events') || (bp_is_current_component('groups') && bp_is_current_action('group-events')) ){
320
+ add_filter('option_dbem_js_limit', create_function('$args','return false;'));
321
+ add_filter('option_dbem_css_limit', create_function('$args','return false;'));
322
+ }
323
+
324
+ }
325
+ add_action('wp_enqueue_scripts','bp_em_enqueue_scripts',1);
326
+
327
+ function bp_em_messages_js_compat() {
328
+ if(bp_is_messages_compose_screen()){
329
+ wp_deregister_script( 'events-manager' );
330
+ }
331
+ }
332
+ add_action( 'wp_print_scripts', 'bp_em_messages_js_compat', 100 );
333
+
334
+ /**
335
+ * Delete events when you delete a user.
336
+ */
337
+ function bp_em_remove_data( $user_id ) {
338
+ $EM_Events = EM_Events::get(array('scope'=>'all','owner'=>$user_id, 'status'=>false));
339
+ EM_Events::delete($EM_Events);
340
+ }
341
+ add_action( 'wpmu_delete_user', 'bp_em_remove_data', 1 );
342
+ add_action( 'delete_user', 'bp_em_remove_data', 1 );
343
+
344
+ define('EM_BP_LOADED',true); //so we know
345
  ?>
buddypress/bp-em-notifications.php CHANGED
@@ -79,7 +79,7 @@ function bp_em_add_booking_notification($result, $EM_Booking){
79
  }elseif( $EM_Booking->get_status() == 3 ){
80
  $action = 'cancelled_booking';
81
  }
82
- if( !empty($action) && !(get_option('dbem_bookings_registration_disable') && get_option('dbem_bookings_registration_user') == $EM_Booking->get_event()->get_contact()->ID) ){
83
  bp_notifications_add_notification( array(
84
  'item_id' => $EM_Booking->booking_id,
85
  'secondary_item_id' => $EM_Booking->event_id,
79
  }elseif( $EM_Booking->get_status() == 3 ){
80
  $action = 'cancelled_booking';
81
  }
82
+ if( !empty($action) && !$EM_Booking->is_no_user() ){
83
  bp_notifications_add_notification( array(
84
  'item_id' => $EM_Booking->booking_id,
85
  'secondary_item_id' => $EM_Booking->event_id,
classes/em-booking.php CHANGED
@@ -353,6 +353,7 @@ class EM_Booking extends EM_Object{
353
  //recalculate price here only if price is not actually set
354
  if( $this->booking_price === null ){
355
  $this->calculate_price();
 
356
  $this->booking_price = apply_filters('em_booking_get_price', $this->booking_price, $this);
357
  }
358
  //return booking_price, formatted or not
@@ -368,7 +369,7 @@ class EM_Booking extends EM_Object{
368
  * @return double|string
369
  */
370
  function get_price_base( $format = false ){
371
- $price = $this->get_tickets_bookings()->get_price();
372
  if($format){
373
  return $this->format_price($price);
374
  }
@@ -378,7 +379,9 @@ class EM_Booking extends EM_Object{
378
  function get_price_pre_taxes( $format = false ){
379
  $price = $base_price = $this->get_price_base();
380
  //apply pre-tax discounts
381
- $price -= $this->get_price_discounts_amount('pre', $price);
 
 
382
  if( $price < 0 ){ $price = 0; } //no negative prices
383
  //return amount of taxes applied, formatted or not
384
  if( $format ) return $this->format_price($price);
@@ -400,7 +403,10 @@ class EM_Booking extends EM_Object{
400
  $this->taxes_applied = true;
401
  }
402
  //apply post-tax discounts
403
- $price -= $this->get_price_discounts_amount('post', $price);
 
 
 
404
  if( $price < 0 ){ $price = 0; } //no negative prices
405
  //return amount of taxes applied, formatted or not
406
  if( $format ) return $this->format_price($price);
@@ -425,10 +431,6 @@ class EM_Booking extends EM_Object{
425
  return $this->booking_taxes;
426
  }
427
 
428
- function get_price_discount(){
429
-
430
- }
431
-
432
  /**
433
  * Calculates (or recalculates) the price of this booking including taxes, discounts etc., saves it to the booking_price property and writes to relevant properties booking_meta variables
434
  * @return double
@@ -444,9 +446,8 @@ class EM_Booking extends EM_Object{
444
  /*
445
  * Gets tax rate of booking
446
  * @see EM_Object::get_tax_rate()
447
- * @return double
448
  */
449
- function get_tax_rate(){
450
  if( $this->booking_tax_rate === null ){
451
  //booking not saved or tax never defined
452
  if( !empty($this->booking_id) && get_option('dbem_legacy_bookings_tax', 'x') !== 'x'){ //even if 0 if defined as tax rate we still use it, delete the option entirely to stop
@@ -465,66 +466,122 @@ class EM_Booking extends EM_Object{
465
  $this->booking_tax_rate = $this->get_event()->get_tax_rate();
466
  }
467
  }
468
- return $this->booking_tax_rate;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  }
470
 
471
  /**
472
  * Returns an array of discounts to be applied to a booking. Here is an example of an array item that is expected:
473
  * array('name' => 'Name of Discount', 'type'=>'% or #', 'amount'=> 0.00, 'desc' => 'Comments about discount', 'tax'=>'pre/post', 'data' => 'any info for hooks to use' );
474
  * About the array keys:
475
- * type - $ means a fixed amount of discount, % means a percentage off the base price
476
  * amount - if type is a percentage, it is written as a number from 0-100, e.g. 10 = 10%
477
  * tax - 'pre' means discount is applied before tax, 'post' means after tax
478
  * data - any data to be stored that can be used by actions/filters
 
479
  * @return array
480
  */
481
- function get_price_discounts(){
482
- $discounts = array();
483
- if( !empty($this->booking_meta['discounts']) && is_array($this->booking_meta['discounts']) ){
484
- $discounts = $this->booking_meta['discounts'];
485
- }
486
- return apply_filters('em_booking_get_price_discounts', $discounts, $this);
 
 
 
 
487
  }
488
 
489
- function get_price_discounts_amount( $pre_or_post = 'pre', $price = false ){
490
- $discounts = $this->get_price_discounts_summary($pre_or_post, $price);
491
- $discount_amount = 0;
492
- foreach($discounts as $discount){
493
- $discount_amount += $discount['amount_discounted'];
494
- }
495
- return $discount_amount;
 
 
 
 
 
 
 
 
496
  }
497
-
498
- function get_price_discounts_summary( $pre_or_post = 'pre', $price = false ){
499
- $discounts= $this->get_price_discounts();
500
- $discount_summary = array();
 
 
 
 
 
 
 
 
 
 
 
 
501
  if( $price === false ){
502
- $price = $this->get_price_base();
503
- if( $pre_or_post == 'post' ) $price = $this->get_price_pre_taxes() + $this->get_price_taxes();
 
 
 
504
  }
505
- foreach($discounts as $discount){
506
- $discount_amount = 0;
507
- if( !empty($discount['amount']) ){
508
- if( !empty($discount['tax']) && $discount['tax'] == $pre_or_post ){
509
- if( !empty($discount['type']) ){
510
- $discount_summary_item = array('name' => $discount['name'], 'desc' => $discount['desc'], 'discount'=>'0', 'amount_discounted'=>0);
511
- if( $discount['type'] == '%' ){ //discount by percentage
512
- $discount_summary_item['amount_discounted'] = round($price * ($discount['amount']/100),2);
513
- $discount_summary_item['amount'] = $this->format_price($discount_summary_item['amount_discounted']);
514
- $discount_summary_item['discount'] = number_format($discount['amount'],2).'%';
515
- $discount_summary[] = $discount_summary_item;
516
- }elseif( $discount['type'] == '#' ){ //discount by amount
517
- $discount_summary_item['amount_discounted'] = round($discount['amount'],2);
518
- $discount_summary_item['amount'] = $this->format_price($discount_summary_item['amount_discounted']);
519
- $discount_summary_item['discount'] = $this->format_price($discount['amount']);
520
- $discount_summary[] = $discount_summary_item;
521
  }
522
  }
523
  }
524
  }
525
  }
526
- return $discount_summary;
527
  }
 
528
 
529
  /**
530
  * When generating totals at the bottom of a booking, this creates a useful array for displaying the summary in a meaningful way.
@@ -533,21 +590,38 @@ class EM_Booking extends EM_Object{
533
  $summary = array();
534
  //get base price of bookings
535
  $summary['total_base'] = $this->get_price_base();
536
- //get discounts
537
  //apply pre-tax discounts
538
- $summary['discounts_pre_tax'] = $this->get_price_discounts_summary('pre');
 
539
  //add taxes to price
540
  $summary['taxes'] = array('rate'=> 0, 'amount'=> 0);
541
  if( $this->get_price_taxes() > 0 ){
542
  $summary['taxes'] = array('rate'=> number_format($this->get_tax_rate(),2, get_option('dbem_bookings_currency_decimal_point'), get_option('dbem_bookings_currency_thousands_sep')).'%', 'amount'=> $this->get_price_taxes(true));
543
  }
544
  //apply post-tax discounts
545
- $summary['discounts_post_tax'] = $this->get_price_discounts_summary('post');
 
546
  //final price
547
  $summary['total'] = $this->get_price(true);
548
  return $summary;
549
  }
550
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  /* Get Objects linked to booking */
552
 
553
  /**
@@ -608,7 +682,7 @@ class EM_Booking extends EM_Object{
608
  $this->person_id = $this->person->ID;
609
  }
610
  //if this user is the parent user of disabled registrations, replace user details here:
611
- if( get_option('dbem_bookings_registration_disable') && $this->person->ID == get_option('dbem_bookings_registration_user') && (empty($this->person->loaded_no_user) || $this->person->loaded_no_user != $this->booking_id) ){
612
  //override any registration data into the person objet
613
  if( !empty($this->booking_meta['registration']) ){
614
  foreach($this->booking_meta['registration'] as $key => $value){
@@ -694,8 +768,6 @@ class EM_Booking extends EM_Object{
694
  }
695
  if( !empty($name_string) ) $user_data['user_name'] = implode(' ', $name_string);
696
  }
697
- //Save full name
698
- if( !empty($user_data['first_name']) || !empty($user_data['last_name']) )
699
  //Check the phone
700
  if( !empty($_REQUEST['dbem_phone']) ){
701
  $user_data['dbem_phone'] = wp_kses(wp_unslash($_REQUEST['dbem_phone']), array());
@@ -854,6 +926,14 @@ class EM_Booking extends EM_Object{
854
  return apply_filters('em_booking_is_reserved', $result, $this);
855
  }
856
 
 
 
 
 
 
 
 
 
857
  /**
858
  * Returns true if booking is either pending or reserved but not confirmed (which is assumed pending)
859
  */
353
  //recalculate price here only if price is not actually set
354
  if( $this->booking_price === null ){
355
  $this->calculate_price();
356
+ /* Deprecated filter - Equivalent of em_booking_calculate_price, please use that instead */
357
  $this->booking_price = apply_filters('em_booking_get_price', $this->booking_price, $this);
358
  }
359
  //return booking_price, formatted or not
369
  * @return double|string
370
  */
371
  function get_price_base( $format = false ){
372
+ $price = apply_filters('em_booking_get_price_base', $this->get_tickets_bookings()->get_price(), $this);
373
  if($format){
374
  return $this->format_price($price);
375
  }
379
  function get_price_pre_taxes( $format = false ){
380
  $price = $base_price = $this->get_price_base();
381
  //apply pre-tax discounts
382
+ $price -= $this->get_price_adjustments_amount('discounts', 'pre', $base_price);
383
+ $price += $this->get_price_adjustments_amount('surcharges', 'pre', $base_price);
384
+ $price = apply_filters('em_booking_get_price_pre_taxes', $price, $base_price, $this);
385
  if( $price < 0 ){ $price = 0; } //no negative prices
386
  //return amount of taxes applied, formatted or not
387
  if( $format ) return $this->format_price($price);
403
  $this->taxes_applied = true;
404
  }
405
  //apply post-tax discounts
406
+ $price_after_taxes = $price;
407
+ $price -= $this->get_price_adjustments_amount('discounts', 'post', $price_after_taxes);
408
+ $price += $this->get_price_adjustments_amount('surcharges', 'post', $price_after_taxes);
409
+ $price = apply_filters('em_booking_get_price_post_taxes', $price, $price_after_taxes, $this);
410
  if( $price < 0 ){ $price = 0; } //no negative prices
411
  //return amount of taxes applied, formatted or not
412
  if( $format ) return $this->format_price($price);
431
  return $this->booking_taxes;
432
  }
433
 
 
 
 
 
434
  /**
435
  * Calculates (or recalculates) the price of this booking including taxes, discounts etc., saves it to the booking_price property and writes to relevant properties booking_meta variables
436
  * @return double
446
  /*
447
  * Gets tax rate of booking
448
  * @see EM_Object::get_tax_rate()
 
449
  */
450
+ function get_tax_rate( $decimal = false ){
451
  if( $this->booking_tax_rate === null ){
452
  //booking not saved or tax never defined
453
  if( !empty($this->booking_id) && get_option('dbem_legacy_bookings_tax', 'x') !== 'x'){ //even if 0 if defined as tax rate we still use it, delete the option entirely to stop
466
  $this->booking_tax_rate = $this->get_event()->get_tax_rate();
467
  }
468
  }
469
+ $this->booking_tax_rate = $this->booking_tax_rate > 0 ? $this->booking_tax_rate : 0;
470
+ $this->booking_tax_rate = apply_filters('em_booking_get_tax_rate', $this->booking_tax_rate, $this);
471
+ if( $this->booking_tax_rate > 0 && $decimal ){
472
+ return $this->booking_tax_rate / 100;
473
+ }else{
474
+ return $this->booking_tax_rate;
475
+ }
476
+ }
477
+
478
+ /* START Price Adjustment Functions */
479
+ //now we can use one function for both discounts and surcharges, the three functions below are now deprecated.
480
+ /**
481
+ * DEPRECATED. Use $this->get_price_adjustments('discounts'); instead.
482
+ */
483
+ function get_price_discounts(){
484
+ return apply_filters('em_booking_get_price_discounts', $this->get_price_adjustments('discounts'), $this);
485
+ }
486
+ /**
487
+ * DEPRECATED - Use $this->get_price_adjustments_amount('discounts', $pre_or_post, $price); instead.
488
+ */
489
+ function get_price_discounts_amount( $pre_or_post = 'pre', $price = false ){
490
+ return $this->get_price_adjustments_amount( 'discounts', $pre_or_post, $price );
491
+ }
492
+ /**
493
+ * DEPRECATED - Use get_price_discounts_summary('discounts', $pre_or_post, $price); instead.
494
+ */
495
+ function get_price_discounts_summary( $pre_or_post = 'pre', $price = false ){
496
+ return $this->get_price_adjustments_summary( 'discounts', $pre_or_post, $price );
497
  }
498
 
499
  /**
500
  * Returns an array of discounts to be applied to a booking. Here is an example of an array item that is expected:
501
  * array('name' => 'Name of Discount', 'type'=>'% or #', 'amount'=> 0.00, 'desc' => 'Comments about discount', 'tax'=>'pre/post', 'data' => 'any info for hooks to use' );
502
  * About the array keys:
503
+ * type - # means a fixed amount of discount, % means a percentage off the base price
504
  * amount - if type is a percentage, it is written as a number from 0-100, e.g. 10 = 10%
505
  * tax - 'pre' means discount is applied before tax, 'post' means after tax
506
  * data - any data to be stored that can be used by actions/filters
507
+ * @param string $type The type of adjustment you would like to retrieve. This would normally be 'discounts' or 'surcharges'.
508
  * @return array
509
  */
510
+ function get_price_adjustments( $type ){
511
+ $adjustments = array();
512
+ if( !empty($this->booking_meta[$type]) && is_array($this->booking_meta[$type]) ){
513
+ $adjustments = $this->booking_meta[$type];
514
+ }
515
+ //run this filter to be backwards compatible, e.g. em_booking_get_price_discount
516
+ if( $type == 'discounts' ){
517
+ $adjustments = apply_filters('em_booking_get_price_discounts', $adjustments, $this);
518
+ }
519
+ return apply_filters('em_booking_get_price_adjustments', $adjustments, $type, $this);
520
  }
521
 
522
+ /**
523
+ * Returns a numerical amount to adjust the price by, in the context of a certain type and before or after taxes.
524
+ * This will be a positive number whether or not this is to be added or subtracted from the price.
525
+ * @param string $type The type of adjustment to get, which would normally be 'discounts' or 'surcharges'
526
+ * @param string $pre_or_post Adjustments limited to 'pre' (before), 'post' (after) taxes or 'both'
527
+ * @param float $price Price relative to be adjusted.
528
+ * @return float
529
+ */
530
+ function get_price_adjustments_amount( $type, $pre_or_post = 'both', $price = false ){
531
+ $adjustments = $this->get_price_adjustments_summary($type, $pre_or_post, $price);
532
+ $adjustment_amount = 0;
533
+ foreach($adjustments as $adjustment){
534
+ $adjustment_amount += $adjustment['amount_adjusted'];
535
+ }
536
+ return $adjustment_amount;
537
  }
538
+
539
+ /**
540
+ * Provides an array summary of adjustments to make to the price, in the context of a certain type and before or after taxes.
541
+ * @param string $type The type of adjustment to get, which would normally be 'discounts' or 'surcharges'
542
+ * @param string $pre_or_post Adjustments limited to 'pre' (before), 'post' (after) taxes or 'both'
543
+ * @param float $price Price to calculate relative to adjustments. If not supplied or if $pre_or_post is 'both', price is automatically obtained from booking instance according to pre/post taxes requirement.
544
+ * @return array
545
+ */
546
+ function get_price_adjustments_summary( $type, $pre_or_post = 'both', $price = false ){
547
+ if( $pre_or_post == 'both' ){
548
+ $adjustment_summary_pre = $this->get_price_adjustments_summary($type, 'pre');
549
+ $adjustment_summary_post = $this->get_price_adjustments_summary($type, 'post');
550
+ return $adjustment_summary = array_merge($adjustment_summary_pre, $adjustment_summary_post);
551
+ }
552
+ $adjustments = $this->get_price_adjustments($type);
553
+ $adjustment_summary = array();
554
  if( $price === false ){
555
+ if( $pre_or_post == 'post' ){
556
+ $price = $this->get_price_pre_taxes() + $this->get_price_taxes();
557
+ }else{
558
+ $price = $this->get_price_base();
559
+ }
560
  }
561
+ foreach($adjustments as $adjustment){
562
+ $adjustment_amount = 0;
563
+ if( !empty($adjustment['amount']) ){
564
+ if( !empty($adjustment['tax']) && $adjustment['tax'] == $pre_or_post ){
565
+ if( !empty($adjustment['type']) ){
566
+ $adjustment_summary_item = array('name' => $adjustment['name'], 'desc' => $adjustment['desc'], 'adjustment'=>'0', 'amount_adjusted'=>0, 'tax'=>$pre_or_post);
567
+ if( $adjustment['type'] == '%' ){ //adjustment by percentage
568
+ $adjustment_summary_item['amount_adjusted'] = round($price * ($adjustment['amount']/100),2);
569
+ $adjustment_summary_item['amount'] = $this->format_price($adjustment_summary_item['amount_adjusted']);
570
+ $adjustment_summary_item['adjustment'] = number_format($adjustment['amount'],2).'%';
571
+ $adjustment_summary[] = $adjustment_summary_item;
572
+ }elseif( $adjustment['type'] == '#' ){ //adjustment by amount
573
+ $adjustment_summary_item['amount_adjusted'] = round($adjustment['amount'],2);
574
+ $adjustment_summary_item['amount'] = $this->format_price($adjustment_summary_item['amount_adjusted']);
575
+ $adjustment_summary_item['adjustment'] = $this->format_price($adjustment['amount']);
576
+ $adjustment_summary[] = $adjustment_summary_item;
577
  }
578
  }
579
  }
580
  }
581
  }
582
+ return $adjustment_summary;
583
  }
584
+ /* END Price Adjustment Functions */
585
 
586
  /**
587
  * When generating totals at the bottom of a booking, this creates a useful array for displaying the summary in a meaningful way.
590
  $summary = array();
591
  //get base price of bookings
592
  $summary['total_base'] = $this->get_price_base();
 
593
  //apply pre-tax discounts
594
+ $summary['discounts_pre_tax'] = $this->get_price_adjustments_summary('discounts', 'pre');
595
+ $summary['surcharges_pre_tax'] = $this->get_price_adjustments_summary('surcharges', 'pre');
596
  //add taxes to price
597
  $summary['taxes'] = array('rate'=> 0, 'amount'=> 0);
598
  if( $this->get_price_taxes() > 0 ){
599
  $summary['taxes'] = array('rate'=> number_format($this->get_tax_rate(),2, get_option('dbem_bookings_currency_decimal_point'), get_option('dbem_bookings_currency_thousands_sep')).'%', 'amount'=> $this->get_price_taxes(true));
600
  }
601
  //apply post-tax discounts
602
+ $summary['discounts_post_tax'] = $this->get_price_adjustments_summary('discounts', 'post');
603
+ $summary['surcharges_post_tax'] = $this->get_price_adjustments_summary('surcharges', 'post');
604
  //final price
605
  $summary['total'] = $this->get_price(true);
606
  return $summary;
607
  }
608
 
609
+ /**
610
+ * Returns the amount paid for this booking. By default, a booking is considered either paid in full or not at all depending on whether the booking is confirmed or not.
611
+ * @param boolean $format If set to true a currency-formatted string value is returned
612
+ * @return string|float
613
+ */
614
+ function get_total_paid( $format = false ){
615
+ $status = ($this->booking_status == 0 && !get_option('dbem_bookings_approval') ) ? 1:$this->booking_status;
616
+ $total = $status ? $this->get_price() : 0;
617
+ $total = apply_filters('em_booking_get_total_paid', $total, $this);
618
+ if( $format ){
619
+ return $this->format_price($total);
620
+ }
621
+ return $total;
622
+ }
623
+
624
+
625
  /* Get Objects linked to booking */
626
 
627
  /**
682
  $this->person_id = $this->person->ID;
683
  }
684
  //if this user is the parent user of disabled registrations, replace user details here:
685
+ if( $this->person->ID === 0 && (empty($this->person->loaded_no_user) || $this->person->loaded_no_user != $this->booking_id) ){
686
  //override any registration data into the person objet
687
  if( !empty($this->booking_meta['registration']) ){
688
  foreach($this->booking_meta['registration'] as $key => $value){
768
  }
769
  if( !empty($name_string) ) $user_data['user_name'] = implode(' ', $name_string);
770
  }
 
 
771
  //Check the phone
772
  if( !empty($_REQUEST['dbem_phone']) ){
773
  $user_data['dbem_phone'] = wp_kses(wp_unslash($_REQUEST['dbem_phone']), array());
926
  return apply_filters('em_booking_is_reserved', $result, $this);
927
  }
928
 
929
+ /**
930
+ * Returns true if booking is associated with a non-registered user, i.e. booked as a guest 'no user mode'.
931
+ * @return mixed
932
+ */
933
+ function is_no_user(){
934
+ return apply_filters('em_booking_is_no_user', $this->get_person()->ID === 0, $this);
935
+ }
936
+
937
  /**
938
  * Returns true if booking is either pending or reserved but not confirmed (which is assumed pending)
939
  */
classes/em-bookings-table.php CHANGED
@@ -529,7 +529,7 @@ class EM_Bookings_Table{
529
  }elseif($col == 'dbem_phone'){
530
  $val = esc_html($EM_Booking->get_person()->phone);
531
  }elseif($col == 'user_name'){
532
- if( $csv || ( get_option('dbem_bookings_registration_disable') && $EM_Booking->get_person()->ID == get_option('dbem_bookings_registration_user') ) ){
533
  $val = $EM_Booking->get_person()->get_name();
534
  }else{
535
  $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. $EM_Booking->person->get_name() .'</a>';
529
  }elseif($col == 'dbem_phone'){
530
  $val = esc_html($EM_Booking->get_person()->phone);
531
  }elseif($col == 'user_name'){
532
+ if( $csv || $EM_Booking->is_no_user() ){
533
  $val = $EM_Booking->get_person()->get_name();
534
  }else{
535
  $val = '<a href="'.esc_url(add_query_arg(array('person_id'=>$EM_Booking->person_id, 'event_id'=>null), $EM_Booking->get_event()->get_bookings_url())).'">'. $EM_Booking->person->get_name() .'</a>';
classes/em-bookings.php CHANGED
@@ -538,19 +538,20 @@ class EM_Bookings extends EM_Object implements Iterator{
538
  $selectors = ( $count ) ? 'COUNT(*)':'*';
539
 
540
  //Create the SQL statement and execute
541
- $sql = "
542
  SELECT $selectors FROM $bookings_table
543
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
544
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
545
  $where
546
  $orderby_sql
547
  $limit $offset
548
- ";
 
549
  //If we're only counting results, return the number of results
550
  if( $count ){
551
  return apply_filters('em_bookings_get_count', $wpdb->get_var($sql), $args);
552
  }
553
- $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
554
 
555
  //If we want results directly in an array, why not have a shortcut here?
556
  if( $args['array'] == true ){
538
  $selectors = ( $count ) ? 'COUNT(*)':'*';
539
 
540
  //Create the SQL statement and execute
541
+ $sql = apply_filters('em_bookings_get_sql',"
542
  SELECT $selectors FROM $bookings_table
543
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
544
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
545
  $where
546
  $orderby_sql
547
  $limit $offset
548
+ ", $args);
549
+
550
  //If we're only counting results, return the number of results
551
  if( $count ){
552
  return apply_filters('em_bookings_get_count', $wpdb->get_var($sql), $args);
553
  }
554
+ $results = $wpdb->get_results($sql, ARRAY_A);
555
 
556
  //If we want results directly in an array, why not have a shortcut here?
557
  if( $args['array'] == true ){
classes/em-calendar.php CHANGED
@@ -446,7 +446,8 @@ class EM_Calendar extends EM_Object {
446
  'orderby' => get_option('dbem_display_calendar_orderby'),
447
  'order' => get_option('dbem_display_calendar_order'),
448
  'number_of_weeks' => false, //number of weeks to be displayed in the calendar
449
- 'limit' => get_option('dbem_display_calendar_events_limit')
 
450
  );
451
  //sort out whether defaults were supplied or just the array of search values
452
  if( empty($array) ){
446
  'orderby' => get_option('dbem_display_calendar_orderby'),
447
  'order' => get_option('dbem_display_calendar_order'),
448
  'number_of_weeks' => false, //number of weeks to be displayed in the calendar
449
+ 'limit' => get_option('dbem_display_calendar_events_limit'),
450
+ 'post_id' => false
451
  );
452
  //sort out whether defaults were supplied or just the array of search values
453
  if( empty($array) ){
classes/em-categories-taxonomy.php CHANGED
@@ -32,9 +32,7 @@ class EM_Categories_Taxonomy{
32
  public static function admin_init(){
33
  global $pagenow;
34
  if( ($pagenow == 'edit-tags.php' || $pagenow == 'term.php') && !empty($_GET['taxonomy']) && $_GET['taxonomy'] == EM_TAXONOMY_CATEGORY){
35
- wp_enqueue_style( 'farbtastic' );
36
- wp_enqueue_style( 'thickbox' );
37
-
38
  wp_enqueue_script( 'em-categories-admin', plugins_url().'/events-manager/includes/js/categories-admin.js', array( 'jquery','media-upload','thickbox','farbtastic' ) );
39
  }
40
  }
@@ -59,16 +57,18 @@ class EM_Categories_Taxonomy{
59
  </tr>
60
  <tr class="form-field">
61
  <th scope="row" valign="top"><label for="category-image"><?php esc_html_e('Image','events-manager'); ?></label></th>
62
- <td>
63
- <?php if( !empty($category_image) ): ?>
64
- <p id="category-image-img"><img src="<?php echo $category_image; ?>" /></p>
65
- <?php endif; ?>
66
- <input type="text" name="category_image" id="category-image" value="<?php echo esc_attr($category_image); ?>" style="width:300px;" />
67
- <input type="hidden" name="category_image_id" id="category-image-id" value="<?php echo esc_attr($category_image); ?>" />
68
- <input id="upload_image_button" type="button" value="<?php _e('Choose/Upload Image','events-manager'); ?>" class="button-secondary" style="width:auto;" />
69
- <?php if( !empty($category_image) ): ?>
70
- <input id="delete_image_button" type="button" value="<?php _e('Remove Image','events-manager'); ?>" class="button-secondary" style="width:auto;" />
71
- <?php endif; ?>
 
 
72
  <br />
73
  <p class="description"><?php echo sprintf(__('Choose an image for your category, which can be displayed using the %s placeholder.','events-manager'),'<code>#_CATEGORYIMAGE</code>'); ?></p>
74
  </td>
32
  public static function admin_init(){
33
  global $pagenow;
34
  if( ($pagenow == 'edit-tags.php' || $pagenow == 'term.php') && !empty($_GET['taxonomy']) && $_GET['taxonomy'] == EM_TAXONOMY_CATEGORY){
35
+ wp_enqueue_media();
 
 
36
  wp_enqueue_script( 'em-categories-admin', plugins_url().'/events-manager/includes/js/categories-admin.js', array( 'jquery','media-upload','thickbox','farbtastic' ) );
37
  }
38
  }
57
  </tr>
58
  <tr class="form-field">
59
  <th scope="row" valign="top"><label for="category-image"><?php esc_html_e('Image','events-manager'); ?></label></th>
60
+ <td id="event-tax-image">
61
+ <div class="img-container">
62
+ <?php if( !empty($category_image) ): ?>
63
+ <img src="<?php echo $category_image; ?>" />
64
+ <?php endif; ?>
65
+ </div>
66
+ <input type="text" name="category_image" id="category-image" class="img-url" value="<?php echo esc_attr($category_image); ?>" />
67
+ <input type="hidden" name="category_image_id" id="category-image-id" class="img-id" value="<?php echo esc_attr($category_image_id); ?>" />
68
+ <p class="hide-if-no-js">
69
+ <input id="upload_image_button" type="button" value="<?php _e('Choose/Upload Image','events-manager'); ?>" class="upload-img-button button-secondary" />
70
+ <input id="delete_image_button" type="button" value="<?php _e('Remove Image','events-manager'); ?>" class="delete-img-button button-secondary" <?php if( empty($category_image) ) echo 'style="display:none;"'; ?> />
71
+ </p>
72
  <br />
73
  <p class="description"><?php echo sprintf(__('Choose an image for your category, which can be displayed using the %s placeholder.','events-manager'),'<code>#_CATEGORYIMAGE</code>'); ?></p>
74
  </td>
classes/em-categories.php CHANGED
@@ -78,19 +78,17 @@ class EM_Categories extends EM_Object implements Iterator{
78
  $default_term = get_term_by('id',get_option('dbem_default_category'), EM_TAXONOMY_CATEGORY);
79
  if($default_term) $term_slugs[] = $default_term->slug;
80
  }
81
- if( count($term_slugs) > 0 ){
82
- if( is_multisite() ){
83
- //In MS Global mode, we also save category meta information for global lookups
84
- if( EM_MS_GLOBAL && !empty($this->event_id) ){
85
- //delete categories
86
- $this->save_index();
87
- }
88
- if( !EM_MS_GLOBAL || is_main_site() ){
89
- wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
90
- }
91
- }else{
92
  wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
93
- }
 
 
94
  }
95
  do_action('em_categories_save', $this);
96
  }
78
  $default_term = get_term_by('id',get_option('dbem_default_category'), EM_TAXONOMY_CATEGORY);
79
  if($default_term) $term_slugs[] = $default_term->slug;
80
  }
81
+ if( is_multisite() ){
82
+ //In MS Global mode, we also save category meta information for global lookups
83
+ if( EM_MS_GLOBAL && !empty($this->event_id) ){
84
+ //delete categories
85
+ $this->save_index();
86
+ }
87
+ if( !EM_MS_GLOBAL || is_main_site() ){
 
 
 
 
88
  wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
89
+ }
90
+ }else{
91
+ wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
92
  }
93
  do_action('em_categories_save', $this);
94
  }
classes/em-event-post-admin.php CHANGED
@@ -8,7 +8,7 @@ class EM_Event_Post_Admin{
8
  if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
9
  add_action('admin_head', array('EM_Event_Post_Admin','admin_head')); //I don't think we need this anymore?
10
  //Meta Boxes
11
- add_action('add_meta_boxes', array('EM_Event_Post_Admin','meta_boxes'));
12
  //Notices
13
  add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices'));
14
  }
@@ -36,7 +36,9 @@ class EM_Event_Post_Admin{
36
  if( $pagenow == 'post.php' && ($post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring') ){
37
  if ( $EM_Event->is_recurring() ) {
38
  $warning = "<p><strong>".__( 'WARNING: This is a recurring event.', 'events-manager')."</strong></p>";
39
- $warning .= "<p>". __( 'Modifications to this event will cause all recurrences of this event to be deleted and recreated and previous bookings will be deleted! You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager');
 
 
40
  ?><div class="updated"><?php echo $warning; ?></div><?php
41
  } elseif ( $EM_Event->is_recurrence() ) {
42
  $warning = "<p><strong>".__('WARNING: This is a recurrence in a set of recurring events.', 'events-manager')."</strong></p>";
@@ -223,10 +225,8 @@ class EM_Event_Post_Admin{
223
  }
224
  }
225
 
226
- public static function meta_boxes(){
227
- global $EM_Event, $post;
228
- //no need to proceed if we're not dealing with an event
229
- if( $post->post_type != EM_POST_TYPE_EVENT ) return;
230
  //since this is the first point when the admin area loads event stuff, we load our EM_Event here
231
  if( empty($EM_Event) && !empty($post) ){
232
  $EM_Event = em_get_event($post->ID, 'post_id');
@@ -253,8 +253,18 @@ class EM_Event_Post_Admin{
253
  if( EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
254
  add_meta_box('em-event-categories', __('Site Categories','events-manager'), array('EM_Event_Post_Admin','meta_box_ms_categories'),EM_POST_TYPE_EVENT, 'side','low');
255
  }
 
256
  }
257
 
 
 
 
 
 
 
 
 
 
258
  public static function meta_box_metadump(){
259
  global $post,$EM_Event;
260
  echo "<pre>"; print_r($EM_Event); echo "</pre>";
@@ -327,7 +337,7 @@ class EM_Event_Recurring_Post_Admin{
327
  if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
328
  add_action('admin_head', array('EM_Event_Recurring_Post_Admin','admin_head'));
329
  //Meta Boxes
330
- add_action('add_meta_boxes', array('EM_Event_Recurring_Post_Admin','meta_boxes'));
331
  //Notices
332
  add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices')); //shared with posts
333
  }
@@ -372,7 +382,7 @@ class EM_Event_Recurring_Post_Admin{
372
  $EM_Event = em_get_event($post_id, 'post_id');
373
  $EM_Event->post_type = $post_type;
374
  //get the list post IDs for recurrences this recurrence
375
- if( !$EM_Event->save_events() && $EM_Event->is_published() ){
376
  $EM_Event->set_status(null, true);
377
  $EM_Notices->add_error(__ ( 'Something went wrong with the recurrence update...', 'events-manager'). __ ( 'There was a problem saving the recurring events.', 'events-manager'));
378
  }
@@ -447,10 +457,8 @@ class EM_Event_Recurring_Post_Admin{
447
  }
448
  }
449
 
450
- public static function meta_boxes(){
451
- global $EM_Event, $post;
452
- //no need to proceed if we're not dealing with a recurring event
453
- if( $post->post_type != 'event-recurring' ) return;
454
  //since this is the first point when the admin area loads event stuff, we load our EM_Event here
455
  if( empty($EM_Event) && !empty($post) ){
456
  $EM_Event = em_get_event($post->ID, 'post_id');
@@ -476,6 +484,7 @@ class EM_Event_Recurring_Post_Admin{
476
  }
477
 
478
  public static function meta_box_recurrence(){
 
479
  em_locate_template('forms/event/recurring-when.php', true);
480
  }
481
  }
8
  if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
9
  add_action('admin_head', array('EM_Event_Post_Admin','admin_head')); //I don't think we need this anymore?
10
  //Meta Boxes
11
+ add_action('add_meta_boxes_'.EM_POST_TYPE_EVENT, array('EM_Event_Post_Admin','meta_boxes'), 10, 1);
12
  //Notices
13
  add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices'));
14
  }
36
  if( $pagenow == 'post.php' && ($post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring') ){
37
  if ( $EM_Event->is_recurring() ) {
38
  $warning = "<p><strong>".__( 'WARNING: This is a recurring event.', 'events-manager')."</strong></p>";
39
+ $warning .= "<p>". __( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager') . '</p>';
40
+ $warning .= "<p>". __( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager') . '</p>';
41
+ $warning .= '<p><a href="'. esc_url( add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url()) ).'">'. esc_html__('You can edit individual recurrences and disassociate them with this recurring event.','events-manager') . '</a></p>';
42
  ?><div class="updated"><?php echo $warning; ?></div><?php
43
  } elseif ( $EM_Event->is_recurrence() ) {
44
  $warning = "<p><strong>".__('WARNING: This is a recurrence in a set of recurring events.', 'events-manager')."</strong></p>";
225
  }
226
  }
227
 
228
+ public static function meta_boxes( $post ){
229
+ global $EM_Event;
 
 
230
  //since this is the first point when the admin area loads event stuff, we load our EM_Event here
231
  if( empty($EM_Event) && !empty($post) ){
232
  $EM_Event = em_get_event($post->ID, 'post_id');
253
  if( EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
254
  add_meta_box('em-event-categories', __('Site Categories','events-manager'), array('EM_Event_Post_Admin','meta_box_ms_categories'),EM_POST_TYPE_EVENT, 'side','low');
255
  }
256
+ add_action('post_submitbox_misc_actions', 'EM_Event_Post_Admin::meta_box_action_post_submitbox_start');
257
  }
258
 
259
+ public static function meta_box_action_post_submitbox_start(){
260
+ global $EM_Event;
261
+ ?>
262
+ <div class="misc-pub-section misc-pub-post-status misc-event-duplicate-link">
263
+ <a href="<?php echo esc_url($EM_Event->duplicate_url()); ?>"><?php echo esc_html(sprintf(__('Duplicate %s','events-manager'), __('Event','events-manager'))); ?></a>
264
+ </div>
265
+ <?php
266
+ }
267
+
268
  public static function meta_box_metadump(){
269
  global $post,$EM_Event;
270
  echo "<pre>"; print_r($EM_Event); echo "</pre>";
337
  if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
338
  add_action('admin_head', array('EM_Event_Recurring_Post_Admin','admin_head'));
339
  //Meta Boxes
340
+ add_action('add_meta_boxes_event-recurring', array('EM_Event_Recurring_Post_Admin','meta_boxes'), 10, 1);
341
  //Notices
342
  add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices')); //shared with posts
343
  }
382
  $EM_Event = em_get_event($post_id, 'post_id');
383
  $EM_Event->post_type = $post_type;
384
  //get the list post IDs for recurrences this recurrence
385
+ if( !$EM_Event->save_events() && ( $EM_Event->is_published() || 'future' == $EM_Event->post_status ) ){
386
  $EM_Event->set_status(null, true);
387
  $EM_Notices->add_error(__ ( 'Something went wrong with the recurrence update...', 'events-manager'). __ ( 'There was a problem saving the recurring events.', 'events-manager'));
388
  }
457
  }
458
  }
459
 
460
+ public static function meta_boxes( $post ){
461
+ global $EM_Event;
 
 
462
  //since this is the first point when the admin area loads event stuff, we load our EM_Event here
463
  if( empty($EM_Event) && !empty($post) ){
464
  $EM_Event = em_get_event($post->ID, 'post_id');
484
  }
485
 
486
  public static function meta_box_recurrence(){
487
+ ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_event'); ?>" /><?php
488
  em_locate_template('forms/event/recurring-when.php', true);
489
  }
490
  }
classes/em-event-post.php CHANGED
@@ -28,10 +28,8 @@ class EM_Event_Post {
28
  add_filter('body_class', array('EM_Event_Post','body_class'), 10, 3);
29
  }
30
  //Override post template tags
31
- add_filter('the_date',array('EM_Event_Post','the_date'),10,2);
32
- add_filter('get_the_date',array('EM_Event_Post','the_date'),10,2);
33
- add_filter('the_time',array('EM_Event_Post','the_time'),10,2);
34
- add_filter('get_the_time',array('EM_Event_Post','the_time'),10,2);
35
  add_filter('the_category',array('EM_Event_Post','the_category'),10,3);
36
  }
37
  add_action('parse_query', array('EM_Event_Post','parse_query'));
@@ -132,7 +130,8 @@ class EM_Event_Post {
132
  }elseif( !post_password_required() ){
133
  $EM_Event = em_get_event($post);
134
  if( $EM_Event->event_rsvp && (!defined('EM_DISABLE_AUTO_BOOKINGSFORM') || !EM_DISABLE_AUTO_BOOKINGSFORM) ){
135
- $content .= $EM_Event->output('<h2>Bookings</h2>#_BOOKINGFORM');
 
136
  }
137
  }
138
  }
@@ -140,8 +139,8 @@ class EM_Event_Post {
140
  return $content;
141
  }
142
 
143
- public static function the_date( $the_date, $d = '' ){
144
- global $post;
145
  if( $post->post_type == EM_POST_TYPE_EVENT ){
146
  $EM_Event = em_get_event($post);
147
  if ( '' == $d ){
@@ -153,8 +152,8 @@ class EM_Event_Post {
153
  return $the_date;
154
  }
155
 
156
- public static function the_time( $the_time, $f = '' ){
157
- global $post;
158
  if( $post->post_type == EM_POST_TYPE_EVENT ){
159
  $EM_Event = em_get_event($post);
160
  if ( '' == $f ){
@@ -232,10 +231,14 @@ class EM_Event_Post {
232
  }
233
  //Scoping
234
  if( !empty($wp_query->query_vars['post_type']) && ($wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT || $wp_query->query_vars['post_type'] == 'event-recurring') && (empty($wp_query->query_vars['post_status']) || !in_array($wp_query->query_vars['post_status'],array('trash','pending','draft'))) ) {
 
235
  //Let's deal with the scope - default is future
236
  if( is_admin() ){
237
  $scope = $wp_query->query_vars['scope'] = (!empty($_REQUEST['scope'])) ? $_REQUEST['scope']:'future';
238
  //TODO limit what a user can see admin side for events/locations/recurring events
 
 
 
239
  }else{
240
  if( !empty($wp_query->query_vars['calendar_day']) ) $wp_query->query_vars['scope'] = $wp_query->query_vars['calendar_day'];
241
  if( empty($wp_query->query_vars['scope']) ){
@@ -248,7 +251,6 @@ class EM_Event_Post {
248
  $scope = $wp_query->query_vars['scope'];
249
  }
250
  }
251
- $query = array();
252
  $time = current_time('timestamp');
253
  if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
254
  $today = strtotime($scope);
28
  add_filter('body_class', array('EM_Event_Post','body_class'), 10, 3);
29
  }
30
  //Override post template tags
31
+ add_filter('get_the_date',array('EM_Event_Post','the_date'),10,3);
32
+ add_filter('get_the_time',array('EM_Event_Post','the_time'),10,3);
 
 
33
  add_filter('the_category',array('EM_Event_Post','the_category'),10,3);
34
  }
35
  add_action('parse_query', array('EM_Event_Post','parse_query'));
130
  }elseif( !post_password_required() ){
131
  $EM_Event = em_get_event($post);
132
  if( $EM_Event->event_rsvp && (!defined('EM_DISABLE_AUTO_BOOKINGSFORM') || !EM_DISABLE_AUTO_BOOKINGSFORM) ){
133
+ $content .= '<h2>'.esc_html__('Bookings','events-manager').'</h2>';
134
+ $content .= $EM_Event->output('#_BOOKINGFORM');
135
  }
136
  }
137
  }
139
  return $content;
140
  }
141
 
142
+ public static function the_date( $the_date, $d = '', $post = null ){
143
+ $post = get_post( $post );
144
  if( $post->post_type == EM_POST_TYPE_EVENT ){
145
  $EM_Event = em_get_event($post);
146
  if ( '' == $d ){
152
  return $the_date;
153
  }
154
 
155
+ public static function the_time( $the_time, $f = '', $post = null ){
156
+ $post = get_post( $post );
157
  if( $post->post_type == EM_POST_TYPE_EVENT ){
158
  $EM_Event = em_get_event($post);
159
  if ( '' == $f ){
231
  }
232
  //Scoping
233
  if( !empty($wp_query->query_vars['post_type']) && ($wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT || $wp_query->query_vars['post_type'] == 'event-recurring') && (empty($wp_query->query_vars['post_status']) || !in_array($wp_query->query_vars['post_status'],array('trash','pending','draft'))) ) {
234
+ $query = array();
235
  //Let's deal with the scope - default is future
236
  if( is_admin() ){
237
  $scope = $wp_query->query_vars['scope'] = (!empty($_REQUEST['scope'])) ? $_REQUEST['scope']:'future';
238
  //TODO limit what a user can see admin side for events/locations/recurring events
239
+ if( !empty($wp_query->query_vars['recurrence_id']) && is_numeric($wp_query->query_vars['recurrence_id']) ){
240
+ $query[] = array( 'key' => '_recurrence_id', 'value' => $wp_query->query_vars['recurrence_id'], 'compare' => '=' );
241
+ }
242
  }else{
243
  if( !empty($wp_query->query_vars['calendar_day']) ) $wp_query->query_vars['scope'] = $wp_query->query_vars['calendar_day'];
244
  if( empty($wp_query->query_vars['scope']) ){
251
  $scope = $wp_query->query_vars['scope'];
252
  }
253
  }
 
254
  $time = current_time('timestamp');
255
  if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
256
  $today = strtotime($scope);
classes/em-event-posts-admin.php CHANGED
@@ -9,6 +9,8 @@ class EM_Event_Posts_Admin{
9
  $_REQUEST['category_id'] = $term->slug;
10
  }
11
  }
 
 
12
  //hide some cols by default:
13
  $screen = 'edit-'.EM_POST_TYPE_EVENT;
14
  $hidden = get_user_option( 'manage' . $screen . 'columnshidden' );
@@ -58,6 +60,18 @@ class EM_Event_Posts_Admin{
58
  <?php
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  /**
62
  * Handles WP_Query filter option in the admin area, which gets executed before EM_Event_Post::parse_query
63
  * Not yet in use
@@ -194,7 +208,12 @@ class EM_Event_Posts_Admin{
194
  //get meta value to see if post has location, otherwise
195
  $EM_Location = $EM_Event->get_location();
196
  if( !empty($EM_Location->location_id) ){
197
- echo "<strong>" . $EM_Location->location_name . "</strong><br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
 
 
 
 
 
198
  }else{
199
  echo __('None','events-manager');
200
  }
@@ -270,12 +289,24 @@ class EM_Event_Recurring_Posts_Admin{
270
  add_filter('manage_edit-event-recurring_columns' , array('EM_Event_Recurring_Posts_Admin','columns_add'));
271
  add_filter('manage_posts_custom_column' , array('EM_Event_Recurring_Posts_Admin','columns_output'),10,1 );
272
  add_action('restrict_manage_posts', array('EM_Event_Posts_Admin','restrict_manage_posts'));
 
 
 
273
  }
274
  }
275
 
276
  public static function admin_notices(){
277
- $warning = sprintf(__( 'Modifications to these events will cause all recurrences of each event to be deleted and recreated and previous bookings will be deleted! You can edit individual recurrences and detach them from recurring events by visiting the <a href="%s">events page</a>.', 'events-manager'), admin_url().'edit.php?post_type='.EM_POST_TYPE_EVENT);
278
- ?><div class="updated"><p><?php echo $warning; ?></p></div><?php
 
 
 
 
 
 
 
 
 
279
  }
280
 
281
  public static function admin_head(){
@@ -328,16 +359,35 @@ class EM_Event_Recurring_Posts_Admin{
328
  //get meta value to see if post has location, otherwise
329
  $EM_Location = $EM_Event->get_location();
330
  if( !empty($EM_Location->location_id) ){
331
- echo "<strong>" . $EM_Location->location_name . "</strong><br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
 
 
 
 
 
332
  }else{
333
  echo __('None','events-manager');
334
  }
335
  break;
336
  case 'date-time':
337
  echo $EM_Event->get_recurrence_description();
 
 
 
 
 
338
  break;
339
  }
340
  }
341
- }
 
 
 
 
 
 
 
 
 
342
  }
343
  add_action('admin_init', array('EM_Event_Recurring_Posts_Admin','init'));
9
  $_REQUEST['category_id'] = $term->slug;
10
  }
11
  }
12
+ //admin warnings
13
+ add_action('admin_notices', 'EM_Event_Posts_Admin::admin_notices');
14
  //hide some cols by default:
15
  $screen = 'edit-'.EM_POST_TYPE_EVENT;
16
  $hidden = get_user_option( 'manage' . $screen . 'columnshidden' );
60
  <?php
61
  }
62
 
63
+ public static function admin_notices(){
64
+ if( !empty($_REQUEST['recurrence_id']) && is_numeric($_REQUEST['recurrence_id']) ){
65
+ $EM_Event = em_get_event($_REQUEST['recurrence_id']);
66
+ ?>
67
+ <div class="updated">
68
+ <p><?php echo sprintf(esc_html__('You are viewing individual recurrences of recurring event %s.', 'events-manager'), '<a href="'.$EM_Event->get_edit_url().'">'.$EM_Event->event_name.'</a>'); ?></p>
69
+ <p><?php esc_html_e('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'); ?></p>
70
+ </div>
71
+ <?php
72
+ }
73
+ }
74
+
75
  /**
76
  * Handles WP_Query filter option in the admin area, which gets executed before EM_Event_Post::parse_query
77
  * Not yet in use
208
  //get meta value to see if post has location, otherwise
209
  $EM_Location = $EM_Event->get_location();
210
  if( !empty($EM_Location->location_id) ){
211
+ echo "<strong><a href='". $EM_Location->get_permalink()."'>" . $EM_Location->location_name . "</a></strong>
212
+ <span class='row-actions'> -
213
+ <a href='". esc_url($EM_Location->get_edit_url())."'>". esc_html__('Edit') ."</a> |
214
+ <a href='". esc_url($EM_Location->get_permalink())."'>". esc_html__('View') ."</a>
215
+ </span>
216
+ <br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
217
  }else{
218
  echo __('None','events-manager');
219
  }
289
  add_filter('manage_edit-event-recurring_columns' , array('EM_Event_Recurring_Posts_Admin','columns_add'));
290
  add_filter('manage_posts_custom_column' , array('EM_Event_Recurring_Posts_Admin','columns_output'),10,1 );
291
  add_action('restrict_manage_posts', array('EM_Event_Posts_Admin','restrict_manage_posts'));
292
+ //actions
293
+ $row_action_type = is_post_type_hierarchical( EM_POST_TYPE_EVENT ) ? 'page_row_actions' : 'post_row_actions';
294
+ add_filter($row_action_type, array('EM_Event_Recurring_Posts_Admin','row_actions'),10,2);
295
  }
296
  }
297
 
298
  public static function admin_notices(){
299
+ ?>
300
+ <div class="updated">
301
+ <p><?php esc_html_e( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager'); ?></p>
302
+ <p><?php esc_html_e( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager'); ?></p>
303
+ <p>
304
+ <a href="<?php echo esc_url( em_get_events_admin_url() ); ?>">
305
+ <strong><?php esc_html_e('You can edit individual recurrences and disassociate them with a recurring event to prevent getting overwritten.', 'events-manager'); ?></strong>
306
+ </a>
307
+ </p>
308
+ </div>
309
+ <?php
310
  }
311
 
312
  public static function admin_head(){
359
  //get meta value to see if post has location, otherwise
360
  $EM_Location = $EM_Event->get_location();
361
  if( !empty($EM_Location->location_id) ){
362
+ echo "<strong><a href='". $EM_Location->get_permalink()."'>" . $EM_Location->location_name . "</a></strong>
363
+ <span class='row-actions'> -
364
+ <a href='". esc_url($EM_Location->get_edit_url())."'>". esc_html__('Edit') ."</a> |
365
+ <a href='". esc_url($EM_Location->get_permalink())."'>". esc_html__('View') ."</a>
366
+ </span>
367
+ <br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
368
  }else{
369
  echo __('None','events-manager');
370
  }
371
  break;
372
  case 'date-time':
373
  echo $EM_Event->get_recurrence_description();
374
+ $edit_url = add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url());
375
+ $link_text = sprintf(__('View %s', 'events-manager'), __('Recurrences', 'events-manager'));
376
+ echo "<br /><span class='row-actions'>
377
+ <a href='". esc_url($edit_url) ."'>". esc_html($link_text) ."</a>
378
+ </span>";
379
  break;
380
  }
381
  }
382
+ }
383
+
384
+ public static function row_actions($actions, $post){
385
+ if($post->post_type == 'event-recurring'){
386
+ global $post, $EM_Event;
387
+ $EM_Event = em_get_event($post, 'post_id');
388
+ $actions['duplicate'] = '<a href="'.$EM_Event->duplicate_url().'" title="'.sprintf(__('Duplicate %s','events-manager'), __('Event','events-manager')).'">'.__('Duplicate','events-manager').'</a>';
389
+ }
390
+ return $actions;
391
+ }
392
  }
393
  add_action('admin_init', array('EM_Event_Recurring_Posts_Admin','init'));
classes/em-event.php CHANGED
@@ -43,8 +43,8 @@ class EM_Event extends EM_Object{
43
  var $event_slug;
44
  var $event_owner;
45
  var $event_name;
46
- var $event_start_time;
47
- var $event_end_time;
48
  var $event_all_day;
49
  var $event_start_date;
50
  var $event_end_date;
@@ -105,10 +105,10 @@ class EM_Event extends EM_Object{
105
  'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s', 'null'=>true ),
106
  'blog_id' => array( 'name'=>'blog_id', 'type'=>'%d', 'null'=>true ),
107
  'group_id' => array( 'name'=>'group_id', 'type'=>'%d', 'null'=>true ),
108
- 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
109
  'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
110
  'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s', 'null'=>true ), //daily,weekly,monthly?
111
- 'recurrence_days' => array( 'name'=>'days', 'type'=>'%d', 'null'=>true ), //daily,weekly,monthly?
112
  'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s', 'null'=>true ), //if weekly or monthly, what days of the week?
113
  'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d', 'null'=>true ), //if monthly which week (-1 is last)
114
  'recurrence_rsvp_days' => array( 'name'=>'recurrence_rsvp_days', 'type'=>'%d', 'null'=>true ), //days before or after start date to generat bookings cut-off date
@@ -188,6 +188,27 @@ class EM_Event extends EM_Object{
188
  * @var mixed
189
  */
190
  var $previous_status = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  /* Post Variables - copied out of post object for easy IDE reference */
193
  var $ID;
@@ -387,14 +408,47 @@ class EM_Event extends EM_Object{
387
  */
388
  function get_post_meta(){
389
  do_action('em_event_get_post_meta_pre', $this);
390
- //Grab POST data
391
- $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : '';
392
- $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date;
393
- //check if this is recurring or not
394
  if( !empty($_POST['recurring']) ){
395
  $this->recurrence = 1;
396
  $this->post_type = 'event-recurring';
397
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  //Get Location info
399
  if( !get_option('dbem_locations_enabled') || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){
400
  $this->location_id = 0;
@@ -406,34 +460,15 @@ class EM_Event extends EM_Object{
406
  $this->get_location()->get_post(false);
407
  $this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise
408
  }
409
- //Sort out time
410
- $this->event_all_day = ( !empty($_POST['event_all_day']) ) ? 1 : 0;
411
- if( !$this->event_all_day ){
412
- $this->event_start_time = $this->event_end_time = '00:00:00';
413
- }
414
- foreach( array('event_start_time','event_end_time', 'event_rsvp_time') as $timeName ){
415
- $match = array();
416
- if( !empty($_POST[$timeName]) && preg_match ( '/^([01]\d|[0-9]|2[0-3])(:([0-5]\d))? ?(AM|PM)?$/', $_POST[$timeName], $match ) ){
417
- if( empty($match[3]) ) $match[3] = '00';
418
- if( strlen($match[1]) == 1 ) $match[1] = '0'.$match[1];
419
- if( !empty($match[4]) && $match[4] == 'PM' && $match[1] != 12 ){
420
- $match[1] = 12+$match[1];
421
- }elseif( !empty($match[4]) && $match[4] == 'AM' && $match[1] == 12 ){
422
- $match[1] = '00';
423
- }
424
- $this->$timeName = $match[1].":".$match[3].":00";
425
- }else{
426
- $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
427
- }
428
- }
429
- //Start/End times should be available as timestamp
430
- $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
431
- $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
432
  //Bookings
433
  $can_manage_bookings = $this->can_manage('manage_bookings','manage_others_bookings');
434
  $preview_autosave = is_admin() && !empty($_REQUEST['_emnonce']) && !empty($_REQUEST['wp-preview']) && $_REQUEST['wp-preview'] == 'dopreview'; //we shouldn't save new data during a preview auto-save
435
  if( !$preview_autosave && $can_manage_bookings && !empty($_POST['event_rsvp']) && $_POST['event_rsvp'] ){
436
- $this->get_bookings()->get_tickets()->get_post();
 
 
 
437
  $this->event_rsvp = 1;
438
  //RSVP cuttoff TIME is set up above where start/end times are as well
439
  if( !$this->is_recurring() ){
@@ -497,9 +532,11 @@ class EM_Event extends EM_Object{
497
  $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0;
498
  $this->event_rsvp_spaces = ( isset($_POST['event_rsvp_spaces']) ) ? absint($_POST['event_rsvp_spaces']):0;
499
  }elseif( !$preview_autosave && ($can_manage_bookings || !$this->event_rsvp) ){
 
500
  $this->event_rsvp = 0;
501
  $this->event_rsvp_time = '00:00:00';
502
  }
 
503
  //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
504
  if(get_option('dbem_attributes_enabled')){
505
  global $allowedtags;
@@ -522,30 +559,90 @@ class EM_Event extends EM_Object{
522
  }
523
  }
524
  }
525
- //Set Blog ID
526
- if( is_multisite() ){
527
- $this->blog_id = get_current_blog_id();
528
- }
529
  //group id
530
  $this->group_id = (!empty($_POST['group_id']) && is_numeric($_POST['group_id'])) ? $_POST['group_id']:0;
 
531
  //Recurrence data
532
  if( $this->is_recurring() ){
533
  $this->recurrence = 1; //just in case
534
- $this->recurrence_freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly','yearly')) ) ? $_POST['recurrence_freq']:'daily';
535
- if( !empty($_POST['recurrence_bydays']) && $this->recurrence_freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){
536
- $this->recurrence_byday = str_replace(' ', '', implode( ",", $_POST['recurrence_bydays'] ));
537
- }elseif( !empty($_POST['recurrence_byday']) && $this->recurrence_freq == 'monthly' ){
538
- $this->recurrence_byday = wp_kses_data($_POST['recurrence_byday']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  }
540
- $this->recurrence_interval = ( !empty($_POST['recurrence_interval']) && is_numeric($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1;
541
- $this->recurrence_byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? wp_kses_data($_POST['recurrence_byweekno']):'';
542
- $this->recurrence_days = ( !empty($_POST['recurrence_days']) && is_numeric($_POST['recurrence_days']) ) ? (int) $_POST['recurrence_days']:0;
543
  }
544
  //categories in MS GLobal
545
  if(EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
546
  $this->get_categories()->get_post(); //it'll know what to do
547
  }
548
- //validate (optional) and return result
549
  $this->compat_keys(); //compatability
550
  return apply_filters('em_event_get_post_meta', count($this->errors) == 0, $this);
551
  }
@@ -634,6 +731,11 @@ class EM_Event extends EM_Object{
634
  //unless events can be submitted by an anonymous user (and this is a new event), user must have permissions.
635
  return apply_filters('em_event_save', false, $this);
636
  }
 
 
 
 
 
637
  do_action('em_event_save_pre', $this);
638
  $post_array = array();
639
  //Deal with updates to an event
@@ -787,7 +889,7 @@ class EM_Event extends EM_Object{
787
  $this->event_id = $wpdb->insert_id;
788
  update_post_meta($this->post_id, '_event_id', $this->event_id);
789
  $this->feedback_message = sprintf(__('Successfully saved %s','events-manager'),__('Event','events-manager'));
790
- $just_added_event = true; //make an easy hook
791
  do_action('em_event_save_new', $this);
792
  }
793
  }else{
@@ -813,6 +915,7 @@ class EM_Event extends EM_Object{
813
  //Add/Delete Tickets
814
  if($this->event_rsvp == 0){
815
  $this->get_bookings()->delete();
 
816
  }elseif( $this->can_manage('manage_bookings','manage_others_bookings') ){
817
  if( !$this->get_bookings()->get_tickets()->save() ){
818
  $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
@@ -829,16 +932,17 @@ class EM_Event extends EM_Object{
829
  }
830
  $this->compat_keys(); //compatability keys, loaded before saving recurrences
831
  //build recurrences if needed
832
- if( $this->is_recurring() && $result && $this->is_published() ){ //only save events if recurring event validates and is published
833
  global $EM_EVENT_SAVE_POST;
834
  //If we're in WP Admin and this was called by EM_Event_Post_Admin::save_post, don't save here, it'll be done later in EM_Event_Recurring_Post_Admin::save_post
835
  if( empty($EM_EVENT_SAVE_POST) ){
 
836
  if( !$this->save_events() ){
837
  $this->add_error(__ ( 'Something went wrong with the recurrence update...', 'events-manager'). __ ( 'There was a problem saving the recurring events.', 'events-manager'));
838
  }
839
  }
840
  }
841
- if( !empty($just_added_event) ){
842
  do_action('em_event_added', $this);
843
  }
844
  }
@@ -960,6 +1064,7 @@ class EM_Event extends EM_Object{
960
  $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->event_id) );
961
  if( $result !== false ){
962
  $this->get_bookings()->delete();
 
963
  //Delete the recurrences then this recurrence event
964
  if( $this->is_recurring() ){
965
  $result = $this->delete_events(); //was true at this point, so false if fails
@@ -1005,14 +1110,15 @@ class EM_Event extends EM_Object{
1005
 
1006
  /**
1007
  * Change the status of the event. This will save to the Database too.
1008
- * @param int $status
1009
- * @param boolean $set_post_status
1010
  * @return string
1011
  */
1012
  function set_status($status, $set_post_status = false){
1013
  global $wpdb;
 
1014
  if($status === null){
1015
- $set_status='NULL';
1016
  if($set_post_status){
1017
  //if the post is trash, don't untrash it!
1018
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
@@ -1021,20 +1127,27 @@ class EM_Event extends EM_Object{
1021
  }elseif( $status == -1 ){ //trashed post
1022
  $set_status = -1;
1023
  if($set_post_status){
 
1024
  $wpdb->update( $wpdb->posts, array( 'post_status' => $this->post_status ), array( 'ID' => $this->post_id ) );
1025
  }
1026
  $this->post_status = 'trash'; //set post status in this instance
1027
  }else{
1028
- $set_status = $status ? 1:0;
1029
  $post_status = $set_status ? 'publish':'pending';
 
 
 
 
 
1030
  if($set_post_status){
1031
- if($this->post_status == 'pending' && empty($this->post_name)){
1032
- $this->post_name = sanitize_title($this->post_title);
1033
- }
1034
  $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
 
 
 
1035
  }
1036
  $this->post_status = $post_status;
1037
  }
 
1038
  $this->get_previous_status();
1039
  $result = $wpdb->query( $wpdb->prepare("UPDATE ".EM_EVENTS_TABLE." SET event_status=$set_status, event_slug=%s WHERE event_id=%d", array($this->post_name, $this->event_id)) );
1040
  $this->get_status(); //reload status
@@ -1158,15 +1271,15 @@ class EM_Event extends EM_Object{
1158
  function get_tickets( $force_reload = false ){
1159
  return $this->get_bookings($force_reload)->get_tickets();
1160
  }
1161
-
1162
- /*
1163
- * Provides the tax rate for this event.
1164
- * Currently a site-wide default, but this hook allows easy overriding of tax rates for specific events.
1165
- * @uses apply_filters() on 'em_event_get_tax_rate' before returning value
1166
- * @uses EM_Object::get_tax_rate()
1167
  */
1168
- function get_tax_rate(){
1169
- return apply_filters('em_event_get_tax_rate', parent::get_tax_rate(), $this);
 
 
 
1170
  }
1171
 
1172
  /**
@@ -1296,6 +1409,7 @@ class EM_Event extends EM_Object{
1296
  * @return string
1297
  */
1298
  function output($format, $target="html") {
 
1299
  $event_string = $format;
1300
  //Time place holder that doesn't show if empty.
1301
  //TODO add filter here too
@@ -1316,7 +1430,7 @@ class EM_Event extends EM_Object{
1316
  $event_string = str_replace($result,$replace,$event_string );
1317
  }
1318
  //This is for the custom attributes
1319
- preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+)\})?/', $event_string, $results);
1320
  $attributes = em_get_attributes();
1321
  foreach($results[0] as $resultKey => $result) {
1322
  //Strip string of placeholder and just leave the reference
@@ -1423,6 +1537,31 @@ class EM_Event extends EM_Object{
1423
  }elseif ($condition == 'not_private'){
1424
  //if event is not a recurrence
1425
  $show_condition = $this->event_private == 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1426
  }elseif ( preg_match('/^has_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){
1427
  //event is in this category
1428
  $show_condition = has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id);
@@ -1472,29 +1611,21 @@ class EM_Event extends EM_Object{
1472
  case '#_EXCERPT': //deprecated
1473
  case '#_EVENTNOTES':
1474
  case '#_EVENTEXCERPT':
 
1475
  $replace = $this->post_content;
1476
- if($result == "#_EXCERPT" || $result == "#_EVENTEXCERPT"){
1477
- if( !empty($this->post_excerpt) ){
1478
  $replace = $this->post_excerpt;
1479
  }else{
1480
- $excerpt_length = 55;
1481
  $excerpt_more = apply_filters('em_excerpt_more', ' ' . '[...]');
1482
- if( !empty($placeholders[3][$key]) ){
1483
- $trim = true;
1484
- $ph_args = explode(',', $placeholders[3][$key]);
1485
- if( is_numeric($ph_args[0]) ) $excerpt_length = $ph_args[0];
1486
- if( !empty($ph_args[1]) ) $excerpt_more = $ph_args[1];
1487
- }
1488
- if ( preg_match('/<!--more(.*?)?-->/', $replace, $matches) ) {
1489
- $content = explode($matches[0], $replace, 2);
1490
- $replace = force_balance_tags($content[0]);
1491
- }
1492
- if( !empty($trim) ){
1493
- //shorten content by supplied number - copied from wp_trim_excerpt
1494
- $replace = strip_shortcodes( $replace );
1495
- $replace = str_replace(']]>', ']]&gt;', $replace);
1496
- $replace = wp_trim_words( $replace, $excerpt_length, $excerpt_more );
1497
  }
 
1498
  }
1499
  }
1500
  break;
@@ -1553,25 +1684,11 @@ class EM_Event extends EM_Object{
1553
  break;
1554
  case '#_EVENTTIMES':
1555
  //get format of time to show
1556
- if( !$this->event_all_day ){
1557
- $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
1558
- if($this->event_start_time != $this->event_end_time ){
1559
- $replace = date_i18n($time_format, $this->start). get_option('dbem_times_separator') . date_i18n($time_format, $this->end);
1560
- }else{
1561
- $replace = date_i18n($time_format, $this->start);
1562
- }
1563
- }else{
1564
- $replace = get_option('dbem_event_all_day_message');
1565
- }
1566
  break;
1567
  case '#_EVENTDATES':
1568
  //get format of time to show
1569
- $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
1570
- if( $this->event_start_date != $this->event_end_date){
1571
- $replace = date_i18n($date_format, $this->start). get_option('dbem_dates_separator') . date_i18n($date_format, $this->end);
1572
- }else{
1573
- $replace = date_i18n($date_format, $this->start);
1574
- }
1575
  break;
1576
  //Links
1577
  case '#_EVENTPAGEURL': //deprecated
@@ -1827,7 +1944,7 @@ class EM_Event extends EM_Object{
1827
  $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url);
1828
  $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url);
1829
  $gcal_url = str_replace('end_date', urlencode($dateEnd), $gcal_url);
1830
- $gcal_url = str_replace('location_name', urlencode($this->output('#_LOCATION')), $gcal_url);
1831
  $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url);
1832
  $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url);
1833
  //calculate URL length so we know how much we can work with to make a description.
@@ -1920,7 +2037,52 @@ class EM_Event extends EM_Object{
1920
  $event_string = str_replace("\n",'\n',$event_string);
1921
  }
1922
  return apply_filters('em_event_output', $event_string, $this, $format, $target);
1923
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1924
 
1925
  /**********************************************************
1926
  * RECURRENCE METHODS
@@ -2011,11 +2173,11 @@ class EM_Event extends EM_Object{
2011
  function save_events() {
2012
  global $wpdb;
2013
  $event_ids = $post_ids = array();
2014
- if( $this->can_manage('edit_events','edit_others_events') && $this->is_published() ){
2015
  do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
2016
- //Make template event index, post, and meta (and we just change event dates)
2017
  $event = $this->to_array(true); //event template - for index
2018
- $event['event_attributes'] = serialize($event['event_attributes']);
2019
  $post_fields = $wpdb->get_row('SELECT * FROM '.$wpdb->posts.' WHERE ID='.$this->post_id, ARRAY_A); //post to copy
2020
  $post_name = $post_fields['post_name']; //save post slug since we'll be using this
2021
  $post_fields['post_type'] = 'event'; //make sure we'll save events, not recurrence templates
@@ -2025,65 +2187,123 @@ class EM_Event extends EM_Object{
2025
  foreach($meta_fields_map as $meta_data){
2026
  $meta_fields[$meta_data['meta_key']] = $meta_data['meta_value'];
2027
  }
 
 
2028
  //remove id and we have a event template to feed to wpdb insert
2029
- unset($event['event_id']);
2030
  unset($post_fields['ID']);
 
 
2031
  //remove recurrence meta info we won't need in events
2032
  foreach( array_keys($this->recurrence_fields) as $recurrence_field){
2033
  unset($event[$recurrence_field]);
2034
  unset($meta_fields['_'.$recurrence_field]);
2035
- }
2036
- $event['event_date_created'] = current_time('mysql'); //since the recurrences are recreated
2037
- unset($event['event_date_modified']);
2038
  //Set the recurrence ID
2039
  $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
2040
  $event['recurrence'] = $meta_fields['_recurrence'] = 0;
 
2041
  //Let's start saving!
2042
- $this->delete_events(); //Delete old events beforehand, this will change soon
2043
  $event_saves = array();
2044
- $matching_days = $this->get_recurrence_days(); //Get days where events recur
2045
- if( count($matching_days) > 0 ){
2046
- //first save event post data
2047
- $recurring_date_format = apply_filters('em_event_save_events_format', 'Y-m-d');
2048
- foreach( $matching_days as $day ) {
2049
- //rewrite post fields if needed
2050
- $post_fields['post_name'] = $event['event_slug'] = $meta_fields['_event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $day), $post_fields, $day, $matching_days, $this);
2051
- //adjust certain meta information
2052
- $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day);
2053
- $meta_fields['_start_ts'] = strtotime($event['event_start_date'].' '.$event['event_start_time']);
2054
- if( !empty($event['recurrence_rsvp_days']) && is_numeric($event['recurrence_rsvp_days']) ){
2055
- $event_rsvp_days = $event['recurrence_rsvp_days'] >= 0 ? '+'. $event['recurrence_rsvp_days']: $event['recurrence_rsvp_days'];
2056
- $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $meta_fields['_start_ts']));
2057
- $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2058
- $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2059
- }else{
2060
- $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event['event_start_date'];
 
 
 
 
 
2061
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2062
- }
2063
- if($this->recurrence_days > 0){
2064
- $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_start_ts'] + ($this->recurrence_days * 60*60*24));
2065
- }else{
2066
- $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
2067
- }
2068
- $meta_fields['_end_ts'] = strtotime($event['event_end_date'].' '.$event['event_end_time']);
2069
- //create the event
2070
- if( $wpdb->insert($wpdb->posts, $post_fields ) ){
2071
- $event['post_id'] = $meta_fields['_post_id'] = $post_id = $post_ids[] = $wpdb->insert_id; //post id saved into event and also as a var for later user
2072
- // Set GUID and event slug as per wp_insert_post
2073
- $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_id ) ), array('ID'=>$post_id) );
2074
- //insert into events index table
2075
- $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
2076
- $event_ids[$post_id] = $event_id = $wpdb->insert_id;
2077
- $event_dates[$event_id] = $meta_fields['_start_ts'];
2078
- //create the meta inserts for each event
2079
- $meta_fields['_event_id'] = $event_id;
2080
- foreach($meta_fields as $meta_key => $meta_val){
2081
- $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($post_id, $meta_key, $meta_val));
2082
- }
2083
- }else{
2084
- $event_saves[] = false;
2085
- }
2086
- //if( EM_DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2087
  }
2088
  //insert the metas in one go, faster than one by one
2089
  if( count($meta_inserts) > 0 ){
@@ -2092,54 +2312,20 @@ class EM_Event extends EM_Object{
2092
  $this->add_error('There was a problem adding custom fields to your recurring events.','events-manager');
2093
  }
2094
  }
2095
- //copy the event tags and categories
2096
- $taxonomies = self::get_taxonomies();
2097
- foreach($taxonomies as $tax_name => $tax_data){
2098
- //In MS Global mode, we also save category meta information for global lookups so we use our objects
2099
- if( EM_MS_GLOBAL && $tax_name == 'category' ){
2100
- //use EM_Categories as this is a special taxonomy in global mode
2101
- $EM_Categories = new EM_Categories($this);
2102
- //we save index data for each category in in MS Global mode
2103
- foreach($event_ids as $post_id => $event_id){
2104
- foreach( $EM_Categories->categories as $EM_Category ){
2105
- $EM_Categories->event_id = $event_id;
2106
- $EM_Categories->post_id = $post_id;
2107
- $EM_Categories->save();
2108
- }
2109
- }
2110
- }else{
2111
- //general taxonomies including event tags
2112
- $terms = get_the_terms( $this->post_id, $tax_data['name']);
2113
- $term_slugs = array();
2114
- if( is_array($terms) ){
2115
- foreach($terms as $term){
2116
- if( !empty($term->slug) ) $term_slugs[] = $term->slug; //save of category will soft-fail if slug is empty
2117
- }
2118
- }
2119
- foreach($post_ids as $post_id){
2120
- wp_set_object_terms($post_id, $term_slugs, $tax_data['name']);
2121
- }
2122
- }
2123
- }
2124
- //featured images
2125
- if( !empty($this->attributes['thumbnail_id']) ){
2126
- $image_inserts = array();
2127
- foreach($post_ids as $post_ids){
2128
- $image_inserts[] = "({$this->post_id}, '_thumbnail_id', {$this->attributes['thumbnail_id']})";
2129
- }
2130
- if( count($image_inserts) > 0 ){
2131
- $wpdb->query('INSERT INTO '.$wpdb->postmeta.' (post_id, meta_key, meta_value) VALUES '.implode(', ', $image_inserts));
2132
  }
2133
  }
2134
- //MS Global Categories
2135
- if( EM_MS_GLOBAL && get_option('dbem_categories_enabled') ){
2136
- foreach( self::get_categories() as $EM_Category ){
2137
- foreach($event_ids as $event_id){
2138
- $wpdb->insert(EM_META_TABLE, array('meta_value'=>$EM_Category->term_id,'object_id'=>$event_id,'meta_key'=>'event-category'));
2139
- }
2140
- }
2141
- }
2142
- //now, save booking info for each event
2143
  if( $this->event_rsvp ){
2144
  $meta_inserts = array();
2145
  foreach($this->get_tickets() as $EM_Ticket){
@@ -2189,10 +2375,51 @@ class EM_Event extends EM_Object{
2189
  $sql = "INSERT INTO ".EM_TICKETS_TABLE." $keys VALUES $values";
2190
  $result = $wpdb->query($sql);
2191
  }
2192
- }else{
2193
- $this->add_error('You have not defined a date range long enough to create a recurrence.','events-manager');
2194
- $result = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2195
  }
 
 
 
 
 
 
 
 
 
2196
  return apply_filters('em_event_save_events', !in_array(false, $event_saves) && $result !== false, $this, $event_ids, $post_ids);
2197
  }
2198
  return apply_filters('em_event_save_events', false, $this, $event_ids, $post_ids);
@@ -2369,7 +2596,7 @@ class EM_Event extends EM_Object{
2369
  $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
2370
  $natural_days = array();
2371
  foreach($weekday_array as $day){
2372
- if( !empty($day) ){
2373
  array_push($natural_days, $weekdays_name[$day]);
2374
  }
2375
  }
@@ -2411,7 +2638,7 @@ class EM_Event extends EM_Object{
2411
  * Can the user manage this?
2412
  */
2413
  function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
2414
- if( $this->event_id == '' && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
2415
  $user_to_check = get_option('dbem_events_anonymous_user');
2416
  }
2417
  return apply_filters('em_event_can_manage', parent::can_manage($owner_capability, $admin_capability, $user_to_check), $this, $owner_capability, $admin_capability, $user_to_check);
@@ -2429,7 +2656,7 @@ class EM_Event extends EM_Object{
2429
  */
2430
  function em_event_output_placeholder($result,$event,$placeholder,$target='html'){
2431
  if( $target == 'raw' ) return $result;
2432
- if( in_array($placeholder, array("#_EXCERPT",'#_EVENTEXCERPT', "#_LOCATIONEXCERPT")) && $target == 'html' ){
2433
  $result = apply_filters('dbem_notes_excerpt', $result);
2434
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
2435
  $result = em_ascii_encode($event->get_contact()->user_email);
43
  var $event_slug;
44
  var $event_owner;
45
  var $event_name;
46
+ var $event_start_time = '00:00:00';
47
+ var $event_end_time = '00:00:00';
48
  var $event_all_day;
49
  var $event_start_date;
50
  var $event_end_date;
105
  'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s', 'null'=>true ),
106
  'blog_id' => array( 'name'=>'blog_id', 'type'=>'%d', 'null'=>true ),
107
  'group_id' => array( 'name'=>'group_id', 'type'=>'%d', 'null'=>true ),
108
+ 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d', 'null'=>true ), //is this a recurring event template
109
  'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
110
  'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s', 'null'=>true ), //daily,weekly,monthly?
111
+ 'recurrence_days' => array( 'name'=>'days', 'type'=>'%d', 'null'=>true ), //each event spans x days
112
  'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s', 'null'=>true ), //if weekly or monthly, what days of the week?
113
  'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d', 'null'=>true ), //if monthly which week (-1 is last)
114
  'recurrence_rsvp_days' => array( 'name'=>'recurrence_rsvp_days', 'type'=>'%d', 'null'=>true ), //days before or after start date to generat bookings cut-off date
188
  * @var mixed
189
  */
190
  var $previous_status = false;
191
+ /**
192
+ * If set to true, recurring events will delete and recreate recurrences when saved.
193
+ * @var boolean
194
+ */
195
+ var $recurring_reschedule = false;
196
+ /**
197
+ * If set to true, recurring events will delete bookings and tickets of recurrences and recreate tickets.
198
+ * @var boolean
199
+ */
200
+ var $recurring_recreate_bookings = false;
201
+ /**
202
+ * Flag used for when saving a recurring event that previously had bookings enabled and then subsequently disabled.
203
+ * If set to true, and $this->recurring_recreate_bookings is false, bookings and tickets of recurrences will be deleted.
204
+ * @var boolean
205
+ */
206
+ var $recurring_delete_bookings = false;
207
+ /**
208
+ * If the event was just added/created during this execution, value will be true. Useful when running validation or making decisions on taking actions when events are saved/created for the first time.
209
+ * @var boolean
210
+ */
211
+ var $just_added_event = false;
212
 
213
  /* Post Variables - copied out of post object for easy IDE reference */
214
  var $ID;
408
  */
409
  function get_post_meta(){
410
  do_action('em_event_get_post_meta_pre', $this);
411
+
412
+ //Check if this is recurring or not early on so we can take appropriate action further down
 
 
413
  if( !empty($_POST['recurring']) ){
414
  $this->recurrence = 1;
415
  $this->post_type = 'event-recurring';
416
  }
417
+
418
+ //Dates and Times - ignored if event is recurring being updated (not new) and not specifically chosen to reschedule event
419
+ if( !$this->is_recurring() || (empty($this->event_id) || !empty($_REQUEST['event_reschedule'])) ){
420
+ //Event Dates
421
+ $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : '';
422
+ $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date;
423
+ //Sort out time
424
+ $this->event_all_day = ( !empty($_POST['event_all_day']) ) ? 1 : 0;
425
+ if( $this->event_all_day ){
426
+ $times_array = array('event_rsvp_time');
427
+ $this->event_start_time = '00:00:00';
428
+ $this->event_end_time = '23:59:59';
429
+ }else{
430
+ $times_array = array('event_start_time','event_end_time', 'event_rsvp_time');
431
+ }
432
+ foreach( $times_array as $timeName ){
433
+ $match = array();
434
+ if( !empty($_POST[$timeName]) && preg_match ( '/^([01]\d|[0-9]|2[0-3])(:([0-5]\d))? ?(AM|PM)?$/', $_POST[$timeName], $match ) ){
435
+ if( empty($match[3]) ) $match[3] = '00';
436
+ if( strlen($match[1]) == 1 ) $match[1] = '0'.$match[1];
437
+ if( !empty($match[4]) && $match[4] == 'PM' && $match[1] != 12 ){
438
+ $match[1] = 12+$match[1];
439
+ }elseif( !empty($match[4]) && $match[4] == 'AM' && $match[1] == 12 ){
440
+ $match[1] = '00';
441
+ }
442
+ $this->$timeName = $match[1].":".$match[3].":00";
443
+ }else{
444
+ $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
445
+ }
446
+ }
447
+ //Start/End times should be available as timestamp
448
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
449
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
450
+ }
451
+
452
  //Get Location info
453
  if( !get_option('dbem_locations_enabled') || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){
454
  $this->location_id = 0;
460
  $this->get_location()->get_post(false);
461
  $this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise
462
  }
463
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  //Bookings
465
  $can_manage_bookings = $this->can_manage('manage_bookings','manage_others_bookings');
466
  $preview_autosave = is_admin() && !empty($_REQUEST['_emnonce']) && !empty($_REQUEST['wp-preview']) && $_REQUEST['wp-preview'] == 'dopreview'; //we shouldn't save new data during a preview auto-save
467
  if( !$preview_autosave && $can_manage_bookings && !empty($_POST['event_rsvp']) && $_POST['event_rsvp'] ){
468
+ //get tickets only if event is new, non-recurring, or recurring but specifically allowed to reschedule by user
469
+ if( !$this->is_recurring() || (empty($this->event_id) || !empty($_REQUEST['event_recreate_tickets'])) ){
470
+ $this->get_bookings()->get_tickets()->get_post();
471
+ }
472
  $this->event_rsvp = 1;
473
  //RSVP cuttoff TIME is set up above where start/end times are as well
474
  if( !$this->is_recurring() ){
532
  $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0;
533
  $this->event_rsvp_spaces = ( isset($_POST['event_rsvp_spaces']) ) ? absint($_POST['event_rsvp_spaces']):0;
534
  }elseif( !$preview_autosave && ($can_manage_bookings || !$this->event_rsvp) ){
535
+ if( empty($_POST['event_rsvp']) && $this->event_rsvp ) $deleting_bookings = true;
536
  $this->event_rsvp = 0;
537
  $this->event_rsvp_time = '00:00:00';
538
  }
539
+
540
  //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
541
  if(get_option('dbem_attributes_enabled')){
542
  global $allowedtags;
559
  }
560
  }
561
  }
562
+
 
 
 
563
  //group id
564
  $this->group_id = (!empty($_POST['group_id']) && is_numeric($_POST['group_id'])) ? $_POST['group_id']:0;
565
+
566
  //Recurrence data
567
  if( $this->is_recurring() ){
568
  $this->recurrence = 1; //just in case
569
+
570
+ //If event is new or reschedule is requested, then proceed with new time pattern
571
+ if( empty($this->event_id) || !empty($_REQUEST['event_reschedule']) ){
572
+ //dates and time schedules of events
573
+ $this->recurrence_freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly','yearly')) ) ? $_POST['recurrence_freq']:'daily';
574
+ if( !empty($_POST['recurrence_bydays']) && $this->recurrence_freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){
575
+ $this->recurrence_byday = str_replace(' ', '', implode( ",", $_POST['recurrence_bydays'] ));
576
+ }elseif( isset($_POST['recurrence_byday']) && $this->recurrence_freq == 'monthly' ){
577
+ $this->recurrence_byday = wp_kses_data($_POST['recurrence_byday']);
578
+ }else{
579
+ $this->recurrence_byday = null;
580
+ }
581
+ $this->recurrence_interval = ( !empty($_POST['recurrence_interval']) && is_numeric($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1;
582
+ $this->recurrence_byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? wp_kses_data($_POST['recurrence_byweekno']):'';
583
+ $this->recurrence_days = ( !empty($_POST['recurrence_days']) && is_numeric($_POST['recurrence_days']) ) ? (int) $_POST['recurrence_days']:0;
584
+ }
585
+
586
+ //here we do a comparison between new and old event data to see if we are to reschedule events or recreate bookings
587
+ if( $this->event_id ){ //only needed if this is an existing event needing rescheduling/recreation
588
+ //Get original recurring event so we can tell whether event recurrences or bookings will be recreated or just modified
589
+ $EM_Event = new EM_Event($this->event_id);
590
+
591
+ //first check event times
592
+ $recurring_event_dates = array(
593
+ 'event_start_date' => $EM_Event->event_start_date,
594
+ 'event_end_date' => $EM_Event->event_end_date,
595
+ 'recurrence_byday' => $EM_Event->recurrence_byday,
596
+ 'recurrence_byweekno' => $EM_Event->recurrence_byweekno,
597
+ 'recurrence_days' => $EM_Event->recurrence_days,
598
+ 'recurrence_freq' => $EM_Event->recurrence_freq,
599
+ 'recurrence_interval' => $EM_Event->recurrence_interval
600
+ );
601
+ //check previously saved event info compared to current recurrence info to see if we need to reschedule
602
+ foreach($recurring_event_dates as $k => $v){
603
+ if( $this->$k != $v ){
604
+ $this->recurring_reschedule = true; //something changed, so we reschedule
605
+ }
606
+ }
607
+
608
+ //now check tickets if we don't already have to reschedule
609
+ if( !$this->recurring_reschedule && $this->event_rsvp ){
610
+ //@TODO - ideally tickets could be independent of events, it'd make life easier here for comparison and editing without rescheduling
611
+ $EM_Tickets = $EM_Event->get_tickets();
612
+ //we compare tickets
613
+ foreach( $this->get_tickets()->tickets as $EM_Ticket ){
614
+ if( !empty($EM_Ticket->ticket_id) && !empty($EM_Tickets->tickets[$EM_Ticket->ticket_id]) ){
615
+ $new_ticket = $EM_Ticket->to_array(true);
616
+ foreach( $EM_Tickets->tickets[$EM_Ticket->ticket_id]->to_array() as $k => $v ){
617
+ if( !(empty($new_ticket[$k]) && empty($v)) && ((empty($new_ticket[$k]) && $v) || $new_ticket[$k] != $v) ){
618
+ if( $k == 'ticket_meta' && is_array($v) && is_array($new_ticket['ticket_meta']) ){
619
+ foreach( $v as $k_meta => $v_meta ){
620
+ if( (empty($new_ticket['ticket_meta'][$k_meta]) && !empty($v_meta)) || $new_ticket['ticket_meta'][$k_meta] != $v_meta ){
621
+ $this->recurring_recreate_bookings = true; //something changed, so we reschedule
622
+ }
623
+ }
624
+ }else{
625
+ $this->recurring_recreate_bookings = true; //something changed, so we reschedule
626
+ }
627
+ }
628
+ }
629
+ }else{
630
+ $this->recurring_recreate_bookings = true; //we have a new ticket
631
+ }
632
+ }
633
+ }elseif( !empty($deleting_bookings) ){
634
+ $this->recurring_delete_bookings = true;
635
+ }
636
+ unset($EM_Event);
637
+ }else{
638
+ //new event so we create everything from scratch
639
+ $this->recurring_reschedule = $this->recurring_recreate_bookings = true;
640
  }
 
 
 
641
  }
642
  //categories in MS GLobal
643
  if(EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
644
  $this->get_categories()->get_post(); //it'll know what to do
645
  }
 
646
  $this->compat_keys(); //compatability
647
  return apply_filters('em_event_get_post_meta', count($this->errors) == 0, $this);
648
  }
731
  //unless events can be submitted by an anonymous user (and this is a new event), user must have permissions.
732
  return apply_filters('em_event_save', false, $this);
733
  }
734
+ //sort out multisite blog id if appliable
735
+ if( is_multisite() && empty($this->blog_id) ){
736
+ $this->blog_id = get_current_blog_id();
737
+ }
738
+ //start saving process
739
  do_action('em_event_save_pre', $this);
740
  $post_array = array();
741
  //Deal with updates to an event
889
  $this->event_id = $wpdb->insert_id;
890
  update_post_meta($this->post_id, '_event_id', $this->event_id);
891
  $this->feedback_message = sprintf(__('Successfully saved %s','events-manager'),__('Event','events-manager'));
892
+ $this->just_added_event = true; //make an easy hook
893
  do_action('em_event_save_new', $this);
894
  }
895
  }else{
915
  //Add/Delete Tickets
916
  if($this->event_rsvp == 0){
917
  $this->get_bookings()->delete();
918
+ $this->get_tickets()->delete();
919
  }elseif( $this->can_manage('manage_bookings','manage_others_bookings') ){
920
  if( !$this->get_bookings()->get_tickets()->save() ){
921
  $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
932
  }
933
  $this->compat_keys(); //compatability keys, loaded before saving recurrences
934
  //build recurrences if needed
935
+ if( $this->is_recurring() && $result && ($this->is_published() || $this->post_status == 'future') ){ //only save events if recurring event validates and is published or set for future
936
  global $EM_EVENT_SAVE_POST;
937
  //If we're in WP Admin and this was called by EM_Event_Post_Admin::save_post, don't save here, it'll be done later in EM_Event_Recurring_Post_Admin::save_post
938
  if( empty($EM_EVENT_SAVE_POST) ){
939
+ if( $this->just_added_event ) $this->recurring_reschedule = true;
940
  if( !$this->save_events() ){
941
  $this->add_error(__ ( 'Something went wrong with the recurrence update...', 'events-manager'). __ ( 'There was a problem saving the recurring events.', 'events-manager'));
942
  }
943
  }
944
  }
945
+ if( !empty($this->just_added_event) ){
946
  do_action('em_event_added', $this);
947
  }
948
  }
1064
  $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->event_id) );
1065
  if( $result !== false ){
1066
  $this->get_bookings()->delete();
1067
+ $this->get_tickets()->delete();
1068
  //Delete the recurrences then this recurrence event
1069
  if( $this->is_recurring() ){
1070
  $result = $this->delete_events(); //was true at this point, so false if fails
1110
 
1111
  /**
1112
  * Change the status of the event. This will save to the Database too.
1113
+ * @param int $status A number to change the status to, which may be -1 for trash, 1 for publish, 0 for pending or null if draft.
1114
+ * @param boolean $set_post_status If set to true the wp_posts table status will also be changed to the new corresponding status.
1115
  * @return string
1116
  */
1117
  function set_status($status, $set_post_status = false){
1118
  global $wpdb;
1119
+ //decide on what status to set and update wp_posts in the process
1120
  if($status === null){
1121
+ $set_status='NULL'; //draft post
1122
  if($set_post_status){
1123
  //if the post is trash, don't untrash it!
1124
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
1127
  }elseif( $status == -1 ){ //trashed post
1128
  $set_status = -1;
1129
  if($set_post_status){
1130
+ //set the post status of the location in wp_posts too
1131
  $wpdb->update( $wpdb->posts, array( 'post_status' => $this->post_status ), array( 'ID' => $this->post_id ) );
1132
  }
1133
  $this->post_status = 'trash'; //set post status in this instance
1134
  }else{
1135
+ $set_status = $status ? 1:0; //published or pending post
1136
  $post_status = $set_status ? 'publish':'pending';
1137
+ if( empty($this->post_name) ){
1138
+ //published or pending posts should have a valid post slug
1139
+ $this->post_name = sanitize_title($this->post_title);
1140
+ $set_post_name = true;
1141
+ }
1142
  if($set_post_status){
 
 
 
1143
  $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
1144
+ }elseif( $set_post_name ){
1145
+ //if we've added a post slug then update wp_posts anyway
1146
+ $wpdb->update( $wpdb->posts, array( 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
1147
  }
1148
  $this->post_status = $post_status;
1149
  }
1150
+ //save in the wp_em_locations table
1151
  $this->get_previous_status();
1152
  $result = $wpdb->query( $wpdb->prepare("UPDATE ".EM_EVENTS_TABLE." SET event_status=$set_status, event_slug=%s WHERE event_id=%d", array($this->post_name, $this->event_id)) );
1153
  $this->get_status(); //reload status
1271
  function get_tickets( $force_reload = false ){
1272
  return $this->get_bookings($force_reload)->get_tickets();
1273
  }
1274
+
1275
+ /* Provides the tax rate for this event.
1276
+ * @see EM_Object::get_tax_rate()
 
 
 
1277
  */
1278
+ function get_tax_rate( $decimal = false ){
1279
+ $tax_rate = apply_filters('em_event_get_tax_rate', parent::get_tax_rate( false ), $this); //we get tax rate but without decimal
1280
+ $tax_rate = ( $tax_rate > 0 ) ? $tax_rate : 0;
1281
+ if( $decimal && $tax_rate > 0 ) $tax_rate = $tax_rate / 100;
1282
+ return $tax_rate;
1283
  }
1284
 
1285
  /**
1409
  * @return string
1410
  */
1411
  function output($format, $target="html") {
1412
+ global $wpdb;
1413
  $event_string = $format;
1414
  //Time place holder that doesn't show if empty.
1415
  //TODO add filter here too
1430
  $event_string = str_replace($result,$replace,$event_string );
1431
  }
1432
  //This is for the custom attributes
1433
+ preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+\}?)\})?/', $event_string, $results);
1434
  $attributes = em_get_attributes();
1435
  foreach($results[0] as $resultKey => $result) {
1436
  //Strip string of placeholder and just leave the reference
1537
  }elseif ($condition == 'not_private'){
1538
  //if event is not a recurrence
1539
  $show_condition = $this->event_private == 0;
1540
+ }elseif ( strpos($condition, 'is_user_attendee') !== false || strpos($condition, 'not_user_attendee') !== false ){
1541
+ //if current user has a booking at this event
1542
+ $show_condition = false;
1543
+ if( is_user_logged_in() ){
1544
+ //we only need a user id, booking id and booking status so we do a direct SQL lookup and once for the loop
1545
+ if( !isset($user_bookings) || !is_array($user_bookings) ){
1546
+ $sql = $wpdb->prepare('SELECT booking_status FROM '.EM_BOOKINGS_TABLE.' WHERE person_id=%d AND event_id=%d', array(get_current_user_id(), $this->event_id));
1547
+ $user_bookings = $wpdb->get_col($sql);
1548
+ }
1549
+ if( $condition == 'is_user_attendee' && count($user_bookings) > 0 ){
1550
+ //user has a booking for this event, could be any booking status
1551
+ $show_condition = true;
1552
+ }elseif( $condition == 'not_user_attendee' && count($user_bookings) == 0 ){
1553
+ //user has no bookings to this event
1554
+ $show_condition = true;
1555
+ }elseif( strpos($condition, 'is_user_attendee_') !== false ){
1556
+ //user has a booking for this event, and we'll now look for a specific status
1557
+ $attendee_booking_status = str_replace('is_user_attendee_', '', $condition);
1558
+ $show_condition = in_array($attendee_booking_status, $user_bookings);
1559
+ }elseif( strpos($condition, 'not_user_attendee_') !== false ){
1560
+ //user has a booking for this event, and we'll now look for a specific status
1561
+ $attendee_booking_status = str_replace('not_user_attendee_', '', $condition);
1562
+ $show_condition = !in_array($attendee_booking_status, $user_bookings);
1563
+ }
1564
+ }
1565
  }elseif ( preg_match('/^has_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){
1566
  //event is in this category
1567
  $show_condition = has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id);
1611
  case '#_EXCERPT': //deprecated
1612
  case '#_EVENTNOTES':
1613
  case '#_EVENTEXCERPT':
1614
+ case '#_EVENTEXCERPTCUT':
1615
  $replace = $this->post_content;
1616
+ if($result == "#_EXCERPT" || $result == "#_EVENTEXCERPT" || $result == "#_EVENTEXCERPTCUT" ){
1617
+ if( !empty($this->post_excerpt) && $result != "#_EVENTEXCERPTCUT" ){
1618
  $replace = $this->post_excerpt;
1619
  }else{
1620
+ $excerpt_length = 55;
1621
  $excerpt_more = apply_filters('em_excerpt_more', ' ' . '[...]');
1622
+ if( !empty($placeholders[3][$key]) ){
1623
+ $trim = true;
1624
+ $ph_args = explode(',', $placeholders[3][$key]);
1625
+ if( is_numeric($ph_args[0]) ) $excerpt_length = $ph_args[0];
1626
+ if( !empty($ph_args[1]) ) $excerpt_more = $ph_args[1];
 
 
 
 
 
 
 
 
 
 
1627
  }
1628
+ $replace = $this->output_excerpt($excerpt_length, $excerpt_more);
1629
  }
1630
  }
1631
  break;
1684
  break;
1685
  case '#_EVENTTIMES':
1686
  //get format of time to show
1687
+ $replace = $this->output_times();
 
 
 
 
 
 
 
 
 
1688
  break;
1689
  case '#_EVENTDATES':
1690
  //get format of time to show
1691
+ $replace = $this->output_dates();
 
 
 
 
 
1692
  break;
1693
  //Links
1694
  case '#_EVENTPAGEURL': //deprecated
1944
  $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url);
1945
  $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url);
1946
  $gcal_url = str_replace('end_date', urlencode($dateEnd), $gcal_url);
1947
+ $gcal_url = str_replace('location_name', urlencode($this->output('#_LOCATION, #_LOCATIONADDRESS, #_LOCATIONCOUNTRY')), $gcal_url);
1948
  $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url);
1949
  $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url);
1950
  //calculate URL length so we know how much we can work with to make a description.
2037
  $event_string = str_replace("\n",'\n',$event_string);
2038
  }
2039
  return apply_filters('em_event_output', $event_string, $this, $format, $target);
2040
+ }
2041
+
2042
+ function output_times(){
2043
+ if( !$this->event_all_day ){
2044
+ $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
2045
+ if($this->event_start_time != $this->event_end_time ){
2046
+ $replace = date_i18n($time_format, $this->start). get_option('dbem_times_separator') . date_i18n($time_format, $this->end);
2047
+ }else{
2048
+ $replace = date_i18n($time_format, $this->start);
2049
+ }
2050
+ }else{
2051
+ $replace = get_option('dbem_event_all_day_message');
2052
+ }
2053
+ return $replace;
2054
+ }
2055
+
2056
+ function output_dates(){
2057
+ $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
2058
+ if( $this->event_start_date != $this->event_end_date){
2059
+ $replace = date_i18n($date_format, $this->start). get_option('dbem_dates_separator') . date_i18n($date_format, $this->end);
2060
+ }else{
2061
+ $replace = date_i18n($date_format, $this->start);
2062
+ }
2063
+ return $replace;
2064
+ }
2065
+
2066
+ function output_excerpt($excerpt_length = 55, $excerpt_more = '[...]', $cut_excerpt = true){
2067
+ if( !empty($this->post_excerpt) ){
2068
+ $replace = $this->post_excerpt;
2069
+ }else{
2070
+ $replace = $this->post_content;
2071
+ }
2072
+ if( empty($this->post_excerpt) || $cut_excerpt ){
2073
+ if ( preg_match('/<!--more(.*?)?-->/', $replace, $matches) ) {
2074
+ $content = explode($matches[0], $replace, 2);
2075
+ $replace = force_balance_tags($content[0]);
2076
+ }
2077
+ if( !empty($excerpt_length) ){
2078
+ //shorten content by supplied number - copied from wp_trim_excerpt
2079
+ $replace = strip_shortcodes( $replace );
2080
+ $replace = str_replace(']]>', ']]&gt;', $replace);
2081
+ $replace = wp_trim_words( $replace, $excerpt_length, $excerpt_more );
2082
+ }
2083
+ }
2084
+ return $replace;
2085
+ }
2086
 
2087
  /**********************************************************
2088
  * RECURRENCE METHODS
2173
  function save_events() {
2174
  global $wpdb;
2175
  $event_ids = $post_ids = array();
2176
+ if( $this->can_manage('edit_events','edit_others_events') && ($this->is_published() || 'future' == $this->post_status) ){
2177
  do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
2178
+ //Make template event index, post, and meta (we change event dates, timestamps, rsvp dates and other recurrence-relative info whilst saving each event recurrence)
2179
  $event = $this->to_array(true); //event template - for index
2180
+ if( !empty($event['event_attributes']) ) $event['event_attributes'] = serialize($event['event_attributes']);
2181
  $post_fields = $wpdb->get_row('SELECT * FROM '.$wpdb->posts.' WHERE ID='.$this->post_id, ARRAY_A); //post to copy
2182
  $post_name = $post_fields['post_name']; //save post slug since we'll be using this
2183
  $post_fields['post_type'] = 'event'; //make sure we'll save events, not recurrence templates
2187
  foreach($meta_fields_map as $meta_data){
2188
  $meta_fields[$meta_data['meta_key']] = $meta_data['meta_value'];
2189
  }
2190
+ if( isset($meta_fields['_edit_last']) ) unset($meta_fields['_edit_last']);
2191
+ if( isset($meta_fields['_edit_lock']) ) unset($meta_fields['_edit_lock']);
2192
  //remove id and we have a event template to feed to wpdb insert
2193
+ unset($event['event_id'], $event['post_id']);
2194
  unset($post_fields['ID']);
2195
+ unset($meta_fields['_event_id']);
2196
+ if( isset($meta_fields['_post_id']) ) unset($meta_fields['_post_id']); //legacy bugfix, post_id was never needed in meta table
2197
  //remove recurrence meta info we won't need in events
2198
  foreach( array_keys($this->recurrence_fields) as $recurrence_field){
2199
  unset($event[$recurrence_field]);
2200
  unset($meta_fields['_'.$recurrence_field]);
2201
+ }
 
 
2202
  //Set the recurrence ID
2203
  $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
2204
  $event['recurrence'] = $meta_fields['_recurrence'] = 0;
2205
+
2206
  //Let's start saving!
 
2207
  $event_saves = array();
2208
+ //First thing - times. If we're changing event times, we need to delete all events and recreate them with the right times, no other way
2209
+ $recurring_date_format = apply_filters('em_event_save_events_format', 'Y-m-d');
2210
+ if( $this->recurring_reschedule ){
2211
+ $this->delete_events(); //Delete old events beforehand, this will change soon
2212
+ $matching_days = $this->get_recurrence_days(); //Get days where events recur
2213
+ $event['event_date_created'] = current_time('mysql'); //since the recurrences are recreated
2214
+ unset($event['event_date_modified']);
2215
+ if( count($matching_days) > 0 ){
2216
+ //first save event post data
2217
+ foreach( $matching_days as $day ) {
2218
+ //rewrite post fields if needed
2219
+ $post_fields['post_name'] = $event['event_slug'] = $meta_fields['_event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $day), $post_fields, $day, $matching_days, $this);
2220
+ //adjust certain meta information
2221
+ $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day);
2222
+ $meta_fields['_start_ts'] = strtotime($event['event_start_date'].' '.$event['event_start_time']);
2223
+ if( !empty($event['recurrence_rsvp_days']) && is_numeric($event['recurrence_rsvp_days']) ){
2224
+ $event_rsvp_days = $event['recurrence_rsvp_days'] >= 0 ? '+'. $event['recurrence_rsvp_days']: $event['recurrence_rsvp_days'];
2225
+ $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $meta_fields['_start_ts']));
2226
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2227
+ }else{
2228
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event['event_start_date'];
2229
+ }
2230
  $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2231
+ if($this->recurrence_days > 0){
2232
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_start_ts'] + ($this->recurrence_days * 60*60*24));
2233
+ }else{
2234
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
2235
+ }
2236
+ $meta_fields['_end_ts'] = strtotime($event['event_end_date'].' '.$event['event_end_time']);
2237
+ //create the event
2238
+ if( $wpdb->insert($wpdb->posts, $post_fields ) ){
2239
+ $event['post_id'] = $post_id = $post_ids[] = $wpdb->insert_id; //post id saved into event and also as a var for later user
2240
+ // Set GUID and event slug as per wp_insert_post
2241
+ $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_id ) ), array('ID'=>$post_id) );
2242
+ //insert into events index table
2243
+ $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
2244
+ $event_ids[$post_id] = $event_id = $wpdb->insert_id;
2245
+ $event_dates[$event_id] = $meta_fields['_start_ts'];
2246
+ //create the meta inserts for each event
2247
+ $meta_fields['_event_id'] = $event_id;
2248
+ foreach($meta_fields as $meta_key => $meta_val){
2249
+ $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($post_id, $meta_key, $meta_val));
2250
+ }
2251
+ }else{
2252
+ $event_saves[] = false;
2253
+ }
2254
+ //if( EM_DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
2255
+ }
2256
+ //insert the metas in one go, faster than one by one
2257
+ if( count($meta_inserts) > 0 ){
2258
+ $result = $wpdb->query("INSERT INTO ".$wpdb->postmeta." (post_id,meta_key,meta_value) VALUES ".implode(',',$meta_inserts));
2259
+ if($result === false){
2260
+ $this->add_error('There was a problem adding custom fields to your recurring events.','events-manager');
2261
+ }
2262
+ }
2263
+ }else{
2264
+ $this->add_error('You have not defined a date range long enough to create a recurrence.','events-manager');
2265
+ $result = false;
2266
+ }
2267
+ }else{
2268
+ //we go through all event main data and meta data, we delete and recreate all meta data
2269
+ $meta_inserts = array();
2270
+ //now unset some vars we don't need to deal with since we're just updating data in the wp_em_events and posts table
2271
+ unset( $event['event_date_created'], $event['recurrence_id'], $event['recurrence'], $event['event_start_date'], $event['event_end_date'], $event['event_start_time'], $event['event_end_time'] );
2272
+ $event['event_date_modified'] = current_time('mysql'); //since the recurrences are modified but not recreated
2273
+ unset( $post_fields['comment_count'], $post_fields['guid'], $post_fields['menu_order']);
2274
+ //now we go through the recurrences and check whether things relative to dates need to be changed
2275
+ //@todo do a direct DB lookup once we have timezones implemented to save processing and memory
2276
+ $EM_Events = EM_Events::get( array('recurrence'=>$this->event_id, 'scope'=>'all', 'status'=>'everything' ) );
2277
+ foreach($EM_Events as $EM_Event){ /* @var $EM_Event EM_Event */
2278
+ $event_ids[$EM_Event->post_id] = $EM_Event->event_id;
2279
+ $post_ids[] = $EM_Event->post_id;
2280
+ //do we need to change the slugs?
2281
+ $post_fields['post_name'] = $event['event_slug'] = $meta_fields['_event_slug'] = apply_filters('em_event_save_events_slug', $post_name.'-'.date($recurring_date_format, $EM_Event->start), $post_fields, $EM_Event->start, array(), $this);
2282
+ //adjust certain meta information relativv
2283
+ if( !empty($event['recurrence_rsvp_days']) && is_numeric($event['recurrence_rsvp_days']) ){
2284
+ $event_rsvp_days = $event['recurrence_rsvp_days'] >= 0 ? '+'. $event['recurrence_rsvp_days']: $event['recurrence_rsvp_days'];
2285
+ $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $EM_Event->start));
2286
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2287
+ }else{
2288
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $EM_Event->event_start_date;
2289
+ }
2290
+ $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2291
+ //add meta fields we deleted and are specific to this event
2292
+ $meta_fields['_event_start_date'] = $EM_Event->event_start_date;
2293
+ $meta_fields['_event_end_date'] = $EM_Event->event_end_date;
2294
+ $meta_fields['_start_ts'] = $EM_Event->start;
2295
+ $meta_fields['_end_ts'] = $EM_Event->end;
2296
+ //overwrite event and post tables
2297
+ $wpdb->update(EM_EVENTS_TABLE, $event, array('event_id' => $EM_Event->event_id));
2298
+ $wpdb->update($wpdb->posts, $post_fields, array('ID' => $EM_Event->post_id));
2299
+ //save meta field data for insertion in one go
2300
+ foreach($meta_fields as $meta_key => $meta_val){
2301
+ $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($EM_Event->post_id, $meta_key, $meta_val));
2302
+ }
2303
+ }
2304
+ //delete all meta
2305
+ if( !empty($post_ids) ){
2306
+ $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE post_id IN (".implode(',', array_keys($post_ids)).")");
2307
  }
2308
  //insert the metas in one go, faster than one by one
2309
  if( count($meta_inserts) > 0 ){
2312
  $this->add_error('There was a problem adding custom fields to your recurring events.','events-manager');
2313
  }
2314
  }
2315
+ }
2316
+ //Next - Bookings. If we're completely rescheduling or just recreating bookings, we're deleting them and starting again
2317
+ if( $this->recurring_reschedule || $this->recurring_recreate_bookings ){
2318
+ //first, delete all bookings & tickets if we haven't done so during the reschedule above - something we'll want to change later if possible so bookings can be modified without losing all data
2319
+ if( !$this->recurring_reschedule ){
2320
+ foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it
2321
+ /* @var $EM_Event EM_Event */
2322
+ if($EM_Event->recurrence_id == $this->event_id){
2323
+ $EM_Event->get_bookings()->delete();
2324
+ $EM_Event->get_tickets()->delete();
2325
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2326
  }
2327
  }
2328
+ //if bookings hasn't been disabled, delete it all
 
 
 
 
 
 
 
 
2329
  if( $this->event_rsvp ){
2330
  $meta_inserts = array();
2331
  foreach($this->get_tickets() as $EM_Ticket){
2375
  $sql = "INSERT INTO ".EM_TICKETS_TABLE." $keys VALUES $values";
2376
  $result = $wpdb->query($sql);
2377
  }
2378
+ }elseif( $this->recurring_delete_bookings ){
2379
+ foreach($EM_Events as $EM_Event){ //$EM_Events was defined in the else statement above so we reuse it
2380
+ /* @var $EM_Event EM_Event */
2381
+ if($EM_Event->recurrence_id == $this->event_id){
2382
+ $EM_Event->get_bookings()->delete();
2383
+ $EM_Event->get_tickets()->delete();
2384
+ }
2385
+ }
2386
+ }
2387
+ //copy the event tags and categories, which are automatically deleted/recreated by WP and EM_Categories
2388
+ foreach( self::get_taxonomies() as $tax_name => $tax_data ){
2389
+ //In MS Global mode, we also save category meta information for global lookups so we use our objects
2390
+ if( $tax_name == 'category' ){
2391
+ //we save index data for each category in in MS Global mode
2392
+ foreach($event_ids as $post_id => $event_id){
2393
+ //set and trick category event and post ids so it saves to the right place
2394
+ $this->get_categories()->event_id = $event_id;
2395
+ $this->get_categories()->post_id = $post_id;
2396
+ $this->get_categories()->save();
2397
+ }
2398
+ $this->get_categories()->event_id = $this->event_id;
2399
+ $this->get_categories()->post_id = $this->post_id;
2400
+ }else{
2401
+ //general taxonomies including event tags
2402
+ $terms = get_the_terms( $this->post_id, $tax_data['name']);
2403
+ $term_slugs = array();
2404
+ if( is_array($terms) ){
2405
+ foreach($terms as $term){
2406
+ if( !empty($term->slug) ) $term_slugs[] = $term->slug; //save of category will soft-fail if slug is empty
2407
+ }
2408
+ }
2409
+ foreach($post_ids as $post_id){
2410
+ wp_set_object_terms($post_id, $term_slugs, $tax_data['name']);
2411
+ }
2412
+ }
2413
  }
2414
+ if( 'future' == $this->post_status ){
2415
+ $time = strtotime( $this->post_date_gmt . ' GMT' );
2416
+ foreach( $post_ids as $post_id ){
2417
+ if( !$this->recurring_reschedule ){
2418
+ wp_clear_scheduled_hook( 'publish_future_post', array( $post_id ) ); // clear anything else in the system
2419
+ }
2420
+ wp_schedule_single_event( $time, 'publish_future_post', array( $post_id ) );
2421
+ }
2422
+ }
2423
  return apply_filters('em_event_save_events', !in_array(false, $event_saves) && $result !== false, $this, $event_ids, $post_ids);
2424
  }
2425
  return apply_filters('em_event_save_events', false, $this, $event_ids, $post_ids);
2596
  $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
2597
  $natural_days = array();
2598
  foreach($weekday_array as $day){
2599
+ if( is_numeric($day) ){
2600
  array_push($natural_days, $weekdays_name[$day]);
2601
  }
2602
  }
2638
  * Can the user manage this?
2639
  */
2640
  function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
2641
+ if( ($this->just_added_event || $this->event_id == '') && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
2642
  $user_to_check = get_option('dbem_events_anonymous_user');
2643
  }
2644
  return apply_filters('em_event_can_manage', parent::can_manage($owner_capability, $admin_capability, $user_to_check), $this, $owner_capability, $admin_capability, $user_to_check);
2656
  */
2657
  function em_event_output_placeholder($result,$event,$placeholder,$target='html'){
2658
  if( $target == 'raw' ) return $result;
2659
+ if( in_array($placeholder, array("#_EXCERPT",'#_EVENTEXCERPT','#_EVENTEXCERPTCUT', "#_LOCATIONEXCERPT")) && $target == 'html' ){
2660
  $result = apply_filters('dbem_notes_excerpt', $result);
2661
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
2662
  $result = em_ascii_encode($event->get_contact()->user_email);
classes/em-events.php CHANGED
@@ -33,7 +33,7 @@ class EM_Events extends EM_Object {
33
  $args = self::get_default_search($args);
34
  $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
35
  $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
36
- $groupby_sql = '';
37
 
38
  //Get the default conditions
39
  $conditions = self::build_sql_conditions($args);
@@ -241,7 +241,6 @@ class EM_Events extends EM_Object {
241
 
242
  $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby');
243
  $args['header_format'] = !empty($args['header_format']) ? $args['header_format'] : get_option('dbem_event_list_groupby_header_format', '<h2>#s</h2>');
244
- $args['date_format'] = !empty($args['date_format']) ? $args['date_format'] : get_option('dbem_event_list_groupby_format');
245
  //Reset some vars for counting events and displaying set arrays of events
246
  $atts = (array) $args;
247
  $atts['pagination'] = false;
@@ -459,6 +458,12 @@ class EM_Events extends EM_Object {
459
  $conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id={$args['post_id']})";
460
  }
461
  }
 
 
 
 
 
 
462
  return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
463
  }
464
 
@@ -490,6 +495,8 @@ class EM_Events extends EM_Object {
490
  'state' => false,
491
  'country' => false,
492
  'region' => false,
 
 
493
  'blog' => get_current_blog_id(),
494
  'private' => current_user_can('read_private_events'),
495
  'private_only' => false,
33
  $args = self::get_default_search($args);
34
  $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
35
  $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
36
+ $groupby_sql = array();
37
 
38
  //Get the default conditions
39
  $conditions = self::build_sql_conditions($args);
241
 
242
  $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby');
243
  $args['header_format'] = !empty($args['header_format']) ? $args['header_format'] : get_option('dbem_event_list_groupby_header_format', '<h2>#s</h2>');
 
244
  //Reset some vars for counting events and displaying set arrays of events
245
  $atts = (array) $args;
246
  $atts['pagination'] = false;
458
  $conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id={$args['post_id']})";
459
  }
460
  }
461
+ //events with or without locations
462
+ if( !empty($args['has_location']) ){
463
+ $conditions['has_location'] = '('.EM_EVENTS_TABLE.'.location_id IS NOT NULL AND '.EM_EVENTS_TABLE.'.location_id != 0)';
464
+ }elseif( !empty($args['no_location']) ){
465
+ $conditions['no_location'] = '('.EM_EVENTS_TABLE.'.location_id IS NULL OR '.EM_EVENTS_TABLE.'.location_id = 0)';
466
+ }
467
  return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
468
  }
469
 
495
  'state' => false,
496
  'country' => false,
497
  'region' => false,
498
+ 'has_location' => false,
499
+ 'no_location' => false,
500
  'blog' => get_current_blog_id(),
501
  'private' => current_user_can('read_private_events'),
502
  'private_only' => false,
classes/em-location-post-admin.php CHANGED
@@ -6,7 +6,7 @@ class EM_Location_Post_Admin{
6
  add_action('admin_head', array('EM_Location_Post_Admin','admin_head'));
7
  }
8
  //Meta Boxes
9
- add_action('add_meta_boxes', array('EM_Location_Post_Admin','meta_boxes'));
10
  //Save/Edit actions
11
  add_filter('wp_insert_post_data',array('EM_Location_Post_Admin','wp_insert_post_data'),100,2); //validate post meta before saving is done
12
  add_action('save_post',array('EM_Location_Post_Admin','save_post'),1,1); //set to 1 so metadata gets saved ASAP
@@ -148,10 +148,8 @@ class EM_Location_Post_Admin{
148
  }
149
  }
150
 
151
- public static function meta_boxes(){
152
- global $EM_Location, $post;
153
- //no need to proceed if we're not dealing with a location
154
- if( $post->post_type != EM_POST_TYPE_LOCATION ) return;
155
  //since this is the first point when the admin area loads location stuff, we load our EM_Event here
156
  if( empty($EM_Location) && !empty($post) ){
157
  $EM_Location = em_get_location($post->ID, 'post_id');
6
  add_action('admin_head', array('EM_Location_Post_Admin','admin_head'));
7
  }
8
  //Meta Boxes
9
+ add_action('add_meta_boxes_'.EM_POST_TYPE_LOCATION, array('EM_Location_Post_Admin','meta_boxes'), 10, 1);
10
  //Save/Edit actions
11
  add_filter('wp_insert_post_data',array('EM_Location_Post_Admin','wp_insert_post_data'),100,2); //validate post meta before saving is done
12
  add_action('save_post',array('EM_Location_Post_Admin','save_post'),1,1); //set to 1 so metadata gets saved ASAP
148
  }
149
  }
150
 
151
+ public static function meta_boxes( $post ){
152
+ global $EM_Location;
 
 
153
  //since this is the first point when the admin area loads location stuff, we load our EM_Event here
154
  if( empty($EM_Location) && !empty($post) ){
155
  $EM_Location = em_get_location($post->ID, 'post_id');
classes/em-location.php CHANGED
@@ -465,38 +465,47 @@ class EM_Location extends EM_Object {
465
 
466
  /**
467
  * Change the status of the location. This will save to the Database too.
468
- * @param int $status
469
- * @param boolean $set_post_status
470
  * @return string
471
  */
472
  function set_status($status, $set_post_status = false){
473
  global $wpdb;
 
474
  if($status === null){
475
- $set_status='NULL';
476
  if($set_post_status){
 
477
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
478
  }
479
  $this->post_status = 'draft';
480
  }elseif( $status == -1 ){ //trashed post
481
  $set_status = -1;
482
  if($set_post_status){
 
483
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $this->post_id ) );
484
  }
485
  $this->post_status = 'trash'; //set post status in this instance
486
  }else{
487
- $set_status = $status ? 1:0;
488
  $post_status = $set_status ? 'publish':'pending';
 
 
 
 
 
489
  if($set_post_status){
490
- if($this->post_status == 'pending' && empty($this->post_name)){
491
- $this->post_name = sanitize_title($this->post_title);
492
- }
493
  $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
 
 
 
494
  }
495
  $this->post_status = $post_status;
496
  }
 
497
  $this->previous_status = $wpdb->get_var('SELECT location_status FROM '.EM_LOCATIONS_TABLE.' WHERE location_id='.$this->location_id); //get status from db, not post_status, as posts get saved quickly
498
  $result = $wpdb->query($wpdb->prepare("UPDATE ".EM_LOCATIONS_TABLE." SET location_status=$set_status, location_slug=%s WHERE location_id=%d", array($this->post_name, $this->location_id)));
499
- $this->get_status();
500
  return apply_filters('em_location_set_status', $result !== false, $status, $this);
501
  }
502
 
@@ -620,6 +629,22 @@ class EM_Location extends EM_Object {
620
  return apply_filters('em_location_get_rss_url', $return);
621
  }
622
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
623
  function get_edit_url(){
624
  if( $this->can_manage('edit_locations','edit_others_locations') ){
625
  if( EM_MS_GLOBAL ){
@@ -756,7 +781,7 @@ class EM_Location extends EM_Object {
756
  $glue = $result == '#_LOCATIONFULLLINE' ? ', ':'<br />';
757
  $replace = $this->get_full_address($glue);
758
  break;
759
- case '#_MAP': //Depricated (but will remain)
760
  case '#_LOCATIONMAP':
761
  ob_start();
762
  $args = array();
@@ -806,10 +831,11 @@ class EM_Location extends EM_Object {
806
  break;
807
  case '#_LOCATIONIMAGEURL':
808
  case '#_LOCATIONIMAGE':
809
- if($this->get_image_url() != ''){
810
- $image_url = esc_url($this->get_image_url());
 
811
  if($result == '#_LOCATIONIMAGEURL'){
812
- $replace = $this->get_image_url();
813
  }else{
814
  if( empty($placeholders[3][$key]) ){
815
  $replace = "<img src='".$image_url."' alt='".esc_attr($this->location_name)."'/>";
465
 
466
  /**
467
  * Change the status of the location. This will save to the Database too.
468
+ * @param int $status A number to change the status to, which may be -1 for trash, 1 for publish, 0 for pending or null if draft.
469
+ * @param boolean $set_post_status If set to true the wp_posts table status will also be changed to the new corresponding status.
470
  * @return string
471
  */
472
  function set_status($status, $set_post_status = false){
473
  global $wpdb;
474
+ //decide on what status to set and update wp_posts in the process
475
  if($status === null){
476
+ $set_status='NULL'; //draft post
477
  if($set_post_status){
478
+ //if the post is trash, don't untrash it!
479
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
480
  }
481
  $this->post_status = 'draft';
482
  }elseif( $status == -1 ){ //trashed post
483
  $set_status = -1;
484
  if($set_post_status){
485
+ //set the post status of the location in wp_posts too
486
  $wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $this->post_id ) );
487
  }
488
  $this->post_status = 'trash'; //set post status in this instance
489
  }else{
490
+ $set_status = $status ? 1:0; //published or pending post
491
  $post_status = $set_status ? 'publish':'pending';
492
+ if( empty($this->post_name) ){
493
+ //published or pending posts should have a valid post slug
494
+ $this->post_name = sanitize_title($this->post_title);
495
+ $set_post_name = true;
496
+ }
497
  if($set_post_status){
 
 
 
498
  $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
499
+ }elseif( $set_post_name ){
500
+ //if we've added a post slug then update wp_posts anyway
501
+ $wpdb->update( $wpdb->posts, array( 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
502
  }
503
  $this->post_status = $post_status;
504
  }
505
+ //save in the wp_em_locations table
506
  $this->previous_status = $wpdb->get_var('SELECT location_status FROM '.EM_LOCATIONS_TABLE.' WHERE location_id='.$this->location_id); //get status from db, not post_status, as posts get saved quickly
507
  $result = $wpdb->query($wpdb->prepare("UPDATE ".EM_LOCATIONS_TABLE." SET location_status=$set_status, location_slug=%s WHERE location_id=%d", array($this->post_name, $this->location_id)));
508
+ $this->get_status(); //reload status
509
  return apply_filters('em_location_set_status', $result !== false, $status, $this);
510
  }
511
 
629
  return apply_filters('em_location_get_rss_url', $return);
630
  }
631
 
632
+ /*
633
+ * Extends the default EM_Object function by switching blogs as needed if in MS Global mode
634
+ * @param string $size
635
+ * @return string
636
+ * @see EM_Object::get_image_url()
637
+ */
638
+ function get_image_url($size = 'full'){
639
+ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){
640
+ switch_to_blog($this->blog_id);
641
+ $switch_back = true;
642
+ }
643
+ $return = parent::get_image_url($size);
644
+ if( !empty($switch_back) ){ restore_current_blog(); }
645
+ return $return;
646
+ }
647
+
648
  function get_edit_url(){
649
  if( $this->can_manage('edit_locations','edit_others_locations') ){
650
  if( EM_MS_GLOBAL ){
781
  $glue = $result == '#_LOCATIONFULLLINE' ? ', ':'<br />';
782
  $replace = $this->get_full_address($glue);
783
  break;
784
+ case '#_MAP': //Deprecated (but will remain)
785
  case '#_LOCATIONMAP':
786
  ob_start();
787
  $args = array();
831
  break;
832
  case '#_LOCATIONIMAGEURL':
833
  case '#_LOCATIONIMAGE':
834
+ $image_url = $this->get_image_url();
835
+ if( $image_url != ''){
836
+ $image_url = esc_url($image_url);
837
  if($result == '#_LOCATIONIMAGEURL'){
838
+ $replace = $image_url;
839
  }else{
840
  if( empty($placeholders[3][$key]) ){
841
  $replace = "<img src='".$image_url."' alt='".esc_attr($this->location_name)."'/>";
classes/em-locations.php CHANGED
@@ -61,18 +61,18 @@ class EM_Locations extends EM_Object {
61
  $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id';
62
  }
63
  //Create the SQL statement and execute
64
- $sql = "
65
  SELECT $selectors FROM $locations_table
66
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
67
  $where
68
  GROUP BY {$locations_table}.location_id
69
  $orderby_sql
70
  $limit $offset
71
- ";
72
 
73
  //If we're only counting results, return the number of results
74
  if( $count ){
75
- return apply_filters('em_locations_get_array', count($wpdb->get_col($sql)), $args);
76
  }
77
  $results = $wpdb->get_results($sql, ARRAY_A);
78
 
61
  $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id';
62
  }
63
  //Create the SQL statement and execute
64
+ $sql = apply_filters('em_locations_get_sql', "
65
  SELECT $selectors FROM $locations_table
66
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
67
  $where
68
  GROUP BY {$locations_table}.location_id
69
  $orderby_sql
70
  $limit $offset
71
+ ", $args);
72
 
73
  //If we're only counting results, return the number of results
74
  if( $count ){
75
+ return apply_filters('em_locations_get_count', count($wpdb->get_col($sql)), $args);
76
  }
77
  $results = $wpdb->get_results($sql, ARRAY_A);
78
 
classes/em-mailer.php CHANGED
@@ -44,24 +44,6 @@ class EM_Mailer {
44
  $this->errors[] = $phpmailer->ErrorInfo;
45
  }
46
  return $send;
47
- }elseif ( $emails_ok && get_option('dbem_rsvp_mail_send_method') == 'mail' ){
48
- if(is_array($receiver)){
49
- $receiver = implode(', ', $receiver);
50
- }
51
- $headers = '';
52
- if( get_option('dbem_smtp_html') ){
53
- $headers = 'MIME-Version: 1.0' . "\r\n";
54
- $headers .= 'Content-type: text/html; charset="UTF-8"' . "\r\n";
55
- }else{
56
- $headers = 'Content-Type: text/plain; charset="UTF-8"' . "\r\n";
57
- }
58
- $from = get_option('dbem_mail_sender_address');
59
- $headers .= get_option('dbem_mail_sender_name') ? 'From: '.get_option('dbem_mail_sender_name').' <'.$from.'>':'From: '.$from;
60
- $send = mail($receiver, $subject, $body, $headers);
61
- if(!$send){
62
- $this->errors[] = __('Could not send email.', 'events-manager');
63
- }
64
- return $send;
65
  }elseif( $emails_ok ){
66
  $this->load_phpmailer();
67
  $mail = new PHPMailer();
@@ -106,7 +88,9 @@ class EM_Mailer {
106
 
107
  //Protocols
108
  if( get_option('dbem_rsvp_mail_send_method') == 'qmail' ){
109
- $mail->IsQmail();
 
 
110
  }else {
111
  $mail->Mailer = get_option('dbem_rsvp_mail_send_method');
112
  }
44
  $this->errors[] = $phpmailer->ErrorInfo;
45
  }
46
  return $send;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  }elseif( $emails_ok ){
48
  $this->load_phpmailer();
49
  $mail = new PHPMailer();
88
 
89
  //Protocols
90
  if( get_option('dbem_rsvp_mail_send_method') == 'qmail' ){
91
+ $mail->isQmail();
92
+ }elseif( get_option('dbem_rsvp_mail_send_method') == 'sendmail' ){
93
+ $mail->isSendmail();
94
  }else {
95
  $mail->Mailer = get_option('dbem_rsvp_mail_send_method');
96
  }
classes/em-object.php CHANGED
@@ -1162,25 +1162,6 @@ class EM_Object {
1162
  }
1163
  return apply_filters('em_object_get_fields', array(), $this, $inverted_array);
1164
  }
1165
-
1166
- /**
1167
- * Sanitize text before inserting into database
1168
- * @param string $value
1169
- * @return string
1170
- */
1171
- function sanitize( $value ) {
1172
- if( get_magic_quotes_gpc() )
1173
- $value = wp_unslash( $value );
1174
-
1175
- //check if this function exists
1176
- if( function_exists( "mysql_real_escape_string" ) ) {
1177
- $value = mysql_real_escape_string( $value );
1178
- //for PHP version < 4.3.0 use addslashes
1179
- } else {
1180
- $value = addslashes( $value );
1181
- }
1182
- return apply_filters('em_object_sanitize', $value);
1183
- }
1184
 
1185
  /**
1186
  * Cleans arrays that contain id lists. Takes an array of items and will clean the keys passed in second argument so that if they keep numbers, explode comma-separated numbers, and unsets the key if there's any other value
@@ -1537,7 +1518,16 @@ class EM_Object {
1537
  return em_get_currency_formatted( $price );
1538
  }
1539
 
1540
- function get_tax_rate(){
1541
- return get_option('dbem_bookings_tax');
 
 
 
 
 
 
 
 
 
1542
  }
1543
  }
1162
  }
1163
  return apply_filters('em_object_get_fields', array(), $this, $inverted_array);
1164
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1165
 
1166
  /**
1167
  * Cleans arrays that contain id lists. Takes an array of items and will clean the keys passed in second argument so that if they keep numbers, explode comma-separated numbers, and unsets the key if there's any other value
1518
  return em_get_currency_formatted( $price );
1519
  }
1520
 
1521
+ /**
1522
+ * Returns contextual tax rate of object, which may be global or instance-specific. By default a number representing percentage is provided, e.g. 21% returns 21.
1523
+ * If $decimal is set to true, 21% is returned as 0.21
1524
+ * @param boolean $decimal If set to true, a decimal representation will be returned.
1525
+ * @return float
1526
+ */
1527
+ function get_tax_rate( $decimal = false ){
1528
+ $tax_rate = get_option('dbem_bookings_tax');
1529
+ $tax_rate = ($tax_rate > 0) ? $tax_rate : 0;
1530
+ if( $decimal && $tax_rate > 0 ) $tax_rate = $tax_rate / 100;
1531
+ return $tax_rate;
1532
  }
1533
  }
classes/em-people.php CHANGED
@@ -1,6 +1,12 @@
1
  <?php
2
  class EM_People extends EM_Object {
3
 
 
 
 
 
 
 
4
  /**
5
  * Handles the action of someone being deleted on WordPress
6
  * @param int $id
@@ -13,17 +19,13 @@ class EM_People extends EM_Object {
13
  //User is being deleted, so we delete their events and cancel their bookings.
14
  $wpdb->query("DELETE FROM ".EM_EVENTS_TABLE." WHERE event_owner=$id");
15
  }
16
- //delete the booking completely
17
- if( !get_option('dbem_bookings_registration_disable') || $id != get_option('dbem_bookings_registration_user') ){
18
- $EM_Person = new EM_Person();
19
- $EM_Person->ID = $EM_Person->person_id = $id;
20
- foreach( $EM_Person->get_bookings() as $EM_Booking){
21
- $EM_Booking->manage_override = true;
22
- $EM_Booking->delete();
23
- }
24
- }else{ //user is the no-user mode assigned user, so don't delete all the guest bookings, in case of mistake.
25
- $wpdb->update(EM_BOOKINGS_TABLE, array('booking_status'=>3, 'person_id'=>0, 'booking_comment'=>__('User deleted by administrators','events-manager')), array('person_id'=>$id));
26
- }
27
  }
28
 
29
  /**
@@ -34,8 +36,15 @@ class EM_People extends EM_Object {
34
  public static function user_contactmethods($array){
35
  $array['dbem_phone'] = __('Phone','events-manager') . ' <span class="description">('. __('Events Manager','events-manager') .')</span>';
36
  return $array;
37
- }
 
 
 
 
 
 
 
 
38
  }
39
- add_action('delete_user', array('EM_People','delete_user'),10,1);
40
- add_filter( 'user_contactmethods' , array('EM_People','user_contactmethods'),10,1);
41
  ?>
1
  <?php
2
  class EM_People extends EM_Object {
3
 
4
+ public static function init(){
5
+ add_action('delete_user', 'EM_People::delete_user', 10, 1);
6
+ add_filter( 'user_contactmethods', 'EM_People::user_contactmethods', 10, 1);
7
+ add_filter('pre_option_dbem_bookings_registration_user', 'EM_People::dbem_bookings_registration_user');
8
+ }
9
+
10
  /**
11
  * Handles the action of someone being deleted on WordPress
12
  * @param int $id
19
  //User is being deleted, so we delete their events and cancel their bookings.
20
  $wpdb->query("DELETE FROM ".EM_EVENTS_TABLE." WHERE event_owner=$id");
21
  }
22
+ //delete their bookings completely
23
+ $EM_Person = new EM_Person();
24
+ $EM_Person->ID = $EM_Person->person_id = $id;
25
+ foreach( $EM_Person->get_bookings() as $EM_Booking){
26
+ $EM_Booking->manage_override = true;
27
+ $EM_Booking->delete();
28
+ }
 
 
 
 
29
  }
30
 
31
  /**
36
  public static function user_contactmethods($array){
37
  $array['dbem_phone'] = __('Phone','events-manager') . ' <span class="description">('. __('Events Manager','events-manager') .')</span>';
38
  return $array;
39
+ }
40
+
41
+ /**
42
+ * Workaround function for any legacy code requesting the dbem_bookings_registration_user option which should always be 0
43
+ * @return int
44
+ */
45
+ public static function dbem_bookings_registration_user(){
46
+ return 0;
47
+ }
48
  }
49
+ EM_People::init();
 
50
  ?>
classes/em-permalinks.php CHANGED
@@ -4,6 +4,7 @@ if( !class_exists('EM_Permalinks') ){
4
  class EM_Permalinks {
5
  static $em_queryvars = array(
6
  'event_id','event_slug', 'em_redirect',
 
7
  'location_id','location_slug',
8
  'person_id',
9
  'booking_id',
@@ -287,6 +288,7 @@ if( !class_exists('EM_Permalinks') ){
287
  */
288
  function em_get_my_bookings_url(){
289
  global $bp, $wp_rewrite;
 
290
  if( !empty($bp->events->link) ){
291
  //get member url
292
  return $bp->events->link.'attending/';
@@ -300,3 +302,17 @@ function em_get_my_bookings_url(){
300
  }
301
  }
302
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  class EM_Permalinks {
5
  static $em_queryvars = array(
6
  'event_id','event_slug', 'em_redirect',
7
+ 'recurrence_id',
8
  'location_id','location_slug',
9
  'person_id',
10
  'booking_id',
288
  */
289
  function em_get_my_bookings_url(){
290
  global $bp, $wp_rewrite;
291
+ // @todo add filter for bookings url, remove bp condition and add it to bp-em-core.php
292
  if( !empty($bp->events->link) ){
293
  //get member url
294
  return $bp->events->link.'attending/';
302
  }
303
  }
304
  }
305
+
306
+ /**
307
+ * Gets the admin URL for editing events. If called from front-end and there's a front-end edit events page, that will be
308
+ * returned, otherwise a url to the dashboard will be returned.
309
+ */
310
+ function em_get_events_admin_url(){
311
+ $admin_url = admin_url('edit.php?post_type=event');
312
+ if( !is_admin() ){
313
+ if( get_option('dbem_edit_events_page') ){
314
+ $admin_url = get_permalink(get_option( 'dbem_edit_events_page' ));
315
+ }
316
+ }
317
+ return apply_filters('em_get_events_admin_url', $admin_url);
318
+ }
classes/em-person.php CHANGED
@@ -2,7 +2,7 @@
2
  // TODO make person details more secure and integrate with WP user data
3
  class EM_Person extends WP_User{
4
 
5
- function __construct( $person_id = 0, $username = '', $blog_id='' ){
6
  if( is_array($person_id) ){
7
  if( array_key_exists('person_id',$person_id) ){
8
  $person_id = $person_id['person_id'];
@@ -16,11 +16,11 @@ class EM_Person extends WP_User{
16
  }
17
  if($username){
18
  parent::__construct($person_id, $username);
19
- }elseif( is_numeric($person_id) && ($person_id <= 0) ){
20
  $this->data = new stdClass();
21
  $this->ID = 0;
22
- $this->display_name = 'Non-Registered User';
23
- $this->user_email = '';
24
  }else{
25
  parent::__construct($person_id);
26
  }
@@ -84,14 +84,13 @@ class EM_Person extends WP_User{
84
 
85
  function display_summary(){
86
  ob_start();
87
- $no_user = get_option('dbem_bookings_registration_disable') && $this->ID == get_option('dbem_bookings_registration_user');
88
  ?>
89
  <table class="em-form-fields">
90
  <tr>
91
  <td><?php echo get_avatar($this->ID); ?></td>
92
  <td style="padding-left:10px; vertical-align: top;">
93
  <table>
94
- <?php if( $no_user ): ?>
95
  <tr><th><?php _e('Name','events-manager'); ?> : </th><th><?php echo $this->get_name(); ?></th></tr>
96
  <?php else: ?>
97
  <tr><th><?php _e('Name','events-manager'); ?> : </th><th><a href="<?php echo $this->get_bookings_url(); ?>"><?php echo $this->get_name(); ?></a></th></tr>
2
  // TODO make person details more secure and integrate with WP user data
3
  class EM_Person extends WP_User{
4
 
5
+ function __construct( $person_id = false, $username = '', $blog_id='' ){
6
  if( is_array($person_id) ){
7
  if( array_key_exists('person_id',$person_id) ){
8
  $person_id = $person_id['person_id'];
16
  }
17
  if($username){
18
  parent::__construct($person_id, $username);
19
+ }elseif( is_numeric($person_id) && $person_id == 0 ){
20
  $this->data = new stdClass();
21
  $this->ID = 0;
22
+ $this->display_name = 'Anonymous User';
23
+ $this->user_email = 'anonymous@'.preg_replace('/https?:\/\//', '', get_site_url());
24
  }else{
25
  parent::__construct($person_id);
26
  }
84
 
85
  function display_summary(){
86
  ob_start();
 
87
  ?>
88
  <table class="em-form-fields">
89
  <tr>
90
  <td><?php echo get_avatar($this->ID); ?></td>
91
  <td style="padding-left:10px; vertical-align: top;">
92
  <table>
93
+ <?php if( $this->ID === 0 ): ?>
94
  <tr><th><?php _e('Name','events-manager'); ?> : </th><th><?php echo $this->get_name(); ?></th></tr>
95
  <?php else: ?>
96
  <tr><th><?php _e('Name','events-manager'); ?> : </th><th><a href="<?php echo $this->get_bookings_url(); ?>"><?php echo $this->get_name(); ?></a></th></tr>
classes/em-ticket.php CHANGED
@@ -249,16 +249,16 @@ class EM_Ticket extends EM_Object{
249
  return apply_filters('em_ticket_validate', count($this->errors) == 0, $this );
250
  }
251
 
252
- function is_available( $include_members_only = false, $include_guests_only = false ){
253
  $timestamp = current_time('timestamp');
254
- if( isset($this->is_available) && !$include_members_only && !$include_guests_only ) return apply_filters('em_ticket_is_available', $this->is_available, $this); //save extra queries if doing a standard check
255
  $is_available = false;
256
  $EM_Event = $this->get_event();
257
  $available_spaces = $this->get_available_spaces();
258
  $condition_1 = (empty($this->ticket_start) || $this->start_timestamp <= $timestamp);
259
  $condition_2 = $this->end_timestamp >= $timestamp || empty($this->ticket_end);
260
  $condition_3 = (empty($EM_Event->event_rsvp_date) && $EM_Event->start > $timestamp) || $EM_Event->rsvp_end > $timestamp;
261
- $condition_4 = !$this->ticket_members || ($this->ticket_members && is_user_logged_in()) || $include_members_only;
262
  $condition_5 = true;
263
  if( !EM_Bookings::$disable_restrictions && $this->ticket_members && !empty($this->ticket_members_roles) ){
264
  //check if user has the right role to use this ticket
@@ -270,26 +270,26 @@ class EM_Ticket extends EM_Object{
270
  }
271
  }
272
  }
273
- $condition_6 = !$this->ticket_guests || ($this->ticket_guests && !is_user_logged_in()) || $include_guests_only;
274
  if( $condition_1 && $condition_2 && $condition_3 && $condition_4 && $condition_5 && $condition_6 ){
275
  //Time Constraints met, now quantities
276
  if( $available_spaces > 0 && ($available_spaces >= $this->ticket_min || empty($this->ticket_min)) ){
277
  $is_available = true;
278
  }
279
  }
280
- if( !$include_members_only && !$include_guests_only ){ //$this->is_available is only stored for the viewing user
281
  $this->is_available = $is_available;
282
  }
283
- return apply_filters('em_ticket_is_available', $is_available, $this);
284
  }
285
 
286
  /**
287
  * Returns whether or not this ticket should be displayed based on availability and other ticket properties and general settings
288
  * @return boolean
289
  */
290
- function is_displayable(){
291
  $return = false;
292
- if( $this->is_available() ){
293
  $return = true;
294
  }else{
295
  if( get_option('dbem_bookings_tickets_show_unavailable') ){
@@ -299,7 +299,7 @@ class EM_Ticket extends EM_Object{
299
  }
300
  }
301
  }
302
- return apply_filters('em_ticket_is_displayable', $return, $this);;
303
  }
304
 
305
  /**
@@ -325,7 +325,7 @@ class EM_Ticket extends EM_Object{
325
  * @param boolean $format
326
  */
327
  function get_price_with_tax( $format = false ){
328
- $price = $this->get_price_without_tax() * (1 + $this->get_event()->get_tax_rate()/100);
329
  if( $format ) return $this->format_price($price);
330
  return $price;
331
  }
249
  return apply_filters('em_ticket_validate', count($this->errors) == 0, $this );
250
  }
251
 
252
+ function is_available( $ignore_member_restrictions = false, $ignore_guest_restrictions = false ){
253
  $timestamp = current_time('timestamp');
254
+ if( isset($this->is_available) && !$ignore_member_restrictions && !$ignore_guest_restrictions ) return apply_filters('em_ticket_is_available', $this->is_available, $this); //save extra queries if doing a standard check
255
  $is_available = false;
256
  $EM_Event = $this->get_event();
257
  $available_spaces = $this->get_available_spaces();
258
  $condition_1 = (empty($this->ticket_start) || $this->start_timestamp <= $timestamp);
259
  $condition_2 = $this->end_timestamp >= $timestamp || empty($this->ticket_end);
260
  $condition_3 = (empty($EM_Event->event_rsvp_date) && $EM_Event->start > $timestamp) || $EM_Event->rsvp_end > $timestamp;
261
+ $condition_4 = !$this->ticket_members || ($this->ticket_members && is_user_logged_in()) || $ignore_member_restrictions;
262
  $condition_5 = true;
263
  if( !EM_Bookings::$disable_restrictions && $this->ticket_members && !empty($this->ticket_members_roles) ){
264
  //check if user has the right role to use this ticket
270
  }
271
  }
272
  }
273
+ $condition_6 = !$this->ticket_guests || ($this->ticket_guests && !is_user_logged_in()) || $ignore_guest_restrictions;
274
  if( $condition_1 && $condition_2 && $condition_3 && $condition_4 && $condition_5 && $condition_6 ){
275
  //Time Constraints met, now quantities
276
  if( $available_spaces > 0 && ($available_spaces >= $this->ticket_min || empty($this->ticket_min)) ){
277
  $is_available = true;
278
  }
279
  }
280
+ if( !$ignore_member_restrictions && !$ignore_guest_restrictions ){ //$this->is_available is only stored for the viewing user
281
  $this->is_available = $is_available;
282
  }
283
+ return apply_filters('em_ticket_is_available', $is_available, $this, $ignore_guest_restrictions, $ignore_member_restrictions);
284
  }
285
 
286
  /**
287
  * Returns whether or not this ticket should be displayed based on availability and other ticket properties and general settings
288
  * @return boolean
289
  */
290
+ function is_displayable( $ignore_member_restrictions = false, $ignore_guest_restrictions = false ){
291
  $return = false;
292
+ if( $this->is_available($ignore_member_restrictions, $ignore_guest_restrictions) ){
293
  $return = true;
294
  }else{
295
  if( get_option('dbem_bookings_tickets_show_unavailable') ){
299
  }
300
  }
301
  }
302
+ return apply_filters('em_ticket_is_displayable', $return, $this, $ignore_guest_restrictions, $ignore_member_restrictions);
303
  }
304
 
305
  /**
325
  * @param boolean $format
326
  */
327
  function get_price_with_tax( $format = false ){
328
+ $price = $this->get_price_without_tax() * (1 + $this->get_event()->get_tax_rate( true ));
329
  if( $format ) return $this->format_price($price);
330
  return $price;
331
  }
classes/em-tickets.php CHANGED
@@ -115,7 +115,7 @@ class EM_Tickets extends EM_Object implements Iterator{
115
  $result = false;
116
  $this->add_error(__('You cannot delete tickets if there are any bookings associated with them. Please delete these bookings first.','events-manager'));
117
  }else{
118
- $result = $wpdb->query("DELETE FROM ".EM_TICKETS_TABLE." WHERE event_id IN (".implode(',',$ticket_ids).")");
119
  }
120
  }
121
  return ($result !== false);
@@ -137,7 +137,11 @@ class EM_Tickets extends EM_Object implements Iterator{
137
  $EM_Ticket = new EM_Ticket();
138
  $ticket_data['event_id'] = $this->event_id;
139
  $EM_Ticket->get_post($ticket_data);
140
- $this->tickets[] = $EM_Ticket;
 
 
 
 
141
  }
142
  }
143
  }else{
115
  $result = false;
116
  $this->add_error(__('You cannot delete tickets if there are any bookings associated with them. Please delete these bookings first.','events-manager'));
117
  }else{
118
+ $result = $wpdb->query("DELETE FROM ".EM_TICKETS_TABLE." WHERE ticket_id IN (".implode(',',$ticket_ids).")");
119
  }
120
  }
121
  return ($result !== false);
137
  $EM_Ticket = new EM_Ticket();
138
  $ticket_data['event_id'] = $this->event_id;
139
  $EM_Ticket->get_post($ticket_data);
140
+ if( $EM_Ticket->ticket_id ){
141
+ $this->tickets[$EM_Ticket->ticket_id] = $EM_Ticket;
142
+ }else{
143
+ $this->tickets[] = $EM_Ticket;
144
+ }
145
  }
146
  }
147
  }else{
em-actions.php CHANGED
@@ -43,6 +43,23 @@ function em_init_actions() {
43
  echo EM_Object::json_encode($json_locations);
44
  die();
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  if(isset($_REQUEST['ajaxCalendar']) && $_REQUEST['ajaxCalendar']) {
48
  //FIXME if long events enabled originally, this won't show up on ajax call
@@ -91,7 +108,7 @@ function em_init_actions() {
91
  $EM_Notices->add_error($EM_Event->errors, true);
92
  wp_redirect( em_wp_get_referer() );
93
  }else{
94
- $EM_Notices->add_confirm($EM_Event->feedback_message, true);
95
  wp_redirect( $event->get_edit_url() );
96
  }
97
  exit();
@@ -250,7 +267,7 @@ function em_init_actions() {
250
  if ( $_REQUEST['action'] == 'booking_add') {
251
  //ADD/EDIT Booking
252
  ob_start();
253
- if( !defined('WP_CACHE') || !WP_CACHE ) em_verify_nonce('booking_add');
254
  if( !is_user_logged_in() || get_option('dbem_bookings_double') || !$EM_Event->get_bookings()->has_booking(get_current_user_id()) ){
255
  $EM_Booking->get_post();
256
  $post_validation = $EM_Booking->validate();
@@ -434,9 +451,8 @@ function em_init_actions() {
434
  em_verify_nonce('booking_modify_person_'.$EM_Booking->booking_id);
435
  if( $EM_Booking->can_manage('manage_bookings','manage_others_bookings') ){
436
  global $wpdb;
437
- $no_user = get_option('dbem_bookings_registration_disable') && $EM_Booking->get_person()->ID == get_option('dbem_bookings_registration_user');
438
  if( //save just the booking meta, avoid extra unneccesary hooks and things to go wrong
439
- $no_user && $EM_Booking->get_person_post() &&
440
  $wpdb->update(EM_BOOKINGS_TABLE, array('booking_meta'=> serialize($EM_Booking->booking_meta)), array('booking_id'=>$EM_Booking->booking_id))
441
  ){
442
  $EM_Notices->add_confirm( $EM_Booking->feedback_message, true );
43
  echo EM_Object::json_encode($json_locations);
44
  die();
45
  }
46
+ if(isset($_REQUEST['query']) && $_REQUEST['query'] == 'GlobalEventsMapData') {
47
+ $_REQUEST['has_location'] = true; //we're looking for locations in this context, so locations necessary
48
+ $EM_Events = EM_Events::get( $_REQUEST );
49
+ $json_locations = array();
50
+ $locations = array();
51
+ foreach($EM_Events as $EM_Event) {
52
+ if( !empty($EM_Event->location_id) && empty($locations[$EM_Event->location_id]) ){
53
+ $EM_Location = $EM_Event->get_location();
54
+ $location_array = $EM_Event->get_location()->to_array();
55
+ $location_array['location_balloon'] = $EM_Location->output(get_option('dbem_map_text_format'));
56
+ $json_locations[] = $location_array;
57
+ $locations[$EM_Event->location_id] = true;
58
+ }
59
+ }
60
+ echo EM_Object::json_encode($json_locations);
61
+ die();
62
+ }
63
 
64
  if(isset($_REQUEST['ajaxCalendar']) && $_REQUEST['ajaxCalendar']) {
65
  //FIXME if long events enabled originally, this won't show up on ajax call
108
  $EM_Notices->add_error($EM_Event->errors, true);
109
  wp_redirect( em_wp_get_referer() );
110
  }else{
111
+ $EM_Notices->add_confirm($event->feedback_message, true);
112
  wp_redirect( $event->get_edit_url() );
113
  }
114
  exit();
267
  if ( $_REQUEST['action'] == 'booking_add') {
268
  //ADD/EDIT Booking
269
  ob_start();
270
+ if( (!defined('WP_CACHE') || !WP_CACHE) && !isset($GLOBALS["wp_fastest_cache"]) ) em_verify_nonce('booking_add');
271
  if( !is_user_logged_in() || get_option('dbem_bookings_double') || !$EM_Event->get_bookings()->has_booking(get_current_user_id()) ){
272
  $EM_Booking->get_post();
273
  $post_validation = $EM_Booking->validate();
451
  em_verify_nonce('booking_modify_person_'.$EM_Booking->booking_id);
452
  if( $EM_Booking->can_manage('manage_bookings','manage_others_bookings') ){
453
  global $wpdb;
 
454
  if( //save just the booking meta, avoid extra unneccesary hooks and things to go wrong
455
+ $EM_Booking->is_no_user() && $EM_Booking->get_person_post() &&
456
  $wpdb->update(EM_BOOKINGS_TABLE, array('booking_meta'=> serialize($EM_Booking->booking_meta)), array('booking_id'=>$EM_Booking->booking_id))
457
  ){
458
  $EM_Notices->add_confirm( $EM_Booking->feedback_message, true );
em-events.php CHANGED
@@ -10,7 +10,7 @@
10
  */
11
  function em_content($page_content) {
12
  global $post, $wpdb, $wp_query, $EM_Event, $EM_Location, $EM_Category;
13
- if( empty($post) ) return $page_content; //fix for any other plugins calling the_content outside the loop
14
  $events_page_id = get_option ( 'dbem_events_page' );
15
  $locations_page_id = get_option( 'dbem_locations_page' );
16
  $categories_page_id = get_option( 'dbem_categories_page' );
@@ -59,6 +59,7 @@ function em_content($page_content) {
59
  $args['limit'] = !empty($args['limit']) ? $args['limit'] : get_option('dbem_events_default_limit');
60
  if( !empty($args['ajax']) ){ echo '<div class="em-search-ajax">'; } //AJAX wrapper open
61
  if( get_option('dbem_event_list_groupby') ){
 
62
  em_locate_template('templates/events-list-grouped.php', true, array('args'=>$args));
63
  }else{
64
  em_locate_template('templates/events-list.php', true, array('args'=>$args));
10
  */
11
  function em_content($page_content) {
12
  global $post, $wpdb, $wp_query, $EM_Event, $EM_Location, $EM_Category;
13
+ if( empty($post) || empty($post->ID) ) return $page_content; //fix for any other plugins calling the_content outside the loop
14
  $events_page_id = get_option ( 'dbem_events_page' );
15
  $locations_page_id = get_option( 'dbem_locations_page' );
16
  $categories_page_id = get_option( 'dbem_categories_page' );
59
  $args['limit'] = !empty($args['limit']) ? $args['limit'] : get_option('dbem_events_default_limit');
60
  if( !empty($args['ajax']) ){ echo '<div class="em-search-ajax">'; } //AJAX wrapper open
61
  if( get_option('dbem_event_list_groupby') ){
62
+ $args['date_format'] = get_option('dbem_event_list_groupby_format');
63
  em_locate_template('templates/events-list-grouped.php', true, array('args'=>$args));
64
  }else{
65
  em_locate_template('templates/events-list.php', true, array('args'=>$args));
em-functions.php CHANGED
@@ -387,7 +387,7 @@ function em_booking_add_registration( $EM_Booking ){
387
  //Validate name, phone and email
388
  if( $EM_Booking->get_person_post() ){
389
  //Save default person to booking
390
- $EM_Booking->person_id = get_option('dbem_bookings_registration_user');
391
  }else{
392
  $registration = false;
393
  }
@@ -555,8 +555,8 @@ function em_get_search_form_defaults($args = array()){
555
  $search_args['category_label'] = get_option('dbem_search_form_category_label'); //field label
556
  $search_args['categories_label'] = get_option('dbem_search_form_categories_label'); //select default
557
  //countries
558
- $search_args['country'] = get_option('dbem_search_form_advanced') ? get_option('dbem_search_form_default_country'):''; //default country
559
  $search_args['search_countries'] = get_option('dbem_search_form_countries');
 
560
  $search_args['country_label'] = get_option('dbem_search_form_country_label'); //field label
561
  $search_args['countries_label'] = get_option('dbem_search_form_countries_label'); //select default
562
  //regions
387
  //Validate name, phone and email
388
  if( $EM_Booking->get_person_post() ){
389
  //Save default person to booking
390
+ $EM_Booking->person_id = 0;
391
  }else{
392
  $registration = false;
393
  }
555
  $search_args['category_label'] = get_option('dbem_search_form_category_label'); //field label
556
  $search_args['categories_label'] = get_option('dbem_search_form_categories_label'); //select default
557
  //countries
 
558
  $search_args['search_countries'] = get_option('dbem_search_form_countries');
559
+ $search_args['country'] = $search_args['search_countries'] ? get_option('dbem_search_form_default_country'):''; //default country
560
  $search_args['country_label'] = get_option('dbem_search_form_country_label'); //field label
561
  $search_args['countries_label'] = get_option('dbem_search_form_countries_label'); //select default
562
  //regions
em-ical.php CHANGED
@@ -4,8 +4,8 @@
4
  */
5
  function em_ical( ){
6
  //check if this is a calendar request for all events
7
- if ( preg_match('/events.ics$/', $_SERVER['REQUEST_URI']) || $_SERVER['REQUEST_URI'] == '/?ical=1' ) {
8
- header('Content-type: text/calendar; charset=utf-8');
9
  header('Content-Disposition: inline; filename="events.ics"');
10
  //send headers
11
  em_locate_template('templates/ical.php', true);
@@ -65,4 +65,50 @@
65
  }
66
  }
67
  add_action ( 'parse_query', 'em_ical_item' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  ?>
4
  */
5
  function em_ical( ){
6
  //check if this is a calendar request for all events
7
+ if ( preg_match('/events.ics(\?.+)?$/', $_SERVER['REQUEST_URI']) || $_SERVER['REQUEST_URI'] == '/?ical=1' ) {
8
+ header('Content-Type: text/calendar; charset=utf-8');
9
  header('Content-Disposition: inline; filename="events.ics"');
10
  //send headers
11
  em_locate_template('templates/ical.php', true);
65
  }
66
  }
67
  add_action ( 'parse_query', 'em_ical_item' );
68
+
69
+
70
+ /**
71
+ * A utf-8 safe wordwrap function, avoiding CRLF issues with Chinese and other multi-byte characters.
72
+ * @param string $string
73
+ * @return string
74
+ */
75
+ function em_mb_ical_wordwrap($string){
76
+ if( !defined('EM_MB_ICAL_WORDWRAP') || !EM_MB_ICAL_WORDWRAP ){
77
+ /*
78
+ // Match anything 1 to $width chars long followed by whitespace or EOS, otherwise match anything $width chars long
79
+ $search = '/(.{1,74})(?:\s|$)|(.{74})/uS';
80
+ $replace = '$1$2'."\r\n ";
81
+ $return = preg_replace($search, $replace, $string);
82
+ return $return;
83
+ return preg_replace('/\r\n $/', '', $return);
84
+ */
85
+ /*
86
+ $str_len = mb_strlen($string,'UTF-8');
87
+ $while = ceil($str_len / 74);
88
+ $return = '';
89
+ for($i = 1; $i < $while; $i++){
90
+ preg_match('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){74}#', $string, $matches);
91
+ $return .= $matches[0]."\r\n ";
92
+ $string = substr($string, strlen($matches[0]));
93
+ }
94
+ return $return.$string;
95
+ */
96
+ /*$strlen = strlen($string);
97
+ $return = '';
98
+ for( $i = 0; $i + 74 <= $strlen; $i = $i + 74 ){
99
+ $return = mb_strcut
100
+ }
101
+ */
102
+ $return = '';
103
+ for ( $i = 0; strlen($string) > 0; $i++ ) {
104
+ $linewidth = ($i == 0? 75 : 74);
105
+ $linesize = (strlen($string) > $linewidth? $linewidth: strlen($string));
106
+ if($i > 0) $return .= "\r\n ";
107
+ $return .= mb_strcut($string,0,$linesize);
108
+ $string = mb_strcut($string,$linewidth);
109
+ }
110
+ return $return;
111
+ }
112
+ return wordwrap($string, 75, "\r\n ", true);
113
+ }
114
  ?>
em-install.php CHANGED
@@ -39,7 +39,8 @@ function em_install() {
39
  }
40
  //set caps and options
41
  em_set_capabilities();
42
- em_add_options();
 
43
  //Update Version
44
  update_option('dbem_version', EM_VERSION);
45
  delete_option('dbem_upgrade_throttle');
@@ -663,7 +664,6 @@ function em_add_options() {
663
  //Bookings
664
  'dbem_bookings_registration_disable' => 0,
665
  'dbem_bookings_registration_disable_user_emails' => 0,
666
- 'dbem_bookings_registration_user' => '',
667
  'dbem_bookings_approval' => 1, //approval is on by default
668
  'dbem_bookings_approval_reserved' => 0, //overbooking before approval?
669
  'dbem_bookings_approval_overbooking' => 0, //overbooking possible when approving?
@@ -822,7 +822,22 @@ function em_add_options() {
822
  foreach($dbem_options as $key => $value){
823
  add_option($key, $value);
824
  }
825
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
  if( !get_option('dbem_version') ){ add_option('dbem_credits',1); }
827
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5 ){
828
  //make events, cats and locs pages
@@ -851,77 +866,77 @@ function em_add_options() {
851
  if( defined('EM_CATEGORIES_SLUG') && EM_CATEGORIES_SLUG != 'categories' ) update_option('dbem_taxonomy_category_slug', $events_page->post_name.'/'.EM_CATEGORIES_SLUG);
852
  }
853
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.19 ){
854
- update_option('dbem_event_reapproved_email_subject', get_option('dbem_event_approved_email_subject'));
855
- update_option('dbem_event_reapproved_email_body', get_option('dbem_event_approved_email_body'));
856
  }
857
  if( get_option('dbem_version') != '' && get_option('dbem_version') <= 5.21 ){
858
- //just remove all rsvp cut-off info
859
- $wpdb->query("UPDATE ".$wpdb->postmeta." SET meta_value = NULL WHERE meta_key IN ('_event_rsvp_date','_event_rsvp_time') AND post_id IN (SELECT post_id FROM ".EM_EVENTS_TABLE." WHERE recurrence_id > 0)");
860
- $wpdb->query("UPDATE ".EM_EVENTS_TABLE." SET event_rsvp_time = NULL, event_rsvp_date = NULL WHERE recurrence_id > 0");
861
  }
862
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.364 ){
863
- if( get_option('dbem_cp_events_template_page') ){
864
- update_option('dbem_cp_events_template', 'page');
865
- delete_option('dbem_cp_events_template_page');
866
- }
867
- if( get_option('dbem_cp_locations_template_page') ){
868
- update_option('dbem_cp_locations_template', 'page');
869
- delete_option('dbem_cp_locations_template_page');
870
- }
871
- update_option('dbem_events_archive_scope', get_option('dbem_events_page_scope'));
872
- update_option('em_last_modified', current_time('timestamp', true));
873
- update_option('dbem_category_event_single_format',get_option('dbem_category_event_list_item_header_format').get_option('dbem_category_event_list_item_format').get_option('dbem_category_event_list_item_footer_format'));
874
- update_option('dbem_category_no_event_message',get_option('dbem_category_event_list_item_header_format').get_option('dbem_category_no_events_message').get_option('dbem_category_event_list_item_footer_format'));
875
- update_option('dbem_location_event_single_format',get_option('dbem_location_event_list_item_header_format').get_option('dbem_location_event_list_item_format').get_option('dbem_location_event_list_item_footer_format'));
876
- update_option('dbem_location_no_event_message',get_option('dbem_location_event_list_item_header_format').get_option('dbem_location_no_events_message').get_option('dbem_location_event_list_item_footer_format'));
877
- update_option('dbem_tag_event_single_format',get_option('dbem_tag_event_list_item_header_format').get_option('dbem_tag_event_list_item_format').get_option('dbem_tag_event_list_item_footer_format'));
878
- update_option('dbem_tag_no_event_message',get_option('dbem_tag_event_list_item_header_format').get_option('dbem_tag_no_events_message').get_option('dbem_tag_event_list_item_footer_format'));
879
  }
880
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.38 ){
881
- update_option('dbem_dates_separator', get_option('dbem_dates_Seperator', get_option('dbem_dates_seperator',' - ')));
882
- update_option('dbem_times_separator', get_option('dbem_times_Seperator', get_option('dbem_times_seperator',' - ')));
883
- delete_option('dbem_dates_Seperator');
884
- delete_option('dbem_times_Seperator');
885
- delete_option('dbem_dates_seperator');
886
- delete_option('dbem_times_seperator');
887
  }
888
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.4 ){
889
- //tax rates now saved at booking level, so that alterations to tax rates don't change previous booking prices
890
- //any past bookings that don't get updated will adhere to these two values when calculating prices
891
- update_option('dbem_legacy_bookings_tax_auto_add', get_option('dbem_bookings_tax_auto_add'));
892
- update_option('dbem_legacy_bookings_tax', get_option('dbem_bookings_tax'));
893
  }
894
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.422 ){
895
- //copy registration email content into new setting
896
- update_option('dbem_rss_limit',0);
897
  }
898
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.4425 ){
899
- //copy registration email content into new setting
900
- update_option('dbem_css_editors',0);
901
- update_option('dbem_css_rsvp',0);
902
- update_option('dbem_css_evlist',0);
903
- update_option('dbem_css_loclist',0);
904
- update_option('dbem_css_rsvpadmin',0);
905
- update_option('dbem_css_catlist',0);
906
- update_option('dbem_css_taglist',0);
907
- if( locate_template('plugins/events-manager/templates/events-search.php') ){
908
- update_option('dbem_css_search', 0);
909
- update_option('dbem_search_form_hide_advanced',0);
910
- }
911
- update_option('dbem_events_page_search_form',get_option('dbem_events_page_search'));
912
- update_option('dbem_search_form_dates_separator',get_option('dbem_dates_separator'));
913
- delete_option('dbem_events_page_search'); //avoids the double search form on overridden templates
914
- update_option('dbem_locations_page_search_form',0); //upgrades shouldn't get extra surprises
915
  }
916
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.512 ){
917
  update_option('dbem_search_form_geo_units',0); //don't display units search for previous installs
918
  //correcting the typo
919
  update_option('dbem_search_form_submit', get_option('dbem_serach_form_submit'));
920
  //if template isn't overridden, assume it is still being used
921
- if( !locate_template('plugins/events-manager/templates/events-search.php') ){
922
- delete_option('dbem_serach_form_submit', 0);
923
- }
924
- //ML translation
925
  if( get_option('dbem_serach_form_submit_ml') ){
926
  update_option('dbem_search_form_submit_ml', get_option('dbem_serach_form_submit_ml'));
927
  delete_option('dbem_serach_form_submit_ml'); //we can assume this isn't used in templates
@@ -932,47 +947,48 @@ function em_add_options() {
932
  update_option('dbem_cp_locations_excerpt_formats',0);
933
  }
934
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.55 ){
935
- //rename email templates sent to admins on new bookings
936
- update_option('dbem_bookings_contact_email_cancelled_subject',get_option('dbem_contactperson_email_cancelled_subject'));
937
- update_option('dbem_bookings_contact_email_cancelled_body',get_option('dbem_contactperson_email_cancelled_body'));
938
- if( get_option('dbem_bookings_approval') ){
939
- //if approvals ENABLED, we should make the old 'New Booking' email the one for a pending booking
940
- update_option('dbem_bookings_contact_email_pending_subject',get_option('dbem_bookings_contact_email_subject'));
941
- update_option('dbem_bookings_contact_email_pending_body',get_option('dbem_bookings_contact_email_body'));
942
- }else{
943
- //if approvals DISABLED, we should make the old 'New Booking' email the one for a confirmed booking
944
- update_option('dbem_bookings_contact_email_confirmed_subject',get_option('dbem_bookings_contact_email_subject'));
945
- update_option('dbem_bookings_contact_email_confirmed_body',get_option('dbem_bookings_contact_email_body'));
946
- }
947
- delete_option('dbem_contactperson_email_cancelled_subject');
948
- delete_option('dbem_contactperson_email_cancelled_body');
949
- delete_option('dbem_bookings_contact_email_subject');
950
- delete_option('dbem_bookings_contact_email_body');
951
  }
952
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.62 ){
953
- //delete all _event_created_date and _event_date_modified records in post_meta, we don't need them anymore, they were never accurate to begin with, refer to the records in em_events table if still needed
954
- $wpdb->query('DELETE FROM '.$wpdb->postmeta." WHERE (meta_key='_event_date_created' OR meta_key='_event_date_modified') AND post_id IN (SELECT ID FROM ".$wpdb->posts." WHERE post_type='".EM_POST_TYPE_EVENT."' OR post_type='event-recurring')");
955
- $wpdb->query('ALTER TABLE '. $wpdb->prefix.'em_bookings CHANGE event_id event_id BIGINT(20) UNSIGNED NULL');
956
  }
957
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.66 ){
958
  if( get_option('dbem_ical_description_format') == "#_EVENTNAME - #_LOCATIONNAME - #_EVENTDATES - #_EVENTTIMES" ) update_option('dbem_ical_description_format',"#_EVENTNAME");
959
  if( get_option('dbem_ical_location_format') == "#_LOCATION" ) update_option('dbem_ical_location_format', "#_LOCATIONNAME, #_LOCATIONFULLLINE, #_LOCATIONCOUNTRY");
960
  $old_values = array(
961
- 'dbem_ical_description_format' => "#_EVENTNAME - #_LOCATIONNAME - #_EVENTDATES - #_EVENTTIMES",
962
- 'dbem_ical_location_format' => "#_LOCATION",
963
  );
964
  }
965
-
966
- //set time localization for first time depending on current settings
967
- if( get_option('dbem_time_24h','not set') == 'not set'){
968
- //Localise vars regardless
969
- $locale_code = substr ( get_locale(), 0, 2 );
970
- if (preg_match('/^en_(?:GB|IE|AU|NZ|ZA|TT|JM)$/', get_locale())) {
971
- $locale_code = 'en-GB';
 
 
 
 
972
  }
973
- //Set time
974
- $show24Hours = ( !preg_match("/en|sk|zh|us|uk/", $locale_code ) ); // Setting 12 hours format for those countries using it
975
- update_option('dbem_time_24h', $show24Hours);
976
  }
977
  }
978
 
39
  }
40
  //set caps and options
41
  em_set_capabilities();
42
+ em_add_options();
43
+ em_upgrade_current_installation();
44
  //Update Version
45
  update_option('dbem_version', EM_VERSION);
46
  delete_option('dbem_upgrade_throttle');
664
  //Bookings
665
  'dbem_bookings_registration_disable' => 0,
666
  'dbem_bookings_registration_disable_user_emails' => 0,
 
667
  'dbem_bookings_approval' => 1, //approval is on by default
668
  'dbem_bookings_approval_reserved' => 0, //overbooking before approval?
669
  'dbem_bookings_approval_overbooking' => 0, //overbooking possible when approving?
822
  foreach($dbem_options as $key => $value){
823
  add_option($key, $value);
824
  }
825
+
826
+ //set time localization for first time depending on current settings
827
+ if( get_option('dbem_time_24h','not set') == 'not set'){
828
+ //Localise vars regardless
829
+ $locale_code = substr ( get_locale(), 0, 2 );
830
+ if (preg_match('/^en_(?:GB|IE|AU|NZ|ZA|TT|JM)$/', get_locale())) {
831
+ $locale_code = 'en-GB';
832
+ }
833
+ //Set time
834
+ $show24Hours = ( !preg_match("/en|sk|zh|us|uk/", $locale_code ) ); // Setting 12 hours format for those countries using it
835
+ update_option('dbem_time_24h', $show24Hours);
836
+ }
837
+ }
838
+
839
+ function em_upgrade_current_installation(){
840
+ global $wpdb, $wp_locale;
841
  if( !get_option('dbem_version') ){ add_option('dbem_credits',1); }
842
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5 ){
843
  //make events, cats and locs pages
866
  if( defined('EM_CATEGORIES_SLUG') && EM_CATEGORIES_SLUG != 'categories' ) update_option('dbem_taxonomy_category_slug', $events_page->post_name.'/'.EM_CATEGORIES_SLUG);
867
  }
868
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.19 ){
869
+ update_option('dbem_event_reapproved_email_subject', get_option('dbem_event_approved_email_subject'));
870
+ update_option('dbem_event_reapproved_email_body', get_option('dbem_event_approved_email_body'));
871
  }
872
  if( get_option('dbem_version') != '' && get_option('dbem_version') <= 5.21 ){
873
+ //just remove all rsvp cut-off info
874
+ $wpdb->query("UPDATE ".$wpdb->postmeta." SET meta_value = NULL WHERE meta_key IN ('_event_rsvp_date','_event_rsvp_time') AND post_id IN (SELECT post_id FROM ".EM_EVENTS_TABLE." WHERE recurrence_id > 0)");
875
+ $wpdb->query("UPDATE ".EM_EVENTS_TABLE." SET event_rsvp_time = NULL, event_rsvp_date = NULL WHERE recurrence_id > 0");
876
  }
877
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.364 ){
878
+ if( get_option('dbem_cp_events_template_page') ){
879
+ update_option('dbem_cp_events_template', 'page');
880
+ delete_option('dbem_cp_events_template_page');
881
+ }
882
+ if( get_option('dbem_cp_locations_template_page') ){
883
+ update_option('dbem_cp_locations_template', 'page');
884
+ delete_option('dbem_cp_locations_template_page');
885
+ }
886
+ update_option('dbem_events_archive_scope', get_option('dbem_events_page_scope'));
887
+ update_option('em_last_modified', current_time('timestamp', true));
888
+ update_option('dbem_category_event_single_format',get_option('dbem_category_event_list_item_header_format').get_option('dbem_category_event_list_item_format').get_option('dbem_category_event_list_item_footer_format'));
889
+ update_option('dbem_category_no_event_message',get_option('dbem_category_event_list_item_header_format').get_option('dbem_category_no_events_message').get_option('dbem_category_event_list_item_footer_format'));
890
+ update_option('dbem_location_event_single_format',get_option('dbem_location_event_list_item_header_format').get_option('dbem_location_event_list_item_format').get_option('dbem_location_event_list_item_footer_format'));
891
+ update_option('dbem_location_no_event_message',get_option('dbem_location_event_list_item_header_format').get_option('dbem_location_no_events_message').get_option('dbem_location_event_list_item_footer_format'));
892
+ update_option('dbem_tag_event_single_format',get_option('dbem_tag_event_list_item_header_format').get_option('dbem_tag_event_list_item_format').get_option('dbem_tag_event_list_item_footer_format'));
893
+ update_option('dbem_tag_no_event_message',get_option('dbem_tag_event_list_item_header_format').get_option('dbem_tag_no_events_message').get_option('dbem_tag_event_list_item_footer_format'));
894
  }
895
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.38 ){
896
+ update_option('dbem_dates_separator', get_option('dbem_dates_Seperator', get_option('dbem_dates_seperator',' - ')));
897
+ update_option('dbem_times_separator', get_option('dbem_times_Seperator', get_option('dbem_times_seperator',' - ')));
898
+ delete_option('dbem_dates_Seperator');
899
+ delete_option('dbem_times_Seperator');
900
+ delete_option('dbem_dates_seperator');
901
+ delete_option('dbem_times_seperator');
902
  }
903
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.4 ){
904
+ //tax rates now saved at booking level, so that alterations to tax rates don't change previous booking prices
905
+ //any past bookings that don't get updated will adhere to these two values when calculating prices
906
+ update_option('dbem_legacy_bookings_tax_auto_add', get_option('dbem_bookings_tax_auto_add'));
907
+ update_option('dbem_legacy_bookings_tax', get_option('dbem_bookings_tax'));
908
  }
909
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.422 ){
910
+ //copy registration email content into new setting
911
+ update_option('dbem_rss_limit',0);
912
  }
913
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.4425 ){
914
+ //copy registration email content into new setting
915
+ update_option('dbem_css_editors',0);
916
+ update_option('dbem_css_rsvp',0);
917
+ update_option('dbem_css_evlist',0);
918
+ update_option('dbem_css_loclist',0);
919
+ update_option('dbem_css_rsvpadmin',0);
920
+ update_option('dbem_css_catlist',0);
921
+ update_option('dbem_css_taglist',0);
922
+ if( locate_template('plugins/events-manager/templates/events-search.php') ){
923
+ update_option('dbem_css_search', 0);
924
+ update_option('dbem_search_form_hide_advanced',0);
925
+ }
926
+ update_option('dbem_events_page_search_form',get_option('dbem_events_page_search'));
927
+ update_option('dbem_search_form_dates_separator',get_option('dbem_dates_separator'));
928
+ delete_option('dbem_events_page_search'); //avoids the double search form on overridden templates
929
+ update_option('dbem_locations_page_search_form',0); //upgrades shouldn't get extra surprises
930
  }
931
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.512 ){
932
  update_option('dbem_search_form_geo_units',0); //don't display units search for previous installs
933
  //correcting the typo
934
  update_option('dbem_search_form_submit', get_option('dbem_serach_form_submit'));
935
  //if template isn't overridden, assume it is still being used
936
+ if( !locate_template('plugins/events-manager/templates/events-search.php') ){
937
+ delete_option('dbem_serach_form_submit', 0);
938
+ }
939
+ //ML translation
940
  if( get_option('dbem_serach_form_submit_ml') ){
941
  update_option('dbem_search_form_submit_ml', get_option('dbem_serach_form_submit_ml'));
942
  delete_option('dbem_serach_form_submit_ml'); //we can assume this isn't used in templates
947
  update_option('dbem_cp_locations_excerpt_formats',0);
948
  }
949
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.55 ){
950
+ //rename email templates sent to admins on new bookings
951
+ update_option('dbem_bookings_contact_email_cancelled_subject',get_option('dbem_contactperson_email_cancelled_subject'));
952
+ update_option('dbem_bookings_contact_email_cancelled_body',get_option('dbem_contactperson_email_cancelled_body'));
953
+ if( get_option('dbem_bookings_approval') ){
954
+ //if approvals ENABLED, we should make the old 'New Booking' email the one for a pending booking
955
+ update_option('dbem_bookings_contact_email_pending_subject',get_option('dbem_bookings_contact_email_subject'));
956
+ update_option('dbem_bookings_contact_email_pending_body',get_option('dbem_bookings_contact_email_body'));
957
+ }else{
958
+ //if approvals DISABLED, we should make the old 'New Booking' email the one for a confirmed booking
959
+ update_option('dbem_bookings_contact_email_confirmed_subject',get_option('dbem_bookings_contact_email_subject'));
960
+ update_option('dbem_bookings_contact_email_confirmed_body',get_option('dbem_bookings_contact_email_body'));
961
+ }
962
+ delete_option('dbem_contactperson_email_cancelled_subject');
963
+ delete_option('dbem_contactperson_email_cancelled_body');
964
+ delete_option('dbem_bookings_contact_email_subject');
965
+ delete_option('dbem_bookings_contact_email_body');
966
  }
967
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.62 ){
968
+ //delete all _event_created_date and _event_date_modified records in post_meta, we don't need them anymore, they were never accurate to begin with, refer to the records in em_events table if still needed
969
+ $wpdb->query('DELETE FROM '.$wpdb->postmeta." WHERE (meta_key='_event_date_created' OR meta_key='_event_date_modified') AND post_id IN (SELECT ID FROM ".$wpdb->posts." WHERE post_type='".EM_POST_TYPE_EVENT."' OR post_type='event-recurring')");
970
+ $wpdb->query('ALTER TABLE '. $wpdb->prefix.'em_bookings CHANGE event_id event_id BIGINT(20) UNSIGNED NULL');
971
  }
972
  if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.66 ){
973
  if( get_option('dbem_ical_description_format') == "#_EVENTNAME - #_LOCATIONNAME - #_EVENTDATES - #_EVENTTIMES" ) update_option('dbem_ical_description_format',"#_EVENTNAME");
974
  if( get_option('dbem_ical_location_format') == "#_LOCATION" ) update_option('dbem_ical_location_format', "#_LOCATIONNAME, #_LOCATIONFULLLINE, #_LOCATIONCOUNTRY");
975
  $old_values = array(
976
+ 'dbem_ical_description_format' => "#_EVENTNAME - #_LOCATIONNAME - #_EVENTDATES - #_EVENTTIMES",
977
+ 'dbem_ical_location_format' => "#_LOCATION",
978
  );
979
  }
980
+ if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.6636 ){
981
+ $sql = $wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_key='_post_id' AND post_id IN (SELECT ID FROM {$wpdb->posts} WHERE post_type=%s OR post_type=%s)", array(EM_POST_TYPE_EVENT, 'event-recurring'));
982
+ $wpdb->query($sql);
983
+ remove_filter('pre_option_dbem_bookings_registration_user', 'EM_People::dbem_bookings_registration_user');
984
+ $no_user = get_option('dbem_bookings_registration_user');
985
+ if( get_option('dbem_bookings_registration_disable') && is_numeric($no_user) ){
986
+ if( $wpdb->update(EM_BOOKINGS_TABLE, array('person_id'=>0), array('person_id'=>$no_user), '%d', '%d') ){
987
+ delete_option('dbem_bookings_registration_user');
988
+ }
989
+ }else{
990
+ delete_option('dbem_bookings_registration_user');
991
  }
 
 
 
992
  }
993
  }
994
 
em-shortcode.php CHANGED
@@ -39,13 +39,57 @@ function em_get_locations_map_shortcode($args){
39
  $args['height'] = $height;
40
  //assign random number for element id reference
41
  $args['random_id'] = substr(md5(rand().rand()),0,5);
 
 
 
 
 
 
 
 
 
 
42
  ob_start();
43
- em_locate_template('templates/map-global.php',true, array('args'=>$args));
44
  return ob_get_clean();
45
  }
46
  add_shortcode('locations_map', 'em_get_locations_map_shortcode');
47
  add_shortcode('locations-map', 'em_get_locations_map_shortcode'); //deprecate this... confusing for WordPress
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  /**
50
  * Shows a list of events according to given specifications. Accepts any event query attribute.
51
  * @param array $args
@@ -108,9 +152,8 @@ add_shortcode ( 'events_list_grouped', 'em_get_events_list_grouped_shortcode' );
108
  * @return string
109
  */
110
  function em_get_event_shortcode($atts, $format='') {
111
- global $EM_Event, $post;
112
  $return = '';
113
- $the_event = is_object($EM_Event) ? clone($EM_Event):null; //save global temporarily
114
  $atts = (array) $atts;
115
  $atts['format'] = ($format != '' || empty($atts['format'])) ? $format : $atts['format'];
116
  $atts['format'] = html_entity_decode($atts['format']); //shorcode doesn't accept html
@@ -128,7 +171,6 @@ function em_get_event_shortcode($atts, $format='') {
128
  $EM_Event = em_get_event($post->ID, 'post_id');
129
  $return = ( !empty($atts['format']) ) ? $EM_Event->output($atts['format']) : $EM_Event->output_single();
130
  }
131
- $EM_Event = is_object($the_event) ? $the_event:$EM_Event; //reset global
132
  return $return;
133
  }
134
  add_shortcode ( 'event', 'em_get_event_shortcode' );
39
  $args['height'] = $height;
40
  //assign random number for element id reference
41
  $args['random_id'] = substr(md5(rand().rand()),0,5);
42
+ if( !empty($args['map_style']) ){
43
+ $style= base64_decode($args['map_style']);
44
+ $style_json= json_decode($style);
45
+ if( is_array($style_json) || is_object($style_json) ){
46
+ $style = preg_replace('/[\r\n\t\s]/', '', $style);
47
+ }else{
48
+ $style = '';
49
+ }
50
+ unset($args['map_style']);
51
+ }
52
  ob_start();
53
+ em_locate_template('templates/map-global.php',true, array('args'=>$args, 'map_json_style' => $style));
54
  return ob_get_clean();
55
  }
56
  add_shortcode('locations_map', 'em_get_locations_map_shortcode');
57
  add_shortcode('locations-map', 'em_get_locations_map_shortcode'); //deprecate this... confusing for WordPress
58
 
59
+
60
+ /**
61
+ * Generates a map of locations that match given query attributes. Accepts any location query attributes.
62
+ * @param array $args
63
+ * @return string
64
+ */
65
+ function em_get_events_map_shortcode($args){
66
+ $args['em_ajax'] = true;
67
+ $args['query'] = 'GlobalEventsMapData';
68
+ //get dimensions with px or % added in
69
+ $width = (!empty($args['width'])) ? $args['width']:get_option('dbem_map_default_width','400px');
70
+ $width = preg_match('/(px)|%/', $width) ? $width:$width.'px';
71
+ $height = (!empty($args['height'])) ? $args['height']:get_option('dbem_map_default_height','300px');
72
+ $height = preg_match('/(px)|%/', $height) ? $height:$height.'px';
73
+ $args['width'] = $width;
74
+ $args['height'] = $height;
75
+ //assign random number for element id reference
76
+ $args['random_id'] = substr(md5(rand().rand()),0,5);
77
+ if( !empty($args['map_style']) ){
78
+ $style= base64_decode($args['map_style']);
79
+ $style_json= json_decode($style);
80
+ if( is_array($style_json) || is_object($style_json) ){
81
+ $style = preg_replace('/[\r\n\t\s]/', '', $style);
82
+ }else{
83
+ $style = '';
84
+ }
85
+ unset($args['map_style']);
86
+ }
87
+ ob_start();
88
+ em_locate_template('templates/map-global.php',true, array('args'=>$args, 'map_json_style' => $style));
89
+ return ob_get_clean();
90
+ }
91
+ add_shortcode('events_map', 'em_get_events_map_shortcode');
92
+
93
  /**
94
  * Shows a list of events according to given specifications. Accepts any event query attribute.
95
  * @param array $args
152
  * @return string
153
  */
154
  function em_get_event_shortcode($atts, $format='') {
155
+ global $post;
156
  $return = '';
 
157
  $atts = (array) $atts;
158
  $atts['format'] = ($format != '' || empty($atts['format'])) ? $format : $atts['format'];
159
  $atts['format'] = html_entity_decode($atts['format']); //shorcode doesn't accept html
171
  $EM_Event = em_get_event($post->ID, 'post_id');
172
  $return = ( !empty($atts['format']) ) ? $EM_Event->output($atts['format']) : $EM_Event->output_single();
173
  }
 
174
  return $return;
175
  }
176
  add_shortcode ( 'event', 'em_get_event_shortcode' );
em-template-tags.php CHANGED
@@ -219,7 +219,7 @@ function em_get_event_form( $args = array() ){
219
  * @param array $args
220
  */
221
  function em_events_admin($args = array()){
222
- global $EM_Event, $bp;
223
  if( is_user_logged_in() && current_user_can('edit_events') ){
224
  if( !empty($_GET['action']) && $_GET['action']=='edit' ){
225
  if( empty($_REQUEST['redirect_to']) ){
@@ -228,11 +228,6 @@ function em_events_admin($args = array()){
228
  em_event_form();
229
  }else{
230
  if( get_option('dbem_css_editors') ) echo '<div class="css-events-admin">';
231
- //template $args for different views
232
- $args_views['pending'] = array('status'=>0, 'owner' =>get_current_user_id(), 'scope' => 'all', 'recurring'=>'include');
233
- $args_views['draft'] = array('status'=>null, 'owner' =>get_current_user_id(), 'scope' => 'all', 'recurring'=>'include');
234
- $args_views['past'] = array('status'=>'all', 'owner' =>get_current_user_id(), 'scope' => 'past');
235
- $args_views['future'] = array('status'=>'1', 'owner' =>get_current_user_id(), 'scope' => 'future');
236
  //get listing options for $args
237
  $limit = ( !empty($_REQUEST['limit']) ) ? $_REQUEST['limit'] : 20;//Default limit
238
  $page = ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
@@ -242,6 +237,20 @@ function em_events_admin($args = array()){
242
  //deal with view or scope/status combinations
243
  $show_add_new = isset($args['show_add_new']) ? $args['show_add_new']:true;
244
  $args = array('order' => $order, 'search' => $search, 'owner' => get_current_user_id());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  if( !empty($_REQUEST['view']) && in_array($_REQUEST['view'], array('future','draft','past','pending')) ){
246
  $args = array_merge($args, $args_views[$_REQUEST['view']]);
247
  }else{
@@ -256,7 +265,10 @@ function em_events_admin($args = array()){
256
  }
257
  $args['status'] = $status;
258
  }
 
 
259
  $events_count = EM_Events::count( $args ); //count events without limits for pagination
 
260
  $args['limit'] = $limit;
261
  $args['offset'] = $offset;
262
  $EM_Events = EM_Events::get( $args ); //now get the limited events to display
@@ -296,7 +308,6 @@ function em_get_events_admin( $args = array() ){
296
  em_events_admin($args);
297
  return ob_get_clean();
298
  }
299
-
300
  /**
301
  * Outputs the event search form.
302
  * @param array $args
219
  * @param array $args
220
  */
221
  function em_events_admin($args = array()){
222
+ global $EM_Event, $EM_Notices, $bp;
223
  if( is_user_logged_in() && current_user_can('edit_events') ){
224
  if( !empty($_GET['action']) && $_GET['action']=='edit' ){
225
  if( empty($_REQUEST['redirect_to']) ){
228
  em_event_form();
229
  }else{
230
  if( get_option('dbem_css_editors') ) echo '<div class="css-events-admin">';
 
 
 
 
 
231
  //get listing options for $args
232
  $limit = ( !empty($_REQUEST['limit']) ) ? $_REQUEST['limit'] : 20;//Default limit
233
  $page = ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
237
  //deal with view or scope/status combinations
238
  $show_add_new = isset($args['show_add_new']) ? $args['show_add_new']:true;
239
  $args = array('order' => $order, 'search' => $search, 'owner' => get_current_user_id());
240
+ if( !empty($_REQUEST['recurrence_id']) ){
241
+ $Event = em_get_event($_REQUEST['recurrence_id']);
242
+ $EM_Notices->add_alert(sprintf(esc_html__('You are viewing individual recurrences of recurring event %s.', 'events-manager'), '<a href="'.$Event->get_edit_url().'">'.$Event->event_name.'</a>'));
243
+ $EM_Notices->add_alert(esc_html__('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'));
244
+ $args['recurrence_id'] = $_REQUEST['recurrence_id'];
245
+ }
246
+ $args = apply_filters('em_events_admin_args', $args);
247
+ //template $args for different views
248
+ $args_views = array();
249
+ $args_views['pending'] = array_merge($args, array('status'=>0, 'scope' => 'all', 'recurring'=>'include'));
250
+ $args_views['draft'] = array_merge($args, array('status'=>null, 'scope' => 'all', 'recurring'=>'include'));
251
+ $args_views['past'] = array_merge($args, array('status'=>'all', 'scope' => 'past'));
252
+ $args_views['future'] = array_merge($args, array('status'=>'1', 'scope' => 'future'));
253
+ //modify $args for current view
254
  if( !empty($_REQUEST['view']) && in_array($_REQUEST['view'], array('future','draft','past','pending')) ){
255
  $args = array_merge($args, $args_views[$_REQUEST['view']]);
256
  }else{
265
  }
266
  $args['status'] = $status;
267
  }
268
+ //reset the limit and offset to allow for filter
269
+ unset($args['limit']); unset($args['offset']);
270
  $events_count = EM_Events::count( $args ); //count events without limits for pagination
271
+ //add limit and offset again to args
272
  $args['limit'] = $limit;
273
  $args['offset'] = $offset;
274
  $EM_Events = EM_Events::get( $args ); //now get the limited events to display
308
  em_events_admin($args);
309
  return ob_get_clean();
310
  }
 
311
  /**
312
  * Outputs the event search form.
313
  * @param array $args
events-manager.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Plugin Name: Events Manager
4
- Version: 5.6.6.1
5
  Plugin URI: http://wp-events-plugin.com
6
  Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
  Author: Marcus Sykes
@@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28
  */
29
 
30
  // Setting constants
31
- define('EM_VERSION', 5.6624); //self expanatory
32
  define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
  define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
  define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
@@ -185,11 +185,7 @@ class EM_Scripts_and_Styles {
185
  public static function init(){
186
  if( is_admin() ){
187
  //Scripts and Styles
188
- if( (!empty($_GET['page']) && substr($_GET['page'],0,14) == 'events-manager') || (!empty($_GET['post_type']) && in_array($_GET['post_type'], array(EM_POST_TYPE_EVENT,EM_POST_TYPE_LOCATION,'event-recurring'))) ){
189
- add_action('admin_print_scripts', array('EM_Scripts_and_Styles','admin_enqueue'));
190
- }else{
191
- add_action('admin_print_styles-post.php', array('EM_Scripts_and_Styles','admin_enqueue'));
192
- }
193
  }else{
194
  add_action('wp_enqueue_scripts', array('EM_Scripts_and_Styles','public_enqueue'));
195
  }
@@ -207,6 +203,7 @@ class EM_Scripts_and_Styles {
207
  'edit-bookings' => get_option('dbem_edit_bookings_page'),
208
  'my-bookings' => get_option('dbem_my_bookings_page')
209
  );
 
210
  $obj = $wp_query->get_queried_object();
211
  $obj_id = 0;
212
  if( is_home() ){
@@ -222,7 +219,7 @@ class EM_Scripts_and_Styles {
222
  if( is_page($pages) ){
223
  $script_deps['jquery'] = 'jquery';
224
  }
225
- if( (!empty($pages['events']) && is_page($pages['events']) && get_option('dbem_events_page_search')) || get_option('dbem_js_limit_search') === '0' || in_array($obj_id, explode(',', get_option('dbem_js_limit_search'))) ){
226
  //events page only needs datepickers
227
  $script_deps['jquery-ui-core'] = 'jquery-ui-core';
228
  $script_deps['jquery-ui-datepicker'] = 'jquery-ui-datepicker';
@@ -294,12 +291,14 @@ class EM_Scripts_and_Styles {
294
  }
295
  }
296
 
297
- public static function admin_enqueue(){
298
- wp_enqueue_script('events-manager', plugins_url('includes/js/events-manager.js',__FILE__), array('jquery', 'jquery-ui-core','jquery-ui-widget','jquery-ui-position','jquery-ui-sortable','jquery-ui-datepicker','jquery-ui-autocomplete','jquery-ui-dialog'), EM_VERSION);
299
- do_action('em_enqueue_admin_scripts');
300
- wp_enqueue_style('events-manager-admin', plugins_url('includes/css/events_manager_admin.css',__FILE__), array(), EM_VERSION);
301
- do_action('em_enqueue_admin_styles');
302
- self::localize_script();
 
 
303
  }
304
 
305
  /**
@@ -321,13 +320,19 @@ class EM_Scripts_and_Styles {
321
  'is_ssl' => is_ssl(),
322
  );
323
  //maps api key
324
- if( get_option('dbem_gmap_is_active') && get_option('dbem_google_maps_browser_key') ){
325
- $em_localized_js['google_maps_api'] = get_option('dbem_google_maps_browser_key');
 
 
 
 
 
326
  }
327
  //debug mode
328
  if( defined('WP_DEBUG') && WP_DEBUG ) $em_localized_js['ui_css'] = plugins_url('includes/css/jquery-ui.css', __FILE__);
329
  //booking-specific stuff
330
  if( get_option('dbem_rsvp_enabled') ){
 
331
  $em_localized_js = array_merge($em_localized_js, array(
332
  'bookingInProgress' => __('Please wait while the booking is being submitted.','events-manager'),
333
  'tickets_save' => __('Save Ticket','events-manager'),
@@ -335,6 +340,7 @@ class EM_Scripts_and_Styles {
335
  'bookings_export_save' => __('Export Bookings','events-manager'),
336
  'bookings_settings_save' => __('Save Settings','events-manager'),
337
  'booking_delete' => __("Are you sure you want to delete?",'events-manager'),
 
338
  //booking button
339
  'bb_full' => get_option('dbem_booking_button_msg_full'),
340
  'bb_book' => get_option('dbem_booking_button_msg_book'),
@@ -354,7 +360,15 @@ class EM_Scripts_and_Styles {
354
  //logged in messages that visitors shouldn't need to see
355
  if( is_user_logged_in() || is_page(get_option('dbem_edit_events_page')) ){
356
  if( get_option('dbem_recurrence_enabled') ){
357
- $em_localized_js['event_reschedule_warning'] = __('Are you sure you want to reschedule this recurring event? If you do this, you will lose all booking information and the old recurring events will be deleted.', 'events-manager');
 
 
 
 
 
 
 
 
358
  $em_localized_js['event_detach_warning'] = __('Are you sure you want to detach this event? By doing so, this event will be independent of the recurring set of events.', 'events-manager');
359
  $delete_text = ( !EMPTY_TRASH_DAYS ) ? __('This cannot be undone.','events-manager'):__('All events will be moved to trash.','events-manager');
360
  $em_localized_js['delete_recurrence_warning'] = __('Are you sure you want to delete all recurrences of this event?', 'events-manager').' '.$delete_text;
@@ -372,53 +386,6 @@ class EM_Scripts_and_Styles {
372
  $em_localized_js['close_text'] = __('Collapse All','events-manager');
373
  $em_localized_js['open_text'] = __('Expand All','events-manager');
374
  }
375
- }
376
- //calendar translations
377
- $locale_code = get_locale();
378
- $locale_code_short = substr ( $locale_code, 0, 2 );
379
- $calendar_languages = array(
380
- 'nl'=>array('closeText'=>'Sluiten','prevText'=>'←','nextText'=>'→','currentText'=>'Vandaag','monthNames'=>array('januari','februari','maart','april','mei','juni','juli','augustus','september','oktober','november','december'),'monthNamesShort'=>array('jan','feb','maa','apr','mei','jun','jul','aug','sep','okt','nov','dec'),'dayNames'=>array('zondag','maandag','dinsdag','woensdag','donderdag','vrijdag','zaterdag'),'dayNamesShort'=>array('zon','maa','din','woe','don','vri','zat'),'dayNamesMin'=>array('zo','ma','di','wo','do','vr','za'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
381
- 'af'=>array('closeText'=>'Selekteer','prevText'=>'Vorige','nextText'=>'Volgende','currentText'=>'Vandag','monthNames'=>array('Januarie','Februarie','Maart','April','Mei','Junie','Julie','Augustus','September','Oktober','November','Desember'),'monthNamesShort'=>array('Jan','Feb','Mrt','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Des'),'dayNames'=>array('Sondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrydag','Saterdag'),'dayNamesShort'=>array('Son','Maa','Din','Woe','Don','Vry','Sat'),'dayNamesMin'=>array('So','Ma','Di','Wo','Do','Vr','Sa'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
382
- 'ar'=>array('closeText'=>'إغلاق','prevText'=>'<السابق','nextText'=>'التالي>','currentText'=>'اليوم','monthNames'=>array('كانون الثاني','شباط','آذار','نيسان','آذار','حزيران','تموز','آب','أيلول','تشرين الأول','تشرين الثاني','كانون الأول'),'monthNamesShort'=>array('1','2','3','4','5','6','7','8','9','10','11','12'),'dayNames'=>array('السبت','الأحد','الاثنين','الثلاثاء','الأربعاء','الخميس','الجمعة'),'dayNamesShort'=>array('سبت','أحد','اثنين','ثلاثاء','أربعاء','خميس','جمعة'),'dayNamesMin'=>array('سبت','أحد','اثنين','ثلاثاء','أربعاء','خميس','جمعة'),'weekHeader'=>'أسبوع','dateFormat'=>'dd/mm/yy','firstDay'=>0,'isRTL'=>true,'showMonthAfterYear'=>false,'yearSuffix'=>''),
383
- 'az'=>array('closeText'=>'Bağla','prevText'=>'<Geri','nextText'=>'İrəli>','currentText'=>'Bugün','monthNames'=>array('Yanvar','Fevral','Mart','Aprel','May','İyun','İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'),'monthNamesShort'=>array('Yan','Fev','Mar','Apr','May','İyun','İyul','Avq','Sen','Okt','Noy','Dek'),'dayNames'=>array('Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'),'dayNamesShort'=>array('B','Be','Ça','Ç','Ca','C','Ş'),'dayNamesMin'=>array('B','B','Ç','С','Ç','C','Ş'),'weekHeader'=>'Hf','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
384
- 'bg'=>array('closeText'=>'затвори','prevText'=>'<назад','nextText'=>'напред>','nextBigText'=>'>>','currentText'=>'днес','monthNames'=>array('Януари','Февруари','Март','Април','Май','Юни','Юли','Август','Септември','Октомври','Ноември','Декември'),'monthNamesShort'=>array('Яну','Фев','Мар','Апр','Май','Юни','Юли','Авг','Сеп','Окт','Нов','Дек'),'dayNames'=>array('Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'),'dayNamesShort'=>array('Нед','Пон','Вто','Сря','Чет','Пет','Съб'),'dayNamesMin'=>array('Не','По','Вт','Ср','Че','Пе','Съ'),'weekHeader'=>'Wk','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
385
- 'bs'=>array('closeText'=>'Zatvori','prevText'=>'<','nextText'=>'>','currentText'=>'Danas','monthNames'=>array('Januar','Februar','Mart','April','Maj','Juni','Juli','August','Septembar','Oktobar','Novembar','Decembar'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aug','Sep','Okt','Nov','Dec'),'dayNames'=>array('Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'),'dayNamesShort'=>array('Ned','Pon','Uto','Sri','Čet','Pet','Sub'),'dayNamesMin'=>array('Ne','Po','Ut','Sr','Če','Pe','Su'),'weekHeader'=>'Wk','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
386
- 'ca' => array('closeText'=> 'Tancar','prevText'=> '&#x3c;Ant','nextText'=> 'Seg&#x3e;','currentText'=> 'Avui','monthNames'=> array('Gener','Febrer','Mar&ccedil;','Abril','Maig','Juny','Juliol','Agost','Setembre','Octubre','Novembre','Desembre'),'monthNamesShort'=> array('Gen','Feb','Mar','Abr','Mai','Jun','Jul','Ago','Set','Oct','Nov','Des'),'dayNames'=> array('Diumenge','Dilluns','Dimarts','Dimecres','Dijous','Divendres','Dissabte'),'dayNamesShort'=> array('Dug','Dln','Dmt','Dmc','Djs','Dvn','Dsb'),'dayNamesMin'=> array('Dg','Dl','Dt','Dc','Dj','Dv','Ds'),'weekHeader'=> 'Sm','dateFormat'=> 'dd/mm/yy','firstDay'=> 1,'isRTL'=> false,'showMonthAfterYear'=> false,'yearSuffix'=> ''),
387
- 'cs'=>array('closeText'=>'Zavřít','prevText'=>'<Dříve','nextText'=>'Později>','currentText'=>'Nyní','monthNames'=>array('leden','únor','březen','duben','květen','červen','červenec','srpen','září','říjen','listopad','prosinec'),'monthNamesShort'=>array('led','úno','bře','dub','kvě','čer','čvc','srp','zář','říj','lis','pro'),'dayNames'=>array('neděle','pondělí','úterý','středa','čtvrtek','pátek','sobota'),'dayNamesShort'=>array('ne','po','út','st','čt','pá','so'),'dayNamesMin'=>array('ne','po','út','st','čt','pá','so'),'weekHeader'=>'Týd','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
388
- 'da'=>array('closeText'=>'Luk','prevText'=>'<Forrige','nextText'=>'Næste>','currentText'=>'Idag','monthNames'=>array('Januar','Februar','Marts','April','Maj','Juni','Juli','August','September','Oktober','November','December'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aug','Sep','Okt','Nov','Dec'),'dayNames'=>array('Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'),'dayNamesShort'=>array('Søn','Man','Tir','Ons','Tor','Fre','Lør'),'dayNamesMin'=>array('Sø','Ma','Ti','On','To','Fr','Lø'),'weekHeader'=>'Uge','dateFormat'=>'dd-mm-yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
389
- 'de'=>array('closeText'=>'schließen','prevText'=>'<zurück','nextText'=>'Vor>','currentText'=>'heute','monthNames'=>array('Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'),'monthNamesShort'=>array('Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'),'dayNames'=>array('Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'),'dayNamesShort'=>array('So','Mo','Di','Mi','Do','Fr','Sa'),'dayNamesMin'=>array('So','Mo','Di','Mi','Do','Fr','Sa'),'weekHeader'=>'Wo','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
390
- 'el'=>array('closeText'=>'Κλείσιμο','prevText'=>'Προηγούμενος','nextText'=>'Επόμενος','currentText'=>'Τρέχων Μήνας','monthNames'=>array('Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος','Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'),'monthNamesShort'=>array('Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν','Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'),'dayNames'=>array('Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'),'dayNamesShort'=>array('Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'),'dayNamesMin'=>array('Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'),'weekHeader'=>'Εβδ','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
391
- 'en_GB'=>array('closeText'=>'Done','prevText'=>'Prev','nextText'=>'Next','currentText'=>'Today','monthNames'=>array('January','February','March','April','May','June','July','August','September','October','November','December'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'),'dayNames'=>array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'),'dayNamesShort'=>array('Sun','Mon','Tue','Wed','Thu','Fri','Sat'),'dayNamesMin'=>array('Su','Mo','Tu','We','Th','Fr','Sa'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
392
- 'eo'=>array('closeText'=>'Fermi','prevText'=>'<Anta','nextText'=>'Sekv>','currentText'=>'Nuna','monthNames'=>array('Januaro','Februaro','Marto','Aprilo','Majo','Junio','Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aŭg','Sep','Okt','Nov','Dec'),'dayNames'=>array('Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'),'dayNamesShort'=>array('Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'),'dayNamesMin'=>array('Di','Lu','Ma','Me','Ĵa','Ve','Sa'),'weekHeader'=>'Sb','dateFormat'=>'dd/mm/yy','firstDay'=>0,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
393
- 'et'=>array('closeText'=>'Sulge','prevText'=>'Eelnev','nextText'=>'Järgnev','currentText'=>'Täna','monthNames'=>array('Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni','Juuli','August','September','Oktoober','November','Detsember'),'monthNamesShort'=>array('Jaan','Veebr','Märts','Apr','Mai','Juuni','Juuli','Aug','Sept','Okt','Nov','Dets'),'dayNames'=>array('Pühapäev','Esmaspäev','Teisipäev','Kolmapäev','Neljapäev','Reede','Laupäev'),'dayNamesShort'=>array('Pühap','Esmasp','Teisip','Kolmap','Neljap','Reede','Laup'),'dayNamesMin'=>array('P','E','T','K','N','R','L'),'weekHeader'=>'Sm','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
394
- 'eu'=>array('closeText'=>'Egina','prevText'=>'<Aur','nextText'=>'Hur>','currentText'=>'Gaur','monthNames'=>array('Urtarrila','Otsaila','Martxoa','Apirila','Maiatza','Ekaina','Uztaila','Abuztua','Iraila','Urria','Azaroa','Abendua'),'monthNamesShort'=>array('Urt','Ots','Mar','Api','Mai','Eka','Uzt','Abu','Ira','Urr','Aza','Abe'),'dayNames'=>array('Igandea','Astelehena','Asteartea','Asteazkena','Osteguna','Ostirala','Larunbata'),'dayNamesShort'=>array('Iga','Ast','Ast','Ast','Ost','Ost','Lar'),'dayNamesMin'=>array('Ig','As','As','As','Os','Os','La'),'weekHeader'=>'Wk','dateFormat'=>'yy/mm/dd','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
395
- 'fa'=>array('closeText'=>'بستن','prevText'=>'<قبلي','nextText'=>'بعدي>','currentText'=>'امروز','monthNames'=>array('فروردين','ارديبهشت','خرداد','تير','مرداد','شهريور','مهر','آبان','آذر','دي','بهمن','اسفند'),'monthNamesShort'=>array('1','2','3','4','5','6','7','8','9','10','11','12'),'dayNames'=>array('يکشنبه','دوشنبه','سه‌شنبه','چهارشنبه','پنجشنبه','جمعه','شنبه'),'dayNamesShort'=>array('ي','د','س','چ','پ','ج','ش'),'dayNamesMin'=>array('ي','د','س','چ','پ','ج','ش'),'weekHeader'=>'هف','dateFormat'=>'yy/mm/dd','firstDay'=>6,'isRTL'=>true,'showMonthAfterYear'=>false,'yearSuffix'=>''),
396
- 'fi'=>array('closeText'=>'Sulje','prevText'=>'<Edel','nextText'=>'Seur>','currentText'=>'Tänään','monthNames'=>array('Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kesäkuu','Heinäkuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'),'monthNamesShort'=>array('Tammi','Helmi','Maalis','Huhti','Touko','Kesä','Heinä','Elo','Syys','Loka','Marras','Joulu'),'dayNames'=>array('Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'),'dayNamesShort'=>array('Su','Ma','Ti','Ke','To','Pe','La'),'dayNamesMin'=>array('Su','Ma','Ti','Ke','To','Pe','La'),'weekHeader'=>'Sm','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
397
- 'fo'=>array('closeText'=>'Lat aftur','prevText'=>'<Fyrra','nextText'=>'Næsta>','currentText'=>'Í dag','monthNames'=>array('Januar','Februar','Mars','Apríl','Mei','Juni','Juli','August','September','Oktober','November','Desember'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Des'),'dayNames'=>array('Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'),'dayNamesShort'=>array('Sun','Mán','Týs','Mik','Hós','Frí','Ley'),'dayNamesMin'=>array('Su','Má','Tý','Mi','Hó','Fr','Le'),'weekHeader'=>'Vk','dateFormat'=>'dd-mm-yy','firstDay'=>0,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
398
- 'fr_CH'=>array('closeText'=>'Fermer','prevText'=>'<Préc','nextText'=>'Suiv>','currentText'=>'Courant','monthNames'=>array('Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'),'monthNamesShort'=>array('Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'),'dayNames'=>array('Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'),'dayNamesShort'=>array('Dim','Lun','Mar','Mer','Jeu','Ven','Sam'),'dayNamesMin'=>array('Di','Lu','Ma','Me','Je','Ve','Sa'),'weekHeader'=>'Sm','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
399
- 'fr'=>array('closeText'=>'Fermer','prevText'=>'<Préc','nextText'=>'Suiv>','currentText'=>'Courant','monthNames'=>array('Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'),'monthNamesShort'=>array('Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'),'dayNames'=>array('Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'),'dayNamesShort'=>array('Dim','Lun','Mar','Mer','Jeu','Ven','Sam'),'dayNamesMin'=>array('Di','Lu','Ma','Me','Je','Ve','Sa'),'weekHeader'=>'Sm','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
400
- 'he'=>array('closeText'=>'סגור','prevText'=>'<הקודם','nextText'=>'הבא>','currentText'=>'היום','monthNames'=>array('ינואר','פברואר','מרץ','אפריל','מאי','יוני','יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'),'monthNamesShort'=>array('1','2','3','4','5','6','7','8','9','10','11','12'),'dayNames'=>array('ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'),'dayNamesShort'=>array('א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'),'dayNamesMin'=>array('א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>0,'isRTL'=>true,'showMonthAfterYear'=>false,'yearSuffix'=>''),
401
- 'hu'=>array('closeText'=>'Kész','prevText'=>'Előző','nextText'=>'Következő','currentText'=>'Ma','monthNames'=>array('január','február','március','április','május','június','július','augusztus','szeptember','október','november','cecember'),'monthNamesShort'=>array('jan','febr','márc','ápr','máj','jún','júl','aug','szept','okt','nov','dec'),'dayNames'=>array('vasárnap','hétfő','kedd','szerda','csütörtök','péntek','szombat'),'dayNamesShort'=>array('va','hé','k','sze','csü','pé','szo'),'dayNamesMin'=>array('v','h','k','sze','cs','p','szo'),'weekHeader'=>'Wk','dateFormat'=>'yy.mm.dd.','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>true,'yearSuffix'=>''),
402
- 'hr'=>array('closeText'=>'Zatvori','prevText'=>'<','nextText'=>'>','currentText'=>'Danas','monthNames'=>array('Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj','Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'),'monthNamesShort'=>array('Sij','Velj','Ožu','Tra','Svi','Lip','Srp','Kol','Ruj','Lis','Stu','Pro'),'dayNames'=>array('Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'),'dayNamesShort'=>array('Ned','Pon','Uto','Sri','Čet','Pet','Sub'),'dayNamesMin'=>array('Ne','Po','Ut','Sr','Če','Pe','Su'),'weekHeader'=>'Tje','dateFormat'=>'dd.mm.yy.','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
403
- 'ja'=>array('closeText'=>'閉じる','prevText'=>'<前','nextText'=>'次>','currentText'=>'今日','monthNames'=>array('1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'),'monthNamesShort'=>array('1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'),'dayNames'=>array('日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'),'dayNamesShort'=>array('日','月','火','水','木','金','土'),'dayNamesMin'=>array('日','月','火','水','木','金','土'),'weekHeader'=>'週','dateFormat'=>'yy/mm/dd','firstDay'=>0,'isRTL'=>false,'showMonthAfterYear'=>true,'yearSuffix'=>'年'),
404
- 'ro'=>array('closeText'=>'Închide','prevText'=>'« Luna precedentă','nextText'=>'Luna următoare »','currentText'=>'Azi','monthNames'=>array('Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie','Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'),'monthNamesShort'=>array('Ian','Feb','Mar','Apr','Mai','Iun','Iul','Aug','Sep','Oct','Nov','Dec'),'dayNames'=>array('Duminică','Luni','Marţi','Miercuri','Joi','Vineri','Sâmbătă'),'dayNamesShort'=>array('Dum','Lun','Mar','Mie','Joi','Vin','Sâm'),'dayNamesMin'=>array('Du','Lu','Ma','Mi','Jo','Vi','Sâ'),'weekHeader'=>'Săpt','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
405
- 'sk'=>array('closeText'=> 'Zavrieť','prevText'=> '&#x3c;Predchádzajúci','nextText'=> 'Nasledujúci&#x3e;','currentText'=> 'Dnes','monthNames'=> array('Január','Február','Marec','Apríl','Máj','Jún','Júl','August','September','Október','November','December'),'monthNamesShort'=> array('Jan','Feb','Mar','Apr','Máj','Jún','Júl','Aug','Sep','Okt','Nov','Dec'),'dayNames'=> array('Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'),'dayNamesShort'=> array('Ned','Pon','Uto','Str','Štv','Pia','Sob'),'dayNamesMin'=> array('Ne','Po','Ut','St','Št','Pia','So'),'weekHeader'=> 'Ty','dateFormat'=> 'dd.mm.yy','firstDay'=> 1,'isRTL'=> false,'showMonthAfterYear'=> false,'yearSuffix'=> ''),
406
- 'sq'=>array('closeText'=>'mbylle','prevText'=>'<mbrapa','nextText'=>'Përpara>','currentText'=>'sot','monthNames'=>array('Janar','Shkurt','Mars','Prill','Maj','Qershor','Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'),'monthNamesShort'=>array('Jan','Shk','Mar','Pri','Maj','Qer','Kor','Gus','Sht','Tet','Nën','Dhj'),'dayNames'=>array('E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'),'dayNamesShort'=>array('Di','Hë','Ma','Më','En','Pr','Sh'),'dayNamesMin'=>array('Di','Hë','Ma','Më','En','Pr','Sh'),'weekHeader'=>'Ja','dateFormat'=>'dd.mm.yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
407
- 'sr_SR'=>array('closeText'=>'Zatvori','prevText'=>'<','nextText'=>'>','currentText'=>'Danas','monthNames'=>array('Januar','Februar','Mart','April','Maj','Jun','Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Maj','Jun','Jul','Avg','Sep','Okt','Nov','Dec'),'dayNames'=>array('Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'),'dayNamesShort'=>array('Ned','Pon','Uto','Sre','Čet','Pet','Sub'),'dayNamesMin'=>array('Ne','Po','Ut','Sr','Če','Pe','Su'),'weekHeader'=>'Sed','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
408
- 'sr'=>array('closeText'=>'Затвори','prevText'=>'<','nextText'=>'>','currentText'=>'Данас','monthNames'=>array('Јануар','Фебруар','Март','Април','Мај','Јун','Јул','Август','Септембар','Октобар','Новембар','Децембар'),'monthNamesShort'=>array('Јан','Феб','Мар','Апр','Мај','Јун','Јул','Авг','Сеп','Окт','Нов','Дец'),'dayNames'=>array('Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'),'dayNamesShort'=>array('Нед','Пон','Уто','Сре','Чет','Пет','Суб'),'dayNamesMin'=>array('Не','По','Ут','Ср','Че','Пе','Су'),'weekHeader'=>'Сед','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
409
- 'sv'=>array('closeText'=>'Stäng','prevText'=>'«Förra','nextText'=>'Nästa»','currentText'=>'Idag','monthNames'=>array('Januari','Februari','Mars','April','Maj','Juni','Juli','Augusti','September','Oktober','November','December'),'monthNamesShort'=>array('Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aug','Sep','Okt','Nov','Dec'),'dayNamesShort'=>array('Sön','Mån','Tis','Ons','Tor','Fre','Lör'),'dayNames'=>array('Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'),'dayNamesMin'=>array('Sö','Må','Ti','On','To','Fr','Lö'),'weekHeader'=>'Ve','dateFormat'=>'yy-mm-dd','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
410
- 'ta'=>array('closeText'=>'மூடு','prevText'=>'முன்னையது','nextText'=>'அடுத்தது','currentText'=>'இன்று','monthNames'=>array('தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி','ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'),'monthNamesShort'=>array('தை','மாசி','பங்','சித்','வைகா','ஆனி','ஆடி','ஆவ','புர','ஐப்','கார்','மார்'),'dayNames'=>array('ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'),'dayNamesShort'=>array('ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'),'dayNamesMin'=>array('ஞா','தி','செ','பு','வி','வெ','ச'),'weekHeader'=>'Не','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
411
- 'th'=>array('closeText'=>'ปิด','prevText'=>'« ย้อน','nextText'=>'ถัดไป »','currentText'=>'วันนี้','monthNames'=>array('มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน','กรกฏาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'),'monthNamesShort'=>array('ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'),'dayNames'=>array('อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'),'dayNamesShort'=>array('อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'),'dayNamesMin'=>array('อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>0,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
412
- 'tr'=>array('closeText' => 'kapat', 'prevText' => '&#x3c;geri', 'nextText' => 'ileri&#x3e', 'currentText' => 'bugün', 'monthNames' => array('Ocak','Şubat','Mart','Nisan','Mayıs','Haziran','Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'),'monthNamesShort' => array('Oca','Şub','Mar','Nis','May','Haz','Tem','Ağu','Eyl','Eki','Kas','Ara'),'dayNames' => array('Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'),'dayNamesShort' => array('Pz','Pt','Sa','Ça','Pe','Cu','Ct'),'dayNamesMin' => array('Pz','Pt','Sa','Ça','Pe','Cu','Ct'),'weekHeader' => 'Hf','dateFormat' => 'dd.mm.yy','firstDay' => 1,'isRTL' => false,'showMonthAfterYear' => false,'yearSuffix' => ''),
413
- 'vi'=>array('closeText'=>'Đóng','prevText'=>'<Trước','nextText'=>'Tiếp>','currentText'=>'Hôm nay','monthNames'=>array('Tháng Một','Tháng Hai','Tháng Ba','Tháng Tư','Tháng Năm','Tháng Sáu','Tháng Bảy','Tháng Tám','Tháng Chín','Tháng Mười','Tháng Mười Một','Tháng Mười Hai'),'monthNamesShort'=>array('Tháng 1','Tháng 2','Tháng 3','Tháng 4','Tháng 5','Tháng 6','Tháng 7','Tháng 8','Tháng 9','Tháng 10','Tháng 11','Tháng 12'),'dayNames'=>array('Chủ Nhật','Thứ Hai','Thứ Ba','Thứ Tư','Thứ Năm','Thứ Sáu','Thứ Bảy'),'dayNamesShort'=>array('CN','T2','T3','T4','T5','T6','T7'),'dayNamesMin'=>array('CN','T2','T3','T4','T5','T6','T7'),'weekHeader'=>'Tu','dateFormat'=>'dd/mm/yy','firstDay'=>0,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
414
- 'zh-TW'=>array('closeText'=>'關閉','prevText'=>'<上月','nextText'=>'下月>','currentText'=>'今天','monthNames'=>array('一月','二月','三月','四月','五月','六月','七月','八月','九月','十月','十一月','十二月'),'monthNamesShort'=>array('一','二','三','四','五','六','七','八','九','十','十一','十二'),'dayNames'=>array('星期日','星期一','星期二','星期三','星期四','星期五','星期六'),'dayNamesShort'=>array('周日','周一','周二','周三','周四','周五','周六'),'dayNamesMin'=>array('日','一','二','三','四','五','六'),'weekHeader'=>'周','dateFormat'=>'yy/mm/dd','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>true,'yearSuffix'=>'年'),
415
- 'es'=>array('closeText'=>'Cerrar','prevText'=>'<Ant','nextText'=>'Sig>','currentText'=>'Hoy','monthNames'=>array('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'),'monthNamesShort'=>array('Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'),'dayNames'=>array('Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'),'dayNamesShort'=>array('Dom','Lun','Mar','Mié','Juv','Vie','Sáb'),'dayNamesMin'=>array('Do','Lu','Ma','Mi','Ju','Vi','Sá'),'weekHeader'=>'Sm','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>''),
416
- 'it'=>array('closeText'=>'Fatto','prevText'=>'Precedente','nextText'=>'Prossimo','currentText'=>'Oggi','monthNames'=>array('Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno','Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'),'monthNamesShort'=>array('Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'),'dayNames'=>array('Domenica','Lunedì','Martedì','Mercoledì','Giovedì','Venerdì','Sabato'),'dayNamesShort'=>array('Dom','Lun','Mar','Mer','Gio','Ven','Sab'),'dayNamesMin'=>array('Do','Lu','Ma','Me','Gi','Ve','Sa'),'weekHeader'=>'Wk','dateFormat'=>'dd/mm/yy','firstDay'=>1,'isRTL'=>false,'showMonthAfterYear'=>false,'yearSuffix'=>'')
417
- );
418
- if( array_key_exists($locale_code, $calendar_languages) ){
419
- $em_localized_js['locale_data'] = $calendar_languages[$locale_code];
420
- }elseif( array_key_exists($locale_code_short, $calendar_languages) ){
421
- $em_localized_js['locale_data'] = $calendar_languages[$locale_code_short];
422
  }
423
  wp_localize_script('events-manager','EM', apply_filters('em_wp_localize_script', $em_localized_js));
424
  }
@@ -495,9 +462,11 @@ function em_init(){
495
  }
496
  }
497
  if( $wp_rewrite->using_permalinks() ){
498
- define('EM_RSS_URI', trailingslashit(home_url()). EM_POST_TYPE_EVENT_SLUG.'/feed/'); //RSS PAGE URI via CPT archives page
 
499
  }else{
500
- define('EM_RSS_URI', em_add_get_params(home_url(), array('post_type'=>EM_POST_TYPE_EVENT, 'feed'=>'rss2'))); //RSS PAGE URI
 
501
  }
502
  $EM_Mailer = new EM_Mailer();
503
  //Upgrade/Install Routine
@@ -577,71 +546,71 @@ function em_load_event(){
577
  add_action('template_redirect', 'em_load_event', 1);
578
  if(is_admin()){ add_action('init', 'em_load_event', 2); }
579
 
580
- /**
581
- * Catches various option names and returns a network-wide option value instead of the individual blog option. Uses the magc __call function to catch unprecedented names.
582
- * @author marcus
583
- *
584
- */
585
- class EM_MS_Globals {
586
- function __construct(){ add_action( 'init', array(&$this, 'add_filters'), 1); }
587
- function add_filters(){
588
- foreach( $this->get_globals() as $global_option_name ){
589
- add_filter('pre_option_'.$global_option_name, array(&$this, 'pre_option_'.$global_option_name), 1,1);
590
- add_filter('pre_update_option_'.$global_option_name, array(&$this, 'pre_update_option_'.$global_option_name), 1,2);
591
- add_action('add_option_'.$global_option_name, array(&$this, 'add_option_'.$global_option_name), 1,1);
592
- }
593
- //if we're in MS Global mode, the categories option currently resides in the main blog, consider moving this to a network setting in the future
594
- if( EM_MS_GLOBAL ){
595
- add_filter('pre_option_dbem_categories_enabled', array(&$this, 'pre_option_dbem_categories_enabled'), 1,1);
596
- }
597
- }
598
- function get_globals(){
599
- $globals = array(
600
- //multisite settings
601
- 'dbem_ms_global_table', 'dbem_ms_global_caps',
602
- 'dbem_ms_global_events', 'dbem_ms_global_events_links','dbem_ms_events_slug',
603
- 'dbem_ms_global_locations','dbem_ms_global_locations_links','dbem_ms_locations_slug','dbem_ms_mainblog_locations',
604
- //mail
605
- 'dbem_rsvp_mail_port', 'dbem_mail_sender_address', 'dbem_smtp_password', 'dbem_smtp_username','dbem_smtp_host', 'dbem_mail_sender_name','dbem_smtp_html','dbem_smtp_html_br','dbem_smtp_host','dbem_rsvp_mail_send_method','dbem_rsvp_mail_SMTPAuth',
606
- //images
607
- 'dbem_image_max_width','dbem_image_max_height','dbem_image_max_size'
608
- );
609
- if( EM_MS_GLOBAL ){
610
- $globals[] = 'dbem_taxonomy_category_slug';
611
  }
612
- return apply_filters('em_ms_globals', $globals);
613
- }
614
- function __call($filter_name, $value){
615
- if( strstr($filter_name, 'pre_option_') !== false ){
616
- $return = get_site_option(str_replace('pre_option_','',$filter_name));
617
- return $return;
618
- }elseif( strstr($filter_name, 'pre_update_option_') !== false ){
619
- if( is_super_admin() ){
620
- update_site_option(str_replace('pre_update_option_','',$filter_name), $value[0]);
 
 
 
 
621
  }
622
- return $value[1];
623
- }elseif( strstr($filter_name, 'add_option_') !== false ){
624
- if( is_super_admin() ){
625
- update_site_option(str_replace('add_option_','',$filter_name),$value[0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
626
  }
627
- delete_option(str_replace('pre_option_','',$filter_name));
628
- return;
 
 
 
 
 
 
 
 
 
 
629
  }
630
- return $value[0];
631
- }
632
- /**
633
- * Returns the option of the main site in this network, this function should only be fired if in MS Global mode.
634
- * @param int $value
635
- * @return int
636
- */
637
- function pre_option_dbem_categories_enabled($value){
638
- if( !is_main_site() ){ //only alter value if not on main site already
639
- $value = get_blog_option(get_current_site()->blog_id, 'dbem_categories_enabled') ? 1:0; //return a number since false will not circumvent pre_option_ filter
640
- }
641
- return $value;
642
  }
643
- }
644
- if( is_multisite() ){
645
  global $EM_MS_Globals;
646
  $EM_MS_Globals = new EM_MS_Globals();
647
  }
1
  <?php
2
  /*
3
  Plugin Name: Events Manager
4
+ Version: 5.7
5
  Plugin URI: http://wp-events-plugin.com
6
  Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
  Author: Marcus Sykes
28
  */
29
 
30
  // Setting constants
31
+ define('EM_VERSION', 5.7); //self expanatory
32
  define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
  define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
  define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
185
  public static function init(){
186
  if( is_admin() ){
187
  //Scripts and Styles
188
+ add_action('admin_enqueue_scripts', array('EM_Scripts_and_Styles','admin_enqueue'));
 
 
 
 
189
  }else{
190
  add_action('wp_enqueue_scripts', array('EM_Scripts_and_Styles','public_enqueue'));
191
  }
203
  'edit-bookings' => get_option('dbem_edit_bookings_page'),
204
  'my-bookings' => get_option('dbem_my_bookings_page')
205
  );
206
+ $pages = apply_filters('em_scripts_and_styles_public_enqueue_pages', $pages);
207
  $obj = $wp_query->get_queried_object();
208
  $obj_id = 0;
209
  if( is_home() ){
219
  if( is_page($pages) ){
220
  $script_deps['jquery'] = 'jquery';
221
  }
222
+ if( (!empty($pages['events']) && is_page($pages['events']) && get_option('dbem_events_page_search_form')) || get_option('dbem_js_limit_search') === '0' || in_array($obj_id, explode(',', get_option('dbem_js_limit_search'))) ){
223
  //events page only needs datepickers
224
  $script_deps['jquery-ui-core'] = 'jquery-ui-core';
225
  $script_deps['jquery-ui-datepicker'] = 'jquery-ui-datepicker';
291
  }
292
  }
293
 
294
+ public static function admin_enqueue( $hook_suffix = false ){
295
+ if( $hook_suffix == 'post.php' || (!empty($_GET['page']) && substr($_GET['page'],0,14) == 'events-manager') || (!empty($_GET['post_type']) && in_array($_GET['post_type'], array(EM_POST_TYPE_EVENT,EM_POST_TYPE_LOCATION,'event-recurring'))) ){
296
+ wp_enqueue_script('events-manager', plugins_url('includes/js/events-manager.js',__FILE__), array('jquery', 'jquery-ui-core','jquery-ui-widget','jquery-ui-position','jquery-ui-sortable','jquery-ui-datepicker','jquery-ui-autocomplete','jquery-ui-dialog'), EM_VERSION);
297
+ do_action('em_enqueue_admin_scripts');
298
+ wp_enqueue_style('events-manager-admin', plugins_url('includes/css/events_manager_admin.css',__FILE__), array(), EM_VERSION);
299
+ do_action('em_enqueue_admin_styles');
300
+ self::localize_script();
301
+ }
302
  }
303
 
304
  /**
320
  'is_ssl' => is_ssl(),
321
  );
322
  //maps api key
323
+ if( get_option('dbem_gmap_is_active') ){
324
+ if( get_option('dbem_google_maps_browser_key') ){
325
+ $em_localized_js['google_maps_api'] = get_option('dbem_google_maps_browser_key');
326
+ }
327
+ if( get_option('dbem_google_maps_styles') ){
328
+ $em_localized_js['google_maps_styles'] = json_decode(get_option('dbem_google_maps_styles'));
329
+ }
330
  }
331
  //debug mode
332
  if( defined('WP_DEBUG') && WP_DEBUG ) $em_localized_js['ui_css'] = plugins_url('includes/css/jquery-ui.css', __FILE__);
333
  //booking-specific stuff
334
  if( get_option('dbem_rsvp_enabled') ){
335
+ $offset = defined('EM_BOOKING_MSG_JS_OFFSET') ? EM_BOOKING_MSG_JS_OFFSET : 30;
336
  $em_localized_js = array_merge($em_localized_js, array(
337
  'bookingInProgress' => __('Please wait while the booking is being submitted.','events-manager'),
338
  'tickets_save' => __('Save Ticket','events-manager'),
340
  'bookings_export_save' => __('Export Bookings','events-manager'),
341
  'bookings_settings_save' => __('Save Settings','events-manager'),
342
  'booking_delete' => __("Are you sure you want to delete?",'events-manager'),
343
+ 'booking_offset' => $offset,
344
  //booking button
345
  'bb_full' => get_option('dbem_booking_button_msg_full'),
346
  'bb_book' => get_option('dbem_booking_button_msg_book'),
360
  //logged in messages that visitors shouldn't need to see
361
  if( is_user_logged_in() || is_page(get_option('dbem_edit_events_page')) ){
362
  if( get_option('dbem_recurrence_enabled') ){
363
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'edit' && !empty($_REQUEST['event_id'])){
364
+ $em_localized_js['event_reschedule_warning'] = __('Are you sure you want to continue?', 'events-manager') .PHP_EOL.PHP_EOL;
365
+ $em_localized_js['event_reschedule_warning'] .= __('Modifications to event times will cause all recurrences of this event to be deleted and recreated, previous bookings will be deleted.', 'events-manager');
366
+ $em_localized_js['event_recurrence_overwrite'] = __('Are you sure you want to continue?', 'events-manager') .PHP_EOL.PHP_EOL;
367
+ $em_localized_js['event_recurrence_overwrite'] .= __( 'Modifications to recurring events will be applied to all recurrences and will overwrite any changes made to those individual event recurrences.', 'events-manager') .PHP_EOL.PHP_EOL;
368
+ $em_localized_js['event_recurrence_overwrite'] .= __( 'Bookings to individual event recurrences will be preserved if event times and ticket settings are not modified.', 'events-manager');
369
+ $em_localized_js['event_recurrence_bookings'] = __('Are you sure you want to continue?', 'events-manager') .PHP_EOL.PHP_EOL;
370
+ $em_localized_js['event_recurrence_bookings'] .= __('Modifications to event tickets will cause all bookings to individual recurrences of this event to be deleted.', 'events-manager');
371
+ }
372
  $em_localized_js['event_detach_warning'] = __('Are you sure you want to detach this event? By doing so, this event will be independent of the recurring set of events.', 'events-manager');
373
  $delete_text = ( !EMPTY_TRASH_DAYS ) ? __('This cannot be undone.','events-manager'):__('All events will be moved to trash.','events-manager');
374
  $em_localized_js['delete_recurrence_warning'] = __('Are you sure you want to delete all recurrences of this event?', 'events-manager').' '.$delete_text;
386
  $em_localized_js['close_text'] = __('Collapse All','events-manager');
387
  $em_localized_js['open_text'] = __('Expand All','events-manager');
388
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  }
390
  wp_localize_script('events-manager','EM', apply_filters('em_wp_localize_script', $em_localized_js));
391
  }
462
  }
463
  }
464
  if( $wp_rewrite->using_permalinks() ){
465
+ $rss_url = trailingslashit(home_url()). EM_POST_TYPE_EVENT_SLUG.'/feed/';
466
+ define('EM_RSS_URI', $rss_url); //RSS PAGE URI via CPT archives page
467
  }else{
468
+ $rss_url = em_add_get_params(home_url(), array('post_type'=>EM_POST_TYPE_EVENT, 'feed'=>'rss2'));
469
+ define('EM_RSS_URI', $rss_url); //RSS PAGE URI
470
  }
471
  $EM_Mailer = new EM_Mailer();
472
  //Upgrade/Install Routine
546
  add_action('template_redirect', 'em_load_event', 1);
547
  if(is_admin()){ add_action('init', 'em_load_event', 2); }
548
 
549
+ if( is_multisite() ){
550
+ /**
551
+ * Catches various option names and returns a network-wide option value instead of the individual blog option. Uses the magc __call function to catch unprecedented names.
552
+ * @author marcus
553
+ *
554
+ */
555
+ class EM_MS_Globals {
556
+ function __construct(){ add_action( 'init', array(&$this, 'add_filters'), 1); }
557
+ function add_filters(){
558
+ foreach( $this->get_globals() as $global_option_name ){
559
+ add_filter('pre_option_'.$global_option_name, array(&$this, 'pre_option_'.$global_option_name), 1,1);
560
+ add_filter('pre_update_option_'.$global_option_name, array(&$this, 'pre_update_option_'.$global_option_name), 1,2);
561
+ add_action('add_option_'.$global_option_name, array(&$this, 'add_option_'.$global_option_name), 1,1);
562
+ }
563
+ //if we're in MS Global mode, the categories option currently resides in the main blog, consider moving this to a network setting in the future
564
+ if( EM_MS_GLOBAL ){
565
+ add_filter('pre_option_dbem_categories_enabled', array(&$this, 'pre_option_dbem_categories_enabled'), 1,1);
566
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  }
568
+ function get_globals(){
569
+ $globals = array(
570
+ //multisite settings
571
+ 'dbem_ms_global_table', 'dbem_ms_global_caps',
572
+ 'dbem_ms_global_events', 'dbem_ms_global_events_links','dbem_ms_events_slug',
573
+ 'dbem_ms_global_locations','dbem_ms_global_locations_links','dbem_ms_locations_slug','dbem_ms_mainblog_locations',
574
+ //mail
575
+ 'dbem_rsvp_mail_port', 'dbem_mail_sender_address', 'dbem_smtp_password', 'dbem_smtp_username','dbem_smtp_host', 'dbem_mail_sender_name','dbem_smtp_html','dbem_smtp_html_br','dbem_smtp_host','dbem_rsvp_mail_send_method','dbem_rsvp_mail_SMTPAuth',
576
+ //images
577
+ 'dbem_image_max_width','dbem_image_max_height','dbem_image_max_size'
578
+ );
579
+ if( EM_MS_GLOBAL ){
580
+ $globals[] = 'dbem_taxonomy_category_slug';
581
  }
582
+ return apply_filters('em_ms_globals', $globals);
583
+ }
584
+ function __call($filter_name, $value){
585
+ if( strstr($filter_name, 'pre_option_') !== false ){
586
+ $return = get_site_option(str_replace('pre_option_','',$filter_name));
587
+ return $return;
588
+ }elseif( strstr($filter_name, 'pre_update_option_') !== false ){
589
+ if( is_super_admin() ){
590
+ update_site_option(str_replace('pre_update_option_','',$filter_name), $value[0]);
591
+ }
592
+ return $value[1];
593
+ }elseif( strstr($filter_name, 'add_option_') !== false ){
594
+ if( is_super_admin() ){
595
+ update_site_option(str_replace('add_option_','',$filter_name),$value[0]);
596
+ }
597
+ delete_option(str_replace('pre_option_','',$filter_name));
598
+ return;
599
  }
600
+ return $value[0];
601
+ }
602
+ /**
603
+ * Returns the option of the main site in this network, this function should only be fired if in MS Global mode.
604
+ * @param int $value
605
+ * @return int
606
+ */
607
+ function pre_option_dbem_categories_enabled($value){
608
+ if( !is_main_site() ){ //only alter value if not on main site already
609
+ $value = get_blog_option(get_current_site()->blog_id, 'dbem_categories_enabled') ? 1:0; //return a number since false will not circumvent pre_option_ filter
610
+ }
611
+ return $value;
612
  }
 
 
 
 
 
 
 
 
 
 
 
 
613
  }
 
 
614
  global $EM_MS_Globals;
615
  $EM_MS_Globals = new EM_MS_Globals();
616
  }
includes/css/events_manager.css CHANGED
@@ -6,7 +6,7 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
6
  .em-warning p { margin:10px 0px !important; padding:0px; color:#333 }
7
  .em-warning-errors { background-color:#FFEBE8; border:1px solid #C00; }
8
  .em-warning-confirms { background-color:#f1fff0; border:1px solid #a8d144; }
9
- a.em-button { float:right; padding:5px 10px; margin:5px; background:#EEE; color:#333; border:1px solid #CCC; border-radius:3px; display:inline-block; text-decoration:none; }
10
  a.em-button:hover { text-decoration:none; }
11
 
12
  /* Search Form */
@@ -17,7 +17,7 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
17
  div.em-search.css-search label { display:inline; }
18
  div.em-search.css-search div { display:block; }
19
  div.css-search input, div.css-search select, div.css-search option, div.css-search div, div.css-search span, div.css-search button {
20
- width:auto; height:auto; margin:0; padding:0; float:none; display:auto; font-size:14px; /* reset everything */
21
  }
22
  div.css-search input, div.css-search select { padding:5px; }
23
  div.css-search { background:#fff; border:1px solid #dedede; border-radius:3px; padding:5px; min-height:40px; position:relative; -moz-border-radius:3px; -webkit-border-radius:3px; }
@@ -25,7 +25,7 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
25
  div.css-search.has-advanced div.em-search-main { padding-bottom:8px; border-bottom:1px solid #dedede; }
26
  div.css-search div.em-search-main div { display:inline; }
27
  div.css-search div.em-search-field { padding:5px 0px; }
28
- div.css-search input.em-search-text, div.css-search input.em-search-geo { width:90%; font-size:16px; line-height:16px; padding:8px; border:none; outline:none !important; color:#666; text-overflow: ellipsis; }
29
  div.css-search div.em-search-geo { margin:0px 0px 0px 5px; padding-left:20px; background:url(../images/search-geo.png) 0px 3px no-repeat; }
30
  div.css-search div.em-search-text { margin:0px 0px 0px 5px; padding-left:20px; background:url(../images/search-mag-ico.png) 0px 4px no-repeat; }
31
  /* Placeholder text in main section */
@@ -110,6 +110,7 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
110
 
111
  /* Events Admin */
112
  #em-wrapper #posts-filter .subsubsub .current { font-weight:bold; }
 
113
 
114
  /* Add Event Form */
115
  #event-form h4 { margin:25px 0px 15px 0px; font-weight:bold; }
@@ -122,6 +123,12 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
122
  #event-form #event-name { width:80%; padding:2px; }
123
  #event-form .event-extra-details { margin-top:20px; }
124
  #event-form .event-extra-details select { vertical-align:top; }
 
 
 
 
 
 
125
  /*Tickets*/
126
  #event-rsvp-box { margin:10px; }
127
  #event-rsvp-options label { font-weight:bold; }
6
  .em-warning p { margin:10px 0px !important; padding:0px; color:#333 }
7
  .em-warning-errors { background-color:#FFEBE8; border:1px solid #C00; }
8
  .em-warning-confirms { background-color:#f1fff0; border:1px solid #a8d144; }
9
+ a.em-button { padding:5px 10px; margin:5px; background:#EEE; color:#333; border:1px solid #CCC; border-radius:3px; display:inline-block; text-decoration:none; }
10
  a.em-button:hover { text-decoration:none; }
11
 
12
  /* Search Form */
17
  div.em-search.css-search label { display:inline; }
18
  div.em-search.css-search div { display:block; }
19
  div.css-search input, div.css-search select, div.css-search option, div.css-search div, div.css-search span, div.css-search button {
20
+ width:auto; height:auto; margin:0; padding:0; float:none; display:inline-block; font-size:14px; /* reset everything */
21
  }
22
  div.css-search input, div.css-search select { padding:5px; }
23
  div.css-search { background:#fff; border:1px solid #dedede; border-radius:3px; padding:5px; min-height:40px; position:relative; -moz-border-radius:3px; -webkit-border-radius:3px; }
25
  div.css-search.has-advanced div.em-search-main { padding-bottom:8px; border-bottom:1px solid #dedede; }
26
  div.css-search div.em-search-main div { display:inline; }
27
  div.css-search div.em-search-field { padding:5px 0px; }
28
+ div.css-search input.em-search-text, div.css-search input.em-search-geo { width:90%; font-size:16px; line-height:16px; padding:8px; border:none; outline:none !important; color:#666; text-overflow: ellipsis; display:inline-block; }
29
  div.css-search div.em-search-geo { margin:0px 0px 0px 5px; padding-left:20px; background:url(../images/search-geo.png) 0px 3px no-repeat; }
30
  div.css-search div.em-search-text { margin:0px 0px 0px 5px; padding-left:20px; background:url(../images/search-mag-ico.png) 0px 4px no-repeat; }
31
  /* Placeholder text in main section */
110
 
111
  /* Events Admin */
112
  #em-wrapper #posts-filter .subsubsub .current { font-weight:bold; }
113
+ #em-wrapper .em-events-admin-list .em-button, #em-wrapper .em-events-admin-list .em-button { float:right; }
114
 
115
  /* Add Event Form */
116
  #event-form h4 { margin:25px 0px 15px 0px; font-weight:bold; }
123
  #event-form #event-name { width:80%; padding:2px; }
124
  #event-form .event-extra-details { margin-top:20px; }
125
  #event-form .event-extra-details select { vertical-align:top; }
126
+ /* Recurring Event Rescheduling */
127
+ #event-form .reschedule-hidden, #post .reschedule-hidden { display:none; visibility:hidden; }
128
+ #event-form .em-recurrence-reschedule, #post .em-recurrence-reschedule { padding:15px 20px; border-left: 4px solid #ffa500; }
129
+ #event-form .em-recurrence-reschedule h4, #post .em-recurrence-reschedule h4 { margin-top:0px; }
130
+ #event-form .recurrence-reschedule-warning, #post .recurrence-reschedule-warning { margin-bottom:25px; color:#c45500; }
131
+ #event-form .recurrence-reschedule-warning p, #post .recurrence-reschedule-warning p { margin-top:0px; font-size:14px; }
132
  /*Tickets*/
133
  #event-rsvp-box { margin:10px; }
134
  #event-rsvp-options label { font-weight:bold; }
includes/css/events_manager_admin.css CHANGED
@@ -23,7 +23,14 @@ table.events-table tr.past { background:#E4E4E4 }
23
  table.events-table .category { color:#888; }
24
 
25
  /* Events Add Page */
 
26
  #event-form #event-name, #location-form, #location-name { margin: 2px 0 7px; padding: 6px 5px; width: 98%; }
 
 
 
 
 
 
27
  /*Locations*/
28
  div.em-location-data table { float:left; margin:0px 15px 0px 0px; }
29
  /* Location form */
23
  table.events-table .category { color:#888; }
24
 
25
  /* Events Add Page */
26
+ #post-body .misc-pub-post-status.misc-event-duplicate-link:before { content: "\f132"; }
27
  #event-form #event-name, #location-form, #location-name { margin: 2px 0 7px; padding: 6px 5px; width: 98%; }
28
+ /* Recurring Event Rescheduling */
29
+ #event-form .reschedule-hidden, #post .reschedule-hidden { display:none; visibility:hidden; }
30
+ #event-form .em-recurrence-reschedule, #post .em-recurrence-reschedule { padding:15px 20px; border-left: 4px solid #ffa500; }
31
+ #event-form .em-recurrence-reschedule h4, #post .em-recurrence-reschedule h4 { margin-top:0px; }
32
+ #event-form .recurrence-reschedule-warning, #post .recurrence-reschedule-warning { margin-bottom:25px; color:#c45500; }
33
+ #event-form .recurrence-reschedule-warning p, #post .recurrence-reschedule-warning p { margin-top:0px; font-size:14px; }
34
  /*Locations*/
35
  div.em-location-data table { float:left; margin:0px 15px 0px 0px; }
36
  /* Location form */
includes/js/bookingsform.js CHANGED
@@ -26,6 +26,9 @@ $(document).on('submit', '.em-booking-form', function(e){
26
  em_booking_form.hide();
27
  $('.em-booking-login').hide();
28
  $(document).trigger('em_booking_success', [response]);
 
 
 
29
  }else{
30
  if( response.errors != null ){
31
  if( $.isArray(response.errors) && response.errors.length > 0 ){
@@ -42,7 +45,7 @@ $(document).on('submit', '.em-booking-form', function(e){
42
  }
43
  $(document).trigger('em_booking_error', [response]);
44
  }
45
- $('html, body').animate({ scrollTop: em_booking_form.parent().offset().top - 30 }); //sends user back to top of form
46
  em_booking_doing_ajax = false;
47
  //run extra actions after showing the message here
48
  if( response.gateway != null ){
26
  em_booking_form.hide();
27
  $('.em-booking-login').hide();
28
  $(document).trigger('em_booking_success', [response]);
29
+ if( response.redirect ){ //custom redirect hook
30
+ window.location.href = response.redirect;
31
+ }
32
  }else{
33
  if( response.errors != null ){
34
  if( $.isArray(response.errors) && response.errors.length > 0 ){
45
  }
46
  $(document).trigger('em_booking_error', [response]);
47
  }
48
+ $('html, body').animate({ scrollTop: $('.em-booking-message').offset().top - EM.booking_offset }); //sends user back to top of form
49
  em_booking_doing_ajax = false;
50
  //run extra actions after showing the message here
51
  if( response.gateway != null ){
includes/js/categories-admin.js CHANGED
@@ -1,68 +1,69 @@
1
  jQuery(document).ready(function($) {
2
  //color picker
3
- var f = $.farbtastic('#picker');
4
- var p = $('#picker').css('opacity', 0.25);
5
- var selected;
6
- $('.colorwell').each(function () { f.linkTo(this); $(this).css('opacity', 0.75); }).focus(function() {
7
- if (selected) { $(selected).css('opacity', 0.75).removeClass('colorwell-selected'); }
8
- f.linkTo(this);
9
- p.css('opacity', 1);
10
- $(selected = this).css('opacity', 1).addClass('colorwell-selected');
11
- });
12
- $('.colorwell').click(function() {
13
  var position = $(selected = this).position();
14
- $('#picker').css('left', (position.left + 150) );
15
- $('#picker').css('top', position.top);
16
- $('#picker').fadeIn(900,function (){
17
- $('#picker').css('display', 'inline');
18
- });
19
  }).blur(function(){
20
- $('#picker').fadeOut('fast');
21
- $('#picker').css('display', 'none');
22
- });
23
-
24
- //image button upload - thanks Brad Williams, Ozh Richard, and Justin Tadlock!
25
- var formfield = null;
26
-
27
- $('#upload_image_button').click(function() {
28
- $('html').addClass('Image');
29
- formfield = $('#category-image').attr('name');
30
- tb_show('', 'media-upload.php?type=image&TB_iframe=true');
31
- return false;
32
  });
33
-
34
- // user inserts file into post. only run custom if user started process using the above process
35
- // window.send_to_editor(html) is how wp would normally handle the received data
36
- window.original_send_to_editor = window.send_to_editor;
37
- window.send_to_editor = function(html){
38
- var fileurl;
39
-
40
- if (formfield != null) {
41
- var img = $(html).find('img');
42
- fileurl = img.attr('src');
43
- $('#category-image').val(fileurl);
44
- $('#category-image-img img').attr('src', fileurl);
45
- //get the attachment id if possible
46
- var fileIdClass = img.attr('class');
47
- var pattern = /wp\-image\-[0-9]+/;
48
- var fileIdFull = pattern.exec(fileIdClass);
49
- if( fileIdFull[0] != '' ){
50
- var fileId = fileIdFull[0].replace('wp-image-','');
51
- $('#category-image-id').val(fileId);
52
- }
53
-
54
- tb_remove();
55
 
56
- $('html').removeClass('Image');
57
- formfield = null;
58
- } else {
59
- window.original_send_to_editor(html);
 
 
 
 
 
60
  }
61
- };
62
-
63
- //detach/remove image from category for saving
64
- $('#delete_image_button').on('click', function(){
65
- $('#category-image-img').remove();
66
- $('#category-image, #category-image-id').val('');
67
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  });
1
  jQuery(document).ready(function($) {
2
  //color picker
3
+ var f = $.farbtastic('#picker');
4
+ var p = $('#picker').css('opacity', 0.25);
5
+ var selected;
6
+ $('.colorwell').each(function () { f.linkTo(this); $(this).css('opacity', 0.75); }).focus(function() {
7
+ if (selected) { $(selected).css('opacity', 0.75).removeClass('colorwell-selected'); }
8
+ f.linkTo(this);
9
+ p.css('opacity', 1);
10
+ $(selected = this).css('opacity', 1).addClass('colorwell-selected');
11
+ });
12
+ $('.colorwell').click(function() {
13
  var position = $(selected = this).position();
14
+ $('#picker').css('left', (position.left + 150) );
15
+ $('#picker').css('top', position.top);
16
+ $('#picker').fadeIn(900,function (){
17
+ $('#picker').css('display', 'inline');
18
+ });
19
  }).blur(function(){
20
+ $('#picker').fadeOut('fast');
21
+ $('#picker').css('display', 'none');
 
 
 
 
 
 
 
 
 
 
22
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
+ //Event Taxonomy Image Picker
25
+ var frame;
26
+ // ADD IMAGE LINK
27
+ $('#event-tax-image .upload-img-button').on( 'click', function( event ){
28
+ event.preventDefault();
29
+ // If the media frame already exists, reopen it.
30
+ if ( frame ) {
31
+ frame.open();
32
+ return;
33
  }
34
+ // Create a new media frame
35
+ frame = wp.media({
36
+ library: {
37
+ type: 'image'
38
+ },
39
+ title: wp.media.view.l10n.chooseImage,
40
+ multiple: false // Set to true to allow multiple files to be selected
41
+ });
42
+ // When an image is selected in the media frame...
43
+ frame.on( 'select', function() {
44
+ // Get media attachment details from the frame state
45
+ var attachment = frame.state().get('selection').first().toJSON();
46
+ // Send the attachment URL to our custom image input field.
47
+ $( '#event-tax-image .img-container').empty().append( '<img src="'+attachment.url+'" alt="" style="max-width:100%;"/>' );
48
+ // Send the attachment id to our hidden input
49
+ $( '#event-tax-image .img-id' ).val( attachment.id );
50
+ $( '#event-tax-image .img-url' ).val( attachment.url );
51
+ // Unhide the remove image link
52
+ $( '#event-tax-image .delete-img-button').show();
53
+ });
54
+ // Finally, open the modal on click
55
+ frame.open();
56
+ });
57
+ // DELETE IMAGE LINK
58
+ $( '#event-tax-image .delete-img-button').on( 'click', function( event ){
59
+ event.preventDefault();
60
+ // Clear out the preview image
61
+ $( '#event-tax-image .img-container').html( '' );
62
+ // Un-hide the add image link
63
+ $(this).hide();
64
+ // Delete the image id from the hidden input
65
+ $( '#event-tax-image .img-id' ).val( '' );
66
+ $( '#event-tax-image .img-url' ).val( '' );
67
+ });
68
+
69
  });
includes/js/events-manager.js CHANGED
@@ -175,6 +175,37 @@ jQuery(document).ready( function($){
175
  el.closest('.event-form-image, .location-form-image').find('#event-image-img, #location-image-img').show();
176
  }
177
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  //Tickets & Bookings
179
  if( $("#em-tickets-form").length > 0 ){
180
  //Enable/Disable Bookings
@@ -557,9 +588,6 @@ jQuery(document).ready( function($){
557
 
558
  //Datepicker
559
  if( $('.em-date-single, .em-date-range, #em-date-start').length > 0 ){
560
- if( EM.locale != 'en' && EM.locale_data ){
561
- $.datepicker.setDefaults(EM.locale_data);
562
- }
563
  load_ui_css = true;
564
  em_setup_datepicker('body');
565
  }
@@ -827,9 +855,9 @@ function em_maps_load(){
827
  script.id = "google-maps";
828
  var proto = (EM.is_ssl) ? 'https:' : 'http:';
829
  if( typeof EM.google_maps_api !== 'undefined' ){
830
- script.src = proto + '//maps.google.com/maps/api/js?v=3.24&libraries=places&callback=em_maps&key='+EM.google_maps_api;
831
  }else{
832
- script.src = proto + '//maps.google.com/maps/api/js?v=3.24&libraries=places&callback=em_maps';
833
  }
834
  document.body.appendChild(script);
835
  }else if( typeof google === 'object' && typeof google.maps === 'object' && !em_maps_loaded ){
@@ -851,47 +879,41 @@ function em_maps_load_locations(el){
851
  if(data.length > 0){
852
  //define default options and allow option for extension via event triggers
853
  var map_options = { mapTypeId: google.maps.MapTypeId.ROADMAP };
 
 
854
  jQuery(document).triggerHandler('em_maps_locations_map_options', map_options);
855
  var marker_options = {};
856
  jQuery(document).triggerHandler('em_maps_location_marker_options', marker_options);
857
 
858
  maps[map_id] = new google.maps.Map(el[0], map_options);
859
  maps_markers[map_id] = [];
 
 
860
 
861
- var minLatLngArr = [0,0];
862
- var maxLatLngArr = [0,0];
863
-
864
- for (var i = 0; i < data.length; i++) {
865
- if( !(data[i].location_latitude == 0 && data[i].location_longitude == 0) ){
866
- var latitude = parseFloat( data[i].location_latitude );
867
- var longitude = parseFloat( data[i].location_longitude );
868
- var location = new google.maps.LatLng( latitude, longitude );
869
  //extend the default marker options
870
  jQuery.extend(marker_options, {
871
- position: location,
872
  map: maps[map_id]
873
  })
874
  var marker = new google.maps.Marker(marker_options);
875
  maps_markers[map_id].push(marker);
876
- marker.setTitle(data[i].location_name);
877
- var myContent = '<div class="em-map-balloon"><div id="em-map-balloon-'+map_id+'" class="em-map-balloon-content">'+ data[i].location_balloon +'</div></div>';
878
  em_map_infobox(marker, myContent, maps[map_id]);
879
-
880
- //Get min and max long/lats
881
- minLatLngArr[0] = (latitude < minLatLngArr[0] || i == 0) ? latitude : minLatLngArr[0];
882
- minLatLngArr[1] = (longitude < minLatLngArr[1] || i == 0) ? longitude : minLatLngArr[1];
883
- maxLatLngArr[0] = (latitude > maxLatLngArr[0] || i == 0) ? latitude : maxLatLngArr[0];
884
- maxLatLngArr[1] = (longitude > maxLatLngArr[1] || i == 0) ? longitude : maxLatLngArr[1];
885
  }
886
- }
887
  // Zoom in to the bounds
888
- var minLatLng = new google.maps.LatLng(minLatLngArr[0],minLatLngArr[1]);
889
- var maxLatLng = new google.maps.LatLng(maxLatLngArr[0],maxLatLngArr[1]);
890
- var bounds = new google.maps.LatLngBounds(minLatLng,maxLatLng);
891
  maps[map_id].fitBounds(bounds);
892
 
893
  //Call a hook if exists
894
- jQuery(document).triggerHandler('em_maps_locations_hook', [maps[map_id], data, map_id]);
895
  }else{
896
  el.children().first().html('No locations found');
897
  jQuery(document).triggerHandler('em_maps_locations_hook_not_found', [el]);
@@ -903,14 +925,22 @@ function em_maps_load_location(el){
903
  var map_id = el.attr('id').replace('em-location-map-','');
904
  em_LatLng = new google.maps.LatLng( jQuery('#em-location-map-coords-'+map_id+' .lat').text(), jQuery('#em-location-map-coords-'+map_id+' .lng').text());
905
  //extend map and markers via event triggers
 
906
  var map_options = {
907
  zoom: 14,
908
  center: em_LatLng,
909
  mapTypeId: google.maps.MapTypeId.ROADMAP,
910
- mapTypeControl: false
 
911
  };
 
 
912
  jQuery(document).triggerHandler('em_maps_location_map_options', map_options);
913
  maps[map_id] = new google.maps.Map( document.getElementById('em-location-map-'+map_id), map_options);
 
 
 
 
914
  var marker_options = {
915
  position: em_LatLng,
916
  map: maps[map_id]
@@ -1033,12 +1063,20 @@ function em_maps() {
1033
  //Load map
1034
  if(jQuery('#em-map').length > 0){
1035
  var em_LatLng = new google.maps.LatLng(0, 0);
1036
- map = new google.maps.Map( document.getElementById('em-map'), {
1037
- zoom: 14,
1038
- center: em_LatLng,
1039
- mapTypeId: google.maps.MapTypeId.ROADMAP,
1040
- mapTypeControl: false
1041
- });
 
 
 
 
 
 
 
 
1042
  var marker = new google.maps.Marker({
1043
  position: em_LatLng,
1044
  map: map,
175
  el.closest('.event-form-image, .location-form-image').find('#event-image-img, #location-image-img').show();
176
  }
177
  });
178
+ //Event Editor
179
+ //Recurrence Warnings
180
+ $('#event-form.em-event-admin-recurring').submit( function(event){
181
+ var form = $(this);
182
+ if( form.find('input[name="event_reschedule"]').first().val() == 1 ){
183
+ var warning_text = EM.event_reschedule_warning;
184
+ }else if( form.find('input[name="event_recreate_tickets"]').first().val() == 1 ){
185
+ var warning_text = EM.event_recurrence_bookings;
186
+ }else{
187
+ var warning_text = EM.event_recurrence_overwrite;
188
+ }
189
+ confirmation = confirm(warning_text);
190
+ if( confirmation == false ){
191
+ event.preventDefault();
192
+ }
193
+ });
194
+ //Buttons for recurrence warnings within event editor forms
195
+ $('.em-reschedule-trigger').click(function(e){
196
+ e.preventDefault();
197
+ var trigger = $(this);
198
+ trigger.closest('.em-recurrence-reschedule').find(trigger.data('target')).removeClass('reschedule-hidden');
199
+ trigger.siblings('.em-reschedule-value').val(1);
200
+ trigger.addClass('reschedule-hidden').siblings('a').removeClass('reschedule-hidden');
201
+ });
202
+ $('.em-reschedule-cancel').click(function(e){
203
+ e.preventDefault();
204
+ var trigger = $(this);
205
+ trigger.closest('.em-recurrence-reschedule').find(trigger.data('target')).addClass('reschedule-hidden');
206
+ trigger.siblings('.em-reschedule-value').val(0);
207
+ trigger.addClass('reschedule-hidden').siblings('a').removeClass('reschedule-hidden');
208
+ });
209
  //Tickets & Bookings
210
  if( $("#em-tickets-form").length > 0 ){
211
  //Enable/Disable Bookings
588
 
589
  //Datepicker
590
  if( $('.em-date-single, .em-date-range, #em-date-start').length > 0 ){
 
 
 
591
  load_ui_css = true;
592
  em_setup_datepicker('body');
593
  }
855
  script.id = "google-maps";
856
  var proto = (EM.is_ssl) ? 'https:' : 'http:';
857
  if( typeof EM.google_maps_api !== 'undefined' ){
858
+ script.src = proto + '//maps.google.com/maps/api/js?v=3&libraries=places&callback=em_maps&key='+EM.google_maps_api;
859
  }else{
860
+ script.src = proto + '//maps.google.com/maps/api/js?v=3&libraries=places&callback=em_maps';
861
  }
862
  document.body.appendChild(script);
863
  }else if( typeof google === 'object' && typeof google.maps === 'object' && !em_maps_loaded ){
879
  if(data.length > 0){
880
  //define default options and allow option for extension via event triggers
881
  var map_options = { mapTypeId: google.maps.MapTypeId.ROADMAP };
882
+ if( typeof EM.google_map_id_styles == 'object' && typeof EM.google_map_id_styles[map_id] !== 'undefined' ){ console.log(EM.google_map_id_styles[map_id]); map_options.styles = EM.google_map_id_styles[map_id]; }
883
+ else if( typeof EM.google_maps_styles !== 'undefined' ){ map_options.styles = EM.google_maps_styles; }
884
  jQuery(document).triggerHandler('em_maps_locations_map_options', map_options);
885
  var marker_options = {};
886
  jQuery(document).triggerHandler('em_maps_location_marker_options', marker_options);
887
 
888
  maps[map_id] = new google.maps.Map(el[0], map_options);
889
  maps_markers[map_id] = [];
890
+
891
+ var bounds = new google.maps.LatLngBounds();
892
 
893
+ jQuery.map( data, function( location, i ){
894
+ if( !(location.location_latitude == 0 && location.location_longitude == 0) ){
895
+ var latitude = parseFloat( location.location_latitude );
896
+ var longitude = parseFloat( location.location_longitude );
897
+ var location_position = new google.maps.LatLng( latitude, longitude );
 
 
 
898
  //extend the default marker options
899
  jQuery.extend(marker_options, {
900
+ position: location_position,
901
  map: maps[map_id]
902
  })
903
  var marker = new google.maps.Marker(marker_options);
904
  maps_markers[map_id].push(marker);
905
+ marker.setTitle(location.location_name);
906
+ var myContent = '<div class="em-map-balloon"><div id="em-map-balloon-'+map_id+'" class="em-map-balloon-content">'+ location.location_balloon +'</div></div>';
907
  em_map_infobox(marker, myContent, maps[map_id]);
908
+ //extend bounds
909
+ bounds.extend(new google.maps.LatLng(latitude,longitude))
 
 
 
 
910
  }
911
+ });
912
  // Zoom in to the bounds
 
 
 
913
  maps[map_id].fitBounds(bounds);
914
 
915
  //Call a hook if exists
916
+ jQuery(document).triggerHandler('em_maps_locations_hook', [maps[map_id], data, map_id, maps_markers[map_id]]);
917
  }else{
918
  el.children().first().html('No locations found');
919
  jQuery(document).triggerHandler('em_maps_locations_hook_not_found', [el]);
925
  var map_id = el.attr('id').replace('em-location-map-','');
926
  em_LatLng = new google.maps.LatLng( jQuery('#em-location-map-coords-'+map_id+' .lat').text(), jQuery('#em-location-map-coords-'+map_id+' .lng').text());
927
  //extend map and markers via event triggers
928
+ var is_touch = 'ontouchstart' in window || navigator.maxTouchPoints;
929
  var map_options = {
930
  zoom: 14,
931
  center: em_LatLng,
932
  mapTypeId: google.maps.MapTypeId.ROADMAP,
933
+ mapTypeControl: false,
934
+ scrollwheel: is_touch
935
  };
936
+ if( typeof EM.google_map_id_styles == 'object' && typeof EM.google_map_id_styles[map_id] !== 'undefined' ){ console.log(EM.google_map_id_styles[map_id]); map_options.styles = EM.google_map_id_styles[map_id]; }
937
+ else if( typeof EM.google_maps_styles !== 'undefined' ){ map_options.styles = EM.google_maps_styles; }
938
  jQuery(document).triggerHandler('em_maps_location_map_options', map_options);
939
  maps[map_id] = new google.maps.Map( document.getElementById('em-location-map-'+map_id), map_options);
940
+ if( !is_touch ){
941
+ maps[map_id].addListener('click', function(){ maps[map_id].setOptions({ scrollwheel:true }); });
942
+ maps[map_id].addListener('mouseout', function(){ maps[map_id].setOptions({ scrollwheel:false }); });
943
+ }
944
  var marker_options = {
945
  position: em_LatLng,
946
  map: maps[map_id]
1063
  //Load map
1064
  if(jQuery('#em-map').length > 0){
1065
  var em_LatLng = new google.maps.LatLng(0, 0);
1066
+ var is_touch = 'ontouchstart' in window || navigator.maxTouchPoints;
1067
+ var map_options = {
1068
+ zoom: 14,
1069
+ center: em_LatLng,
1070
+ mapTypeId: google.maps.MapTypeId.ROADMAP,
1071
+ mapTypeControl: false,
1072
+ scrollwheel: is_touch
1073
+ };
1074
+ if( typeof EM.google_maps_styles !== 'undefined' ){ map_options.styles = EM.google_maps_styles; }
1075
+ map = new google.maps.Map( document.getElementById('em-map'), map_options);
1076
+ if( !is_touch ){
1077
+ map.addListener('click', function(){ map.setOptions({ scrollwheel:true }); });
1078
+ map.addListener('mouseout', function(){ map.setOptions({ scrollwheel:false }); });
1079
+ }
1080
  var marker = new google.maps.Marker({
1081
  position: em_LatLng,
1082
  map: map,
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
  === Events Manager ===
2
  Contributors: netweblogic, nutsmuggler
3
  Donate link: http://wp-events-plugin.com
4
- Tags: bookings, buddypress, calendar, event, event management, events, google maps, maps, locations, registration, registration, tickets
5
  Text Domain: events-manager
6
  Requires at least: 3.5
7
- Tested up to: 4.7
8
- Stable tag: 5.6.6.1
9
 
10
  Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
 
@@ -99,6 +99,73 @@ See our [FAQ](http://wp-events-plugin.com/documentation/faq/) page, which is upd
99
  6. Manage attendees with various booking reports
100
 
101
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  = 5.6.6.1 =
103
  * fixed search forms disappearing in latest update when Styling Options for search forms are turned off (props @factchecker)
104
 
1
  === Events Manager ===
2
  Contributors: netweblogic, nutsmuggler
3
  Donate link: http://wp-events-plugin.com
4
+ Tags: bookings, calendar, tickets, events, buddypress, event management, google maps, maps, locations, registration
5
  Text Domain: events-manager
6
  Requires at least: 3.5
7
+ Tested up to: 4.7.4
8
+ Stable tag: 5.7
9
 
10
  Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
 
99
  6. Manage attendees with various booking reports
100
 
101
  == Changelog ==
102
+ = 5.7 =
103
+ * added em_events_admin_args filter allowing modification of event search arguments
104
+ * removed jQuery UI localize files for the datepicker in favor of WP 4.6 native localization
105
+ * fixed potential bug where modified ticket spaces aren't saving correctly when editing a booking
106
+ * added is_user_attendee, not_user_attendee and variations of both proceeding with _0 or another number representing booking status
107
+ * added edit/view shortcut links for each event location in events list admin area
108
+ * fixed conflict with BuddyPress Group Extras and potentially other plugins when one or more of our list pages aren't assigned a page (e.g. locations page) resulting in a blank page
109
+ * fixed ical feed not serving wrapped content lines,
110
+ * added EM_ICAL_APPLE_STRUCT constant to allow ommitting of X-APPLE-STRUCTURED-LOCATION lines in the ical file
111
+ * fixed formatting issues with ical X-APPLE-STRUCTURED-LOCATION line
112
+ * fixed instances where locations or events automatically creating a post slug if needed when published
113
+ * fixed location image display issues on other blogs when in MultiSite Global mode
114
+ * corrected and updated docs
115
+ * fixed switch_to_blog() being used instead of restore_current_blog() in buddypress/bp-em-core.php (props @mikegillihan)
116
+ * fixed search form CSS inconsistencies for Twenty Seventeen theme
117
+ * fixed locations map breaking when provided with object versions of JSON response (such as with WPML compat add-on)
118
+ * updated maps google library to always use most stable version
119
+ * fixed issues when creating MS Global Events programmatically
120
+ * moved some logic out of the EM_Event->output() function into their own function for easier future use in templates
121
+ * fixed google calendar links not including full location address
122
+ * added an import/export settings option in settings page
123
+ * added ability to use post_id in calendar shortcode and PHP functions
124
+ * added has_location and no_location to event search attributes
125
+ * added [events_map] shortcode which searches by event rather than location
126
+ * changed behaviour of zooming when mouse is over a map so a click is required first to avoid catching whilst scrolling the page
127
+ * fixed all errors and warnings for PHP 7 and others highlighted by PHP Compatibility Checker plugin
128
+ * added decimal parameter to get_tax_rate functions which allows fixing of minor PHP warning when tax is set to 0
129
+ * fixed filter typos and _get_sql positions in EM_Bookings::get() and EM_Locations::get()
130
+ * removed unnecessary storage of _post_id in postmeta for recurring events
131
+ * fixed bug where tickets aren't deleted with event
132
+ * fixed incompatibility with WP Fastest Cache for bookings on cached pages
133
+ * fixed EM_Categories not removing categories if none are selected when resaving an event
134
+ * added em_get_events_admin_url() function
135
+ * added major improvements to recurring events including ability to duplicate templates and also make changes without deleting previous recurrences,
136
+ * changed various event editor templates to accommodate new recurring event changes
137
+ * changed no-user bookings feature to not require a dummy user
138
+ * changed no-user bookings so previous bookings appear correctly regardless of whether NU bookings is enabled or disabled
139
+ * tweaked PHP Mail sending method to go through WP PHPMailer class for better encoding
140
+ * fixed overly aggressive filtering of get_the_date and get_the_time filters (kudos @boonebgorges)
141
+ * fixed missing map markers array variable to be supplied in JS hook em_maps_locations_hook (kudos @raruto)
142
+ * changed booking discount php functions into price adjustment functions which will now allow for surcharges to be implemented
143
+ * fixed guest submissions with bookings enabled producing false permission errors instead of a confirmation
144
+ * fixed/updated media uploader JS interface for category image
145
+ * added more booking price filters to individual functions
146
+ * fixed minor nuance where upcoming events scope filter not selectable on mobile view
147
+ * fixed JS not being loaded automatically on events list when JS performance loading enabled
148
+ * fixed regex matching preventing use of a #_LATT attribute within an #_ATT default value bracket
149
+ * fixed confirmation message not showing for event duplication
150
+ * added duplicate shortcut link on dashboard edit event page
151
+ * fixed issues with selection of Sunday on monthly recurrences and the generated pattern summary
152
+ * changed/fixed events_list_grouped using date format for sub-section titles from settings page if no date_format supplied regardless of grouping mode
153
+ * added em_scripts_and_styles_public_enqueue_pages filter for custom pages to automatically include EM script/styles when limiting for performance is enabled
154
+ * fixed PHP non-object notices on certain non-EM dashboard pages
155
+ * changed booking form scrolling JS to scroll to booking message feedback element and added EM_BOOKING_MSG_JS_OFFSET constant to allow adjusting the offset in wp-config.php
156
+ * fixed redirect link on booking form login not taking into account SSL pages
157
+ * added #_EVENTEXCERPTCUT to allow cutting of both excerpts and post content
158
+ * changed event all day times to start at 00:00:00 and end at 23:59:59 when saved (kudos @cliffpaulick)
159
+ * changed default search form settings behaviour to ignore country filtering if search option is not enabled
160
+ * fixed scheduled recurring events not publishing recurrences
161
+ * improved google maps JS for multiple events/locations maps and auto-zooming of included locations (kudos @benklocek)
162
+ * fixed minor php warning on user profile page
163
+ * tweaked booking JS to allow a redirect variable passed on with a successful response
164
+ * fixed 'Bookings' header not being translated when formats are disabled and booking form is added just after content
165
+ * fixed ticket availability status indicator showing false to admins when ticket is restricted to guests
166
+ * added get_total_paid function (mainly for hooking purposes in Pro add-ons)
167
+ * added support for Google Maps styles via services like the Google Maps Style Wizard or Snazzy Maps
168
+
169
  = 5.6.6.1 =
170
  * fixed search forms disappearing in latest update when Styling Options for search forms are turned off (props @factchecker)
171
 
templates/buddypress/group-events.php CHANGED
@@ -28,7 +28,7 @@
28
  // TODO localize
29
  echo "<p>". __( 'No Events','events-manager') ."</p>";
30
  } else {
31
- foreach( $EM_Events as $EM_Event ) break;
32
  $can_edit_events = $EM_Event->can_manage('edit_events','edit_others_events');
33
  ?>
34
  <table class="widefat events-table">
28
  // TODO localize
29
  echo "<p>". __( 'No Events','events-manager') ."</p>";
30
  } else {
31
+ foreach( $EM_Events as $EM_Event ){ break; }
32
  $can_edit_events = $EM_Event->can_manage('edit_events','edit_others_events');
33
  ?>
34
  <table class="widefat events-table">
templates/emails/bookingsummary.php CHANGED
@@ -32,8 +32,17 @@ $price_summary = $EM_Booking->get_price_summary_array();
32
  (<?php echo $discount_summary['name']; ?>) : -<?php echo $discount_summary['amount']; ?>
33
 
34
  <?php endforeach; ?>
 
 
 
 
 
 
 
35
 
 
36
  <?php endif; ?>
 
37
  <?php if( !empty($price_summary['taxes']['amount']) ): ?>
38
  <?php _e('Taxes','events-manager'); ?> ( <?php echo $price_summary['taxes']['rate']; ?> ) : <?php echo $price_summary['taxes']['amount']; ?>
39
  <?php endif; ?>
@@ -45,6 +54,15 @@ $price_summary = $EM_Booking->get_price_summary_array();
45
  <?php foreach( $price_summary['discounts_post_tax'] as $discount_summary ): ?>
46
  <?php echo $discount_summary['name']; ?> : -<?php echo $discount_summary['amount']; ?>
47
 
 
 
 
 
 
 
 
 
 
48
  <?php endforeach; ?>
49
  <?php endif; ?>
50
 
32
  (<?php echo $discount_summary['name']; ?>) : -<?php echo $discount_summary['amount']; ?>
33
 
34
  <?php endforeach; ?>
35
+ <?php endif; ?>
36
+ <?php if( count($price_summary['surcharges_pre_tax']) > 0 ): ?>
37
+
38
+ <?php _e('Surcharges Before Taxes','events-manager'); ?>
39
+
40
+ <?php foreach( $price_summary['surcharges_pre_tax'] as $surcharge_summary ): ?>
41
+ (<?php echo $surcharge_summary['name']; ?>) : <?php echo $surcharge_summary['amount']; ?>
42
 
43
+ <?php endforeach; ?>
44
  <?php endif; ?>
45
+
46
  <?php if( !empty($price_summary['taxes']['amount']) ): ?>
47
  <?php _e('Taxes','events-manager'); ?> ( <?php echo $price_summary['taxes']['rate']; ?> ) : <?php echo $price_summary['taxes']['amount']; ?>
48
  <?php endif; ?>
54
  <?php foreach( $price_summary['discounts_post_tax'] as $discount_summary ): ?>
55
  <?php echo $discount_summary['name']; ?> : -<?php echo $discount_summary['amount']; ?>
56
 
57
+ <?php endforeach; ?>
58
+ <?php endif; ?>
59
+ <?php if( count($price_summary['surcharges_post_tax']) > 0 ): ?>
60
+
61
+ <?php _e('Surcharges (After Taxes)','events-manager'); ?>
62
+
63
+ <?php foreach( $price_summary['surcharges_post_tax'] as $surcharge_summary ): ?>
64
+ <?php echo $surcharge_summary['name']; ?> : <?php echo $surcharge_summary['amount']; ?>
65
+
66
  <?php endforeach; ?>
67
  <?php endif; ?>
68
 
templates/forms/bookingform/login.php CHANGED
@@ -17,7 +17,7 @@
17
  <?php do_action('login_form'); ?>
18
  <input type="submit" name="wp-submit" id="em_wp-submit" value="<?php esc_html_e('Log In', 'events-manager'); ?>" tabindex="100" />
19
  <input name="rememberme" type="checkbox" id="em_rememberme" value="forever" /> <label><?php esc_html_e( 'Remember Me','events-manager') ?></label>
20
- <input type="hidden" name="redirect_to" value="<?php echo esc_url($_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']); ?>#em-booking" />
21
  <br />
22
  <?php
23
  //Signup Links
17
  <?php do_action('login_form'); ?>
18
  <input type="submit" name="wp-submit" id="em_wp-submit" value="<?php esc_html_e('Log In', 'events-manager'); ?>" tabindex="100" />
19
  <input name="rememberme" type="checkbox" id="em_rememberme" value="forever" /> <label><?php esc_html_e( 'Remember Me','events-manager') ?></label>
20
+ <input type="hidden" name="redirect_to" value="<?php echo esc_url( get_site_url(false, $_SERVER['REQUEST_URI']) ); ?>#em-booking" />
21
  <br />
22
  <?php
23
  //Signup Links
templates/forms/event-editor.php CHANGED
@@ -23,7 +23,7 @@ if( !empty($_REQUEST['success']) ){
23
  if(!get_option('dbem_events_form_reshow')) return false;
24
  }
25
  ?>
26
- <form enctype='multipart/form-data' id="event-form" method="post" action="<?php echo esc_url(add_query_arg(array('success'=>null))); ?>">
27
  <div class="wrap">
28
  <?php do_action('em_front_event_form_header'); ?>
29
  <?php if(get_option('dbem_events_anonymous_submissions') && !is_user_logged_in()): ?>
23
  if(!get_option('dbem_events_form_reshow')) return false;
24
  }
25
  ?>
26
+ <form enctype='multipart/form-data' id="event-form" class="em-event-admin-editor <?php if( $EM_Event->is_recurring() ) echo 'em-event-admin-recurring' ?>" method="post" action="<?php echo esc_url(add_query_arg(array('success'=>null))); ?>">
27
  <div class="wrap">
28
  <?php do_action('em_front_event_form_header'); ?>
29
  <?php if(get_option('dbem_events_anonymous_submissions') && !is_user_logged_in()): ?>
templates/forms/event/bookings.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
  global $EM_Event, $post, $allowedposttags, $EM_Ticket, $col_count;
 
3
  ?>
4
  <div id="event-rsvp-box">
5
  <input id="event-rsvp" name='event_rsvp' value='1' type='checkbox' <?php echo ($EM_Event->event_rsvp) ? 'checked="checked"' : ''; ?> />
@@ -7,117 +8,154 @@ global $EM_Event, $post, $allowedposttags, $EM_Ticket, $col_count;
7
  <?php _e ( 'Enable registration for this event', 'events-manager')?>
8
  </div>
9
  <div id="event-rsvp-options" style="<?php echo ($EM_Event->event_rsvp) ? '':'display:none;' ?>">
10
- <?php do_action('em_events_admin_bookings_header', $EM_Event); ?>
11
- <div id="em-tickets-form">
12
- <?php
13
  //get tickets here and if there are none, create a blank ticket
14
  $EM_Tickets = $EM_Event->get_tickets();
15
  if( count($EM_Tickets->tickets) == 0 ){
16
  $EM_Tickets->tickets[] = new EM_Ticket();
17
  $delete_temp_ticket = true;
18
  }
19
- if( get_option('dbem_bookings_tickets_single') && count($EM_Tickets->tickets) == 1 ){
20
- ?>
21
- <h4><?php esc_html_e('Ticket Options','events-manager'); ?></h4>
22
  <?php
23
- $col_count = 1;
24
- $EM_Ticket = $EM_Tickets->get_first();
25
- include( em_locate_template('forms/ticket-form.php') ); //in future we'll be accessing forms/event/bookings-ticket-form.php directly
26
- }else{
27
- ?>
28
- <h4><?php esc_html_e('Tickets','events-manager'); ?></h4>
29
- <p><em><?php esc_html_e('You can have single or multiple tickets, where certain tickets become available under certain conditions, e.g. early bookings, group discounts, maximum bookings per ticket, etc.', 'events-manager'); ?> <?php esc_html_e('Basic HTML is allowed in ticket labels and descriptions.','events-manager'); ?></em></p>
30
- <table class="form-table">
31
- <thead>
32
- <tr valign="top">
33
- <th colspan="2"><?php esc_html_e('Ticket Name','events-manager'); ?></th>
34
- <th><?php esc_html_e('Price','events-manager'); ?></th>
35
- <th><?php esc_html_e('Min/Max','events-manager'); ?></th>
36
- <th><?php esc_html_e('Start/End','events-manager'); ?></th>
37
- <th><?php esc_html_e('Avail. Spaces','events-manager'); ?></th>
38
- <th><?php esc_html_e('Booked Spaces','events-manager'); ?></th>
39
- <th>&nbsp;</th>
40
- </tr>
41
- </thead>
42
- <tfoot>
43
- <tr valign="top">
44
- <td colspan="8">
45
- <a href="#" id="em-tickets-add"><?php esc_html_e('Add new ticket','events-manager'); ?></a>
46
- </td>
47
- </tr>
48
- </tfoot>
49
  <?php
50
- $EM_Ticket = new EM_Ticket();
51
- $EM_Ticket->event_id = $EM_Event->event_id;
52
- array_unshift($EM_Tickets->tickets, $EM_Ticket); //prepend template ticket for JS
53
- $col_count = 0;
54
- foreach( $EM_Tickets->tickets as $EM_Ticket){
55
- /* @var $EM_Ticket EM_Ticket */
56
- ?>
57
- <tbody id="em-ticket-<?php echo $col_count ?>" <?php if( $col_count == 0 ) echo 'style="display:none;"' ?>>
58
- <tr class="em-tickets-row">
59
- <td class="ticket-status"><span class="<?php if($EM_Ticket->ticket_id && $EM_Ticket->is_available()){ echo 'ticket_on'; }elseif($EM_Ticket->ticket_id > 0){ echo 'ticket_off'; }else{ echo 'ticket_new'; } ?>"></span></td>
60
- <td class="ticket-name">
61
- <span class="ticket_name"><?php if($EM_Ticket->ticket_members) echo '* ';?><?php echo wp_kses_data($EM_Ticket->ticket_name); ?></span>
62
- <div class="ticket_description"><?php echo wp_kses($EM_Ticket->ticket_description,$allowedposttags); ?></div>
63
- <div class="ticket-actions">
64
- <a href="#" class="ticket-actions-edit"><?php esc_html_e('Edit','events-manager'); ?></a>
65
- <?php if( count($EM_Ticket->get_bookings()->bookings) == 0 ): ?>
66
- | <a href="<?php bloginfo('wpurl'); ?>/wp-load.php" class="ticket-actions-delete"><?php esc_html_e('Delete','events-manager'); ?></a>
67
- <?php else: ?>
68
- | <a href="<?php echo esc_url(add_query_arg('ticket_id', $EM_Ticket->ticket_id, $EM_Event->get_bookings_url())); ?>"><?php esc_html_e('View Bookings','events-manager'); ?></a>
69
- <?php endif; ?>
70
- </div>
71
- </td>
72
- <td class="ticket-price">
73
- <span class="ticket_price"><?php echo ($EM_Ticket->ticket_price) ? esc_html($EM_Ticket->get_price_precise()) : esc_html__('Free','events-manager'); ?></span>
74
- </td>
75
- <td class="ticket-limit">
76
- <span class="ticket_min">
77
- <?php echo ( !empty($EM_Ticket->ticket_min) ) ? esc_html($EM_Ticket->ticket_min):'-'; ?>
78
- </span> /
79
- <span class="ticket_max"><?php echo ( !empty($EM_Ticket->ticket_max) ) ? esc_html($EM_Ticket->ticket_max):'-'; ?></span>
80
- </td>
81
- <td class="ticket-time">
82
- <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date(get_option('dbem_date_format'), $EM_Ticket->start_timestamp):''; ?></span>
83
- <span class="ticket_start_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['start_days']; ?></span>
84
- <span class="ticket_start_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
85
- <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?></span>
86
- <br />
87
- <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date(get_option('dbem_date_format'), $EM_Ticket->end_timestamp):''; ?></span>
88
- <span class="ticket_end_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['end_days']; ?></span>
89
- <span class="ticket_end_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
90
- <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?></span>
91
- </td>
92
- <td class="ticket-qty">
93
- <span class="ticket_available_spaces"><?php echo $EM_Ticket->get_available_spaces(); ?></span>/
94
- <span class="ticket_spaces"><?php echo $EM_Ticket->get_spaces() ? $EM_Ticket->get_spaces() : '-'; ?></span>
95
- </td>
96
- <td class="ticket-booked-spaces">
97
- <span class="ticket_booked_spaces"><?php echo $EM_Ticket->get_booked_spaces(); ?></span>
98
- </td>
99
- <?php do_action('em_event_edit_ticket_td', $EM_Ticket); ?>
100
- </tr>
101
- <tr class="em-tickets-row-form" style="display:none;">
102
- <td colspan="<?php echo apply_filters('em_event_edit_ticket_td_colspan', 7); ?>">
103
- <?php include( em_locate_template('forms/event/bookings-ticket-form.php')); ?>
104
- <div class="em-ticket-form-actions">
105
- <button type="button" class="ticket-actions-edited"><?php esc_html_e('Close Ticket Editor','events-manager')?></button>
106
- </div>
107
- </td>
108
- </tr>
109
- </tbody>
110
- <?php
111
- $col_count++;
112
- }
113
- array_shift($EM_Tickets->tickets);
114
  ?>
115
- </table>
116
- <?php
117
- }
118
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  </div>
120
- <div id="em-booking-options">
121
  <?php if( !get_option('dbem_bookings_tickets_single') || count($EM_Ticket->get_event()->get_tickets()->tickets) > 1 ): ?>
122
  <h4><?php esc_html_e('Event Options','events-manager'); ?></h4>
123
  <p>
1
  <?php
2
  global $EM_Event, $post, $allowedposttags, $EM_Ticket, $col_count;
3
+ $reschedule_warnings = !empty($EM_Event->event_id) && $EM_Event->is_recurring() && $EM_Event->event_rsvp;
4
  ?>
5
  <div id="event-rsvp-box">
6
  <input id="event-rsvp" name='event_rsvp' value='1' type='checkbox' <?php echo ($EM_Event->event_rsvp) ? 'checked="checked"' : ''; ?> />
8
  <?php _e ( 'Enable registration for this event', 'events-manager')?>
9
  </div>
10
  <div id="event-rsvp-options" style="<?php echo ($EM_Event->event_rsvp) ? '':'display:none;' ?>">
11
+ <?php
12
+ do_action('em_events_admin_bookings_header', $EM_Event);
 
13
  //get tickets here and if there are none, create a blank ticket
14
  $EM_Tickets = $EM_Event->get_tickets();
15
  if( count($EM_Tickets->tickets) == 0 ){
16
  $EM_Tickets->tickets[] = new EM_Ticket();
17
  $delete_temp_ticket = true;
18
  }
19
+ ?>
20
+ <div class="event-rsvp-options-tickets <?php if( $reschedule_warnings ) echo 'em-recurrence-reschedule'; ?>">
 
21
  <?php
22
+ //output title
23
+ if( get_option('dbem_bookings_tickets_single') && count($EM_Tickets->tickets) == 1 ){
24
+ ?>
25
+ <h4><?php esc_html_e('Ticket Options','events-manager'); ?></h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  <?php
27
+ }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  ?>
29
+ <h4><?php esc_html_e('Tickets','events-manager'); ?></h4>
30
+ <?php
31
+ }
32
+ //If this event is a recurring template, we need to warn the user that editing tickets will delete previous bookings
33
+ if( $reschedule_warnings ){
34
+ ?>
35
+ <div class="recurrence-reschedule-warning">
36
+ <p><?php esc_html_e( 'Modifications to event tickets will cause all bookings to individual recurrences of this event to be deleted.', 'events-manager'); ?></p>
37
+ <p>
38
+ <a href="<?php echo esc_url( add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url()) ); ?>">
39
+ <strong><?php esc_html_e('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'); ?></strong>
40
+ </a>
41
+ </p>
42
+ </div>
43
+ <?php
44
+ }
45
+ ?>
46
+ <div id="em-tickets-form" class="em-tickets-form<?php if( $reschedule_warnings && empty($_REQUEST['recreate_tickets']) ) echo ' reschedule-hidden' ?>">
47
+ <?php
48
+ //output ticket options
49
+ if( get_option('dbem_bookings_tickets_single') && count($EM_Tickets->tickets) == 1 ){
50
+ $col_count = 1;
51
+ $EM_Ticket = $EM_Tickets->get_first();
52
+ include( em_locate_template('forms/ticket-form.php') ); //in future we'll be accessing forms/event/bookings-ticket-form.php directly
53
+ }else{
54
+ ?>
55
+ <p><em><?php esc_html_e('You can have single or multiple tickets, where certain tickets become available under certain conditions, e.g. early bookings, group discounts, maximum bookings per ticket, etc.', 'events-manager'); ?> <?php esc_html_e('Basic HTML is allowed in ticket labels and descriptions.','events-manager'); ?></em></p>
56
+ <table class="form-table">
57
+ <thead>
58
+ <tr valign="top">
59
+ <th colspan="2"><?php esc_html_e('Ticket Name','events-manager'); ?></th>
60
+ <th><?php esc_html_e('Price','events-manager'); ?></th>
61
+ <th><?php esc_html_e('Min/Max','events-manager'); ?></th>
62
+ <th><?php esc_html_e('Start/End','events-manager'); ?></th>
63
+ <th><?php esc_html_e('Avail. Spaces','events-manager'); ?></th>
64
+ <th><?php esc_html_e('Booked Spaces','events-manager'); ?></th>
65
+ <th>&nbsp;</th>
66
+ </tr>
67
+ </thead>
68
+ <tfoot>
69
+ <tr valign="top">
70
+ <td colspan="8">
71
+ <a href="#" id="em-tickets-add"><?php esc_html_e('Add new ticket','events-manager'); ?></a>
72
+ </td>
73
+ </tr>
74
+ </tfoot>
75
+ <?php
76
+ $EM_Ticket = new EM_Ticket();
77
+ $EM_Ticket->event_id = $EM_Event->event_id;
78
+ array_unshift($EM_Tickets->tickets, $EM_Ticket); //prepend template ticket for JS
79
+ $col_count = 0;
80
+ foreach( $EM_Tickets->tickets as $EM_Ticket){
81
+ /* @var $EM_Ticket EM_Ticket */
82
+ ?>
83
+ <tbody id="em-ticket-<?php echo $col_count ?>" <?php if( $col_count == 0 ) echo 'style="display:none;"' ?>>
84
+ <tr class="em-tickets-row">
85
+ <td class="ticket-status"><span class="<?php if($EM_Ticket->ticket_id && $EM_Ticket->is_available(true, true)){ echo 'ticket_on'; }elseif($EM_Ticket->ticket_id > 0){ echo 'ticket_off'; }else{ echo 'ticket_new'; } ?>"></span></td>
86
+ <td class="ticket-name">
87
+ <span class="ticket_name"><?php if($EM_Ticket->ticket_members) echo '* ';?><?php echo wp_kses_data($EM_Ticket->ticket_name); ?></span>
88
+ <div class="ticket_description"><?php echo wp_kses($EM_Ticket->ticket_description,$allowedposttags); ?></div>
89
+ <div class="ticket-actions">
90
+ <a href="#" class="ticket-actions-edit"><?php esc_html_e('Edit','events-manager'); ?></a>
91
+ <?php if( count($EM_Ticket->get_bookings()->bookings) == 0 ): ?>
92
+ | <a href="<?php bloginfo('wpurl'); ?>/wp-load.php" class="ticket-actions-delete"><?php esc_html_e('Delete','events-manager'); ?></a>
93
+ <?php else: ?>
94
+ | <a href="<?php echo esc_url(add_query_arg('ticket_id', $EM_Ticket->ticket_id, $EM_Event->get_bookings_url())); ?>"><?php esc_html_e('View Bookings','events-manager'); ?></a>
95
+ <?php endif; ?>
96
+ </div>
97
+ </td>
98
+ <td class="ticket-price">
99
+ <span class="ticket_price"><?php echo ($EM_Ticket->ticket_price) ? esc_html($EM_Ticket->get_price_precise()) : esc_html__('Free','events-manager'); ?></span>
100
+ </td>
101
+ <td class="ticket-limit">
102
+ <span class="ticket_min">
103
+ <?php echo ( !empty($EM_Ticket->ticket_min) ) ? esc_html($EM_Ticket->ticket_min):'-'; ?>
104
+ </span> /
105
+ <span class="ticket_max"><?php echo ( !empty($EM_Ticket->ticket_max) ) ? esc_html($EM_Ticket->ticket_max):'-'; ?></span>
106
+ </td>
107
+ <td class="ticket-time">
108
+ <span class="ticket_start ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date(get_option('dbem_date_format'), $EM_Ticket->start_timestamp):''; ?></span>
109
+ <span class="ticket_start_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['start_days']; ?></span>
110
+ <span class="ticket_start_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['start_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
111
+ <span class="ticket_start_time"><?php echo ( !empty($EM_Ticket->ticket_start) ) ? date( em_get_hour_format(), $EM_Ticket->start_timestamp):''; ?></span>
112
+ <br />
113
+ <span class="ticket_end ticket-dates-from-normal"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date(get_option('dbem_date_format'), $EM_Ticket->end_timestamp):''; ?></span>
114
+ <span class="ticket_end_recurring_days ticket-dates-from-recurring"><?php if( !empty($EM_Ticket->ticket_meta['recurrences']) ) echo $EM_Ticket->ticket_meta['recurrences']['end_days']; ?></span>
115
+ <span class="ticket_end_recurring_days_text ticket-dates-from-recurring <?php if( !empty($EM_Ticket->ticket_meta['recurrences']) && !is_numeric($EM_Ticket->ticket_meta['recurrences']['end_days']) ) echo 'hidden'; ?>"><?php _e('day(s)','events-manager'); ?></span>
116
+ <span class="ticket_end_time"><?php echo ( !empty($EM_Ticket->ticket_end) ) ? date( em_get_hour_format(), $EM_Ticket->end_timestamp):''; ?></span>
117
+ </td>
118
+ <td class="ticket-qty">
119
+ <span class="ticket_available_spaces"><?php echo $EM_Ticket->get_available_spaces(); ?></span>/
120
+ <span class="ticket_spaces"><?php echo $EM_Ticket->get_spaces() ? $EM_Ticket->get_spaces() : '-'; ?></span>
121
+ </td>
122
+ <td class="ticket-booked-spaces">
123
+ <span class="ticket_booked_spaces"><?php echo $EM_Ticket->get_booked_spaces(); ?></span>
124
+ </td>
125
+ <?php do_action('em_event_edit_ticket_td', $EM_Ticket); ?>
126
+ </tr>
127
+ <tr class="em-tickets-row-form" style="display:none;">
128
+ <td colspan="<?php echo apply_filters('em_event_edit_ticket_td_colspan', 7); ?>">
129
+ <?php include( em_locate_template('forms/event/bookings-ticket-form.php')); ?>
130
+ <div class="em-ticket-form-actions">
131
+ <button type="button" class="ticket-actions-edited"><?php esc_html_e('Close Ticket Editor','events-manager')?></button>
132
+ </div>
133
+ </td>
134
+ </tr>
135
+ </tbody>
136
+ <?php
137
+ $col_count++;
138
+ }
139
+ array_shift($EM_Tickets->tickets);
140
+ ?>
141
+ </table>
142
+ <?php
143
+ }
144
+ ?>
145
+ </div>
146
+ <?php if( $reschedule_warnings ): //If this event is a recurring template, we need to warn the user that editing tickets will delete previous bookings ?>
147
+ <div class="recurrence-reschedule-buttons">
148
+ <a href="<?php echo esc_url(add_query_arg('recreate_tickets', null)); ?>" class="button-secondary em-button em-reschedule-cancel<?php if( empty($_REQUEST['recreate_tickets']) ) echo ' reschedule-hidden'; ?>" data-target=".em-tickets-form">
149
+ <?php esc_html_e('Cancel Ticket Recreation', 'events-manager'); ?>
150
+ </a>
151
+ <a href="<?php echo esc_url(add_query_arg('recreate_tickets', '1')); ?>" class="em-reschedule-trigger em-button button-secondary<?php if( !empty($_REQUEST['recreate_tickets']) ) echo ' reschedule-hidden'; ?>" data-target=".em-tickets-form">
152
+ <?php esc_html_e('Modify Recurring Event Tickets ', 'events-manager'); ?>
153
+ </a>
154
+ <input type="hidden" name="event_recreate_tickets" class="em-reschedule-value" value="<?php echo empty($_REQUEST['recreate_tickets']) ? 0:1 ?>" />
155
+ </div>
156
+ <?php endif; ?>
157
  </div>
158
+ <div id="em-booking-options" class="em-booking-options">
159
  <?php if( !get_option('dbem_bookings_tickets_single') || count($EM_Ticket->get_event()->get_tickets()->tickets) > 1 ): ?>
160
  <h4><?php esc_html_e('Event Options','events-manager'); ?></h4>
161
  <p>
templates/forms/event/recurring-when.php CHANGED
@@ -3,11 +3,23 @@
3
  global $EM_Event;
4
  $days_names = em_get_days_names();
5
  $hours_format = em_get_hour_format();
 
6
  ?>
7
- <?php if( is_admin() ): ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_event'); ?>" /><?php endif; ?>
8
  <!-- START recurrence postbox -->
9
- <div id="em-form-recurrence" class="event-form-recurrence event-form-when">
10
- <?php _e ( 'This event repeats', 'events-manager'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
11
  <select id="recurrence-frequency" name="recurrence_freq">
12
  <?php
13
  $freq_options = array ("daily" => __ ( 'Daily', 'events-manager'), "weekly" => __ ( 'Weekly', 'events-manager'), "monthly" => __ ( 'Monthly', 'events-manager'), 'yearly' => __('Yearly','events-manager') );
@@ -24,55 +36,56 @@ $hours_format = em_get_hour_format();
24
  <span class='interval-desc' id="interval-monthly-plural"><?php _e ( 'months on the', 'events-manager')?></span>
25
  <span class='interval-desc' id="interval-yearly-singular"><?php _e ( 'year', 'events-manager')?></span>
26
  <span class='interval-desc' id="interval-yearly-plural"><?php _e ( 'years', 'events-manager') ?></span>
27
- <p class="alternate-selector" id="weekly-selector">
28
- <?php
29
- $saved_bydays = ($EM_Event->is_recurring() && $EM_Event->recurrence_byday != '' ) ? explode ( ",", $EM_Event->recurrence_byday ) : array();
30
- em_checkbox_items ( 'recurrence_bydays[]', $days_names, $saved_bydays );
31
- ?>
32
- </p>
33
- <p class="alternate-selector" id="monthly-selector" style="display:inline;">
34
- <select id="monthly-modifier" name="recurrence_byweekno">
35
  <?php
36
- $weekno_options = array ("1" => __ ( 'first', 'events-manager'), '2' => __ ( 'second', 'events-manager'), '3' => __ ( 'third', 'events-manager'), '4' => __ ( 'fourth', 'events-manager'), '-1' => __ ( 'last', 'events-manager') );
37
- em_option_items ( $weekno_options, $EM_Event->recurrence_byweekno );
38
  ?>
39
- </select>
40
- <select id="recurrence-weekday" name="recurrence_byday">
41
- <?php em_option_items ( $days_names, $EM_Event->recurrence_byday ); ?>
42
- </select>
43
- <?php _e('of each month','events-manager'); ?>
44
- &nbsp;
45
- </p>
46
- <div class="event-form-recurrence-when">
47
- <p class="em-date-range">
48
- <?php _e ( 'Recurrences span from ', 'events-manager'); ?>
49
- <input class="em-date-start em-date-input-loc" type="text" />
50
- <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" />
51
- <?php _e('to','events-manager'); ?>
52
- <input class="em-date-end em-date-input-loc" type="text" />
53
- <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" />
54
- </p>
55
- <p class="em-time-range">
56
- <?php _e('Events start from','events-manager'); ?>
57
- <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" />
58
- <?php _e('to','events-manager'); ?>
59
- <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" />
60
- <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
61
  </p>
62
- <p class="em-duration-range">
63
- <?php echo sprintf(__('Each event spans %s day(s)','events-manager'), '<input id="end-days" type="text" size="8" maxlength="8" name="recurrence_days" value="'. $EM_Event->recurrence_days .'" />'); ?>
 
 
 
 
 
 
 
 
 
 
64
  </p>
65
- <p class="em-range-description"><em><?php _e( 'For a recurring event, a one day event will be created on each recurring date within this date range.', 'events-manager'); ?></em></p>
66
- </div>
67
- <script type="text/javascript">
68
- jQuery(document).ready( function($) {
69
- //Recurrence Warnings
70
- $('#event-form').submit( function(event){
71
- confirmation = confirm(EM.event_reschedule_warning);
72
- if( confirmation == false ){
73
- event.preventDefault();
74
- }
75
- });
76
- });
77
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  </div>
3
  global $EM_Event;
4
  $days_names = em_get_days_names();
5
  $hours_format = em_get_hour_format();
6
+ $classes = array();
7
  ?>
 
8
  <!-- START recurrence postbox -->
9
+ <div id="em-form-recurrence" class="event-form-recurrence event-form-when <?php if( !empty($EM_Event->event_id) ) echo 'em-recurrence-reschedule'; ?>">
10
+ <?php if( !empty($EM_Event->event_id) ): ?>
11
+ <div class="recurrence-reschedule-warning">
12
+ <p><em><?php echo sprintf(esc_html__('Current Recurrence Pattern: %s', 'events-manager'), $EM_Event->get_recurrence_description()); ?></em></p>
13
+ <p><strong><?php esc_html_e( 'Modifications to event times will cause all recurrences of this event to be deleted and recreated, previous bookings will be deleted.', 'events-manager'); ?></strong></p>
14
+ <p>
15
+ <a href="<?php echo esc_url( add_query_arg(array('scope'=>'all', 'recurrence_id'=>$EM_Event->event_id), em_get_events_admin_url()) ); ?>">
16
+ <strong><?php esc_html_e('You can edit individual recurrences and disassociate them with this recurring event.', 'events-manager'); ?></strong>
17
+ </a>
18
+ </p>
19
+ </div>
20
+ <?php endif; ?>
21
+ <div class="event-form-when-wrap <?php if( !empty($EM_Event->event_id) && empty($_REQUEST['reschedule']) ) echo 'reschedule-hidden'; ?>">
22
+ <?php _e ( 'This event repeats', 'events-manager'); ?>
23
  <select id="recurrence-frequency" name="recurrence_freq">
24
  <?php
25
  $freq_options = array ("daily" => __ ( 'Daily', 'events-manager'), "weekly" => __ ( 'Weekly', 'events-manager'), "monthly" => __ ( 'Monthly', 'events-manager'), 'yearly' => __('Yearly','events-manager') );
36
  <span class='interval-desc' id="interval-monthly-plural"><?php _e ( 'months on the', 'events-manager')?></span>
37
  <span class='interval-desc' id="interval-yearly-singular"><?php _e ( 'year', 'events-manager')?></span>
38
  <span class='interval-desc' id="interval-yearly-plural"><?php _e ( 'years', 'events-manager') ?></span>
39
+ <p class="alternate-selector" id="weekly-selector">
 
 
 
 
 
 
 
40
  <?php
41
+ $saved_bydays = ($EM_Event->is_recurring() && $EM_Event->recurrence_byday != '' ) ? explode ( ",", $EM_Event->recurrence_byday ) : array();
42
+ em_checkbox_items ( 'recurrence_bydays[]', $days_names, $saved_bydays );
43
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  </p>
45
+ <p class="alternate-selector" id="monthly-selector" style="display:inline;">
46
+ <select id="monthly-modifier" name="recurrence_byweekno">
47
+ <?php
48
+ $weekno_options = array ("1" => __ ( 'first', 'events-manager'), '2' => __ ( 'second', 'events-manager'), '3' => __ ( 'third', 'events-manager'), '4' => __ ( 'fourth', 'events-manager'), '-1' => __ ( 'last', 'events-manager') );
49
+ em_option_items ( $weekno_options, $EM_Event->recurrence_byweekno );
50
+ ?>
51
+ </select>
52
+ <select id="recurrence-weekday" name="recurrence_byday">
53
+ <?php em_option_items ( $days_names, $EM_Event->recurrence_byday ); ?>
54
+ </select>
55
+ <?php _e('of each month','events-manager'); ?>
56
+ &nbsp;
57
  </p>
58
+ <div class="event-form-recurrence-when">
59
+ <p class="em-date-range">
60
+ <?php _e ( 'Recurrences span from ', 'events-manager'); ?>
61
+ <input class="em-date-start em-date-input-loc" type="text" />
62
+ <input class="em-date-input" type="hidden" name="event_start_date" value="<?php echo $EM_Event->event_start_date ?>" />
63
+ <?php _e('to','events-manager'); ?>
64
+ <input class="em-date-end em-date-input-loc" type="text" />
65
+ <input class="em-date-input" type="hidden" name="event_end_date" value="<?php echo $EM_Event->event_end_date ?>" />
66
+ </p>
67
+ <p class="em-time-range">
68
+ <?php _e('Events start from','events-manager'); ?>
69
+ <input id="start-time" class="em-time-input em-time-start" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_format, $EM_Event->start ); ?>" />
70
+ <?php _e('to','events-manager'); ?>
71
+ <input id="end-time" class="em-time-input em-time-end" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_format, $EM_Event->end ); ?>" />
72
+ <?php _e('All day','events-manager'); ?> <input type="checkbox" class="em-time-allday" name="event_all_day" id="em-time-all-day" value="1" <?php if(!empty($EM_Event->event_all_day)) echo 'checked="checked"'; ?> />
73
+ </p>
74
+ <p class="em-duration-range">
75
+ <?php echo sprintf(__('Each event spans %s day(s)','events-manager'), '<input id="end-days" type="text" size="8" maxlength="8" name="recurrence_days" value="'. $EM_Event->recurrence_days .'" />'); ?>
76
+ </p>
77
+ <p class="em-range-description"><em><?php _e( 'For a recurring event, a one day event will be created on each recurring date within this date range.', 'events-manager'); ?></em></p>
78
+ </div>
79
+ </div>
80
+ <?php if( !empty($EM_Event->event_id) ): ?>
81
+ <div class="recurrence-reschedule-buttons">
82
+ <a href="<?php echo esc_url(add_query_arg('reschedule', null)); ?>" class="button-secondary em-button em-reschedule-cancel<?php if( empty($_REQUEST['reschedule']) ) echo ' reschedule-hidden'; ?>" data-target=".event-form-when-wrap">
83
+ <?php esc_html_e('Cancel Reschedule', 'events-manager'); ?>
84
+ </a>
85
+ <a href="<?php echo esc_url(add_query_arg('reschedule', '1')); ?>" class="em-reschedule-trigger em-button button-secondary<?php if( !empty($_REQUEST['reschedule']) ) echo ' reschedule-hidden'; ?>" data-target=".event-form-when-wrap">
86
+ <?php esc_html_e('Reschedule Recurring Event', 'events-manager'); ?>
87
+ </a>
88
+ <input type="hidden" name="event_reschedule" class="em-reschedule-value" value="<?php echo empty($_REQUEST['reschedule']) ? 0:1 ?>" />
89
+ </div>
90
+ <?php endif; ?>
91
  </div>
templates/forms/event/when-with-recurring.php CHANGED
@@ -5,7 +5,6 @@ $days_names = em_get_days_names();
5
  $hours_format = em_get_hour_format();
6
  $admin_recurring = is_admin() && $EM_Event->is_recurring();
7
  ?>
8
- <?php if( is_admin() ): ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_event'); ?>" /><?php endif; ?>
9
  <!-- START recurrence postbox -->
10
  <div id="em-form-with-recurrence" class="event-form-with-recurrence event-form-when">
11
  <p><?php _e('This is a recurring event.', 'events-manager'); ?> <input type="checkbox" id="em-recurrence-checkbox" name="recurring" value="1" <?php if($EM_Event->is_recurring()) echo 'checked' ?> /></p>
5
  $hours_format = em_get_hour_format();
6
  $admin_recurring = is_admin() && $EM_Event->is_recurring();
7
  ?>
 
8
  <!-- START recurrence postbox -->
9
  <div id="em-form-with-recurrence" class="event-form-with-recurrence event-form-when">
10
  <p><?php _e('This is a recurring event.', 'events-manager'); ?> <input type="checkbox" id="em-recurrence-checkbox" name="recurring" value="1" <?php if($EM_Event->is_recurring()) echo 'checked' ?> /></p>
templates/placeholders/attendees.php CHANGED
@@ -6,13 +6,11 @@ if( count($EM_Bookings->bookings) > 0 ){
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
9
- $guest_bookings = get_option('dbem_bookings_registration_disable');
10
- $guest_booking_user = get_option('dbem_bookings_registration_user');
11
- foreach( $EM_Bookings as $EM_Booking){
12
  if($EM_Booking->booking_status == 1 && !in_array($EM_Booking->get_person()->ID, $people) ){
13
  $people[] = $EM_Booking->get_person()->ID;
14
  echo '<li>'. get_avatar($EM_Booking->get_person()->ID, 50) .'</li>';
15
- }elseif($EM_Booking->booking_status == 1 && $guest_bookings && $EM_Booking->get_person()->ID == $guest_booking_user ){
16
  echo '<li>'. get_avatar($EM_Booking->get_person()->ID, 50) .'</li>';
17
  }
18
  }
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
9
+ foreach( $EM_Bookings as $EM_Booking){ /* @var $EM_Booking EM_Booking */
 
 
10
  if($EM_Booking->booking_status == 1 && !in_array($EM_Booking->get_person()->ID, $people) ){
11
  $people[] = $EM_Booking->get_person()->ID;
12
  echo '<li>'. get_avatar($EM_Booking->get_person()->ID, 50) .'</li>';
13
+ }elseif($EM_Booking->booking_status == 1 && $EM_Booking->is_no_user() ){
14
  echo '<li>'. get_avatar($EM_Booking->get_person()->ID, 50) .'</li>';
15
  }
16
  }
templates/placeholders/attendeeslist.php CHANGED
@@ -6,13 +6,11 @@ if( count($EM_Bookings->bookings) > 0 ){
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
9
- $guest_bookings = get_option('dbem_bookings_registration_disable');
10
- $guest_booking_user = get_option('dbem_bookings_registration_user');
11
- foreach( $EM_Bookings as $EM_Booking){
12
  if($EM_Booking->booking_status == 1 && !in_array($EM_Booking->get_person()->ID, $people) ){
13
  $people[] = $EM_Booking->get_person()->ID;
14
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
15
- }elseif($EM_Booking->booking_status == 1 && $guest_bookings && $EM_Booking->get_person()->ID == $guest_booking_user ){
16
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
17
  }
18
  }
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
9
+ foreach( $EM_Bookings as $EM_Booking){ /* @var $EM_Booking EM_Booking */
 
 
10
  if($EM_Booking->booking_status == 1 && !in_array($EM_Booking->get_person()->ID, $people) ){
11
  $people[] = $EM_Booking->get_person()->ID;
12
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
13
+ }elseif($EM_Booking->booking_status == 1 && $EM_Booking->is_no_user() ){
14
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
15
  }
16
  }
templates/placeholders/attendeespendinglist.php CHANGED
@@ -6,13 +6,11 @@ if( count($EM_Bookings->bookings) > 0 ){
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
9
- $guest_bookings = get_option('dbem_bookings_registration_disable');
10
- $guest_booking_user = get_option('dbem_bookings_registration_user');
11
  foreach( $EM_Bookings as $EM_Booking){ /* @var $EM_Booking EM_Booking */
12
  if( $EM_Booking->is_pending() && !in_array($EM_Booking->get_person()->ID, $people) ){
13
  $people[] = $EM_Booking->get_person()->ID;
14
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
15
- }elseif( $EM_Booking->is_pending() && $guest_bookings && $EM_Booking->get_person()->ID == $guest_booking_user ){
16
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
17
  }
18
  }
6
  ?>
7
  <ul class="event-attendees">
8
  <?php
 
 
9
  foreach( $EM_Bookings as $EM_Booking){ /* @var $EM_Booking EM_Booking */
10
  if( $EM_Booking->is_pending() && !in_array($EM_Booking->get_person()->ID, $people) ){
11
  $people[] = $EM_Booking->get_person()->ID;
12
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
13
+ }elseif( $EM_Booking->is_pending() && $EM_Booking->is_no_user() ){
14
  echo '<li>'. $EM_Booking->get_person()->get_name() .'</li>';
15
  }
16
  }
templates/tables/events.php CHANGED
@@ -11,10 +11,12 @@
11
  /* @var $show_add_new bool */
12
  /* @var $limit int */
13
  //add new button will only appear if called from em_event_admin template tag, or if the $show_add_new var is set
14
- if(!empty($show_add_new) && current_user_can('edit_events')) echo '<a class="em-button button add-new-h2" href="'.em_add_get_params($_SERVER['REQUEST_URI'],array('action'=>'edit','scope'=>null,'status'=>null,'event_id'=>null, 'success'=>null)).'">'.__('Add New','events-manager').'</a>';
15
  ?>
16
- <div class="wrap">
17
- <?php echo $EM_Notices; ?>
 
 
 
18
  <form id="posts-filter" action="" method="get">
19
  <div class="subsubsub">
20
  <?php $default_params = array('scope'=>null,'status'=>null,'em_search'=>null,'pno'=>null); //template for cleaning the link for each view below ?>
11
  /* @var $show_add_new bool */
12
  /* @var $limit int */
13
  //add new button will only appear if called from em_event_admin template tag, or if the $show_add_new var is set
 
14
  ?>
15
+ <div class="em-events-admin-list">
16
+ <?php
17
+ echo $EM_Notices;
18
+ if(!empty($show_add_new) && current_user_can('edit_events')) echo '<a class="em-button button add-new-h2" href="'.em_add_get_params($_SERVER['REQUEST_URI'],array('action'=>'edit','scope'=>null,'status'=>null,'event_id'=>null, 'success'=>null)).'">'.__('Add New','events-manager').'</a>';
19
+ ?>
20
  <form id="posts-filter" action="" method="get">
21
  <div class="subsubsub">
22
  <?php $default_params = array('scope'=>null,'status'=>null,'em_search'=>null,'pno'=>null); //template for cleaning the link for each view below ?>
templates/tables/locations.php CHANGED
@@ -3,6 +3,7 @@
3
  //add new button will only appear if called from em_location_admin template tag, or if the $show_add_new var is set
4
  if(!empty($show_add_new) && current_user_can('edit_locations')) echo '<a class="em-button button add-new-h2" href="'.em_add_get_params($_SERVER['REQUEST_URI'],array('action'=>'edit','scope'=>null,'status'=>null,'location_id'=>null)).'">'.__('Add New','events-manager').'</a>';
5
  ?>
 
6
  <?php if(!is_admin()) echo $EM_Notices; ?>
7
  <form id='locations-filter' method='post' action=''>
8
  <input type='hidden' name='pno' value='<?php echo esc_attr($page) ?>' />
@@ -89,4 +90,5 @@
89
  <?php endif; ?>
90
 
91
  <?php if ( !empty($locations_nav) ) echo $locations_nav; ?>
92
- </form>
 
3
  //add new button will only appear if called from em_location_admin template tag, or if the $show_add_new var is set
4
  if(!empty($show_add_new) && current_user_can('edit_locations')) echo '<a class="em-button button add-new-h2" href="'.em_add_get_params($_SERVER['REQUEST_URI'],array('action'=>'edit','scope'=>null,'status'=>null,'location_id'=>null)).'">'.__('Add New','events-manager').'</a>';
5
  ?>
6
+ <div class="em-locations-admin-list">
7
  <?php if(!is_admin()) echo $EM_Notices; ?>
8
  <form id='locations-filter' method='post' action=''>
9
  <input type='hidden' name='pno' value='<?php echo esc_attr($page) ?>' />
90
  <?php endif; ?>
91
 
92
  <?php if ( !empty($locations_nav) ) echo $locations_nav; ?>
93
+ </form>
94
+ </div>
templates/templates/ical.php CHANGED
@@ -43,17 +43,24 @@ while ( count($EM_Events) > 0 ){
43
  }
44
 
45
  //formats
46
- $summary = $EM_Event->output($summary_format,'ical');
47
- $description = $EM_Event->output($description_format,'ical');
48
- $location = $geo = $apple_geo = $apple_location = $apple_location_title = $categories = false;
 
 
49
  if( $EM_Event->location_id ){
50
- $location = $EM_Event->output($location_format, 'ical');
51
  if( $EM_Event->get_location()->location_latitude || $EM_Event->get_location()->location_longitude ){
52
- $geo = $EM_Event->get_location()->location_latitude.";".$EM_Event->get_location()->location_longitude;
 
 
 
 
 
 
 
 
53
  }
54
- $apple_location = $EM_Event->output('#_LOCATIONFULLLINE, #_LOCATIONCOUNTRY', 'ical');
55
- $apple_location_title = $EM_Event->get_location()->location_name;
56
- $apple_geo = !empty($geo) ? $geo:'0,0';
57
  }
58
  $categories = array();
59
  foreach( $EM_Event->get_categories() as $EM_Category ){ /* @var EM_Category $EM_Category */
@@ -64,43 +71,46 @@ while ( count($EM_Events) > 0 ){
64
  //create a UID, make it unique and update independent
65
  $UID = $EM_Event->event_id . '@' . $site_domain;
66
  if( is_multisite() ) $UID = absint($EM_Event->blog_id) . '-' . $UID;
 
67
 
68
  //output ical item
69
- $output = "
70
- BEGIN:VEVENT
71
- UID:{$UID}
72
  DTSTART{$dateStart}
73
  DTEND{$dateEnd}
74
  DTSTAMP:{$dateModified}
75
- URL:{$EM_Event->get_permalink()}
76
- SUMMARY:{$summary}";
77
  //Description if available
78
  if( $description ){
79
- $output .= "
80
- DESCRIPTION:{$description}";
81
  }
82
  //add featured image if exists
83
  if( $image ){
 
84
  $output .= "
85
- ATTACH;FMTTYPE=image/jpeg:".esc_url_raw($image);
86
  }
87
  //add categories if there are any
88
  if( !empty($categories) ){
 
89
  $output .= "
90
- CATEGORIES:".implode(',', $categories);
91
  }
92
  //Location if there is one
93
  if( $location ){
94
  $output .= "
95
- LOCATION:{$location}";
96
  //geo coordinates if they exist
97
  if( $geo ){
98
  $output .= "
99
- GEO:{$geo}";
100
  }
101
  //create apple-compatible feature for locations
 
102
  $output .= "
103
- X-APPLE-STRUCTURED-LOCATION;VALUE=URI;X-ADDRESS={$apple_location};X-APPLE-RADIUS=100;X-TITLE={$apple_location_title}:geo:{$apple_geo}";
 
104
  }
105
  //end the event
106
  $output .= "
@@ -121,6 +131,5 @@ END:VEVENT";
121
  }
122
 
123
  //calendar footer
124
- $output = "
125
- END:VCALENDAR";
126
  echo preg_replace("/([^\r])\n/", "$1\r\n", $output);
43
  }
44
 
45
  //formats
46
+ $summary = em_mb_ical_wordwrap('SUMMARY:'.$EM_Event->output($summary_format,'ical'));
47
+ $description = em_mb_ical_wordwrap('DESCRIPTION:'.$EM_Event->output($description_format,'ical'));
48
+ $url = 'URL:'.$EM_Event->get_permalink();
49
+ $url = wordwrap($url, 74, "\n ", true);
50
+ $location = $geo = $apple_geo = $apple_location = $apple_location_title = $apple_structured_location = $categories = false;
51
  if( $EM_Event->location_id ){
52
+ $location = em_mb_ical_wordwrap('LOCATION:'.$EM_Event->output($location_format, 'ical'));
53
  if( $EM_Event->get_location()->location_latitude || $EM_Event->get_location()->location_longitude ){
54
+ $geo = 'GEO:'.$EM_Event->get_location()->location_latitude.";".$EM_Event->get_location()->location_longitude;
55
+ }
56
+ if( !defined('EM_ICAL_APPLE_STRUCT') || !EM_ICAL_APPLE_STRUCT ){
57
+ $apple_location = $EM_Event->output('#_LOCATIONFULLLINE, #_LOCATIONCOUNTRY', 'ical');
58
+ $apple_location_title = $EM_Event->output('#_LOCATIONNAME', 'ical');
59
+ $apple_geo = !empty($geo) ? $EM_Event->get_location()->location_latitude.",".$EM_Event->get_location()->location_longitude:'0,0';
60
+ $apple_structured_location = "X-APPLE-STRUCTURED-LOCATION;VALUE=URI;X-ADDRESS={$apple_location};X-APPLE-RADIUS=100;X-TITLE={$apple_location_title}:geo:{$apple_geo}";
61
+ $apple_structured_location = str_replace('"', '\"', $apple_structured_location); //google chucks a wobbly with these on this line
62
+ $apple_structured_location = em_mb_ical_wordwrap($apple_structured_location);
63
  }
 
 
 
64
  }
65
  $categories = array();
66
  foreach( $EM_Event->get_categories() as $EM_Category ){ /* @var EM_Category $EM_Category */
71
  //create a UID, make it unique and update independent
72
  $UID = $EM_Event->event_id . '@' . $site_domain;
73
  if( is_multisite() ) $UID = absint($EM_Event->blog_id) . '-' . $UID;
74
+ $UID = wordwrap("UID:".$UID, 74, "\r\n ", true);
75
 
76
  //output ical item
77
+ $output = "\r\n"."BEGIN:VEVENT
78
+ {$UID}
 
79
  DTSTART{$dateStart}
80
  DTEND{$dateEnd}
81
  DTSTAMP:{$dateModified}
82
+ {$url}
83
+ {$summary}";
84
  //Description if available
85
  if( $description ){
86
+ $output .= "\r\n" . $description;
 
87
  }
88
  //add featured image if exists
89
  if( $image ){
90
+ $image = wordwrap("ATTACH;FMTTYPE=image/jpeg:".esc_url_raw($image), 74, "\n ", true);
91
  $output .= "
92
+ {$image}";
93
  }
94
  //add categories if there are any
95
  if( !empty($categories) ){
96
+ $categories = wordwrap("CATEGORIES:".implode(',', $categories), 74, "\n ", true);
97
  $output .= "
98
+ {$categories}";
99
  }
100
  //Location if there is one
101
  if( $location ){
102
  $output .= "
103
+ {$location}";
104
  //geo coordinates if they exist
105
  if( $geo ){
106
  $output .= "
107
+ {$geo}";
108
  }
109
  //create apple-compatible feature for locations
110
+ if( !empty($apple_structured_location) ){
111
  $output .= "
112
+ {$apple_structured_location}";
113
+ }
114
  }
115
  //end the event
116
  $output .= "
131
  }
132
 
133
  //calendar footer
134
+ $output = "\r\n"."END:VCALENDAR";
 
135
  echo preg_replace("/([^\r])\n/", "$1\r\n", $output);
templates/templates/map-global.php CHANGED
@@ -12,6 +12,14 @@ if (get_option('dbem_gmap_is_active') == '1') {
12
  <div class="em-location-map-container" style='position:relative; background: #CDCDCD; width: <?php echo $args['width'] ?>; height: <?php echo $args['height'] ?>;'>
13
  <div class='em-locations-map' id='em-locations-map-<?php echo $args['random_id']; ?>' style="width:100%; height:100%"><em><?php _e('Loading Map....', 'events-manager'); ?></em></div>
14
  <div class='em-locations-map-coords' id='em-locations-map-coords-<?php echo $args['random_id']; ?>' style="display:none; visibility:hidden;"><?php echo EM_Object::json_encode($args); ?></div>
 
 
 
 
 
 
 
 
15
  </div>
16
  <?php
17
  }
12
  <div class="em-location-map-container" style='position:relative; background: #CDCDCD; width: <?php echo $args['width'] ?>; height: <?php echo $args['height'] ?>;'>
13
  <div class='em-locations-map' id='em-locations-map-<?php echo $args['random_id']; ?>' style="width:100%; height:100%"><em><?php _e('Loading Map....', 'events-manager'); ?></em></div>
14
  <div class='em-locations-map-coords' id='em-locations-map-coords-<?php echo $args['random_id']; ?>' style="display:none; visibility:hidden;"><?php echo EM_Object::json_encode($args); ?></div>
15
+ <?php if( !empty($map_json_style) ): ?>
16
+ <script type="text/javascript">
17
+ if( typeof EM == 'object'){
18
+ if( typeof EM.google_map_id_styles != 'object' ) EM.google_map_id_styles = [];
19
+ EM.google_map_id_styles['<?php echo $args['random_id']; ?>'] = <?php echo $map_json_style; ?>;
20
+ }
21
+ </script>
22
+ <?php endif; ?>
23
  </div>
24
  <?php
25
  }