Events Manager - Version 5.5.5

Version Description

  • fixed booking cut-off time not being editable after event is saved
  • fixed taxonomy search arguments not being applied on calendars and ajax lists,
  • changed taxonomy search argument - not cleaned or converted to array during get_default_search() to prevent pagination link errors,
  • fixed calendar pagination link argument comparison issues due to loose type comparison,
  • changed calendar default arguments so scope=false and limit=settings_value (should have no effect - mainly future feature-proofing)
  • fixed issue with weekly sunday only recurrences not validating
  • fixed BP unregistered actions in admin area
  • added new admin booking status emails to prevent confusion when pending/confirmed statuses are changed
  • updated POT file
Download this release

Release Info

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

Code changes from version 4.0 to 5.5.5

Files changed (53) hide show
  1. admin/bookings/em-cancelled.php +12 -12
  2. admin/bookings/em-confirmed.php +13 -13
  3. admin/bookings/em-events.php +45 -60
  4. admin/bookings/em-pending.php +15 -16
  5. admin/bookings/em-person.php +18 -18
  6. admin/bookings/em-rejected.php +12 -12
  7. admin/em-admin.php +242 -152
  8. admin/em-bookings.php +330 -151
  9. admin/em-categories.php +0 -191
  10. admin/em-docs.php +245 -66
  11. admin/em-event.php +0 -753
  12. admin/em-events.php +0 -236
  13. admin/em-help.php +26 -9
  14. admin/em-locations-search.php +2 -1
  15. admin/em-locations.php +0 -282
  16. admin/em-ms-locations.php +52 -0
  17. admin/em-ms-options.php +205 -0
  18. admin/em-options.php +2139 -475
  19. admin/em-people.php +0 -77
  20. admin/wpfc-admin.php +47 -0
  21. buddypress/bp-em-activity.php +163 -52
  22. buddypress/bp-em-admin.php +0 -65
  23. buddypress/bp-em-core.php +302 -212
  24. buddypress/bp-em-groups.php +112 -19
  25. buddypress/bp-em-notifications.php +29 -78
  26. buddypress/bp-em-templatetags.php +19 -5
  27. buddypress/screens/attending.php +2 -2
  28. buddypress/screens/group-events.php +3 -0
  29. buddypress/screens/my-bookings.php +10 -6
  30. buddypress/screens/my-events.php +10 -20
  31. buddypress/screens/my-group-events.php +3 -0
  32. buddypress/screens/my-locations.php +8 -29
  33. buddypress/screens/profile.php +2 -24
  34. buddypress/screens/settings.php +0 -56
  35. classes/em-booking.php +763 -225
  36. classes/em-bookings-table.php +641 -0
  37. classes/em-bookings.php +252 -160
  38. classes/em-calendar.php +216 -82
  39. classes/em-categories-taxonomy.php +126 -0
  40. classes/em-categories.php +155 -164
  41. classes/em-category-taxonomy.php +169 -0
  42. classes/em-category.php +205 -134
  43. classes/em-event-post-admin.php +443 -0
  44. classes/em-event-post.php +354 -0
  45. classes/em-event-posts-admin.php +343 -0
  46. classes/em-event.php +1986 -766
  47. classes/em-events.php +266 -136
  48. classes/em-location-post-admin.php +171 -0
  49. classes/em-location-post.php +121 -0
  50. classes/em-location-posts-admin.php +84 -0
  51. classes/em-location.php +801 -196
  52. classes/em-locations.php +157 -92
  53. classes/em-mailer.php +66 -15
admin/bookings/em-cancelled.php CHANGED
@@ -35,9 +35,9 @@ function em_bookings_cancelled_table(){
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -46,7 +46,7 @@ function em_bookings_cancelled_table(){
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
- <?php _e('Bulk Actions'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
@@ -81,10 +81,10 @@ function em_bookings_cancelled_table(){
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
- <th class='manage-column' scope='col'>Booker</th>
85
- <th class='manage-column' scope='col'>E-mail</th>
86
- <th class='manage-column' scope='col'>Phone number</th>
87
- <th class='manage-column' scope='col'>Spaces</th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
@@ -97,16 +97,16 @@ function em_bookings_cancelled_table(){
97
  $rowno++;
98
  ?>
99
  <tr>
100
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
101
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->display_name ?></a></td>
102
  <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
108
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
109
- $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->id));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
112
  <a class="em-bookings-edit" href="<?php echo $edit_url; ?>"><?php _e('Edit/View','dbem'); ?></a> |
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
+ <?php _e('Bulk Actions', 'dbem'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
85
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
97
  $rowno++;
98
  ?>
99
  <tr>
100
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
101
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
102
  <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
108
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
109
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
112
  <a class="em-bookings-edit" href="<?php echo $edit_url; ?>"><?php _e('Edit/View','dbem'); ?></a> |
admin/bookings/em-confirmed.php CHANGED
@@ -36,9 +36,9 @@ function em_bookings_confirmed_table(){
36
  </li>
37
  </ul>
38
  <p class="search-box">
39
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
40
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
41
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
42
  </p>
43
  -->
44
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -47,7 +47,7 @@ function em_bookings_confirmed_table(){
47
  <div class="alignleft actions">
48
  <select name="action">
49
  <option value="-1" selected="selected">
50
- <?php _e('Bulk Actions'); ?>
51
  </option>
52
  <option value="approve">
53
  <?php _e('Approve', 'dbem'); ?>
@@ -82,10 +82,10 @@ function em_bookings_confirmed_table(){
82
  <th class='manage-column column-cb check-column' scope='col'>
83
  <input class='select-all' type="checkbox" value='1' />
84
  </th>
85
- <th class='manage-column' scope='col'>Booker</th>
86
- <th class='manage-column' scope='col'>E-mail</th>
87
- <th class='manage-column' scope='col'>Phone number</th>
88
- <th class='manage-column' scope='col'>Spaces</th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
@@ -98,17 +98,17 @@ function em_bookings_confirmed_table(){
98
  $rowno++;
99
  ?>
100
  <tr>
101
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
102
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person_id; ?>"><?php echo $EM_Booking->person->display_name ?></a></td>
103
  <td><?php echo $EM_Booking->person->user_email ?></td>
104
  <td><?php echo $EM_Booking->person->phone ?></td>
105
  <td><?php echo $EM_Booking->get_spaces() ?></td>
106
  <td>
107
  <?php
108
- $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->id));
109
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->id));
110
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
111
- $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->id));
112
  ?>
113
  <?php if( current_user_can('manage_bookings') && get_option('dbem_bookings_approval') ): ?>
114
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
36
  </li>
37
  </ul>
38
  <p class="search-box">
39
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
40
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
41
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
42
  </p>
43
  -->
44
  <?php if ( $bookings_count >= $limit ) : ?>
47
  <div class="alignleft actions">
48
  <select name="action">
49
  <option value="-1" selected="selected">
50
+ <?php _e('Bulk Actions', 'dbem'); ?>
51
  </option>
52
  <option value="approve">
53
  <?php _e('Approve', 'dbem'); ?>
82
  <th class='manage-column column-cb check-column' scope='col'>
83
  <input class='select-all' type="checkbox" value='1' />
84
  </th>
85
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
88
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
98
  $rowno++;
99
  ?>
100
  <tr>
101
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
102
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person_id; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
103
  <td><?php echo $EM_Booking->person->user_email ?></td>
104
  <td><?php echo $EM_Booking->person->phone ?></td>
105
  <td><?php echo $EM_Booking->get_spaces() ?></td>
106
  <td>
107
  <?php
108
+ $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->booking_id));
109
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
110
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
111
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
112
  ?>
113
  <?php if( current_user_can('manage_bookings') && get_option('dbem_bookings_approval') ): ?>
114
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
admin/bookings/em-events.php CHANGED
@@ -35,29 +35,26 @@ function em_bookings_events_table() {
35
  $title = __ ( 'Future Events', 'dbem' );
36
  $scope = "future";
37
  }
38
- $owner = !current_user_can('edit_others_events') ? get_current_user_id() : false;
39
- $events = EM_Events::get( array('scope'=>$scope, 'limit'=>0, 'order'=>$order, 'rsvp'=>true, 'owner' => $owner ) );
40
- $events_count = count ( $events );
41
 
42
  $use_events_end = get_option ( 'dbem_use_event_end' );
43
  ?>
44
  <div class="wrap em_bookings_events_table em_obj">
45
- <form id="posts-filter" action="<?php echo $_SERVER['REQUEST_URI'] ?>" method="get">
46
  <input type="hidden" name="em_obj" value="em_bookings_events_table" />
47
  <?php if(!empty($_GET['page'])): ?>
48
  <input type='hidden' name='page' value='events-manager-bookings' />
49
- <?php endif; ?>
50
- <ul class="subsubsub">
51
- <li><a href='#' class="current"><?php _e ( 'Total', 'dbem' ); ?> <span class="count">(<?php echo (count ( $events )); ?>)</span></a></li>
52
- </ul>
53
  <div class="tablenav">
54
  <div class="alignleft actions">
55
  <!--
56
  <select name="action">
57
- <option value="-1" selected="selected"><?php _e ( 'Bulk Actions' ); ?></option>
58
- <option value="deleteEvents"><?php _e ( 'Delete selected','dbem' ); ?></option>
59
  </select>
60
- <input type="submit" value="<?php _e ( 'Apply' ); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
61
  -->
62
  <select name="scope">
63
  <?php
@@ -69,7 +66,7 @@ function em_bookings_events_table() {
69
  }
70
  ?>
71
  </select>
72
- <input id="post-query-submit" class="button-secondary" type="submit" value="<?php _e ( 'Filter' )?>" />
73
  </div>
74
  <!--
75
  <div class="view-switch">
@@ -82,7 +79,6 @@ function em_bookings_events_table() {
82
  echo $events_nav;
83
  }
84
  ?>
85
- <br class="clear" />
86
  </div>
87
 
88
  <?php
@@ -95,61 +91,50 @@ function em_bookings_events_table() {
95
  <table class="widefat">
96
  <thead>
97
  <tr>
98
- <th class='manage-column column-cb check-column' scope='col'>
99
- <input class='select-all' type="checkbox" value='1' />
100
- </th>
101
- <th><?php _e ( 'Event', 'dbem' ); ?></th>
102
- <th><?php _e ( 'Date and time', 'dbem' ); ?></th>
103
  </tr>
104
  </thead>
105
  <tbody>
106
  <?php
107
  $rowno = 0;
108
- $event_count = 0;
109
  foreach ( $events as $event ) {
110
  /* @var $event EM_Event */
111
- if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
112
- $rowno++;
113
- $class = ($rowno % 2) ? ' class="alternate"' : '';
114
- // FIXME set to american
115
- $localised_start_date = date_i18n('D d M Y', $event->start);
116
- $localised_end_date = date_i18n('D d M Y', $event->end);
117
- $style = "";
118
- $today = date ( "Y-m-d" );
119
-
120
- if ($event->start_date < $today && $event->end_date < $today){
121
- $style = "style ='background-color: #FADDB7;'";
122
- }
123
- ?>
124
- <tr <?php echo "$class $style"; ?>>
125
-
126
- <td>
127
- <input type='checkbox' class='row-selector' value='<?php echo $event->id; ?>' name='events[]' />
128
- </td>
129
- <td>
130
- <strong>
131
- <?php echo $event->output('#_BOOKINGSLINK'); ?>
132
- </strong>
133
- &ndash;
134
- <?php _e("Booked Spaces",'dbem') ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces() ?>
135
- <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
136
- | <?php _e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?>
137
- <?php endif; ?>
138
- </td>
139
 
140
- <td>
141
- <?php echo $localised_start_date; ?>
142
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
143
- &ndash;
144
- <?php
145
- //TODO Should 00:00 - 00:00 be treated as an all day event?
146
- echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );
147
- ?>
148
- </td>
149
- </tr>
150
- <?php
151
- }
152
- $event_count++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
  ?>
155
  </tbody>
35
  $title = __ ( 'Future Events', 'dbem' );
36
  $scope = "future";
37
  }
38
+ $owner = !current_user_can('manage_others_bookings') ? get_current_user_id() : false;
39
+ $events = EM_Events::get( array('scope'=>$scope, 'limit'=>$limit, 'offset' => $offset, 'order'=>$order, 'bookings'=>true, 'owner' => $owner ) );
40
+ $events_count = EM_Events::count( array('scope'=>$scope, 'limit'=>0, 'order'=>$order, 'bookings'=>true, 'owner' => $owner ) );
41
 
42
  $use_events_end = get_option ( 'dbem_use_event_end' );
43
  ?>
44
  <div class="wrap em_bookings_events_table em_obj">
45
+ <form id="posts-filter" action="" method="get">
46
  <input type="hidden" name="em_obj" value="em_bookings_events_table" />
47
  <?php if(!empty($_GET['page'])): ?>
48
  <input type='hidden' name='page' value='events-manager-bookings' />
49
+ <?php endif; ?>
 
 
 
50
  <div class="tablenav">
51
  <div class="alignleft actions">
52
  <!--
53
  <select name="action">
54
+ <option value="-1" selected="selected"><?php esc_html_e( 'Bulk Actions' ); ?></option>
55
+ <option value="deleteEvents"><?php esc_html_e( 'Delete selected','dbem' ); ?></option>
56
  </select>
57
+ <input type="submit" value="<?php esc_html_e( 'Apply' ); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
58
  -->
59
  <select name="scope">
60
  <?php
66
  }
67
  ?>
68
  </select>
69
+ <input id="post-query-submit" class="button-secondary" type="submit" value="<?php esc_html_e( 'Filter' )?>" />
70
  </div>
71
  <!--
72
  <div class="view-switch">
79
  echo $events_nav;
80
  }
81
  ?>
 
82
  </div>
83
 
84
  <?php
91
  <table class="widefat">
92
  <thead>
93
  <tr>
94
+ <th><?php esc_html_e( 'Event', 'dbem' ); ?></th>
95
+ <th><?php esc_html_e( 'Date and time', 'dbem' ); ?></th>
 
 
 
96
  </tr>
97
  </thead>
98
  <tbody>
99
  <?php
100
  $rowno = 0;
 
101
  foreach ( $events as $event ) {
102
  /* @var $event EM_Event */
103
+ $rowno++;
104
+ $class = ($rowno % 2) ? ' class="alternate"' : '';
105
+ // FIXME set to american
106
+ $localised_start_date = date_i18n(get_option('date_format'), $event->start);
107
+ $localised_end_date = date_i18n(get_option('date_format'), $event->end);
108
+ $style = "";
109
+ $today = date ( "Y-m-d" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ if ($event->start_date < $today && $event->end_date < $today){
112
+ $style = "style ='background-color: #FADDB7;'";
113
+ }
114
+ ?>
115
+ <tr <?php echo "$class $style"; ?>>
116
+ <td>
117
+ <strong>
118
+ <?php echo $event->output('#_BOOKINGSLINK'); ?>
119
+ </strong>
120
+ &ndash;
121
+ <?php esc_html_e("Booked Spaces",'dbem') ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces() ?>
122
+ <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
123
+ | <?php esc_html_e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?>
124
+ <?php endif; ?>
125
+ </td>
126
+
127
+ <td>
128
+ <?php echo $localised_start_date; ?>
129
+ <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
130
+ &ndash;
131
+ <?php
132
+ //TODO Should 00:00 - 00:00 be treated as an all day event?
133
+ echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );
134
+ ?>
135
+ </td>
136
+ </tr>
137
+ <?php
138
  }
139
  ?>
140
  </tbody>
admin/bookings/em-pending.php CHANGED
@@ -50,9 +50,9 @@ function em_bookings_pending_table($event_id = false){
50
  </li>
51
  </ul>
52
  <p class="search-box">
53
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
54
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
55
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
56
  </p>
57
  -->
58
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -61,7 +61,7 @@ function em_bookings_pending_table($event_id = false){
61
  <div class="alignleft actions">
62
  <select name="action">
63
  <option value="-1" selected="selected">
64
- <?php _e('Bulk Actions'); ?>
65
  </option>
66
  <option value="approve">
67
  <?php _e('Approve', 'dbem'); ?>
@@ -96,13 +96,13 @@ function em_bookings_pending_table($event_id = false){
96
  <th class='manage-column column-cb check-column' scope='col'>
97
  <input class='select-all' type="checkbox" value='1' />
98
  </th>
99
- <th class='manage-column' scope='col'>Booker</th>
100
  <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
101
- <th class='manage-column' scope="col">Event</th>
102
  <?php endif; ?>
103
- <th class='manage-column' scope='col'>E-mail</th>
104
- <th class='manage-column' scope='col'>Phone number</th>
105
- <th class='manage-column' scope='col'>Spaces</th>
106
  <th class='manage-column' scope='col'>&nbsp;</th>
107
  </tr>
108
  </thead>
@@ -115,24 +115,24 @@ function em_bookings_pending_table($event_id = false){
115
  $rowno++;
116
  ?>
117
  <tr>
118
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
119
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->display_name ?></a></td>
120
  <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
121
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Booking->event_id; ?>"><?php echo $events[$EM_Booking->event_id]->name ?></a></td>
122
  <?php endif; ?>
123
  <td><?php echo $EM_Booking->person->user_email ?></td>
124
  <td><?php echo $EM_Booking->person->phone ?></td>
125
  <td><?php echo $EM_Booking->get_spaces() ?></td>
126
  <td>
127
  <?php
128
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
129
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->id));
130
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
131
  ?>
132
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
133
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
134
  <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span> |
135
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit/View','dbem'); ?></a>
136
  </td>
137
  </tr>
138
  <?php
@@ -155,6 +155,5 @@ function em_bookings_pending_table($event_id = false){
155
  <?php endif; ?>
156
  </div>
157
  <?php
158
-
159
  }
160
  ?>
50
  </li>
51
  </ul>
52
  <p class="search-box">
53
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
54
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
55
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
56
  </p>
57
  -->
58
  <?php if ( $bookings_count >= $limit ) : ?>
61
  <div class="alignleft actions">
62
  <select name="action">
63
  <option value="-1" selected="selected">
64
+ <?php _e('Bulk Actions', 'dbem'); ?>
65
  </option>
66
  <option value="approve">
67
  <?php _e('Approve', 'dbem'); ?>
96
  <th class='manage-column column-cb check-column' scope='col'>
97
  <input class='select-all' type="checkbox" value='1' />
98
  </th>
99
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
100
  <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
101
+ <th class='manage-column' scope="col"><?php _e('Event', 'dbem'); ?></th>
102
  <?php endif; ?>
103
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
104
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
105
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
106
  <th class='manage-column' scope='col'>&nbsp;</th>
107
  </tr>
108
  </thead>
115
  $rowno++;
116
  ?>
117
  <tr>
118
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
119
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
120
  <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
121
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Booking->event_id; ?>"><?php echo $events[$EM_Booking->event_id]->name ?></a></td>
122
  <?php endif; ?>
123
  <td><?php echo $EM_Booking->person->user_email ?></td>
124
  <td><?php echo $EM_Booking->person->phone ?></td>
125
  <td><?php echo $EM_Booking->get_spaces() ?></td>
126
  <td>
127
  <?php
128
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
129
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
130
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
131
  ?>
132
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
133
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
134
  <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span> |
135
+ <a class="em-bookings-edit" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->booking_id; ?>"><?php _e('Edit/View','dbem'); ?></a>
136
  </td>
137
  </tr>
138
  <?php
155
  <?php endif; ?>
156
  </div>
157
  <?php
 
158
  }
159
  ?>
admin/bookings/em-person.php CHANGED
@@ -37,9 +37,9 @@ function em_bookings_person_table(){
37
  </li>
38
  </ul>
39
  <p class="search-box">
40
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
41
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
42
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
43
  </p>
44
  -->
45
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -48,7 +48,7 @@ function em_bookings_person_table(){
48
  <div class="alignleft actions">
49
  <select name="action">
50
  <option value="-1" selected="selected">
51
- <?php _e('Bulk Actions'); ?>
52
  </option>
53
  <option value="approve">
54
  <?php _e('Approve', 'dbem'); ?>
@@ -83,9 +83,9 @@ function em_bookings_person_table(){
83
  <th class='manage-column column-cb check-column' scope='col'>
84
  <input class='select-all' type="checkbox" value='1' />
85
  </th>
86
- <th class='manage-column' scope='col'>Event</th>
87
- <th class='manage-column' scope='col'>Spaces</th>
88
- <th class='manage-column' scope='col'>Status</th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
@@ -99,31 +99,31 @@ function em_bookings_person_table(){
99
  $rowno++;
100
  ?>
101
  <tr>
102
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
103
- <td><a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
- <td><?php echo $EM_Booking->status_array[$EM_Booking->status]; ?>
106
  </td>
107
  <td>
108
  <?php
109
- $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'bookings'=>$EM_Booking->id));
110
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'bookings'=>$EM_Booking->id));
111
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'bookings'=>$EM_Booking->id));
112
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'bookings'=>$EM_Booking->id));
113
  ?>
114
- <?php if( get_option('dbem_bookings_approval') && ($EM_Booking->status == 0 ) ): ?>
115
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
116
  <?php endif; ?>
117
- <?php if( get_option('dbem_bookings_approval') && $EM_Booking->status == 1 ): ?>
118
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
119
  <?php endif; ?>
120
- <?php if( $EM_Booking->status == 2 ): ?>
121
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
122
  <?php endif; ?>
123
- <?php if( $EM_Booking->status == 0 || $EM_Booking->status == 1 ): ?>
124
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
125
  <?php endif; ?>
126
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit/View','dbem'); ?></a> |
127
  <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span>
128
  </td>
129
  </tr>
37
  </li>
38
  </ul>
39
  <p class="search-box">
40
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
41
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
42
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
43
  </p>
44
  -->
45
  <?php if ( $bookings_count >= $limit ) : ?>
48
  <div class="alignleft actions">
49
  <select name="action">
50
  <option value="-1" selected="selected">
51
+ <?php _e('Bulk Actions', 'dbem'); ?>
52
  </option>
53
  <option value="approve">
54
  <?php _e('Approve', 'dbem'); ?>
83
  <th class='manage-column column-cb check-column' scope='col'>
84
  <input class='select-all' type="checkbox" value='1' />
85
  </th>
86
+ <th class='manage-column' scope='col'><?php _e('Event', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
+ <th class='manage-column' scope='col'><?php _e('Status', 'dbem'); ?></th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
99
  $rowno++;
100
  ?>
101
  <tr>
102
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
103
+ <td><a class="row-title" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->event_id ?>"><?php echo ($EM_Event->event_name); ?></a></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
+ <td><?php echo $EM_Booking->status_array[$EM_Booking->booking_status]; ?>
106
  </td>
107
  <td>
108
  <?php
109
+ $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->booking_id));
110
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
111
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
112
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
113
  ?>
114
+ <?php if( get_option('dbem_bookings_approval') && ($EM_Booking->booking_status == 0 ) ): ?>
115
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
116
  <?php endif; ?>
117
+ <?php if( get_option('dbem_bookings_approval') && $EM_Booking->booking_status == 1 ): ?>
118
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
119
  <?php endif; ?>
120
+ <?php if( $EM_Booking->booking_status == 2 ): ?>
121
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
122
  <?php endif; ?>
123
+ <?php if( $EM_Booking->booking_status == 0 || $EM_Booking->booking_status == 1 ): ?>
124
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
125
  <?php endif; ?>
126
+ <a class="em-bookings-edit" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->booking_id; ?>"><?php _e('Edit/View','dbem'); ?></a> |
127
  <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span>
128
  </td>
129
  </tr>
admin/bookings/em-rejected.php CHANGED
@@ -35,9 +35,9 @@ function em_bookings_rejected_table(){
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -46,7 +46,7 @@ function em_bookings_rejected_table(){
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
- <?php _e('Bulk Actions'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
@@ -81,10 +81,10 @@ function em_bookings_rejected_table(){
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
- <th class='manage-column' scope='col'>Booker</th>
85
- <th class='manage-column' scope='col'>E-mail</th>
86
- <th class='manage-column' scope='col'>Phone number</th>
87
- <th class='manage-column' scope='col'>Spaces</th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
@@ -97,16 +97,16 @@ function em_bookings_rejected_table(){
97
  $rowno++;
98
  ?>
99
  <tr>
100
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
101
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->display_name ?></a></td>
102
  <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
108
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
109
- $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->id));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
112
  <a class="em-bookings-edit" href="<?php echo $edit_url ?>"><?php _e('Edit/View','dbem'); ?></a> |
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
+ <?php _e('Bulk Actions', 'dbem'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
85
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
97
  $rowno++;
98
  ?>
99
  <tr>
100
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
101
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
102
  <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
  <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
108
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
109
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
112
  <a class="em-bookings-edit" href="<?php echo $edit_url ?>"><?php _e('Edit/View','dbem'); ?></a> |
admin/em-admin.php CHANGED
@@ -1,10 +1,138 @@
1
  <?php
2
  //Admin functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  /**
5
  * Generate warnings and notices in the admin area
6
  */
7
  function em_admin_warnings() {
 
8
  //If we're editing the events page show hello to new user
9
  $events_page_id = get_option ( 'dbem_events_page' );
10
  $dismiss_link_joiner = ( count($_GET) > 0 ) ? '&amp;':'?';
@@ -13,204 +141,166 @@ function em_admin_warnings() {
13
  //New User Intro
14
  if (isset ( $_GET ['disable_hello_to_user'] ) && $_GET ['disable_hello_to_user'] == 'true'){
15
  // Disable Hello to new user if requested
16
- update_option ( 'dbem_hello_to_user', 0 );
17
- }elseif ( get_option ( 'dbem_hello_to_user' ) == 1 && !empty($_GET['page']) && $_GET['page'] == 'events-manager-events' ) {
18
- $current_user = wp_get_current_user ();
19
  //FIXME update welcome msg with good links
20
- $advice = sprintf ( __ ( "<p>Hey, <strong>%s</strong>, welcome to <strong>Events Manager</strong>! We hope you like it around here.</p>
21
- <p>Now it's time to insert events lists through <a href='%s' title='Widgets page'>widgets</a>, <a href='%s' title='Template tags documentation'>template tags</a> or <a href='%s' title='Shortcodes documentation'>shortcodes</a>.</p>
22
- <p>By the way, have you taken a look at the <a href='%s' title='Change settings'>Settings page</a>? That's where you customize the way events and locations are displayed.</p>
23
- <p>What? Tired of seeing this advice? I hear you, <a href='%s' title='Don't show this advice again'>click here</a> and you won't see this again!</p>", 'dbem' ), $current_user->display_name, get_bloginfo ( 'url' ) . '/wp-admin/widgets.php', 'http://wp-events-plugin.com/documentation/template-tags/', 'http://wp-events-plugin.com/documentation/shortcodes/', get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager&disable_hello_to_user=true' );
24
  ?>
25
  <div id="message" class="updated">
26
  <?php echo $advice; ?>
27
  </div>
28
  <?php
29
- }
30
-
31
- //Image upload folders
32
- if( is_super_admin() && EM_IMAGE_DS == '/' ){
33
- $errs = array();
34
- if( !file_exists(EM_IMAGE_UPLOAD_DIR) && @mkdir(EM_IMAGE_UPLOAD_DIR, 0777)){
35
- if( !file_exists(EM_IMAGE_UPLOAD_DIR.'/events/') && !@mkdir(EM_IMAGE_UPLOAD_DIR."events/", 0777) ){ $errs[] = 'events'; }
36
- if( !file_exists(EM_IMAGE_UPLOAD_DIR.'/locations/') && !@mkdir(EM_IMAGE_UPLOAD_DIR."locations/", 0777) ){ $errs[] = 'locations'; }
37
- if( !file_exists(EM_IMAGE_UPLOAD_DIR.'/categories/') && !@mkdir(EM_IMAGE_UPLOAD_DIR."categories/", 0777) ){ $errs[] = 'categories'; }
38
- }elseif( !file_exists(EM_IMAGE_UPLOAD_DIR) ){
39
- $errs = array('events','categories','locations');
40
- }
41
- if( count($errs) > 0 ){
42
- ?>
43
- <div class="updated">
44
- <p><?php echo sprintf(__('The upload directory '.EM_IMAGE_UPLOAD_DIR.' is must be present with these writeable folders: %s. Please create these folders with the same write permissions you use for your normal wordpress image upload folders.','dbem'),implode(', ',$errs)); ?></p>
45
- </div>
46
- <?php
47
- }
48
  }
49
 
50
- //If events page couldn't be created
51
- if( !empty($_GET['em_dismiss_admin_notice']) ){
52
- delete_option('dbem_admin_notice_'.$_GET['em_dismiss_admin_notice']);
53
- }else{
54
- if ( get_option('dbem_admin_notice_3.0.91') ){
55
- ?>
56
- <div class="updated">
57
- <p><?php echo sprintf ( __( '<strong>Events Manager has some new features!</strong><ul><li>Bookings can now be approved before they count towards your event\'s space allocations.</li><li>Events now have owners, and you can restrict users so they can only manage events/locations/categories they create.<br/><br/>These new permissions are enabled by default, but since you upgraded it has been disabled to maintain the previous plugin behaviour. You can re-enable it from the <a href="%s">settings page</a>. <a href="%s">Dismiss</a>', 'dbem'), get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_admin_notice=3.0.91' ); ?></p>
58
- </div>
59
- <?php
60
- }
61
- }
62
-
63
- //If events page couldn't be created
64
  if( !empty($_GET['em_dismiss_events_page']) ){
65
  update_option('dbem_dismiss_events_page',1);
66
  }else{
67
  if ( !get_page($events_page_id) && !get_option('dbem_dismiss_events_page') ){
68
  ?>
69
  <div id="em_page_error" class="updated">
70
- <p><?php echo sprintf ( __( 'Uh Oh! For some reason wordpress could not create an events page for you (or you just deleted it). Not to worry though, all you have to do is create an empty page, name it whatever you want, and select it as your events page in your <a href="%s">settings page</a>. Sorry for the extra step! If you know what you are doing, you may have done this on purpose, if so <a href="%s">ignore this message</a>', 'dbem'), get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_events_page=1' ); ?></p>
71
  </div>
72
  <?php
73
  }
74
  }
75
- //If events page couldn't be created
76
- if( !empty($_GET['em_dismiss_notice_migrate_v3']) ){
77
- delete_option('em_notice_migrate_v3');
78
- }else{
79
- if( get_option('em_notice_migrate_v3') ){
 
 
 
 
 
 
 
 
80
  ?>
81
  <div id="em_page_error" class="updated">
82
- <p><?php echo sprintf ( __( 'A <strong>LOT</strong> has changed since Events Manager 3. We recommend you take a look at the <a href="%s">settings page</a> for new features and upgrade instructions, and you may particualarly be interested in modifying permissions. <a href="%s">Dismiss</a>' ), 'admin.php?page=events-manager-options', em_add_get_params($_SERVER['REQUEST_URI'], array('em_dismiss_notice_migrate_v3'=>1))); ?></p>
83
  </div>
84
- <?php
85
  }
86
  }
87
- //Fixing the RC2 fiasco
88
- if( !empty($_GET['em_dismiss_notice_rc_reimport']) ){
89
- delete_option('dbem_notice_rc_reimport');
90
- }else{
91
- if( get_option('dbem_notice_rc_reimport') ){
92
  ?>
93
  <div id="em_page_error" class="updated">
94
- <p><?php echo sprintf ( __( 'If you upgraded from 3.x to the RC2 and the update did not go so well, <a href="%s">try reimporting old settings</a>. Warning! Re-importing will rename all event slugs, re-import your old category settings from events, and recreate all tickets, so changes to these areas will be lost. <a href="%s">Dismiss</a>' ), 'admin.php?page=events-manager-options&action=em_rc_reimport&_wpnonce='.wp_create_nonce('em_rc_reimport'), em_add_get_params($_SERVER['REQUEST_URI'], array('em_dismiss_notice_rc_reimport'=>1))); ?></p>
95
  </div>
96
- <?php
97
  }
98
  }
99
- if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'em_rc_reimport' && wp_verify_nonce($_REQUEST['_wpnonce'], 'em_rc_reimport') ){
100
- require_once( dirname(__FILE__).'/../em-install.php');
101
- em_migrate_v3();
102
  ?>
103
- <div id="em_page_error" class="updated">
104
- <p>Reimporting old settings was successful. Click the dismiss button on the other notification if after checking things are now working.</p>
105
  </div>
106
  <?php
107
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
  //Warn about EM page edit
110
  if ( preg_match( '/(post|page).php/', $_SERVER ['SCRIPT_NAME']) && isset ( $_GET ['action'] ) && $_GET ['action'] == 'edit' && isset ( $_GET ['post'] ) && $_GET ['post'] == "$events_page_id") {
111
- $message = sprintf ( __ ( "This page corresponds to <strong>Events Manager</strong> events page. Its content will be overriden by Events Manager, although if you include the word CONTENTS (exactly in capitals) and surround it with other text, only CONTENTS will be overwritten. If you want to change the way your events look, go to the <a href='%s'>settings</a> page. ", 'dbem' ), 'admin.php?page=events-manager-options' );
112
  $notice = "<div class='error'><p>$message</p></div>";
113
  echo $notice;
114
  }
115
-
116
- }
117
- add_action ( 'admin_notices', 'em_admin_warnings' );
118
-
119
- /**
120
- * Creates a wp-admin style navigation. All this does is wrap some html around the em_paginate function result to make it style correctly in the admin area.
121
- * @param string $link
122
- * @param int $total
123
- * @param int $limit
124
- * @param int $page
125
- * @param int $pagesToShow
126
- * @return string
127
- * @uses em_paginate()
128
- */
129
- function em_admin_paginate($total, $limit, $page=1, $vars=false){
130
- $return = '<div class="tablenav-pages">';
131
- $events_nav = paginate_links( array(
132
- 'base' => add_query_arg( 'pno', '%#%' ),
133
- 'format' => '',
134
- 'total' => ceil($total / $limit),
135
- 'current' => $page,
136
- 'add_args' => $vars
137
- ));
138
- $return .= sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>%s',
139
- number_format_i18n( ( $page - 1 ) * $limit + 1 ),
140
- number_format_i18n( min( $page * $limit, $total ) ),
141
- number_format_i18n( $total ),
142
- $events_nav
143
- );
144
- $return .= '</div>';
145
- return $return;
146
  }
 
147
 
148
  /**
149
- * Called by admin_print_scripts-(hook|page) action, created when adding menu items in events-manager.php
 
 
 
150
  */
151
- function em_admin_load_scripts(){
152
- //Load the UI items, currently date picker and autocomplete plus dependencies
153
- //wp_enqueue_script('em-ui-js', WP_PLUGIN_URL.'/events-manager/includes/js/jquery-ui-1.8.5.custom.min.js', array('jquery', 'jquery-ui-core'));
154
- wp_enqueue_script('events-manager', WP_PLUGIN_URL.'/events-manager/includes/js/events-manager.js', array('jquery', 'jquery-ui-core'));
155
-
156
- //Add maps
157
- if( get_option('dbem_gmap_is_active') ){
158
- wp_enqueue_script('em-google-maps', 'http://maps.google.com/maps/api/js?sensor=false');
159
- }
160
- //Time Entry
161
- wp_enqueue_script('em-timeentry', WP_PLUGIN_URL.'/events-manager/includes/js/timeentry/jquery.timeentry.js', array('jquery'));
162
-
163
- //Date Picker Locale
164
- $locale_code = substr ( get_locale (), 0, 2 );
165
- $locale_file = "/events-manager/includes/js/i18n/jquery.ui.datepicker-$locale_code.js";
166
- if ( file_exists(WP_PLUGIN_DIR.$locale_file) ) {
167
- wp_enqueue_script("em-ui-datepicker-$locale_code", WP_PLUGIN_URL.$locale_file, array('events-manager'));
168
  }
169
-
170
- //TinyMCE Editor
171
- remove_filter('the_editor', 'qtrans_modifyRichEditor'); //qtranslate filter
172
- add_action( 'admin_print_footer_scripts', 'wp_tiny_mce', 25 );
173
- add_action( 'admin_print_footer_scripts', 'wp_tiny_mce_preload_dialogs', 30 );
174
- wp_enqueue_script('post');
175
- if ( user_can_richedit() )
176
- wp_enqueue_script('editor');
177
-
178
- add_thickbox();
179
- wp_enqueue_script('media-upload');
180
- wp_enqueue_script('word-count');
181
- wp_enqueue_script('quicktags');
182
  }
 
183
 
184
- /**
185
- * Called by admin_print_styles-(hook|page) action, created when adding menu items in events-manager.php
186
- */
187
- function em_admin_load_styles() {
188
- add_thickbox();
189
- wp_enqueue_style('em-ui-css', WP_PLUGIN_URL.'/events-manager/includes/css/jquery-ui-1.7.3.custom.css');
190
- wp_enqueue_style('events-manager-admin', WP_PLUGIN_URL.'/events-manager/includes/css/events_manager_admin.css');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
 
192
 
193
- /**
194
- * Loads script inline due to insertion of php values
195
- */
196
- function em_admin_general_script() {
197
- //TODO clean script up, remove dependency of php so it can be moved to js file.
198
- // Check if the locale is there and loads it
199
- $locale_code = substr ( get_locale (), 0, 2 );
200
- $show24Hours = 'true';
201
- // Setting 12 hours format for those countries using it
202
- if (preg_match ( "/en|sk|zh|us|uk/", $locale_code ))
203
- $show24Hours = 'false';
204
- ?>
205
- <script type="text/javascript">
206
- //<![CDATA[
207
- // TODO: make more general, to support also latitude and longitude (when added)
208
- jQuery(document).ready( function($) {
209
- $("#start-time").timeEntry({spinnerImage: '', show24Hours: <?php echo $show24Hours; ?> });
210
- $("#end-time").timeEntry({spinnerImage: '', show24Hours: <?php echo $show24Hours; ?>});
211
- });
212
- //]]>
213
- </script>
214
- <?php
215
  }
 
216
  ?>
1
  <?php
2
  //Admin functions
3
+ function em_admin_menu(){
4
+ global $menu, $submenu, $pagenow;
5
+ //Count pending bookings
6
+ if( get_option('dbem_rsvp_enabled') ){
7
+ $bookings_num = '';
8
+ $bookings_pending_count = apply_filters('em_bookings_pending_count',0);
9
+ if( get_option('dbem_bookings_approval') == 1){
10
+ $bookings_pending_count += count(EM_Bookings::get(array('status'=>'0', 'blog'=>get_current_blog_id()))->bookings);
11
+ }
12
+ if($bookings_pending_count > 0){
13
+ $bookings_num = '<span class="update-plugins count-'.$bookings_pending_count.'"><span class="plugin-count">'.$bookings_pending_count.'</span></span>';
14
+ }
15
+ }else{
16
+ $bookings_num = '';
17
+ $bookings_pending_count = 0;
18
+ }
19
+ //Count pending events
20
+ $events_num = '';
21
+ $events_pending_count = EM_Events::count(array('status'=>0, 'scope'=>'all', 'blog'=>get_current_blog_id()));
22
+ //TODO Add flexible permissions
23
+ if($events_pending_count > 0){
24
+ $events_num = '<span class="update-plugins count-'.$events_pending_count.'"><span class="plugin-count">'.$events_pending_count.'</span></span>';
25
+ }
26
+ //Count pending recurring events
27
+ $events_recurring_num = '';
28
+ $events_recurring_pending_count = EM_Events::count(array('status'=>0, 'recurring'=>1, 'scope'=>'all', 'blog'=>get_current_blog_id()));
29
+ //TODO Add flexible permissions
30
+ if($events_recurring_pending_count > 0){
31
+ $events_recurring_num = '<span class="update-plugins count-'.$events_recurring_pending_count.'"><span class="plugin-count">'.$events_recurring_pending_count.'</span></span>';
32
+ }
33
+ $both_pending_count = apply_filters('em_items_pending_count', $events_pending_count + $bookings_pending_count + $events_recurring_pending_count);
34
+ $both_num = ($both_pending_count > 0) ? '<span class="update-plugins count-'.$both_pending_count.'"><span class="plugin-count">'.$both_pending_count.'</span></span>':'';
35
+ // Add a submenu to the custom top-level menu:
36
+ $plugin_pages = array();
37
+ if( get_option('dbem_rsvp_enabled') ){
38
+ $plugin_pages['bookings'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Bookings', 'dbem'), __('Bookings', 'dbem').$bookings_num, 'manage_bookings', 'events-manager-bookings', "em_bookings_page");
39
+ }
40
+ $plugin_pages['options'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Events Manager Settings','dbem'),__('Settings','dbem'), 'list_users', "events-manager-options", 'em_admin_options_page');
41
+ $plugin_pages['help'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Getting Help for Events Manager','dbem'),__('Help','dbem'), 'list_users', "events-manager-help", 'em_admin_help_page');
42
+ //If multisite global with locations set to be saved in main blogs we can force locations to be created on the main blog only
43
+ if( EM_MS_GLOBAL && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
44
+ include( dirname(__FILE__)."/em-ms-locations.php" );
45
+ $plugin_pages['locations'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Locations','dbem'),__('Locations','dbem'), 'read_others_locations', "locations", 'em_admin_ms_locations');
46
+ }
47
+ $plugin_pages = apply_filters('em_create_events_submenu',$plugin_pages);
48
+ //We have to modify the menus manually
49
+ if( !empty($both_num) ){ //Main Event Menu
50
+ //go through the menu array and modify the events menu if found
51
+ foreach ( (array)$menu as $key => $parent_menu ) {
52
+ if ( $parent_menu[2] == 'edit.php?post_type='.EM_POST_TYPE_EVENT ){
53
+ $menu[$key][0] = $menu[$key][0]. $both_num;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ if( !empty($events_num) && !empty($submenu['edit.php?post_type='.EM_POST_TYPE_EVENT]) ){ //Submenu Event Item
59
+ //go through the menu array and modify the events menu if found
60
+ foreach ( (array)$submenu['edit.php?post_type='.EM_POST_TYPE_EVENT] as $key => $submenu_item ) {
61
+ if ( $submenu_item[2] == 'edit.php?post_type='.EM_POST_TYPE_EVENT ){
62
+ $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0] = $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0]. $events_num;
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ if( !empty($events_recurring_num) && !empty($submenu['edit.php?post_type='.EM_POST_TYPE_EVENT]) ){ //Submenu Recurring Event Item
68
+ //go through the menu array and modify the events menu if found
69
+ foreach ( (array)$submenu['edit.php?post_type='.EM_POST_TYPE_EVENT] as $key => $submenu_item ) {
70
+ if ( $submenu_item[2] == 'edit.php?post_type=event-recurring' ){
71
+ $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0] = $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0]. $events_recurring_num;
72
+ break;
73
+ }
74
+ }
75
+ }
76
+ /* Hack! Add location/recurrence isn't possible atm so this is a workaround */
77
+ global $_wp_submenu_nopriv;
78
+ if( $pagenow == 'post-new.php' && !empty($_REQUEST['post_type']) ){
79
+ if( $_REQUEST['post_type'] == EM_POST_TYPE_LOCATION && !empty($_wp_submenu_nopriv['edit.php']['post-new.php']) && current_user_can('edit_locations') ){
80
+ unset($_wp_submenu_nopriv['edit.php']['post-new.php']);
81
+ }
82
+ if( $_REQUEST['post_type'] == 'event-recurring' && !empty($_wp_submenu_nopriv['edit.php']['post-new.php']) && current_user_can('edit_recurring_events') ){
83
+ unset($_wp_submenu_nopriv['edit.php']['post-new.php']);
84
+ }
85
+ }
86
+ }
87
+ add_action('admin_menu','em_admin_menu');
88
+
89
+ function em_admin_dashicon(){
90
+ ?>
91
+ <style type="text/css">
92
+ @font-face {
93
+ font-family: 'em_dashicons';
94
+ src: url('../fonts/em-dashicons.eot'); // this is for IE
95
+ }
96
+ @font-face {
97
+ font-family: 'em_dashicons';
98
+ src: url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAAVIAAoAAAAABQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAAAb8AAAG/+vk+uU9TLzIAAAK0AAAAYAAAAGAIIvy2Y21hcAAAAxQAAABMAAAATBpVzFdnYXNwAAADYAAAAAgAAAAIAAAAEGhlYWQAAANoAAAANgAAADYBZ6hBaGhlYQAAA6AAAAAkAAAAJAPIAeZobXR4AAADxAAAABQAAAAUAwAAM21heHAAAAPYAAAABgAAAAYABVAAbmFtZQAAA+AAAAFFAAABRVcZpu5wb3N0AAAFKAAAACAAAAAgAAMAAAEABAQAAQEBCGljb21vb24AAQIAAQA6+BwC+BsD+BgEHgoAGVP/i4seCgAZU/+LiwwHi2v4lPh0BR0AAAB2Dx0AAAB7ER0AAAAJHQAAAbYSAAYBAQgPERMWG2ljb21vb25pY29tb29udTB1MXUyMHVFNjAwAAACAYkAAwAFAgABAAQABwAKAA0BLfyUDvyUDvyUDvuUDvcu+FoVfIuAgIt9CItYBYt8loCai5mLlpaLmgiLvgWLmYCWfYsI93qLFX2Lf4CLfQiLWAWLfJeAmYuZi5eWi5oIi74Fi5l/ln2LCPth+0cVi1hYi4u+vosFpYsVvouLWFiLi74F2IsVvouLWFiLi74F14sVv4uLWFeLi74Fiz4VvouLWFiLi74FPosVv4uLWFeLi74FPosVv4uLWFeLi74FP4sVvouLWFiLi74F1z8Vv4uLV1eLi78F2IsVv4uLV1eLi78F9y33ihWGc3d5cotui3Wii6gIi5cFdI91jXiLd4t1iXWHCIt+BYtvdHRui3KLd52Go2yCdoSLi4uLi2eLfIv7lfduWYuLi4v3bb2L95WLmYuwi4uLi3aSbJQIDviUFPiUFYsMCgAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmAAHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYA//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAEAAIXyBpNfDzz1AAsCAAAAAADQMTPCAAAAANAxM8IAAP/6AeYBxgAAAAgAAgAAAAAAAAABAAAB4P/gAAACAAAAAAAB5gABAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAEAAAACAAAzAABQAAAFAAAAAAAOAK4AAQAAAAAAAQAOAAAAAQAAAAAAAgAOAEcAAQAAAAAAAwAOACQAAQAAAAAABAAOAFUAAQAAAAAABQAWAA4AAQAAAAAABgAHADIAAQAAAAAACgA0AGMAAwABBAkAAQAOAAAAAwABBAkAAgAOAEcAAwABBAkAAwAOACQAAwABBAkABAAOAFUAAwABBAkABQAWAA4AAwABBAkABgAOADkAAwABBAkACgA0AGMAaQBjAG8AbQBvAG8AbgBWAGUAcgBzAGkAbwBuACAAMQAuADAAaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AbgBSAGUAZwB1AGwAYQByAGkAYwBvAG0AbwBvAG4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('woff'),
99
+ url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggi/LYAAAC8AAAAYGNtYXAaVcxXAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5ZsaoTWEAAAFwAAACFGhlYWQBZ6hBAAADhAAAADZoaGVhA8gB5gAAA7wAAAAkaG10eAMAADMAAAPgAAAAFGxvY2EAKAEeAAAD9AAAAAxtYXhwABMAowAABAAAAAAgbmFtZVcZpu4AAAQgAAABRXBvc3QAAwAAAAAFaAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmAAHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYA//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAADQAz//oB5gHGABoANQA6AD8ARABJAE4AUwBYAF0AYgBnAKAAABMiBgcOAQcXBhYXHgEzMjY3PgE3JzYmJy4BIzMiBgcOARcHHgEXHgEzMjY3PgEnNy4BJy4BIwcXIzczOwEXIzc7AQcjJzsBFyM3BzMHIycjMxcjNyMzByMnIzMXIzcXMwcjJzsBFyM3Nw4BBw4BIyImJy4BJzcuASciJiMiBiMOAQ8BFgYHDgEjIiYnLgEnDgEzIhYHHgEzIjYnNiYzIiYnmgUKAgUDAQEBBQMECAcECgMEAwEBAQUCBQgG5wYJBAMFAQEBAwUCCwQGCQQDBQEBAQMFAgsEzgE0ATIbMgE0AUw0ATIBTTMBNQEBNAEyAUwzATUBTjUBMwFLMgE0AUs1ATMBTjMBNQGYAQoGBxAKChQFCAcBAQoPCQcRBgkOCQgRBwEBCgUIEgwIEgUICAMWHgEBAQEB2QEB2gEBAQEBHBgBxgQDBAkFMwYJBAMEBAMECQYzBQkEAwQEAwQJBTMGCQQDBAQDBAkGMwUJBAMEszMzMzMzMzMzTTMzMzMzMzMzTDQ0NDT2CQ8GBQcIBwcTCwwCAgEBAQECAg0KEwcHCAcFBg8JBwkoC8FycsELKAkHAAEAAAABAACs5UCKXw889QALAgAAAAAA0DEzwgAAAADQMTPCAAD/+gHmAcYAAAAIAAIAAAAAAAAAAQAAAeD/4AAAAgAAAAAAAeYAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAABAAAAAgAAMwAAAAAACgAUAB4BCgABAAAABQChAA0AAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIADgBHAAEAAAAAAAMADgAkAAEAAAAAAAQADgBVAAEAAAAAAAUAFgAOAAEAAAAAAAYABwAyAAEAAAAAAAoANABjAAMAAQQJAAEADgAAAAMAAQQJAAIADgBHAAMAAQQJAAMADgAkAAMAAQQJAAQADgBVAAMAAQQJAAUAFgAOAAMAAQQJAAYADgA5AAMAAQQJAAoANABjAGkAYwBvAG0AbwBvAG4AVgBlAHIAcwBpAG8AbgAgADEALgAwAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG4AUgBlAGcAdQBsAGEAcgBpAGMAbwBtAG8AbwBuAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype');
100
+ font-weight: normal;
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>
108
+ <?php
109
+ }
110
+ add_action('admin_head','em_admin_dashicon');
111
+
112
+ function em_ms_admin_menu(){
113
+ add_menu_page( __('Events Manager','dbem'), __('Events Manager','dbem'), 'activate_plugins', 'events-manager-options', 'em_ms_admin_options_page', 'dashicons-calendar' );
114
+ add_submenu_page('events-manager-options', __('Update Blogs','dbem'),__('Update Blogs','dbem'), 'activate_plugins', "events-manager-update", 'em_ms_upgrade');
115
+ }
116
+ add_action('network_admin_menu','em_ms_admin_menu');
117
+
118
+ function em_admin_init(){
119
+ //in MS global mode and locations are stored in the main blog, then a user must have at least a subscriber role
120
+ if( EM_MS_GLOBAL && is_user_logged_in() && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
121
+ EM_Object::ms_global_switch();
122
+ $user = new WP_User(get_current_user_id());
123
+ if( count($user->roles) == 0 ){
124
+ $user->set_role('subscriber');
125
+ }
126
+ EM_Object::ms_global_switch_back();
127
+ }
128
+ }
129
+ add_action('admin_init','em_admin_init');
130
 
131
  /**
132
  * Generate warnings and notices in the admin area
133
  */
134
  function em_admin_warnings() {
135
+ global $EM_Notices;
136
  //If we're editing the events page show hello to new user
137
  $events_page_id = get_option ( 'dbem_events_page' );
138
  $dismiss_link_joiner = ( count($_GET) > 0 ) ? '&amp;':'?';
141
  //New User Intro
142
  if (isset ( $_GET ['disable_hello_to_user'] ) && $_GET ['disable_hello_to_user'] == 'true'){
143
  // Disable Hello to new user if requested
144
+ update_option('dbem_hello_to_user',0);
145
+ }elseif ( get_option ( 'dbem_hello_to_user' ) ) {
 
146
  //FIXME update welcome msg with good links
147
+ $advice = sprintf( __("<p>Events Manager is ready to go! It is highly recommended you read the <a href='%s'>Getting Started</a> guide on our site, as well as checking out the <a href='%s'>Settings Page</a>. <a href='%s' title='Don't show this advice again'>Dismiss</a></p>", 'dbem'), 'http://wp-events-plugin.com/documentation/getting-started/?utm_source=em&utm_medium=plugin&utm_content=installationlink&utm_campaign=plugin_links', EM_ADMIN_URL .'&amp;page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'disable_hello_to_user=true');
 
 
 
148
  ?>
149
  <div id="message" class="updated">
150
  <?php echo $advice; ?>
151
  </div>
152
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
 
155
+ //If events page couldn't be created or is missing
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  if( !empty($_GET['em_dismiss_events_page']) ){
157
  update_option('dbem_dismiss_events_page',1);
158
  }else{
159
  if ( !get_page($events_page_id) && !get_option('dbem_dismiss_events_page') ){
160
  ?>
161
  <div id="em_page_error" class="updated">
162
+ <p><?php echo sprintf ( __( 'Uh Oh! For some reason WordPress could not create an events page for you (or you just deleted it). Not to worry though, all you have to do is create an empty page, name it whatever you want, and select it as your events page in your <a href="%s">settings page</a>. Sorry for the extra step! If you know what you are doing, you may have done this on purpose, if so <a href="%s">ignore this message</a>', 'dbem'), EM_ADMIN_URL .'&amp;page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_events_page=1' ); ?></p>
163
  </div>
164
  <?php
165
  }
166
  }
167
+
168
+ if( defined('EMP_VERSION') && EMP_VERSION < EM_PRO_MIN_VERSION && !defined('EMP_DISABLE_WARNINGS')){
169
+ ?>
170
+ <div id="em_page_error" class="updated">
171
+ <p><?php _e('There is a newer version of Events Manager Pro which is recommended for this current version of Events Manager as new features have been added. Please go to the plugin website and download the latest update.','dbem'); ?></p>
172
+ </div>
173
+ <?php
174
+ }
175
+
176
+ if( is_multisite() && !empty($_REQUEST['page']) && $_REQUEST['page']=='events-manager-options' && is_super_admin() && get_option('dbem_ms_update_nag') ){
177
+ if( !empty($_GET['disable_dbem_ms_update_nag']) ){
178
+ delete_site_option('dbem_ms_update_nag');
179
+ }else{
180
  ?>
181
  <div id="em_page_error" class="updated">
182
+ <p><?php echo sprintf(__('MultiSite options have moved <a href="%s">here</a>. <a href="%s">Dismiss message</a>','dbem'),admin_url().'network/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].'&amp;disable_dbem_ms_update_nag=1'); ?></p>
183
  </div>
184
+ <?php
185
  }
186
  }
187
+
188
+ if( is_super_admin() && get_option('dbem_migrate_images_nag') ){
189
+ if( !empty($_GET['disable_dbem_migrate_images_nag']) ){
190
+ delete_site_option('dbem_migrate_images_nag');
191
+ }else{
192
  ?>
193
  <div id="em_page_error" class="updated">
194
+ <p><?php echo sprintf(__('Whilst they will still appear using placeholders, you need to <a href="%s">migrate your location and event images</a> in order for them to appear in your edit forms and media library. <a href="%s">Dismiss message</a>','dbem'),admin_url().'edit.php?post_type=event&page=events-manager-options&em_migrate_images=1&_wpnonce='.wp_create_nonce('em_migrate_images'), em_add_get_params($_SERVER['REQUEST_URI'], array('disable_dbem_migrate_images_nag' => 1))); ?></p>
195
  </div>
196
+ <?php
197
  }
198
  }
199
+ if( !empty($_REQUEST['page']) && 'events-manager-options' == $_REQUEST['page'] && get_option('dbem_pro_dev_updates') == 1 ){
 
 
200
  ?>
201
+ <div id="message" class="updated">
202
+ <p><?php echo sprintf(__('Dev Mode active: Just a friendly reminder that you are updating to development versions. Only admins see this message, and it will go away when you disable this <a href="#pro-api">here</a> in your settings.','dbem'),'<code>define(\'EMP_DEV_UPDATES\',true);</code>'); ?></p>
203
  </div>
204
  <?php
205
  }
206
+ if( class_exists('SitePress') && !class_exists('EM_WPML') && !get_site_option('disable_em_wpml_warning') ){
207
+ if( !empty($_REQUEST['disable_em_wpml_warning']) ){
208
+ update_site_option('disable_em_wpml_warning',1);
209
+ }else{
210
+ ?>
211
+ <div id="message" class="updated">
212
+ <p><?php echo sprintf(__('It looks like you have WPML enabled on your site. We advise you also install our extra <a href="%s">Events Manager WPML Connector</a> plugin which helps the two work better together. <a href="%s">Dismiss message</a>','dbem'),'http://wordpress.org/extend/plugins/events-manager-wpml/', add_query_arg(array('disable_em_wpml_warning'=>1))); ?></p>
213
+ </div>
214
+ <?php
215
+ }
216
+ }
217
+ if( array_key_exists('dbem_disable_timthumb', wp_load_alloptions()) ){
218
+ if( !empty($_REQUEST['dbem_disable_timthumb']) ){
219
+ delete_option('dbem_disable_timthumb',1);
220
+ }else{
221
+ ?>
222
+ <div id="message" class="updated">
223
+ <p>We have stopped using TimThumb for thumbnails in Events Manager, <a href="http://wp-events-plugin.com/blog/2014/12/05/bye-timthumb/">please see this post</a> for more information on how this may affect you and what options are available to you. <a href="<?php echo add_query_arg(array('dbem_disable_timthumb'=>1)); ?>">Dismiss</a></p>
224
+ </div>
225
+ <?php
226
+ }
227
+ }
228
  }
229
  //Warn about EM page edit
230
  if ( preg_match( '/(post|page).php/', $_SERVER ['SCRIPT_NAME']) && isset ( $_GET ['action'] ) && $_GET ['action'] == 'edit' && isset ( $_GET ['post'] ) && $_GET ['post'] == "$events_page_id") {
231
+ $message = sprintf ( __ ( "This page corresponds to the <strong>Events Manager</strong> %s page. Its content will be overriden by Events Manager, although if you include the word CONTENTS (exactly in capitals) and surround it with other text, only CONTENTS will be overwritten. If you want to change the way your events look, go to the <a href='%s'>settings</a> page. ", 'dbem' ), __('Events','dbem'), EM_ADMIN_URL .'&amp;page=events-manager-options' );
232
  $notice = "<div class='error'><p>$message</p></div>";
233
  echo $notice;
234
  }
235
+ echo $EM_Notices;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
237
+ add_action ( 'admin_notices', 'em_admin_warnings', 100 );
238
 
239
  /**
240
+ * Settings link in the plugins page menu
241
+ * @param array $links
242
+ * @param string $file
243
+ * @return array
244
  */
245
+ function em_plugin_action_links($actions, $file, $plugin_data) {
246
+ $new_actions = array();
247
+ $new_actions[] = sprintf( '<a href="'.EM_ADMIN_URL.'&amp;page=events-manager-options">%s</a>', __('Settings', 'dbem') );
248
+ $new_actions = array_merge($new_actions, $actions);
249
+ if( is_multisite() ){
250
+ $uninstall_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
251
+ }else{
252
+ $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');
 
 
 
 
 
 
 
 
 
253
  }
254
+ $new_actions[] = '<span class="delete"><a href="'.$uninstall_url.'" class="delete">'.__('Uninstall','dbem').'</a></span>';
255
+ return $new_actions;
 
 
 
 
 
 
 
 
 
 
 
256
  }
257
+ add_filter( 'plugin_action_links_events-manager/events-manager.php', 'em_plugin_action_links', 10, 3 );
258
 
259
+ //Updates and Dev versions
260
+ function em_updates_check( $transient ) {
261
+ // Check if the transient contains the 'checked' information
262
+ if( empty( $transient->checked ) )
263
+ return $transient;
264
+
265
+ //only bother if we're checking for dev versions
266
+ if( get_option('em_check_dev_version') || get_option('dbem_pro_dev_updates') ){
267
+ //check WP repo for trunk version
268
+ $request = wp_remote_get('http://plugins.svn.wordpress.org/events-manager/trunk/events-manager.php');
269
+
270
+ if( !is_wp_error($request) ){
271
+ preg_match('/Version: ([0-9a-z\.]+)/', $request['body'], $matches);
272
+
273
+ if( !empty($matches[1]) ){
274
+ //we have a version number!
275
+ if( version_compare($transient->checked[EM_SLUG], $matches[1]) < 0) {
276
+ $response = new stdClass();
277
+ $response->slug = EM_SLUG;
278
+ $response->new_version = $matches[1] ;
279
+ $response->url = 'http://wordpress.org/extend/plugins/events-manager/';
280
+ $response->package = 'http://downloads.wordpress.org/plugin/events-manager.zip';
281
+ $transient->response[EM_SLUG] = $response;
282
+ }
283
+ }
284
+ }
285
+
286
+ delete_option('em_check_dev_version');
287
+ }
288
+
289
+ return $transient;
290
  }
291
+ add_filter('pre_set_site_transient_update_plugins', 'em_updates_check'); // Hook into the plugin update check and mod for dev version
292
 
293
+ function em_user_action_links( $actions, $user ){
294
+ if ( !is_network_admin() && current_user_can( 'manage_others_bookings' ) ){
295
+ if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){
296
+ $my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page'));
297
+ $bookings_link = em_add_get_params($my_bookings_page, array('person_id'=>$user->ID), false);
298
+ }else{
299
+ $bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&person_id=".$user->ID;
300
+ }
301
+ $actions['bookings'] = "<a href='$bookings_link'>" . __( 'Bookings','dbem' ) . "</a>";
302
+ }
303
+ return $actions;
 
 
 
 
 
 
 
 
 
 
 
304
  }
305
+ add_filter('user_row_actions','em_user_action_links',10,2);
306
  ?>
admin/em-bookings.php CHANGED
@@ -8,43 +8,14 @@ function em_admin_actions_bookings() {
8
  global $dbem_form_delete_message;
9
  global $wpdb, $EM_Booking, $EM_Event, $EM_Notices;
10
 
11
- if( current_user_can(EM_MIN_CAPABILITY) && is_object($EM_Booking) && !empty($_REQUEST['action']) ) {
12
- if( $_REQUEST['action'] == 'bookings_delete' ){
13
- //Delete
14
- if( isset($_POST['booking_id']) ){
15
- $EM_Booking = new EM_Booking($_POST['booking_id']);
16
- $EM_Booking->delete();
17
- }
18
- }elseif( $_REQUEST['action'] == 'bookings_edit' ){
19
- //Edit Booking
20
- $validation = $EM_Booking->get_post();
21
- if ( $validation ) { //EM_Event gets the event if submitted via POST and validates it (safer than to depend on JS)
22
- //Save
23
- if( $EM_Booking->save() ) {
24
- $EM_Notices->add_confirm($EM_Booking->feedback_message);
25
- }else{
26
- $EM_Notices->add_error($EM_Booking->feedback_message);
27
- }
28
- }else{
29
- //TODO make errors clearer when saving person
30
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="error"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
31
- }
32
- add_action ( 'admin_notices', 'em_booking_save_notification' );
33
- }elseif( $_REQUEST['action'] == 'bookings_approve' || $_REQUEST['action'] == 'bookings_reject' || $_REQUEST['action'] == 'bookings_unapprove' ){
34
- //Booking Approvals
35
- $status_array = array('bookings_unapprove' => 0,'bookings_approve' => 1,'bookings_reject' => 2, 'bookings_cancel' => 3);
36
- if( $EM_Booking->set_status( $status_array[$_REQUEST['action']] ) ) {
37
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
38
- }else{
39
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="error"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
40
- }
41
- add_action ( 'admin_notices', 'em_booking_save_notification' );
42
- }elseif( $_REQUEST['action'] == 'bookings_add_note' ){
43
  $EM_Booking->add_note($_REQUEST['booking_note']);
44
  function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
45
  add_action ( 'admin_notices', 'em_booking_save_notification' );
46
  }
47
- }elseif( is_object($EM_Event) && !empty($_REQUEST['action']) ){
 
48
  if( $_REQUEST['action'] == 'bookings_export_csv' && wp_verify_nonce($_REQUEST['_wpnonce'],'bookings_export_csv') ){
49
  $EM_Event->get_bookings()->export_csv();
50
  exit();
@@ -58,7 +29,11 @@ add_action('admin_init','em_admin_actions_bookings',100);
58
  */
59
  function em_bookings_page(){
60
  //First any actions take priority
61
- if( !empty($_REQUEST['booking_id']) ){
 
 
 
 
62
  em_bookings_single();
63
  }elseif( !empty($_REQUEST['person_id']) ){
64
  em_bookings_person();
@@ -77,21 +52,30 @@ function em_bookings_page(){
77
  function em_bookings_dashboard(){
78
  global $EM_Notices;
79
  ?>
80
- <div class='wrap'>
 
81
  <div id='icon-users' class='icon32'>
82
  <br/>
83
  </div>
84
  <h2>
85
- <?php _e('Event Bookings Dashboard', 'dbem'); ?>
86
  </h2>
87
- <?php echo $EM_Notices; ?>
88
- <?php if( get_option('dbem_bookings_approval')): ?>
89
- <h2><?php _e('Pending Bookings','dbem'); ?></h2>
90
- <?php em_bookings_pending_table(); ?>
91
- <?php endif; ?>
92
- <h2><?php _e('Events With Bookings Enabled','dbem'); ?></h2>
93
- <?php em_bookings_events_table(); ?>
94
- <?php do_action('em_bookings_dashboard'); ?>
 
 
 
 
 
 
 
 
95
  </div>
96
  <?php
97
  }
@@ -104,7 +88,7 @@ function em_bookings_event(){
104
  //check that user can access this page
105
  if( is_object($EM_Event) && !$EM_Event->can_manage('manage_bookings','manage_others_bookings') ){
106
  ?>
107
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
108
  <?php
109
  return false;
110
  }
@@ -116,35 +100,41 @@ function em_bookings_event(){
116
  <br/>
117
  </div>
118
  <h2>
119
- <?php echo sprintf(__('Manage %s Bookings', 'dbem'), "'{$EM_Event->name}'"); ?>
120
- <a href="<?php echo $EM_Event->output('#_EDITEVENTURL'); ?>" class="button add-new-h2"><?php _e('View/Edit Event','dbem') ?></a>
 
 
 
 
 
121
  </h2>
122
- <?php echo $EM_Notices; ?>
123
- <div><a href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=bookings_export_csv&_wpnonce=".wp_create_nonce('bookings_export_csv')."&event_id=".$EM_Event->id ?>'><?php _e('export csv','dbem')?></a></div>
124
  <div>
125
- <p><strong><?php _e('Event Name','dbem'); ?></strong> : <?php echo ($EM_Event->name); ?></p>
126
- <p><strong>Availability :</strong> <?php echo $EM_Event->get_bookings()->get_booked_spaces() . '/'. $EM_Event->get_spaces() ." ". __('Spaces confirmed','dbem'); ?></p>
 
 
 
 
 
 
127
  <p>
128
- <strong><?php _e('Date','dbem'); ?></strong> :
129
  <?php echo $localised_start_date; ?>
130
  <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
131
- <?php echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 ); ?>
132
  </p>
133
  <p>
134
- <strong><?php _e('Location','dbem'); ?></strong> :
135
- <a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-locations&amp;location_id=<?php echo $EM_Event->location->id ?>"><?php echo ($EM_Event->location->name); ?></a>
136
  </p>
137
  </div>
138
- <?php if( get_option('dbem_bookings_approval')): ?>
139
- <h2><?php _e('Pending Bookings','dbem'); ?></h2>
140
- <?php em_bookings_pending_table(); ?>
141
- <?php endif; ?>
142
- <h2><?php _e('Confirmed Bookings','dbem'); ?></h2>
143
- <?php em_bookings_confirmed_table(); ?>
144
- <h2><?php _e('Rejected Bookings','dbem'); ?></h2>
145
- <?php em_bookings_rejected_table(); ?>
146
- <h2><?php _e('Cancelled Bookings','dbem'); ?></h2>
147
- <?php em_bookings_cancelled_table(); ?>
148
  <?php do_action('em_bookings_event_footer', $EM_Event); ?>
149
  </div>
150
  <?php
@@ -159,7 +149,7 @@ function em_bookings_ticket(){
159
  //check that user can access this page
160
  if( is_object($EM_Ticket) && !$EM_Ticket->can_manage() ){
161
  ?>
162
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this ticket.','dbem'); ?></p></div>
163
  <?php
164
  return false;
165
  }
@@ -170,32 +160,30 @@ function em_bookings_ticket(){
170
  </div>
171
  <h2>
172
  <?php echo sprintf(__('Ticket for %s', 'dbem'), "'{$EM_Event->name}'"); ?>
173
- <a href="admin.php?page=events-manager-event&event_id=<?php echo $EM_Event->id; ?>" class="button add-new-h2"><?php _e('View/Edit Event','dbem') ?></a>
174
- <a href="admin.php?page=events-manager-bookings&event_id=<?php echo $EM_Event->id; ?>" class="button add-new-h2"><?php _e('View Event Bookings','dbem') ?></a>
175
  </h2>
176
- <?php echo $EM_Notices; ?>
177
  <div>
178
  <table>
179
- <tr><td><?php echo __('Name','dbem'); ?></td><td></td><td><?php echo $EM_Ticket->name; ?></td></tr>
180
- <tr><td><?php echo __('Description','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td></td><td><?php echo ($EM_Ticket->description) ? $EM_Ticket->description : '-'; ?></td></tr>
181
- <tr><td><?php echo __('Price','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->price) ? $EM_Ticket->price : '-'; ?></td></tr>
182
- <tr><td><?php echo __('Spaces','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->spaces) ? $EM_Ticket->spaces : '-'; ?></td></tr>
183
- <tr><td><?php echo __('Min','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->min) ? $EM_Ticket->min : '-'; ?></td></tr>
184
- <tr><td><?php echo __('Max','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->max) ? $EM_Ticket->max : '-'; ?></td></tr>
185
- <tr><td><?php echo __('Start','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->start) ? $EM_Ticket->start : '-'; ?></td></tr>
186
- <tr><td><?php echo __('End','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->end) ? $EM_Ticket->end : '-'; ?></td></tr>
 
187
  </table>
188
  </div>
189
- <?php if( get_option('dbem_bookings_approval')): ?>
190
- <h2><?php _e('Pending Bookings','dbem'); ?></h2>
191
- <?php em_bookings_pending_table(); ?>
192
- <?php endif; ?>
193
- <h2><?php _e('Confirmed Bookings','dbem'); ?></h2>
194
- <?php em_bookings_confirmed_table(); ?>
195
- <h2><?php _e('Rejected Bookings','dbem'); ?></h2>
196
- <?php em_bookings_rejected_table(); ?>
197
- <h2><?php _e('Cancelled Bookings','dbem'); ?></h2>
198
- <?php em_bookings_cancelled_table(); ?>
199
  <?php do_action('em_bookings_ticket_footer', $EM_Ticket); ?>
200
  </div>
201
  <?php
@@ -205,112 +193,278 @@ function em_bookings_ticket(){
205
  * Shows a single booking for a single person.
206
  */
207
  function em_bookings_single(){
208
- global $EM_Booking, $EM_Notices;
209
  //check that user can access this page
210
  if( is_object($EM_Booking) && !$EM_Booking->can_manage() ){
211
  ?>
212
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
213
  <?php
214
  return false;
215
  }
216
  ?>
217
- <div class='wrap'>
218
- <div id='icon-users' class='icon32'>
219
- <br/>
220
- </div>
221
  <h2>
222
- <?php _e('Edit Booking', 'dbem'); ?>
223
  </h2>
224
- <?php echo $EM_Notices; ?>
225
  <div id="poststuff" class="metabox-holder">
226
  <div id="post-body">
227
  <div id="post-body-content">
228
- <div id="em-booking-details" class="stuffbox">
229
  <h3>
230
- <?php _e ( 'Event Details', 'dbem' ); ?>
231
  </h3>
232
  <div class="inside">
233
  <?php
234
  $EM_Event = $EM_Booking->get_event();
235
- $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
236
- $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
237
  ?>
238
  <table>
239
- <tr><td><strong><?php _e('Name','dbem'); ?></strong></td><td><a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td></tr>
240
  <tr>
241
- <td><strong><?php _e('Date/Time','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
242
  <td>
243
  <?php echo $localised_start_date; ?>
244
  <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
245
- <?php echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 ); ?>
246
  </td>
247
  </tr>
248
  </table>
 
249
  </div>
250
  </div>
251
- <div id="em-booking-details" class="stuffbox">
252
  <h3>
253
- <?php _e ( 'Personal Details', 'dbem' ); ?>
254
  </h3>
255
  <div class="inside">
256
- <?php echo $EM_Booking->get_person()->display_summary(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  </div>
258
  </div>
259
- <div id="em-booking-details" class="stuffbox">
260
  <h3>
261
- <?php _e ( 'Booking Details', 'dbem' ); ?>
262
  </h3>
263
  <div class="inside">
264
  <?php
265
  $EM_Event = $EM_Booking->get_event();
266
- $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
267
- $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
 
268
  ?>
269
- <table class="em-tickets-bookings-table" cellspacing="0" cellpadding="0">
270
- <thead>
271
- <tr>
272
- <th><?php _e('Ticket Type','dbem'); ?></th>
273
- <th><?php _e('Spaces','dbem'); ?></th>
274
- <th><?php _e('Price','dbem'); ?></th>
275
- </tr>
276
- </thead>
277
- <tbody>
278
- <?php foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking): ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  <tr>
280
- <td class="ticket-type"><a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;ticket_id=<?php echo $EM_Ticket_Booking->get_ticket()->id ?>"><?php echo $EM_Ticket_Booking->get_ticket()->name ?></a></td>
281
- <td><?php echo $EM_Ticket_Booking->get_spaces(); ?></td>
282
- <td><?php echo $EM_Ticket_Booking->get_price(); ?></td>
283
  </tr>
284
- <?php endforeach; ?>
285
- </tbody>
286
- <tfoot>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  <tr>
288
- <th><?php _e('Totals','dbem'); ?></th>
289
- <th><?php echo $EM_Booking->get_spaces(); ?></th>
290
- <th><?php echo $EM_Booking->get_price(); ?></th>
 
 
291
  </tr>
292
- </tfoot>
293
- </table>
294
- <table cellspacing="0" cellpadding="0">
295
- <tr><td><strong><?php _e('Comment','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td><td><?php echo $EM_Booking->comment; ?></td></tr>
296
- <?php foreach( $EM_Booking->get_custom() as $custom_option ){
297
- ?><tr><td><strong><?php echo $custom_option['name'] ?></strong></td><td><?php echo $custom_option['value'] ?></td></tr><?php
298
- }
299
- ?>
300
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  </div>
302
  </div>
303
- <div id="event_name" class="stuffbox">
304
  <h3>
305
- <?php _e ( 'Booking Notes', 'dbem' ); ?>
306
  </h3>
307
  <div class="inside">
308
- <p><?php _e('You can add private notes below for internal reference that only event managers will see.','dbem'); ?></p>
309
- <?php foreach( $EM_Booking->notes as $note ):
310
- $user = get_userdata($note['author']);
311
  ?>
312
  <div>
313
- <?php echo date(get_option('date_format'), $note['timestamp']) .' - '. $user->display_name; ?> <?php _e('wrote','dbem'); ?>:
314
  <p style="background:#efefef; padding:5px;"><?php echo nl2br($note['note']); ?></p>
315
  </div>
316
  <?php endforeach; ?>
@@ -321,6 +475,7 @@ function em_bookings_single(){
321
  </form>
322
  </div>
323
  </div>
 
324
  </div>
325
  </div>
326
  </div>
@@ -343,9 +498,9 @@ function em_bookings_person(){
343
  $has_booking = true;
344
  }
345
  }
346
- if( !$has_booking ){
347
  ?>
348
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
349
  <?php
350
  return false;
351
  }
@@ -355,19 +510,22 @@ function em_bookings_person(){
355
  <br/>
356
  </div>
357
  <h2>
358
- <?php _e('Manage Person\'s Booking', 'dbem'); ?>
359
  <?php if( current_user_can('edit_users') ) : ?>
360
- <a href="user-edit.php?user_id=<?php echo $EM_Person->ID; ?>" class="button add-new-h2"><?php _e('Edit User','dbem') ?></a>
 
 
 
361
  <?php endif; ?>
362
  </h2>
363
- <?php echo $EM_Notices; ?>
364
  <?php do_action('em_bookings_person_header'); ?>
365
  <div id="poststuff" class="metabox-holder has-right-sidebar">
366
  <div id="post-body">
367
  <div id="post-body-content">
368
  <div id="event_name" class="stuffbox">
369
  <h3>
370
- <?php _e ( 'Personal Details', 'dbem' ); ?>
371
  </h3>
372
  <div class="inside">
373
  <?php echo $EM_Person->display_summary(); ?>
@@ -378,11 +536,32 @@ function em_bookings_person(){
378
  </div>
379
  <br style="clear:both;" />
380
  <?php do_action('em_bookings_person_body_1'); ?>
381
- <h3><?php _e('Past And Present Bookings','dbem'); ?></h3>
382
- <?php em_bookings_person_table(); ?>
 
 
 
 
 
 
383
  <?php do_action('em_bookings_person_footer', $EM_Person); ?>
384
  </div>
385
  <?php
386
  }
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  ?>
8
  global $dbem_form_delete_message;
9
  global $wpdb, $EM_Booking, $EM_Event, $EM_Notices;
10
 
11
+ if( is_object($EM_Booking) && !empty($_REQUEST['action']) && $EM_Booking->can_manage('manage_bookings','manage_others_bookings') ) {
12
+ if( $_REQUEST['action'] == 'bookings_add_note' ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  $EM_Booking->add_note($_REQUEST['booking_note']);
14
  function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
15
  add_action ( 'admin_notices', 'em_booking_save_notification' );
16
  }
17
+ }
18
+ if( is_object($EM_Event) && !empty($_REQUEST['action']) ){
19
  if( $_REQUEST['action'] == 'bookings_export_csv' && wp_verify_nonce($_REQUEST['_wpnonce'],'bookings_export_csv') ){
20
  $EM_Event->get_bookings()->export_csv();
21
  exit();
29
  */
30
  function em_bookings_page(){
31
  //First any actions take priority
32
+ do_action('em_bookings_admin_page');
33
+ if( !empty($_REQUEST['_wpnonce']) ){ $_REQUEST['_wpnonce'] = $_GET['_wpnonce'] = $_POST['_wpnonce'] = esc_attr($_REQUEST['_wpnonce']); } //XSS fix just in case here too
34
+ if( !empty($_REQUEST['action']) && substr($_REQUEST['action'],0,7) != 'booking' ){ //actions not starting with booking_
35
+ do_action('em_bookings_'.$_REQUEST['action']);
36
+ }elseif( !empty($_REQUEST['booking_id']) ){
37
  em_bookings_single();
38
  }elseif( !empty($_REQUEST['person_id']) ){
39
  em_bookings_person();
52
  function em_bookings_dashboard(){
53
  global $EM_Notices;
54
  ?>
55
+ <div class='wrap em-bookings-dashboard'>
56
+ <?php if( is_admin() ): ?>
57
  <div id='icon-users' class='icon32'>
58
  <br/>
59
  </div>
60
  <h2>
61
+ <?php esc_html_e('Event Bookings Dashboard', 'dbem'); ?>
62
  </h2>
63
+ <?php else: echo $EM_Notices; ?>
64
+ <?php endif; ?>
65
+ <div class="em-bookings-recent">
66
+ <h2><?php esc_html_e('Recent Bookings','dbem'); ?></h2>
67
+ <?php
68
+ $EM_Bookings_Table = new EM_Bookings_Table();
69
+ $EM_Bookings_Table->status = get_option('dbem_bookings_approval') ? 'needs-attention':'confirmed';
70
+ $EM_Bookings_Table->output();
71
+ ?>
72
+ </div>
73
+ <br class="clear" />
74
+ <div class="em-bookings-events">
75
+ <h2><?php esc_html_e('Events With Bookings Enabled','dbem'); ?></h2>
76
+ <?php em_bookings_events_table(); ?>
77
+ <?php do_action('em_bookings_dashboard'); ?>
78
+ </div>
79
  </div>
80
  <?php
81
  }
88
  //check that user can access this page
89
  if( is_object($EM_Event) && !$EM_Event->can_manage('manage_bookings','manage_others_bookings') ){
90
  ?>
91
+ <div class="wrap"><h2><?php esc_html_e('Unauthorized Access','dbem'); ?></h2><p><?php esc_html_e('You do not have the rights to manage this event.','dbem'); ?></p></div>
92
  <?php
93
  return false;
94
  }
100
  <br/>
101
  </div>
102
  <h2>
103
+ <?php echo sprintf(__('Manage %s Bookings', 'dbem'), "'{$EM_Event->event_name}'"); ?>
104
+ <a href="<?php echo $EM_Event->get_permalink(); ?>" class="button add-new-h2"><?php echo sprintf(__('View %s','dbem'), __('Event', 'dbem')) ?></a>
105
+ <a href="<?php echo $EM_Event->get_edit_url(); ?>" class="button add-new-h2"><?php echo sprintf(__('Edit %s','dbem'), __('Event', 'dbem')) ?></a>
106
+ <?php if( locate_template('plugins/events-manager/templates/csv-event-bookings.php', false) ): //support for legacy template ?>
107
+ <a href='<?php echo EM_ADMIN_URL ."&amp;page=events-manager-bookings&amp;action=bookings_export_csv&amp;_wpnonce=".wp_create_nonce('bookings_export_csv')."&amp;event_id=".$EM_Event->event_id ?>' class="button add-new-h2"><?php esc_html_e('Export CSV','dbem')?></a>
108
+ <?php endif; ?>
109
+ <?php do_action('em_admin_event_booking_options_buttons'); ?>
110
  </h2>
111
+ <?php if( !is_admin() ) echo $EM_Notices; ?>
 
112
  <div>
113
+ <p><strong><?php esc_html_e('Event Name','dbem'); ?></strong> : <?php echo esc_html($EM_Event->event_name); ?></p>
114
+ <p>
115
+ <strong><?php esc_html_e('Availability','dbem'); ?></strong> :
116
+ <?php echo $EM_Event->get_bookings()->get_booked_spaces() . '/'. $EM_Event->get_spaces() ." ". __('Spaces confirmed','dbem'); ?>
117
+ <?php if( get_option('dbem_bookings_approval_reserved') ): ?>
118
+ , <?php echo $EM_Event->get_bookings()->get_available_spaces() . '/'. $EM_Event->get_spaces() ." ". __('Available spaces','dbem'); ?>
119
+ <?php endif; ?>
120
+ </p>
121
  <p>
122
+ <strong><?php esc_html_e('Date','dbem'); ?></strong> :
123
  <?php echo $localised_start_date; ?>
124
  <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
125
+ <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?>
126
  </p>
127
  <p>
128
+ <strong><?php esc_html_e('Location','dbem'); ?></strong> :
129
+ <a class="row-title" href="<?php echo admin_url(); ?>post.php?action=edit&amp;post=<?php echo $EM_Event->get_location()->post_id ?>"><?php echo ($EM_Event->get_location()->location_name); ?></a>
130
  </p>
131
  </div>
132
+ <h2><?php esc_html_e('Bookings','dbem'); ?></h2>
133
+ <?php
134
+ $EM_Bookings_Table = new EM_Bookings_Table();
135
+ $EM_Bookings_Table->status = 'all';
136
+ $EM_Bookings_Table->output();
137
+ ?>
 
 
 
 
138
  <?php do_action('em_bookings_event_footer', $EM_Event); ?>
139
  </div>
140
  <?php
149
  //check that user can access this page
150
  if( is_object($EM_Ticket) && !$EM_Ticket->can_manage() ){
151
  ?>
152
+ <div class="wrap"><h2><?php esc_html_e('Unauthorized Access','dbem'); ?></h2><p><?php esc_html_e('You do not have the rights to manage this ticket.','dbem'); ?></p></div>
153
  <?php
154
  return false;
155
  }
160
  </div>
161
  <h2>
162
  <?php echo sprintf(__('Ticket for %s', 'dbem'), "'{$EM_Event->name}'"); ?>
163
+ <a href="<?php echo $EM_Event->get_edit_url(); ?>" class="button add-new-h2"><?php esc_html_e('View/Edit Event','dbem') ?></a>
164
+ <a href="<?php echo $EM_Event->get_bookings_url(); ?>" class="button add-new-h2"><?php esc_html_e('View Event Bookings','dbem') ?></a>
165
  </h2>
166
+ <?php if( !is_admin() ) echo $EM_Notices; ?>
167
  <div>
168
  <table>
169
+ <tr><td><?php echo __('Name','dbem'); ?></td><td></td><td><?php echo $EM_Ticket->ticket_name; ?></td></tr>
170
+ <tr><td><?php echo __('Description','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td></td><td><?php echo ($EM_Ticket->ticket_description) ? $EM_Ticket->ticket_description : '-'; ?></td></tr>
171
+ <tr><td><?php echo __('Price','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_price) ? $EM_Ticket->ticket_price : '-'; ?></td></tr>
172
+ <tr><td><?php echo __('Spaces','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_spaces) ? $EM_Ticket->ticket_spaces : '-'; ?></td></tr>
173
+ <tr><td><?php echo __('Min','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_min) ? $EM_Ticket->ticket_min : '-'; ?></td></tr>
174
+ <tr><td><?php echo __('Max','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_max) ? $EM_Ticket->ticket_max : '-'; ?></td></tr>
175
+ <tr><td><?php echo __('Start','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_start) ? $EM_Ticket->ticket_start : '-'; ?></td></tr>
176
+ <tr><td><?php echo __('End','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->ticket_end) ? $EM_Ticket->ticket_end : '-'; ?></td></tr>
177
+ <?php do_action('em_booking_admin_ticket_row', $EM_Ticket); ?>
178
  </table>
179
  </div>
180
+ <div class="icon32" id="icon-bookings"><br></div>
181
+ <h2><?php esc_html_e('Bookings','dbem'); ?></h2>
182
+ <?php
183
+ $EM_Bookings_Table = new EM_Bookings_Table();
184
+ $EM_Bookings_Table->status = get_option('dbem_bookings_approval') ? 'needs-attention':'confirmed';
185
+ $EM_Bookings_Table->output();
186
+ ?>
 
 
 
187
  <?php do_action('em_bookings_ticket_footer', $EM_Ticket); ?>
188
  </div>
189
  <?php
193
  * Shows a single booking for a single person.
194
  */
195
  function em_bookings_single(){
196
+ global $EM_Booking, $EM_Notices; /* @var $EM_Booking EM_Booking */
197
  //check that user can access this page
198
  if( is_object($EM_Booking) && !$EM_Booking->can_manage() ){
199
  ?>
200
+ <div class="wrap"><h2><?php esc_html_e('Unauthorized Access','dbem'); ?></h2><p><?php esc_html_e('You do not have the rights to manage this event.','dbem'); ?></p></div>
201
  <?php
202
  return false;
203
  }
204
  ?>
205
+ <div class='wrap' id="em-bookings-admin-booking">
206
+ <div class="icon32" id="icon-bookings"><br></div>
 
 
207
  <h2>
208
+ <?php esc_html_e('Edit Booking', 'dbem'); ?>
209
  </h2>
 
210
  <div id="poststuff" class="metabox-holder">
211
  <div id="post-body">
212
  <div id="post-body-content">
213
+ <div class="stuffbox">
214
  <h3>
215
+ <?php esc_html_e( 'Event Details', 'dbem' ); ?>
216
  </h3>
217
  <div class="inside">
218
  <?php
219
  $EM_Event = $EM_Booking->get_event();
220
+ $localised_start_date = date_i18n(get_option('dbem_date_format'), $EM_Event->start);
221
+ $localised_end_date = date_i18n(get_option('dbem_date_format'), $EM_Event->end);
222
  ?>
223
  <table>
224
+ <tr><td><strong><?php esc_html_e('Name','dbem'); ?></strong></td><td><a class="row-title" href="<?php echo $EM_Event->get_bookings_url(); ?>"><?php echo ($EM_Event->event_name); ?></a></td></tr>
225
  <tr>
226
+ <td><strong><?php esc_html_e('Date/Time','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
227
  <td>
228
  <?php echo $localised_start_date; ?>
229
  <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
230
+ <?php echo substr ( $EM_Event->event_start_time, 0, 5 ) . " - " . substr ( $EM_Event->event_end_time, 0, 5 ); ?>
231
  </td>
232
  </tr>
233
  </table>
234
+ <?php do_action('em_bookings_admin_booking_event', $EM_Event); ?>
235
  </div>
236
  </div>
237
+ <div class="stuffbox">
238
  <h3>
239
+ <?php esc_html_e( 'Personal Details', 'dbem' ); ?>
240
  </h3>
241
  <div class="inside">
242
+ <?php $no_user = get_option('dbem_bookings_registration_disable') && $EM_Booking->get_person()->ID == get_option('dbem_bookings_registration_user'); ?>
243
+ <div class="em-booking-person-details">
244
+ <?php echo $EM_Booking->get_person()->display_summary(); ?>
245
+ <?php if( $no_user ): ?>
246
+ <input type="button" id="em-booking-person-modify" value="<?php esc_attr_e('Edit Details','dbem'); ?>" />
247
+ <?php endif; ?>
248
+ </div>
249
+ <?php if( $no_user ): ?>
250
+ <form action="" method="post" class="em-booking-person-form">
251
+ <div class="em-booking-person-editor" style="display:none;">
252
+ <?php echo $EM_Booking->get_person_editor(); ?>
253
+ <input type='hidden' name='action' value='booking_modify_person'/>
254
+ <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
255
+ <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
256
+ <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_modify_person_'.$EM_Booking->booking_id); ?>'/>
257
+ <input type="submit" class="em-booking-person-modify-submit" id="em-booking-person-modify-submit" value="<?php esc_attr_e('Submit Changes', 'dbem'); ?>" />
258
+ <input type="button" id="em-booking-person-modify-cancel" value="<?php esc_attr_e('Cancel','dbem'); ?>" />
259
+ </div>
260
+ </form>
261
+ <script type="text/javascript">
262
+ jQuery(document).ready( function($){
263
+ $('#em-booking-person-modify').click(function(){
264
+ $('.em-booking-person-details').hide();
265
+ $('.em-booking-person-editor').show();
266
+ });
267
+ $('#em-booking-person-modify-cancel').click(function(){
268
+ $('.em-booking-person-details').show();
269
+ $('.em-booking-person-editor').hide();
270
+ });
271
+ });
272
+ </script>
273
+ <?php endif; ?>
274
+ <?php do_action('em_bookings_admin_booking_person', $EM_Booking); ?>
275
  </div>
276
  </div>
277
+ <div class="stuffbox">
278
  <h3>
279
+ <?php esc_html_e( 'Booking Details', 'dbem' ); ?>
280
  </h3>
281
  <div class="inside">
282
  <?php
283
  $EM_Event = $EM_Booking->get_event();
284
+ $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start);
285
+ $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end);
286
+ $shown_tickets = array();
287
  ?>
288
+ <div>
289
+ <form action="" method="post" class="em-booking-single-status-info">
290
+ <strong><?php esc_html_e('Status','dbem'); ?> : </strong>
291
+ <?php echo $EM_Booking->get_status(); ?>
292
+ <input type="button" class="em-booking-submit-status-modify" id="em-booking-submit-status-modify" value="<?php esc_attr_e('Change', 'dbem'); ?>" />
293
+ <input type="submit" class="em-booking-resend-email" id="em-booking-resend-email" value="<?php esc_attr_e('Resend Email', 'dbem'); ?>" />
294
+ <input type='hidden' name='action' value='booking_resend_email'/>
295
+ <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
296
+ <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
297
+ <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_resend_email_'.$EM_Booking->booking_id); ?>'/>
298
+ </form>
299
+ <form action="" method="post" class="em-booking-single-status-edit">
300
+ <strong><?php esc_html_e('Status','dbem'); ?> : </strong>
301
+ <select name="booking_status">
302
+ <?php foreach($EM_Booking->status_array as $status => $status_name): ?>
303
+ <option value="<?php echo esc_attr($status); ?>" <?php if($status == $EM_Booking->booking_status){ echo 'selected="selected"'; } ?>><?php echo esc_html($status_name); ?></option>
304
+ <?php endforeach; ?>
305
+ </select>
306
+ <input type="checkbox" checked="checked" name="send_email" value="1" />
307
+ <?php esc_html_e('Send Email','dbem'); ?>
308
+ <input type="submit" class="em-booking-submit-status" id="em-booking-submit-status" value="<?php esc_attr_e('Submit Changes', 'dbem'); ?>" />
309
+ <input type="button" class="em-booking-submit-status-cancel" id="em-booking-submit-status-cancel" value="<?php esc_attr_e('Cancel', 'dbem'); ?>" />
310
+ <input type='hidden' name='action' value='booking_set_status'/>
311
+ <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
312
+ <input type='hidden' name='event_id' value='<?php echo $EM_Event->event_id; ?>'/>
313
+ <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_set_status_'.$EM_Booking->booking_id); ?>'/>
314
+ <br /><em><?php wp_kses_data(_e('<strong>Notes:</strong> Ticket availability not taken into account when approving new bookings (i.e. you can overbook).','dbem')); ?></em>
315
+ </form>
316
+ </div>
317
+ <form action="" method="post" class="em-booking-form">
318
+ <table class="em-tickets-bookings-table" cellpadding="0" cellspacing="0">
319
+ <thead>
320
  <tr>
321
+ <th><?php esc_html_e('Ticket Type','dbem'); ?></th>
322
+ <th><?php esc_html_e('Spaces','dbem'); ?></th>
323
+ <th><?php esc_html_e('Price','dbem'); ?></th>
324
  </tr>
325
+ </thead>
326
+ <tbody>
327
+ <?php foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking): /* @var $EM_Ticket_Booking EM_Ticket_Booking */ ?>
328
+ <tr>
329
+ <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_Booking->ticket_id)); ?>"><?php echo $EM_Ticket_Booking->get_ticket()->ticket_name ?></a></td>
330
+ <td>
331
+ <span class="em-booking-single-info"><?php echo $EM_Ticket_Booking->get_spaces(); ?></span>
332
+ <div class="em-booking-single-edit"><input name="em_tickets[<?php echo $EM_Ticket_Booking->ticket_id; ?>][spaces]" class="em-ticket-select" id="em-ticket-spaces-<?php echo $EM_Ticket_Booking->ticket_id; ?>" value="<?php echo $EM_Ticket_Booking->get_spaces(); ?>" /></div>
333
+ </td>
334
+ <td><?php echo $EM_Ticket_Booking->get_price(true,true); ?></td>
335
+ </tr>
336
+ <?php
337
+ $shown_tickets[] = $EM_Ticket_Booking->ticket_id;
338
+ do_action('em_bookings_admin_ticket_row', $EM_Ticket_Booking->get_ticket(), $EM_Booking);
339
+ ?>
340
+ <?php endforeach; ?>
341
+ <?php if( count($shown_tickets) < count($EM_Event->get_bookings()->get_tickets()->tickets)): ?><tr>
342
+ <?php foreach($EM_Event->get_bookings()->get_tickets()->tickets as $EM_Ticket): /* @var $EM_Ticket EM_Ticket */ ?>
343
+ <?php if( !in_array($EM_Ticket->ticket_id, $shown_tickets) ): ?>
344
+ <tr>
345
+ <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>
346
+ <td>
347
+ <span class="em-booking-single-info">0</span>
348
+ <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>
349
+ </td>
350
+ <td><?php echo em_get_currency_symbol() ?>0.00</td>
351
+ </tr>
352
+ <?php do_action('em_bookings_admin_ticket_row', $EM_Ticket, $EM_Booking); ?>
353
+ <?php endif; ?>
354
+ <?php endforeach; ?>
355
+ <?php endif; ?>
356
+ </tbody>
357
+ <tfoot>
358
+ <?php
359
+ do_action('em_bookings_admin_ticket_totals_header');
360
+ $price_summary = $EM_Booking->get_price_summary_array();
361
+ //we should now have an array of information including base price, taxes and post/pre tax discounts
362
+ ?>
363
+ <tr>
364
+ <th><?php esc_html_e('Price','dbem'); ?></th>
365
+ <th><?php echo sprintf(__('%d Spaces','dbem'), $EM_Booking->get_spaces()); ?></th>
366
+ <th><?php echo $EM_Booking->get_price_base(true); ?></th>
367
+ </tr>
368
+ <?php if( count($price_summary['discounts_pre_tax']) > 0 ): ?>
369
+ <?php foreach( $price_summary['discounts_pre_tax'] as $discount_summary ): ?>
370
+ <tr>
371
+ <th><?php echo $discount_summary['name']; ?></th>
372
+ <th><?php echo $discount_summary['discount']; ?></th>
373
+ <th>- <?php echo $discount_summary['amount']; ?></th>
374
+ </tr>
375
+ <?php endforeach; ?>
376
+ <?php endif; ?>
377
+ <?php if( !empty($price_summary['taxes']['amount']) ): ?>
378
+ <tr>
379
+ <th><?php esc_html_e('Tax','dbem'); ?></th>
380
+ <th>
381
+ <span class="em-booking-single-info"><?php echo $price_summary['taxes']['rate'] ?></span>
382
+ <div class="em-booking-single-edit"><input name="booking_tax_rate" value="<?php echo esc_attr($EM_Booking->get_tax_rate()); ?>">%</div>
383
+ </th>
384
+ <th><?php echo $price_summary['taxes']['amount']; ?></th>
385
+ </tr>
386
+ <?php endif; ?>
387
+ <?php if( count($price_summary['discounts_post_tax']) > 0 ): ?>
388
+ <?php foreach( $price_summary['discounts_post_tax'] as $discount_summary ): ?>
389
+ <tr>
390
+ <th><?php echo $discount_summary['name']; ?></th>
391
+ <th><?php echo $discount_summary['discount']; ?></th>
392
+ <th>- <?php echo $discount_summary['amount']; ?></th>
393
+ </tr>
394
+ <?php endforeach; ?>
395
+ <?php endif; ?>
396
+ <tr>
397
+ <th><?php esc_html_e('Total Price','dbem'); ?></th>
398
+ <th>&nbsp;</th>
399
+ <th><?php echo $price_summary['total']; ?></th>
400
+ </tr>
401
+ <?php do_action('em_bookings_admin_ticket_totals_footer'); ?>
402
+ </tfoot>
403
+ </table>
404
+ <table class="em-form-fields" cellspacing="0" cellpadding="0">
405
+ <?php if( !has_action('em_bookings_single_custom') ): //default behaviour ?>
406
  <tr>
407
+ <th><?php esc_html_e('Comment','dbem'); ?></th>
408
+ <td>
409
+ <span class="em-booking-single-info"><?php echo esc_html($EM_Booking->booking_comment); ?></span>
410
+ <div class="em-booking-single-edit"><textarea name="booking_comment"><?php echo esc_html($EM_Booking->booking_comment); ?></textarea></div>
411
+ </td>
412
  </tr>
413
+ <?php else: do_action('em_bookings_single_custom',$EM_Booking); //do your own thing, e.g. pro ?>
414
+ <?php endif; ?>
415
+ </table>
416
+ <p class="em-booking-single-info">
417
+ <input type="button" class="em-booking-submit-modify" id="em-booking-submit-modify" value="<?php esc_attr_e('Modify Booking', 'dbem'); ?>" />
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.','dbem'); ?></em>
421
+ <br /><br />
422
+ <input type="submit" class="em-booking-submit" id="em-booking-submit" value="<?php esc_attr_e('Submit Changes', 'dbem'); ?>" />
423
+ <input type="button" class="em-booking-submit-cancel" id="em-booking-submit-cancel" value="<?php esc_attr_e('Cancel', 'dbem'); ?>" />
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; ?>'/>
427
+ <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_save_'.$EM_Booking->booking_id); ?>'/>
428
+ </p>
429
+ </form>
430
+ <script type="text/javascript">
431
+ jQuery(document).ready( function($){
432
+ $('#em-booking-submit-modify').click(function(){
433
+ $('.em-booking-single-info').hide();
434
+ $('.em-booking-single-edit').show();
435
+ });
436
+ $('#em-booking-submit-cancel').click(function(){
437
+ $('.em-booking-single-info').show();
438
+ $('.em-booking-single-edit').hide();
439
+ });
440
+ $('.em-booking-single-info').show();
441
+ $('.em-booking-single-edit').hide();
442
+
443
+ $('#em-booking-submit-status-modify').click(function(){
444
+ $('.em-booking-single-status-info').hide();
445
+ $('.em-booking-single-status-edit').show();
446
+ });
447
+ $('#em-booking-submit-status-cancel').click(function(){
448
+ $('.em-booking-single-status-info').show();
449
+ $('.em-booking-single-status-edit').hide();
450
+ });
451
+ $('.em-booking-single-status-info').show();
452
+ $('.em-booking-single-status-edit').hide();
453
+ });
454
+ </script>
455
  </div>
456
  </div>
457
+ <div id="em-booking-notes" class="stuffbox">
458
  <h3>
459
+ <?php esc_html_e( 'Booking Notes', 'dbem' ); ?>
460
  </h3>
461
  <div class="inside">
462
+ <p><?php esc_html_e('You can add private notes below for internal reference that only event managers will see.','dbem'); ?></p>
463
+ <?php foreach( $EM_Booking->get_notes() as $note ):
464
+ $user = new EM_Person($note['author']);
465
  ?>
466
  <div>
467
+ <?php echo sprintf(esc_html_x('%1$s - %2$s wrote','[Date] - [Name] wrote','dbem'), date(get_option('date_format'), $note['timestamp']), $user->get_name()); ?>:
468
  <p style="background:#efefef; padding:5px;"><?php echo nl2br($note['note']); ?></p>
469
  </div>
470
  <?php endforeach; ?>
475
  </form>
476
  </div>
477
  </div>
478
+ <?php do_action('em_bookings_single_metabox_footer', $EM_Booking); ?>
479
  </div>
480
  </div>
481
  </div>
498
  $has_booking = true;
499
  }
500
  }
501
+ if( !$has_booking && !current_user_can('manage_others_bookings') ){
502
  ?>
503
+ <div class="wrap"><h2><?php esc_html_e('Unauthorized Access','dbem'); ?></h2><p><?php esc_html_e('You do not have the rights to manage this event.','dbem'); ?></p></div>
504
  <?php
505
  return false;
506
  }
510
  <br/>
511
  </div>
512
  <h2>
513
+ <?php esc_html_e('Manage Person\'s Booking', 'dbem'); ?>
514
  <?php if( current_user_can('edit_users') ) : ?>
515
+ <a href="<?php echo admin_url('user-edit.php?user_id='.$EM_Person->ID); ?>" class="button add-new-h2"><?php esc_html_e('Edit User','dbem') ?></a>
516
+ <?php endif; ?>
517
+ <?php if( current_user_can('delete_users') ) : ?>
518
+ <a href="<?php echo wp_nonce_url( admin_url("users.php?action=delete&amp;user=$EM_Person->ID"), 'bulk-users' ); ?>" class="button add-new-h2"><?php esc_html_e('Delete User','dbem') ?></a>
519
  <?php endif; ?>
520
  </h2>
521
+ <?php if( !is_admin() ) echo $EM_Notices; ?>
522
  <?php do_action('em_bookings_person_header'); ?>
523
  <div id="poststuff" class="metabox-holder has-right-sidebar">
524
  <div id="post-body">
525
  <div id="post-body-content">
526
  <div id="event_name" class="stuffbox">
527
  <h3>
528
+ <?php esc_html_e( 'Personal Details', 'dbem' ); ?>
529
  </h3>
530
  <div class="inside">
531
  <?php echo $EM_Person->display_summary(); ?>
536
  </div>
537
  <br style="clear:both;" />
538
  <?php do_action('em_bookings_person_body_1'); ?>
539
+ <div class="icon32" id="icon-bookings"><br></div>
540
+ <h2><?php esc_html_e('Past And Present Bookings','dbem'); ?></h2>
541
+ <?php
542
+ $EM_Bookings_Table = new EM_Bookings_Table();
543
+ $EM_Bookings_Table->status = 'all';
544
+ $EM_Bookings_Table->scope = 'all';
545
+ $EM_Bookings_Table->output();
546
+ ?>
547
  <?php do_action('em_bookings_person_footer', $EM_Person); ?>
548
  </div>
549
  <?php
550
  }
551
 
552
+ function em_printable_booking_report() {
553
+ global $EM_Event;
554
+ //check that user can access this page
555
+ if( isset($_GET['page']) && $_GET['page']=='events-manager-bookings' && isset($_GET['action']) && $_GET['action'] == 'bookings_report' && is_object($EM_Event)){
556
+ if( is_object($EM_Event) && !$EM_Event->can_manage('edit_events','edit_others_events') ){
557
+ ?>
558
+ <div class="wrap"><h2><?php esc_html_e('Unauthorized Access','dbem'); ?></h2><p><?php esc_html_e('You do not have the rights to manage this event.','dbem'); ?></p></div>
559
+ <?php
560
+ return false;
561
+ }
562
+ em_locate_template('templates/bookings-event-printable.php', true);
563
+ die();
564
+ }
565
+ }
566
+ add_action('admin_init', 'em_printable_booking_report');
567
  ?>
admin/em-categories.php DELETED
@@ -1,191 +0,0 @@
1
- <?php
2
- function em_admin_categories_page() {
3
- global $wpdb, $EM_Category, $EM_Notices;
4
-
5
- //Take actions
6
- if( (!empty($_REQUEST['action']) && ( ($_REQUEST['action'] == "edit" && !empty($_REQUEST['category_id'])) || $_REQUEST['action'] == "add")) ) {
7
- em_categories_edit_layout();
8
- } elseif( !empty($_REQUEST['action']) && $_REQUEST['action'] == "category_save" ) {
9
- em_categories_edit_layout();
10
- } else {
11
- // no action, just a locations list
12
- em_categories_table_layout();
13
- }
14
- return;
15
- //TODO move categories action logic to em-actions.php
16
- if( !empty($_REQUEST['action']) ){
17
- if( $_REQUEST['action'] == "save") {
18
- // save (add/update) category
19
- if( empty($EM_Category) || !is_object($EM_Category) ){
20
- $EM_Category = new EM_Category(); //blank category
21
- $success_message = __('The category has been added.', 'dbem');
22
- }else{
23
- $success_message = __('The category has been updated.', 'dbem');
24
- }
25
-
26
- if ( $EM_Category->get_post() && $EM_Category->save() ) {
27
- $EM_Notices->add_confirm($EM_Category->feedback_message);
28
- em_categories_table_layout();
29
- } else {
30
- $EM_Notices->add_error($EM_Category->errors);
31
- em_categories_edit_layout();
32
- }
33
- } elseif( $_REQUEST['action'] == "edit" ){
34
- em_categories_edit_layout();
35
- } elseif( $_REQUEST['action'] == "delete" ){
36
- //delelte category
37
- EM_Categories::delete($_REQUEST['categories']);
38
- //FIXME no result verification when deleting various categories
39
- $message = __('Categories Deleted', "dbem" );
40
- em_categories_table_layout($message);
41
- }
42
- }else{
43
- em_categories_table_layout();
44
- }
45
- }
46
-
47
- function em_categories_table_layout($message = "") {
48
- global $EM_Notices;
49
- $categories = EM_Categories::get();
50
- $destination = get_bloginfo('url')."/wp-admin/admin.php";
51
- ?>
52
- <div class='wrap'>
53
- <div id='icon-edit' class='icon32'>
54
- <br/>
55
- </div>
56
- <h2>
57
- <?php echo __('Categories', 'dbem') ?>
58
- <a href="admin.php?page=events-manager-categories&action=add" class="button add-new-h2"><?php _e('Add New') ?></a>
59
- </h2>
60
-
61
- <?php echo $EM_Notices; ?>
62
-
63
- <form id='bookings-filter' method='post' action='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories'>
64
- <input type='hidden' name='action' value='category_delete'/>
65
- <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('category_delete'); ?>'/>
66
- <?php if (count($categories)>0) : ?>
67
- <table class='widefat'>
68
- <thead>
69
- <tr>
70
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
71
- <th><?php echo __('ID', 'dbem') ?></th>
72
- <th><?php echo __('Name', 'dbem') ?></th>
73
- </tr>
74
- </thead>
75
- <tfoot>
76
- <tr>
77
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
78
- <th><?php echo __('ID', 'dbem') ?></th>
79
- <th><?php echo __('Name', 'dbem') ?></th>
80
- </tr>
81
- </tfoot>
82
- <tbody>
83
- <?php foreach ($categories as $EM_Category) : ?>
84
- <tr>
85
- <td><input type='checkbox' class ='row-selector' value='<?php echo $EM_Category->id ?>' name='categories[]'/></td>
86
- <td><a href='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories&amp;action=edit&amp;category_id=<?php echo $EM_Category->id ?>'><?php echo htmlspecialchars($EM_Category->id, ENT_QUOTES); ?></a></td>
87
- <td><a href='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories&amp;action=edit&amp;category_id=<?php echo $EM_Category->id ?>'><?php echo htmlspecialchars($EM_Category->name, ENT_QUOTES); ?></a></td>
88
- </tr>
89
- <?php endforeach; ?>
90
- </tbody>
91
-
92
- </table>
93
-
94
- <div class='tablenav'>
95
- <div class='alignleft actions'>
96
- <input class='button-secondary action' type='submit' name='doaction2' value='Delete'/>
97
- <br class='clear'/>
98
- </div>
99
- <br class='clear'/>
100
- </div>
101
- <?php else: ?>
102
- <p><?php echo __('No categories have been inserted yet!', 'dbem'); ?></p>
103
- <?php endif; ?>
104
- </form>
105
- </div>
106
- <?php
107
- }
108
-
109
-
110
- function em_categories_edit_layout($message = "") {
111
- global $EM_Category, $EM_Notices;
112
- if( !is_object($EM_Category) ){
113
- $EM_Category = new EM_Category();
114
- }
115
- //check that user can access this page
116
- if( is_object($EM_Category) && !$EM_Category->can_manage('edit_categories') ){
117
- ?>
118
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php implode('<br/>',$EM_Category->get_errors()); ?></p></div>
119
- <?php
120
- return;
121
- }
122
- ?>
123
- <div class='wrap'>
124
- <div id='icon-edit' class='icon32'>
125
- <br/>
126
- </div>
127
-
128
- <h2><?php echo __('Edit category', 'dbem') ?></h2>
129
-
130
- <?php echo $EM_Notices ?>
131
-
132
- <div id='ajax-response'></div>
133
-
134
- <div id="poststuff" class="metabox-holder">
135
- <div id="post-body">
136
- <div id="post-body-content">
137
- <form enctype='multipart/form-data' name='editcat' id='editcat' method='post' action='admin.php?page=events-manager-categories' class='validate'>
138
- <input type='hidden' name='action' value='category_save' />
139
- <input type='hidden' name='category_id' value='<?php echo $EM_Category->id ?>'/>
140
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('category_save'); ?>" />
141
-
142
- <?php do_action('em_admin_category_form_header'); ?>
143
-
144
- <div id="category_description" class="postbox">
145
- <h3><?php echo __('Category name', 'dbem') ?></h3>
146
- <div class="inside">
147
- <input name='category_name' id='category-name' type='text' value='<?php echo $EM_Category->name ?>' size='40' />
148
- <br />
149
- <em><?php echo __('The name of the category', 'dbem') ?></em>
150
- </div>
151
- </div>
152
-
153
- <div id="category_description" class="postbox">
154
- <h3>
155
- <?php _e ( 'Details', 'dbem' ); ?>
156
- </h3>
157
- <div class="inside">
158
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
159
- <?php the_editor($EM_Category->description ); ?>
160
- </div>
161
- <br />
162
- <em><?php _e ( 'Details about the category', 'dbem' )?></em>
163
- </div>
164
- </div>
165
-
166
- <div id="category_description" class="stuffbox">
167
- <h3>
168
- <?php _e ( 'Category image', 'dbem' ); ?>
169
- </h3>
170
- <div class="inside" style="padding:10px;">
171
- <?php if ($EM_Category->get_image_url() != '') : ?>
172
- <img src='<?php echo $EM_Category->image_url; ?>' alt='<?php echo $EM_Category->name ?>'/>
173
- <?php else : ?>
174
- <em><?php _e('No image uploaded for this category yet', 'debm') ?></em>
175
- <?php endif; ?>
176
- <br /><br />
177
- <label for='category_image'><?php _e('Upload/change picture', 'dbem') ?></label> <input id='locacategoryge' name='category_image' id='category_image' type='file' size='40' />
178
- </div>
179
- </div>
180
- </div>
181
- <?php do_action('em_admin_category_form_footer'); ?>
182
- <p class='submit'><input type='submit' class='button-primary' name='submit' value='<?php echo __('Update category', 'dbem') ?>' /></p>
183
- </form>
184
- </div>
185
- </div>
186
- </div>
187
-
188
- </div>
189
- <?php
190
- }
191
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-docs.php CHANGED
@@ -1,7 +1,8 @@
1
  <?php
2
 
3
- function em_docs_init(){
4
- if( class_exists('EM_Event') ){
 
5
  add_action('wp_head', 'emd_head');
6
  //Generate the docs
7
  global $EM_Documentation;
@@ -12,95 +13,137 @@ function em_docs_init(){
12
  $EM_Documentation = array(
13
  'arguments' => array(
14
  'events' => array(
15
- 'limit' => array( 'default'=>'See the events lists limit option on the settings page.' ),
16
- 'orderby' => array( 'desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'default'=>'See the event lists ordering option on the settings page.', 'args'=>'name, start_date, start_time, end_date, end_time'),
17
- 'order' => array( 'default'=>'See the event lists ordering option on the settings page.' )
 
 
 
 
 
 
 
 
 
 
 
 
18
  ),
19
  'locations' => array(
20
- 'eventful' => array( 'desc'=>'If set to 1 will only show locations that have at least one event occurring during the scope.', 'default' => 0),
21
- 'eventless' => array( 'desc'=>'If set to 1 will only show locations that have no events occurring during the scope.', 'default' => 0),
22
- 'orderby' => array('desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'default'=>'name', 'args' => 'name, address, town'),
23
- 'scope' => array( 'default' => 'all')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  ),
25
  'calendar' => array(
26
- 'full' => array( 'desc'=>'If set to 1 it will display a full calendar that shows event names.', 'default' => 0),
27
- 'long_events' => array( 'desc'=>'If set to 1, will show events that last longer than a day.', 'default' => 0),
28
- 'order' => array( 'desc'=>'Same as for events.' ),
29
- 'scope' => array( 'default' => 'future')
30
  ),
31
  //The object is commonly shared by all, so entries above overwrite entries here
32
  'general' => array(
33
- 'limit' => array( 'desc'=>'Limits the amount of values returned to this number.', 'default'=>'0 (no limit)'),
34
- 'scope' => array( 'desc'=>'Choose the time frame of events to show. Accepted values are "future", "past" or "all" events. Additionally you can supply dates (in format of YYYY-MM-DD), either single for events on a specific date or two dates seperated by a comma (e.g. 2010-12-25,2010-12-31) for events ocurring between these dates.', 'default'=>'future'),
35
- 'order' => array( 'desc'=>'Indicates the order of the events. Choose between ASC (ascending) and DESC (descending).', 'default'=>'ASC'),
36
- 'orderby' => array( 'desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name"). See specific instances (e.g. events, locations, etc.) for field names.', 'default'=>0),
37
- 'format' => array( 'desc'=>'If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here.', 'default'=>'The relevant default format will be taken from the settings page.'),
38
- 'event' => array( 'desc'=>'Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events with these id(s).', 'default'=>0),
39
- 'category' => array( 'desc'=>'Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events in these categories.', 'default'=>0),
40
- 'location' => array( 'desc'=>'Supply a single id or comma-seperated ids to limit the search to these locations (or events in these locations).', 'default'=>0),
41
- 'offset' => array( 'desc'=>'For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. Useful for pagination.', 'default'=>0),
42
- 'recurrence' => array( 'desc'=>'If set to 1, will show only events that are recurring (i.e. events that are repeated over different dates).', 'default'=>0),
43
- 'recurring' => array( 'desc'=>'If set to 1, will only show recurring event templates. Only useful if you know what you\'re doing, use recurrence if you want events that are recurrences.', 'default'=>0),
44
- 'month' => array( 'desc'=>'If set to a month (1 to 12) only events that start or end during this month/year will be retured. Must be used in conjunction with year and does not work as intended if used with scope.', 'default'=>''),
45
- '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'=>''),
46
- 'array' => array( 'desc'=>'If you supply this as an argument, the returned data will be in an array, no objects (only useful wen using PHP, not shortcodes)', 'default'=>0),
47
- 'pagination' => array('desc'=>'When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'default'=>0)
48
  )
49
  ),
50
  'placeholders' => array(
51
  'events' => array(
52
  'Event Details' => array(
53
  'placeholders' => array(
54
- '#_NAME' => array( 'desc' => 'Displays the name of the event.' ),
55
- '#_NOTES' => array( 'desc' => 'Shows the description of the event.' ),
56
- '#_EXCERPT' => array( 'desc' => '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 (currently, no read more link is added).' ),
57
- '#_EVENTID' => array( 'desc' => 'Shows the event corresponding ID number in the database table.' ),
58
- '#_EVENTIMAGE' => array( 'desc' => 'Shows the event image, if available.' )
 
 
 
 
 
 
59
  )
60
- ),
61
- 'Time' => array(
62
- 'desc' => '',
63
  'placeholders' => array(
64
  '#_24HSTARTTIME' => array( 'desc' => 'Displays the start time in a 24 hours format (e.g. 16:30).' ),
65
  '#_24HENDTIME' => array( 'desc' => 'Displays the end time in a 24 hours format (e.g. 18:30).' ),
66
  '#_12HSTARTTIME' => array( 'desc' => 'Displays the start time in a 12 hours format (e.g. 4:30 PM).' ),
67
- '#_12HENDTIME' => array( 'desc' => 'Displays the end time in a 12 hours format (e.g. 6:30 PM).' )
 
 
68
  )
69
  ),
70
  'Custom Date/Time Formatting' => array(
71
  'desc' => 'Events Manager allows extremely flexible date formatting by using <a href="http://www.php.net/manual/en/function.date.php">PHP date syntax format characters</a> along with placeholders.',
72
  'placeholders' => array(
73
  '# or #@' => array( 'desc' => 'Prepend <code>#</code> or <code>#@</code> before a valid PHP date syntax format character to show start and end date/time information respectively (e.g. <code>#F</code> will show the starting month name like "January", #@h shows the end hour).' ),
74
- '#{x} or #@{x}' => array( 'desc' => 'You can also create a date format without prepending # to each character by wrapping a valid php date() format in <code>#{}</code> or <code>#@{}</code> (e.g. <code>#_{d/m/Y}</code>). If there is no end date (or is same as start date), the value is not shown. This is useful if you want to show event end dates only on events that are longer than on day, e.g. <code>#j #M #Y #@_{ \u\n\t\i\l j M Y}</code>.' ),
75
  )
76
  ),
77
- 'Links' => array(
78
  'placeholders' => array(
79
- '#_EVENTURL' => array( 'desc' => 'Simply prints the event URL. You can use this placeholder to build your own customised links.' ),
80
  '#_EVENTIMAGEURL' => array( 'desc' => 'Shows the event image url, if available.' ),
 
81
  '#_EVENTLINK' => array( 'desc' => 'Displays the event name with a link to the event page.' ),
82
  '#_EDITEVENTLINK' => array( 'desc' => 'Inserts a link to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.' ),
83
- '#_EDITEVENTURL' => array( 'desc' => 'Inserts a url to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.' )
84
  )
85
  ),
86
  'Custom Attributes' => array(
87
- 'desc' => 'Events Manager allows you to create dynamic attributes to your events, which act as extra information fields for your events (e.g. "Dress Code"). For more information see <a href="http://wp-events-plugin.com/documentation/categories-and-attributes/">our online documentation</a> for more info on attributes.',
88
  'placeholders' => array(
89
- '#_ATT{key}{alternative text}' => array('desc'=>'This key will appear as an option when adding attributes to your event. The second braces are optional and will appear if the attribute is not defined or left blank for that event.')
 
 
90
  )
91
  ),
92
- 'Bookings/RSVP' => array(
93
- 'desc' => 'These placeholders will only show if RSVP is enabled for the given event and in the events manager settings page. Spaces placeholders will default to 0',
94
  'placeholders' => array(
95
  '#_BOOKINGFORM' => array( 'desc' => 'Adds a booking forms for this event.' ),
 
96
  '#_AVAILABLESPACES' => array( 'desc' => 'Shows available spaces for the event.' ),
97
  '#_BOOKEDSPACES' => array( 'desc' => 'Shows the amount of currently booked spaces for the event.' ),
98
  '#_PENDINGSPACES' => array( 'desc' => 'Shows the amount of pending spaces for the event.' ),
99
  '#_SPACES' => array( 'desc' => 'Shows the total spaces for the event.' ),
100
- '#_ATTENDEES' => array( 'desc' => 'Shows the list of user avatars attending events.' ),
101
- '#_BOOKINGBUTTON' => array( 'desc' => 'A single button that will appear to logged in users, if they click on it, they apply for a booking. This button will only display if there is one ticket.' ),
102
- '#_BOOKINGSURL' => array( 'desc' => 'Shows the url to the admin or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.' ),
103
- '#_BOOKINGSLINK' => array( 'desc' => 'Shows a link to the admin or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.' )
 
 
 
 
 
104
  )
105
  ),
106
  'Contact Details' => array(
@@ -109,46 +152,127 @@ function em_docs_init(){
109
  '#_CONTACTNAME' => array( 'desc' => 'Name of the contact person for this event (as shown in the dropdown when adding an event).' ),
110
  '#_CONTACTUSERNAME' => array( 'desc' => 'Contact person\'s username.' ),
111
  '#_CONTACTEMAIL' => array( 'desc' => 'E-mail of the contact person for this event.' ),
 
112
  '#_CONTACTPHONE' => array( 'desc' => 'Phone number of the contact person for this event. Can be set in the user profile page.' ),
113
  '#_CONTACTAVATAR' => array( 'desc' => 'Contact person\'s avatar.' ),
114
  '#_CONTACTPROFILELINK' => array( 'desc' => 'Contact person\'s "Profile" link. Only works with BuddyPress enabled.' ),
115
  '#_CONTACTPROFILEURL' => array( 'desc' => 'Contact person\'s profile url. Only works with BuddyPress enabled.' ),
116
- '#_CONTACTID' => array( 'desc' => 'Contact person\'s wordpress user ID.')
 
117
  )
118
- ),
 
 
 
 
 
 
 
 
119
  ),
120
  'categories' => array(
121
  'Category Details' => array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  'placeholders' => array(
123
- '#_CATEGORYNAME' => array( 'desc' => 'Shows the category name of the event.' ),
124
- '#_CATEGORYID' => array( 'desc' => 'Shows the category ID of the event.' ),
125
- '#_CATEGORYIMAGE' => array( 'desc' => 'Shows the event image, if available.' ),
126
- '#_CATEGORYIMAGEURL' => array( 'desc' => 'Shows the event image url, if available.' ),
127
- '#_CATEGORYNOTES' => array( 'desc' => 'Shows the location description.' )
128
  )
129
- )
130
  ),
131
  'locations' => array(
132
  'Location Details' => array(
133
  'desc' => '',
134
  'placeholders' => array(
 
 
135
  '#_LOCATIONNAME' => array( 'desc' => 'Displays the location name.' ),
136
  '#_LOCATIONADDRESS' => array( 'desc' => 'Displays the address.' ),
137
  '#_LOCATIONTOWN' => array( 'desc' => 'Displays the town.' ),
138
  '#_LOCATIONSTATE' => array( 'desc' => 'Displays the state/county.' ),
139
  '#_LOCATIONPOSTCODE' => array( 'desc' => 'Displays the postcode.' ),
 
140
  '#_LOCATIONCOUNTRY' => array( 'desc' => 'Displays the country.' ),
141
- '#_LOCATIONMAP' => array( 'desc' => 'Displays a google map showing where the event is located (Will not show if maps are disabled in the settings page)' ),
 
 
142
  '#_LOCATIONNOTES' => array( 'desc' => 'Shows the location description.' ),
143
- '#_LOCATIONEXCERPT' => array( 'desc' => 'If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your location description, only the content before this tag will show (currently, no read more link is added).' ),
 
144
  '#_LOCATIONIMAGE' => array( 'desc' => 'Shows the location image.' ),
145
- '#_LOCATIONID' => array( 'desc' => 'Displays the location ID number.' )
 
 
 
 
 
 
 
 
 
 
 
146
  )
147
  ),
148
  'Links' => array(
149
  'placeholders' => array(
150
  '#_LOCATIONURL' => array( 'desc' => 'Simply prints the location URL. You can use this placeholder to build your own customised links.' ),
151
- '#_LOCATIONLINK' => array( 'desc' => 'Displays the location name with a link to the location page.' )
 
 
152
  )
153
  ),
154
  'Related Events' => array(
@@ -156,19 +280,58 @@ function em_docs_init(){
156
  'placeholders' => array(
157
  '#_LOCATIONPASTEVENTS' => array( 'desc' => 'Will show a list of all past events at this location.' ),
158
  '#_LOCATIONNEXTEVENTS' => array( 'desc' => 'Will show a list of all future events at this location.' ),
159
- '#_LOCATIONALLEVENTS' => array( 'desc' => 'Will show a list of all events at this location.' )
 
160
  )
161
  ),
 
 
 
 
 
 
 
 
162
  ),
163
  'bookings' => array(
164
- 'Booking Person Information' => array(
165
- 'desc' => 'When a specific booking is displayed (on screen and on email), you can use these placeholders to show specific information about the booking. For contact details of the contact of this event, see the events placeholders.',
166
  'placeholders' => array(
 
167
  '#_BOOKINGNAME' => array( 'desc' => 'Name of person who made the booking.' ),
168
  '#_BOOKINGEMAIL' => array( 'desc' => 'Email of person who made the booking.' ),
169
  '#_BOOKINGPHONE' => array( 'desc' => 'Phone number of person who made the booking.' ),
170
  '#_BOOKINGSPACES' => array( 'desc' => 'Number of spaces the person has booked.' ),
171
- '#_BOOKINGCOMMENT' => array( 'desc' => 'Any specific comments made by the person who made the booking.' )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  )
173
  ),
174
  'Links' => array(
@@ -176,7 +339,23 @@ function em_docs_init(){
176
  'placeholders' => array(
177
  '#_BOOKINGLISTURL' => array( 'desc' => 'URL to page showing that users booked events.' )
178
  )
179
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  ),
181
  ),
182
  //TODO add capabilites explanations
1
  <?php
2
 
3
+ function em_docs_init($force_init = false){
4
+ global $pagenow;
5
+ if( ($pagenow == 'edit.php' && !empty($_GET['page']) && $_GET['page']=='events-manager-help' && class_exists('EM_Event')) || $force_init){
6
  add_action('wp_head', 'emd_head');
7
  //Generate the docs
8
  global $EM_Documentation;
13
  $EM_Documentation = array(
14
  'arguments' => array(
15
  'events' => array(
16
+ 'blog' => array( 'desc' => sprintf('Limit search to %s created in a specific blog id (MultiSite only)','events')),
17
+ 'bookings' => array( 'desc'=> 'Include only events with bookings enabled. Use \'user\' to show events a logged in user has booked.'.'1 = yes, 0 = no'),
18
+ 'category' => array( 'desc'=> str_replace('%s','categories', 'Supply a single id, slug or comma-seperated 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 seperate ids and slugs, in which case events must contain (or not contain) both %s to be shown.'), 'default'=>0),
19
+ 'tag' => array( 'desc'=> str_replace('%s', 'tags', 'Supply a single id, slug or comma-seperated 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 seperate ids and slugs, in which case events must contain (or not contain) both %s to be shown.'), 'default'=>0),
20
+ 'event' => array( 'desc'=> sprintf('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to %s with the %s.','events', 'event_id(s)'), 'default'=>0),
21
+ 'group' => array( 'desc' => 'Limit search to events belonging to a specific group id (BuddyPress only). Using \'my\' will show events belonging to groups the logged in user is a member of.'),
22
+ 'post_id' => array( 'desc' => sprintf('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to %s with the %s.','events', 'post_id(s)')),
23
+ 'private' => array( 'desc' => sprintf('Display private %s within your list?','events'), 'args' => '1 = yes, 0 = no', 'default' => 'If user can view private events, 1, otherwise 0.'),
24
+ 'private_only' => array( 'desc' =>sprintf('Display only private %s ?','events'), 'args' => '1 = yes, 0 = no', 'default' => '0'),
25
+ 'recurrence' => array( 'desc'=> 'If set to the event id of the recurring event, this will show only events this event recurrences.', 'default'=>0),
26
+ 'recurring' => array( 'desc'=> 'If set to 1, will only show recurring event templates. Only useful if you know what you\'re doing, use recurrence if you want events that are recurrences.', 'default'=>0),
27
+ 'search' => array( 'desc'=> 'Do a search for this string within event name, details and location address.' ),
28
+ 'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','events'), 'default'=>1),
29
+ 'scope' => array( 'desc'=> 'Choose the time frame of events to show. Additionally you can supply dates (in format of YYYY-MM-DD), either single for events on a specific date or two dates seperated by a comma (e.g. 2010-12-25,2010-12-31) for events ocurring between these dates.', 'default'=>'future', 'args'=>array("future", "past", "today", "tomorrow", "month", "next-month", "1-months", "2-months", "3-months", "6-months", "12-months","all")),
30
+ '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'=>''),
31
  ),
32
  'locations' => array(
33
+ 'blog' => array( 'desc' => sprintf('Limit search to %s created in a specific blog id (MultiSite only)','locations')),
34
+ 'eventful' => array( 'desc'=> 'If set to 1 will only show locations that have at least one event occurring during the scope.', 'default' => 0),
35
+ 'eventless' => array( 'desc'=> 'If set to 1 will only show locations that have no events occurring during the scope.', 'default' => 0),
36
+ 'location' => array( 'desc'=> sprintf('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to %s with the %s.','locations', 'location_id(s)'), 'default'=>0),
37
+ 'post_id' => array( 'desc' => sprintf('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to %s with the %s.','locations', 'post_id(s)')),
38
+ 'private' => array( 'desc' => sprintf('Display private %s within your list?','locations'), 'args' => '1 = yes, 0 = no', 'default' => 'If user can view private locations, 1, otherwise 0.'),
39
+ 'private_only' => array( 'desc' =>sprintf('Display only private %s ?','locations'), 'args' => '1 = yes, 0 = no', 'default' => '0'),
40
+ 'scope' => array( 'default' => 'all'),
41
+ 'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','locations'), 'default'=>1),
42
+ 'country' => array( 'desc'=> sprintf('Search for %s in this %s (no partial matches, case sensitive).','locations','Country'), 'default' => 'none', 'args'=>'Use two-character country codes as defined in <a href="http://countrycode.org/">countrycode.org</a>, e.g. US,GB,ES'),
43
+ 'region' => array( 'desc'=> sprintf('Search for %s in this %s (no partial matches, case sensitive).','locations','Region'), 'default' => 'none'),
44
+ 'state' => array( 'desc'=> sprintf('Search for %s in this %s (no partial matches, case sensitive).','locations','State'), 'default' => 'none'),
45
+ 'town' => array( 'desc'=> sprintf('Search for %s in this %s (no partial matches, case sensitive).','locations','Town'), 'default' => 'none'),
46
+ 'postcode' => array( 'desc'=> sprintf('Search for %s in this %s (no partial matches, case sensitive).','locations','Postcode'), 'default' => 'none')
47
+ ),
48
+ 'categories' => array(
49
+ '' => array( 'desc' => 'See the <a href="http://codex.wordpress.org/Function_Reference/get_terms">WordPress get_terms() Codex</a> for a list of possible search attributes/arguments.'),
50
+ ),
51
+ 'tags' => array(
52
+ '' => array( 'desc' => 'See the <a href="http://codex.wordpress.org/Function_Reference/get_terms">WordPress get_terms() Codex</a> for a list of possible search attributes/arguments.'),
53
  ),
54
  'calendar' => array(
55
+ 'full' => array( 'desc'=> 'If set to 1 it will display a full calendar that shows event names.', 'default' => 0),
56
+ 'long_events' => array( 'desc'=> 'If set to 1, will show events that last longer than a day.', 'default' => 0),
 
 
57
  ),
58
  //The object is commonly shared by all, so entries above overwrite entries here
59
  'general' => array(
60
+ 'array' => array( 'desc'=> 'If you supply this as an argument, the returned data will be in an array, not an object (only useful wen using PHP, not shortcodes)', 'default'=>0),
61
+ 'format_header' => array( 'desc'=> sprintf('If you are displaying lists (e.g. listing events), you can supply the %s html and placeholders here.','header'), 'default'=> 'The relevant default format will be taken from the settings page.'),
62
+ 'format' => array( 'desc'=> 'If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here.', 'default'=> 'The relevant default format will be taken from the settings page.'),
63
+ 'format_footer' => array( 'desc'=> sprintf('If you are displaying lists (e.g. listing events), you can supply the %s html and placeholders here.','footer'), 'default'=> 'The relevant default format will be taken from the settings page.'),
64
+ 'limit' => array( 'desc'=> 'Limits the amount of values returned to this number.', 'default'=>'0 (no limit)'),
65
+ 'offset' => array( 'desc'=> 'For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. Useful for pagination.', 'default'=>0),
66
+ 'order' => array( 'desc'=> 'Indicates the alphabeitcal/numerical order of the lists. Choose between ASC (ascending) and DESC (descending).', 'default'=>'ASC'),
67
+ 'orderby' => array( 'desc'=> 'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "event_start_date,event_name").', 'default'=>0, 'args'=>'Database table fields, e.g. <code>event_name</code> or <code>location_name</code>'),
68
+ 'owner' => array('desc'=> 'Limits returned results to a specific owner, identified by their user id (e.g. list events or locations owned by user)', 'default'=>0),
69
+ 'pagination' => array('desc'=> 'When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'default'=>0),
70
+ 'page' => array('desc' => 'Which page shall be shown. Requires pagination to be set to 1 and will override the offset value if also provided.'),
71
+ 'page_queryvar' => array('desc'=>'The default parameter name used to figure out the page number to show is pno, provide a unique name if you want to display two lists on the same page with independent pagination.'),
72
+ 'near' => array('desc'=>'Accepts a comma-seperated coordinates (e.g. 1,1) value, which searches for events or locations located near this coordinate.'),
73
+ 'near_unit' => array('desc'=>'The distance unit used when a near attribute is provided.', 'default'=>'mi', 'args'=>'mi or km'),
74
+ 'near_distance' => array('desc'=>'The radius distance when searching with the near attribute. near_unit will determine whether this is in miles or kilometers.'),
75
  )
76
  ),
77
  'placeholders' => array(
78
  'events' => array(
79
  'Event Details' => array(
80
  'placeholders' => array(
81
+ '#_EVENTID' => array( 'desc' => 'Shows the event ID number in the wp_em_events table.' ),
82
+ '#_EVENTPOSTID' => array( 'desc' => 'Shows the event corresponding Post ID in the wp_posts table.' ),
83
+ '#_EVENTNAME' => array( 'desc' => 'Displays the name of the event.' ),
84
+ '#_EVENTNOTES' => array( 'desc' => 'Shows the description of the event.' ),
85
+ '#_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.' ),
86
+ '#_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.' ),
87
+ '#_EVENTIMAGE' => array( 'desc' => 'Shows the event image, if available.' ),
88
+ '#_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' ),
89
+ '#_EVENTCATEGORIES' => array( 'desc' => 'Shows a list of category links this event belongs to.' ),
90
+ '#_EVENTCATEGORIESIMAGES' => array( 'desc' => 'Shows a list of category images this event belongs to. Categories without an image will be ignored.' ),
91
+ '#_EVENTTAGS' => array( 'desc' => 'Shows a list of tag links this event belongs to.' ),
92
  )
93
+ ),
94
+ 'Date and Times' => array(
95
+ 'desc' => 'These are shortcut placeholders for pre-formatted dates and times. See the Custom Date/Time Formatting section below for more refined formatting placeholders.',
96
  'placeholders' => array(
97
  '#_24HSTARTTIME' => array( 'desc' => 'Displays the start time in a 24 hours format (e.g. 16:30).' ),
98
  '#_24HENDTIME' => array( 'desc' => 'Displays the end time in a 24 hours format (e.g. 18:30).' ),
99
  '#_12HSTARTTIME' => array( 'desc' => 'Displays the start time in a 12 hours format (e.g. 4:30 PM).' ),
100
+ '#_12HENDTIME' => array( 'desc' => 'Displays the end time in a 12 hours format (e.g. 6:30 PM).' ),
101
+ '#_EVENTTIMES' => array( 'desc' => 'Displays either a single time, time-span, or "All Day" depending on your event times. Format is taken from your Events Manager settings page.' ),
102
+ '#_EVENTDATES' => array( 'desc' => 'Displays either a single date or a date range depending on your event dates. Format is taken from your Events Manager settings page.' ),
103
  )
104
  ),
105
  'Custom Date/Time Formatting' => array(
106
  'desc' => 'Events Manager allows extremely flexible date formatting by using <a href="http://www.php.net/manual/en/function.date.php">PHP date syntax format characters</a> along with placeholders.',
107
  'placeholders' => array(
108
  '# or #@' => array( 'desc' => 'Prepend <code>#</code> or <code>#@</code> before a valid PHP date syntax format character to show start and end date/time information respectively (e.g. <code>#F</code> will show the starting month name like "January", #@h shows the end hour).' ),
109
+ '#{x} or #@{x}' => array( 'desc' => 'You can also create a date format without prepending # to each character by wrapping a valid php date() format in <code>#{}</code> or <code>#@{}</code> (e.g. <code>#_{d/m/Y}</code>). If there is no end date (or is same as start date), the value is not shown. This is useful if you want to show event end dates only on events that are longer than one day, e.g. <code>#j #M #Y #@_{ \u\n\t\i\l j M Y}</code>.' ),
110
  )
111
  ),
112
+ 'Links/URLs' => array(
113
  'placeholders' => array(
 
114
  '#_EVENTIMAGEURL' => array( 'desc' => 'Shows the event image url, if available.' ),
115
+ '#_EVENTURL' => array( 'desc' => 'Simply prints the event URL. You can use this placeholder to build your own customised links.' ),
116
  '#_EVENTLINK' => array( 'desc' => 'Displays the event name with a link to the event page.' ),
117
  '#_EDITEVENTLINK' => array( 'desc' => 'Inserts a link to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.' ),
118
+ '#_EDITEVENTURL' => array( 'desc' => 'Inserts a url to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.' ),
119
  )
120
  ),
121
  'Custom Attributes' => array(
122
+ 'desc' => 'Events Manager allows you to create dynamic attributes to your events, which act as extra information fields for your events (e.g. "Dress Code"). For more information see <a href="http://wp-events-plugin.com/documentation/event-attributes/">our online documentation</a> for more info on attributes.',
123
  'placeholders' => array(
124
+ '#_ATT{key}' => array('desc'=> 'This key will appear as an option when adding attributes to your event.'),
125
+ '#_ATT{key}{alternative text}' => array('desc'=> 'This key will appear as an option when adding attributes to your event. The text in the second braces will appear if the attribute is not defined or left blank for that event.'),
126
+ '#_ATT{key}{option 1|option 2|option 3|etc.}' => array('desc'=> 'This key will appear as an option when adding attributes to your event. The second braces are optional and will use a select box with these values as input. If no valid value is defined, the first option is used.'),
127
  )
128
  ),
129
+ 'Bookings' => array(
130
+ 'desc' => 'These placeholders will only show if bookings are enabled for the given event and in the events manager settings page. Spaces placeholders will default to 0',
131
  'placeholders' => array(
132
  '#_BOOKINGFORM' => array( 'desc' => 'Adds a booking forms for this event.' ),
133
+ '#_BOOKINGBUTTON' => array( 'desc' => 'A single button that will appear to logged in users, if they click on it, they apply for a booking. This button will only display if there is one ticket.' ),
134
  '#_AVAILABLESPACES' => array( 'desc' => 'Shows available spaces for the event.' ),
135
  '#_BOOKEDSPACES' => array( 'desc' => 'Shows the amount of currently booked spaces for the event.' ),
136
  '#_PENDINGSPACES' => array( 'desc' => 'Shows the amount of pending spaces for the event.' ),
137
  '#_SPACES' => array( 'desc' => 'Shows the total spaces for the event.' ),
138
+ '#_ATTENDEES' => array( 'desc' => 'Shows the list of user avatars attending the event.' ),
139
+ '#_ATTENDEESLIST' => array( 'desc' => 'Shows the list of people attending the event.' ),
140
+ '#_ATTENDEESPENDINGLIST' => array( 'desc' => 'Shows the list of people with a pending booking for the event.' ),
141
+ '#_BOOKINGSURL' => array( 'desc' => 'Shows the url to the admin, front-end or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.' ),
142
+ '#_BOOKINGSLINK' => array( 'desc' => 'Shows a link to the admin, front-end or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.' ),
143
+ '#_EVENTPRICERANGE' => array( 'desc' => 'Shows a "maximum - minimum" price range for available tickets at the time of display, or a single price if there is no range. Once bookings are closed this will show a 0 value, if you have enabled \'Show unavailable tickets\' in your booking settings these will be included. Price is formatted according to currency formatting in your settings page.' ),
144
+ '#_EVENTPRICERANGEALL' => array( 'desc' => 'Like #_EVENTPRICERANGE but shows all tickets price range whether or not bookings or individual tickets are available.' ),
145
+ '#_EVENTPRICEMIN' => array( 'desc' => 'Shows the lowest ticket price for this event.' ),
146
+ '#_EVENTPRICEMAX' => array( 'desc' => 'Shows the highest ticket price for this event.' ),
147
  )
148
  ),
149
  'Contact Details' => array(
152
  '#_CONTACTNAME' => array( 'desc' => 'Name of the contact person for this event (as shown in the dropdown when adding an event).' ),
153
  '#_CONTACTUSERNAME' => array( 'desc' => 'Contact person\'s username.' ),
154
  '#_CONTACTEMAIL' => array( 'desc' => 'E-mail of the contact person for this event.' ),
155
+ '#_CONTACTURL' => array( 'desc' => 'Website of the contact person for this event.' ),
156
  '#_CONTACTPHONE' => array( 'desc' => 'Phone number of the contact person for this event. Can be set in the user profile page.' ),
157
  '#_CONTACTAVATAR' => array( 'desc' => 'Contact person\'s avatar.' ),
158
  '#_CONTACTPROFILELINK' => array( 'desc' => 'Contact person\'s "Profile" link. Only works with BuddyPress enabled.' ),
159
  '#_CONTACTPROFILEURL' => array( 'desc' => 'Contact person\'s profile url. Only works with BuddyPress enabled.' ),
160
+ '#_CONTACTID' => array( 'desc' => 'Contact person\'s WordPress user ID.'),
161
+ '#_CONTACTMETA' => array( 'desc' => 'Display any user meta of a WordPress account by including the meta key, e.g. #_CONTACTMETA{dbem_phone}'),
162
  )
163
+ ),
164
+ 'iCal/Calendar' => array(
165
+ 'placeholders' => array(
166
+ '#_EVENTICALURL' => array( 'desc' => 'Displays the URL of the event ical feed (ics file format).' ),
167
+ '#_EVENTICALLINK' => array( 'desc' => 'Displays an html link to the event ical feed (ics file format).' ),
168
+ '#_EVENTGCALURL' => array( 'desc' => 'Displays URL which would take the user to Google Calendar and pre-fill their add new event form.' ),
169
+ '#_EVENTGCALLINK' => array( 'desc' => 'Displays a button which would take the user to Google Calendar and pre-fill their add new event form.' )
170
+ )
171
+ ),
172
  ),
173
  'categories' => array(
174
  'Category Details' => array(
175
+ 'desc' => 'You can use these when displaying categories or for showing the first available category in an event format.',
176
+ 'placeholders' => array(
177
+ '#_CATEGORYNAME' => array( 'desc' => 'Shows the category name.' ),
178
+ '#_CATEGORYID' => array( 'desc' => 'Shows the category ID.' ),
179
+ '#_CATEGORYSLUG' => array( 'desc' => 'Shows the category slug.' ),
180
+ '#_CATEGORYCOLOR' => array( 'desc' => 'Shows the category color (useful for inline styling), in hex format, if no color is defined #FFFFFF (white) will be used.' ),
181
+ '#_CATEGORYIMAGE' => array( 'desc' => 'Shows the category image, if available.' ),
182
+ '#_CATEGORYIMAGE{x,y}' => array( 'desc' => 'Shows the category image thumbnail if available, x and y are width and height respectively, both being numbers e.g. <code>#_CATEGORYIMAGE{100,100}</code>. If 0 is used for either width or height, the corresponding dimension will be proportionally sized.' ),
183
+ '#_CATEGORYIMAGEURL' => array( 'desc' => 'Shows the category image url, if available.' ),
184
+ '#_CATEGORYNOTES' => array( 'desc' => 'Shows the category description.' )
185
+ )
186
+ ),
187
+ 'Related Events' => array(
188
+ 'desc' => 'You can show lists of other events belonging to this category. The formatting of the list is the same as a normal events list.',
189
+ 'placeholders' => array(
190
+ '#_CATEGORYPASTEVENTS' => array( 'desc' => 'Will show a list of all past events with this category.' ),
191
+ '#_CATEGORYNEXTEVENTS' => array( 'desc' => 'Will show a list of all future events with this category.' ),
192
+ '#_CATEGORYALLEVENTS' => array( 'desc' => 'Will show a list of all events with this category.' ),
193
+ '#_CATEGORYNEXTEVENT' => array( 'desc' => 'Will show the next event with this category.' )
194
+ )
195
+ ),
196
+ 'iCal/RSS Feeds' => array(
197
+ 'placeholders' => array(
198
+ '#_CATEGORYICALURL' => array( 'desc' => 'Displays the URL of the event ical feed (ics file format) which shows all events happening in this category.', 'since'=>'5.5.2' ),
199
+ '#_CATEGORYICALLINK' => array( 'desc' => 'Displays an html link to the event ical feed (ics file format) which shows all events happening in this category.', 'since'=>'5.5.2' ),
200
+ '#_CATEGORYRSSURL' => array( 'desc' => 'Displays the URL of an RSS feed showing all upcoming events happening in this category.', 'since'=>'5.5.2' ),
201
+ '#_CATEGORYRSSLINK' => array( 'desc' => 'Displays an html link to an RSS feed showing all upcoming events happening in this category.', 'since'=>'5.5.2' )
202
+ )
203
+ )
204
+ ),
205
+ 'tags' => array(
206
+ 'Tag Details' => array(
207
+ 'desc' => 'You can use these when displaying tags or for showing the first available tag in an event format.',
208
+ 'placeholders' => array(
209
+ '#_TAGNAME' => array( 'desc' => 'Shows the tag name.' ),
210
+ '#_TAGID' => array( 'desc' => 'Shows the tag ID.' ),
211
+ '#_TAGSLUG' => array( 'desc' => 'Shows the tag slug.' ),
212
+ '#_TAGIMAGE' => array( 'desc' => 'Shows the tag image, if available.' ),
213
+ '#_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.' ),
214
+ '#_TAGIMAGEURL' => array( 'desc' => 'Shows the tag image url, if available.' ),
215
+ '#_TAGNOTES' => array( 'desc' => 'Shows the tag description.' )
216
+ )
217
+ ),
218
+ 'Related Events' => array(
219
+ 'desc' => 'You can show lists of other events belonging to this tag. The formatting of the list is the same as a normal events list.',
220
+ 'placeholders' => array(
221
+ '#_TAGPASTEVENTS' => array( 'desc' => 'Will show a list of all past events with this tag.' ),
222
+ '#_TAGNEXTEVENTS' => array( 'desc' => 'Will show a list of all future events with this tag.' ),
223
+ '#_TAGALLEVENTS' => array( 'desc' => 'Will show a list of all events with this tag.' ),
224
+ '#_TAGNEXTEVENT' => array( 'desc' => 'Will show the next event with this tag.' )
225
+ )
226
+ ),
227
+ 'iCal/RSS Feeds' => array(
228
  'placeholders' => array(
229
+ '#_TAGICALURL' => array( 'desc' => 'Displays the URL of the event ical feed (ics file format) which shows all events happening in this tag.', 'since'=>'5.5.2' ),
230
+ '#_TAGICALLINK' => array( 'desc' => 'Displays an html link to the event ical feed (ics file format) which shows all events happening in this tag.' , 'since'=>'5.5.2'),
231
+ '#_TAGRSSURL' => array( 'desc' => 'Displays the URL of an RSS feed showing all upcoming events happening in this tag.', 'since'=>'5.5.2' ),
232
+ '#_TAGRSSLINK' => array( 'desc' => 'Displays an html link to an RSS feed showing all upcoming events happening in this tag.', 'since'=>'5.5.2' )
 
233
  )
234
+ )
235
  ),
236
  'locations' => array(
237
  'Location Details' => array(
238
  'desc' => '',
239
  'placeholders' => array(
240
+ '#_LOCATIONID' => array( 'desc' => 'Shows the event ID number in the wp_em_locations table.' ),
241
+ '#_LOCATIONPOSTID' => array( 'desc' => 'Shows the location corresponding Post ID in the wp_posts table.' ),
242
  '#_LOCATIONNAME' => array( 'desc' => 'Displays the location name.' ),
243
  '#_LOCATIONADDRESS' => array( 'desc' => 'Displays the address.' ),
244
  '#_LOCATIONTOWN' => array( 'desc' => 'Displays the town.' ),
245
  '#_LOCATIONSTATE' => array( 'desc' => 'Displays the state/county.' ),
246
  '#_LOCATIONPOSTCODE' => array( 'desc' => 'Displays the postcode.' ),
247
+ '#_LOCATIONREGION' => array( 'desc' => 'Displays the region.' ),
248
  '#_LOCATIONCOUNTRY' => array( 'desc' => 'Displays the country.' ),
249
+ '#_LOCATIONLONGITUDE' => array( 'desc' => 'Displays the longitude, used for locating in Google Maps.' ),
250
+ '#_LOCATIONLATITUDE' => array( 'desc' => 'Displays the latitude, used for locating in Google Maps.' ),
251
+ '#_LOCATIONMAP' => array( 'desc' => 'Displays a google map showing where the location is located (Will not show if maps are disabled in the settings page)' ),
252
  '#_LOCATIONNOTES' => array( 'desc' => 'Shows the location description.' ),
253
+ '#_LOCATIONEXCERPT' => array( 'desc' => 'If an excerpt has been added to the location, it will be used. If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your location description, only the content before this tag will show.' ),
254
+ '#_LOCATIONEXCERPT{words, ...}' => array( 'desc' => 'If an excerpt has not been added to the location, only a specific length is shown, e.g. <code>#_EVENTEXCERPT{10,...}</code> where 10 is the number of words to show and ... is what is used at the cut-off point.' ),
255
  '#_LOCATIONIMAGE' => array( 'desc' => 'Shows the location image.' ),
256
+ '#_LOCATIONIMAGE{x,y}' => array( 'desc' => 'Shows the location image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_LOCATIONIMAGE{100,100}</code>. If 0 is used for either width or height, the corresponding dimension will be proportionally sized.' ),
257
+ '#_LOCATIONIMAGEURL' => array( 'desc' => 'Shows the location image url, if available.' ),
258
+ '#_LOCATIONFULLLINE' => array( 'desc' => 'Shows a comma-seperated line of location information, ommitting blanks (format of address, town, state, postcode, region' ),
259
+ '#_LOCATIONFULLBR' => array( 'desc' => 'Shows a line-break (br tag) seperated location information, ommitting blanks (format of address, town, state, postcode, region' ),
260
+ )
261
+ ),
262
+ 'Custom Attributes' => array(
263
+ 'desc' => 'Events Manager allows you to create dynamic attributes to your locations, which act as extra information fields for your locations (e.g. "Dress Code"). For more information see <a href="http://wp-events-plugin.com/documentation/event-attributes/">our online documentation</a> for more info on attributes.',
264
+ 'placeholders' => array(
265
+ '#_LATT{key}' => array('desc'=> 'This key will appear as an option when adding attributes to your location.'),
266
+ '#_LATT{key}{alternative text}' => array('desc'=> 'This key will appear as an option when adding attributes to your location. The text in the second braces will appear if the attribute is not defined or left blank for that location.'),
267
+ '#_LATT{key}{option 1|option 2|option 3|etc.}' => array('desc'=> 'This key will appear as an option when adding attributes to your location. The second braces are optional and will use a select box with these values as input. If no valid value is defined, the first option is used.'),
268
  )
269
  ),
270
  'Links' => array(
271
  'placeholders' => array(
272
  '#_LOCATIONURL' => array( 'desc' => 'Simply prints the location URL. You can use this placeholder to build your own customised links.' ),
273
+ '#_LOCATIONLINK' => array( 'desc' => 'Displays the location name with a link to the location page.' ),
274
+ '#_EDITLOCATIONLINK' => array( 'desc' => 'Inserts a link to the admin or buddypress (if activated) edit location page, only if a user is logged in and is allowed to edit the location.' ),
275
+ '#_EDITLOCATIONURL' => array( 'desc' => 'Inserts a url to the admin or buddypress (if activated) edit location page, only if a user is logged in and is allowed to edit the location.' )
276
  )
277
  ),
278
  'Related Events' => array(
280
  'placeholders' => array(
281
  '#_LOCATIONPASTEVENTS' => array( 'desc' => 'Will show a list of all past events at this location.' ),
282
  '#_LOCATIONNEXTEVENTS' => array( 'desc' => 'Will show a list of all future events at this location.' ),
283
+ '#_LOCATIONALLEVENTS' => array( 'desc' => 'Will show a list of all events at this location.' ),
284
+ '#_LOCATIONNEXTEVENT' => array( 'desc' => 'Will show a link to the next event at this location, or the no events message.' ),
285
  )
286
  ),
287
+ 'iCal/RSS Feeds' => array(
288
+ 'placeholders' => array(
289
+ '#_LOCATIONICALURL' => array( 'desc' => 'Displays the URL of the location ical feed (ics file format) which shows all events happening at that location.', 'since'=>'5.5.2' ),
290
+ '#_LOCATIONICALLINK' => array( 'desc' => 'Displays an html link to the event ical feed (ics file format) which shows all events happening at that location.', 'since'=>'5.5.2' ),
291
+ '#_LOCATIONRSSURL' => array( 'desc' => 'Displays the URL of an RSS feed showing all upcoming events happening at this location.', 'since'=>'5.5.2' ),
292
+ '#_LOCATIONRSSLINK' => array( 'desc' => 'Displays an html link to an RSS feed showing all upcoming events happening at this location.', 'since'=>'5.5.2' )
293
+ )
294
+ )
295
  ),
296
  'bookings' => array(
297
+ 'Individual Booking Information' => array(
298
+ 'desc' => 'When a specific booking is displayed (on screen and on email), you can use these placeholders to show specific information about the booking. Event and Location placeholders are also available in these cases.',
299
  'placeholders' => array(
300
+ '#_BOOKINGID' => array( 'desc' => 'The unique ID of this booking, useful if you are making your own customizations to this plugin.' ),
301
  '#_BOOKINGNAME' => array( 'desc' => 'Name of person who made the booking.' ),
302
  '#_BOOKINGEMAIL' => array( 'desc' => 'Email of person who made the booking.' ),
303
  '#_BOOKINGPHONE' => array( 'desc' => 'Phone number of person who made the booking.' ),
304
  '#_BOOKINGSPACES' => array( 'desc' => 'Number of spaces the person has booked.' ),
305
+ '#_BOOKINGCOMMENT' => array( 'desc' => 'Any specific comments made by the person who made the booking.' ),
306
+ '#_BOOKINGTICKETNAME' => array( 'desc' => 'Name of the ticket booked. Useful in single ticket mode, if multiple tickets are booked a random ticket is used.' ),
307
+ '#_BOOKINGTICKETDESCRIPTION' => array( 'desc' => 'Description of the ticket booked. Useful in single ticket mode, if multiple tickets are booked a random ticket is used.' ),
308
+ '#_BOOKINGTICKETPRICE' => array( 'desc' => 'Booked ticket price with currency symbol (e.g. $ 10.00). Useful in single ticket mode, if multiple tickets are booked a random ticket is used.' ),
309
+ '#_BOOKINGTICKETS' => array( 'desc' => 'A list of booked tickets. You can modify this by using template files and modifying templates/emails/bookingtickets.php' ),
310
+ '#_BOOKINGSUMMARY' => array( 'desc' => 'Shows a breakdown of price/quantity booked by ticket, followed by a summary of price totals, taxes, and other discounts applied.' ),
311
+ '#_BOOKINGFORMCUSTOM{field_id}' => array( 'desc' => sprintf('(<a href="%s">pro only</a>) Shows booking form custom fields. The field_id value must match that of your custom booking form field.','http://wp-events-plugin.com/features/') ),
312
+ '#_BOOKINGFORMCUSTOMREG{field_id}' => array( 'desc' => sprintf('(<a href="%s">pro only</a>) Shows booking form custom fields that are used for guest user registration. The field_id value must match that of your custom booking form field.','http://wp-events-plugin.com/features/') ),
313
+ '#_BOOKINGFORMCUSTOMFIELDS' => array( 'desc' => sprintf('(<a href="%s">pro only</a>) Generates a list of booking form custom fields that are used in the booking.','http://wp-events-plugin.com/features/') ),
314
+ '#_BOOKINGATTENDEES' => array('desc' => sprintf('(<a href="%s">pro only</a>) Generates a list of attendee information displaying the filled in form data for each attendee (requires individual attendee forms enabled for the event). This list is split by ticket type, then by individual attendee.','http://wp-events-plugin.com/features/')), //coupons too!
315
+ )
316
+ ),
317
+ 'Pricing Information' => array(
318
+ 'desc' => '',
319
+ 'placeholders' => array(
320
+ '#_BOOKINGPRICE' => array( 'desc' => 'Displays booking total price (tax inclusion depends on your booking settings).' ),
321
+ '#_BOOKINGPRICETAX' => array( 'desc' => 'Displays booking total tax.' ),
322
+ '#_BOOKINGPRICEWITHOUTTAX' => array( 'desc' => 'Displays booking total without tax.' ),
323
+ '#_BOOKINGPRICEWITHTAX' => array( 'desc' => 'Displays booking total with tax.' ),
324
+ )
325
+ ),
326
+ 'Ticket Information' => array(
327
+ 'desc' => '',
328
+ 'placeholders' => array(
329
+ '#_BOOKINGTICKETS' => array( 'desc' => 'Shows a breakdown of tickets and pricing, defined in the <code>emails/bookingtickets.php</code> template. (See <a href="http://wp-events-plugin.com/documentation/using-template-files/">Using Template Files</a> for more information)' ),
330
+ '#_BOOKINGTICKETDESCRIPTION' => array( 'desc' => 'Shows the description of the first ticket booked (useful in single ticket mode/events).' ),
331
+ '#_BOOKINGTICKETPRICE' => array( 'desc' => 'Shows the price of the first ticket booked, tax inclusion depending on your booking settings (useful in single ticket mode/events).' ),
332
+ '#_BOOKINGTICKETTAX' => array( 'desc' => 'Shows the tax of the first ticket booked (useful in single ticket mode/events).' ),
333
+ '#_BOOKINGTICKETPRICEWITHTAX' => array( 'desc' => 'Shows the price including tax of the first ticket booked (useful in single ticket mode/events).' ),
334
+ '#_BOOKINGTICKETPRICEWITHOUTTAX' => array( 'desc' => 'Shows the price excluding tax of the first ticket booked (useful in single ticket mode/events).' ),
335
  )
336
  ),
337
  'Links' => array(
339
  'placeholders' => array(
340
  '#_BOOKINGLISTURL' => array( 'desc' => 'URL to page showing that users booked events.' )
341
  )
342
+ ),
343
+ 'Gateway-Specific Information' => array(
344
+ 'desc' => 'Information pertaining to speicifc gateways. '. sprintf('Requires <a href="%s">Events Manager Pro</a>','http://wp-events-plugin.com/features/'),
345
+ 'placeholders' => array(
346
+ '#_BOOKINGTXNID' => array( 'desc' => '<em>Online Payments Only</em> - Prints the transaction ID of this booking if available.' )
347
+ )
348
+ ),
349
+ 'Coupon Information' => array(
350
+ 'desc' => 'When a booking has been made with a coupon, you can display coupon information using these placeholders. If no coupon is used, nothing will be shown. '.sprintf('Requires <a href="%s">Events Manager Pro</a>','http://wp-events-plugin.com/features/'),
351
+ 'placeholders' => array(
352
+ '#_BOOKINGCOUPON' => array('desc' => 'Displays the coupon code followed by the amount/percentage discounted.'),
353
+ '#_BOOKINGCOUPONCODE' => array('desc' => 'Displays the coupon code used.'),
354
+ '#_BOOKINGCOUPONNAME' => array('desc' => 'Displays the name given to this coupon.'),
355
+ '#_BOOKINGCOUPONDISCOUNT' => array('desc' => 'Displays amount/percentage discounted (e.g. 25% Off).'),
356
+ '#_BOOKINGCOUPONDESCRIPTION' => array('desc' => 'Displays the coupon description.'),
357
+ )
358
+ ),
359
  ),
360
  ),
361
  //TODO add capabilites explanations
admin/em-event.php DELETED
@@ -1,753 +0,0 @@
1
- <?php
2
- /**
3
- * Generates Event Admin page, for adding and updating a single (or recurring) event.
4
- * @param $title
5
- * @return null
6
- */
7
- function em_admin_event_page() {
8
- global $EM_Event, $current_user, $EM_Notices, $localised_date_formats;
9
- //$EM_Event->get_bookings()->get_tickets()->get_ticket_bookings(); print_r($EM_Event);die();
10
-
11
- //check that user can access this page
12
- if( is_object($EM_Event) && !$EM_Event->can_manage('edit_events','edit_others_events') ){
13
- ?>
14
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php echo sprintf(__('You do not have the rights to manage this %s.','dbem'),__('Event','dbem')); ?></p></div>
15
- <?php
16
- return false;
17
- }elseif( !is_object($EM_Event) ){
18
- $EM_Event = new EM_Event();
19
- }
20
-
21
- if( is_object($EM_Event) && $EM_Event->id > 0 ){
22
- if($EM_Event->is_recurring()){
23
- $title = __( "Reschedule", 'dbem' )." '{$EM_Event->name}'";
24
- }else{
25
- $title = __ ( "Edit Event", 'dbem' ) . " '" . $EM_Event->name . "'";
26
- }
27
- } else {
28
- $EM_Event = ( is_object($EM_Event) && get_class($EM_Event) == 'EM_Event') ? $EM_Event : new EM_Event();
29
- $title = __ ( "Insert New Event", 'dbem' );
30
- //Give a default location & category
31
- $default_cat = get_option('dbem_default_category');
32
- $default_loc = get_option('dbem_default_location');
33
- if( is_numeric($default_cat) && $default_cat > 0 ){
34
- $EM_Category = new EM_Category($default_cat);
35
- $EM_Event->get_categories()->categories[] = $EM_Category;
36
- }
37
- if( is_numeric($default_loc) && $default_loc > 0 && ( empty($EM_Event->location->id) && empty($EM_Event->location->name) && empty($EM_Event->location->address) && empty($EM_Event->location->town) ) ){
38
- $EM_Event->location_id = $default_loc;
39
- $EM_Event->location = new EM_Location($default_loc);
40
- }
41
- }
42
-
43
- $use_select_for_locations = get_option('dbem_use_select_for_locations');
44
- // change prefix according to event/recurrence
45
- $pref = "event_";
46
-
47
- $locale_code = substr ( get_locale (), 0, 2 );
48
- $localised_date_format = $localised_date_formats[$locale_code];
49
-
50
- //FIXME time useage is very flimsy imho
51
- $hours_locale_regexp = "H:i";
52
- // Setting 12 hours format for those countries using it
53
- if (preg_match ( "/en|sk|zh|us|uk/", $locale_code ))
54
- $hours_locale_regexp = "h:iA";
55
-
56
- $days_names = array (1 => __ ( 'Mon' ), 2 => __ ( 'Tue' ), 3 => __ ( 'Wed' ), 4 => __ ( 'Thu' ), 5 => __ ( 'Fri' ), 6 => __ ( 'Sat' ), 0 => __ ( 'Sun' ) );
57
- $required = "<i>*</i>";
58
- ?>
59
- <?php echo $EM_Notices; ?>
60
-
61
- <form id="event-form" method="post" action="" enctype='multipart/form-data'>
62
- <div class="wrap">
63
- <div id="icon-events" class="icon32"><br /></div>
64
- <h2><?php echo $title; ?></h2>
65
- <?php if ( count($EM_Event->warnings) > 0 ) : ?>
66
- <?php foreach($EM_Event->warnings as $warning): ?>
67
- <p class="warning"><?php echo $warning; ?></p>
68
- <?php endforeach; ?>
69
- <?php endif; ?>
70
- <div id="poststuff" class="metabox-holder has-right-sidebar">
71
- <!-- SIDEBAR -->
72
- <div id="side-info-column" class='inner-sidebar'>
73
- <div id='side-sortables'>
74
- <?php do_action('em_admin_event_form_side_header'); ?>
75
- <?php if(get_option('dbem_recurrence_enabled') && ($EM_Event->is_recurrence() || $EM_Event->is_recurring() || $EM_Event->id == '')) : ?>
76
- <!-- START recurrence postbox -->
77
- <div class="postbox ">
78
- <div class="handlediv" title="Fare clic per cambiare."><br />
79
- </div>
80
- <h3 class='hndle'><span>
81
- <?php _e ( "Recurrence", 'dbem' ); ?>
82
- </span></h3>
83
- <div class="inside">
84
- <?php //TODO add js warning if rescheduling, since all bookings are deleted ?>
85
- <?php if ( !$EM_Event->id || $EM_Event->is_recurring() ) : ?>
86
- <p>
87
- <input id="event-recurrence" type="checkbox" name="repeated_event" value="1" <?php echo ( $EM_Event->is_recurring() ) ? 'checked="checked"':'' ; ?> />
88
- <?php _e ( 'Repeated event', 'dbem' ); ?>
89
- </p>
90
- <div id="event_recurrence_pattern">
91
- <p>
92
- Frequency:
93
- <select id="recurrence-frequency" name="recurrence_freq">
94
- <?php
95
- $freq_options = array ("daily" => __ ( 'Daily', 'dbem' ), "weekly" => __ ( 'Weekly', 'dbem' ), "monthly" => __ ( 'Monthly', 'dbem' ) );
96
- em_option_items ( $freq_options, $EM_Event->freq );
97
- ?>
98
- </select>
99
- </p>
100
- <p>
101
- <?php _e ( 'Every', 'dbem' )?>
102
- <input id="recurrence-interval" name='recurrence_interval' size='2' value='<?php echo $EM_Event->interval ; ?>' />
103
- <span class='interval-desc' id="interval-daily-singular">
104
- <?php _e ( 'day', 'dbem' )?>
105
- </span> <span class='interval-desc' id="interval-daily-plural">
106
- <?php _e ( 'days', 'dbem' ) ?>
107
- </span> <span class='interval-desc' id="interval-weekly-singular">
108
- <?php _e ( 'week', 'dbem' )?>
109
- </span> <span class='interval-desc' id="interval-weekly-plural">
110
- <?php _e ( 'weeks', 'dbem' )?>
111
- </span> <span class='interval-desc' id="interval-monthly-singular">
112
- <?php _e ( 'month', 'dbem' )?>
113
- </span> <span class='interval-desc' id="interval-monthly-plural">
114
- <?php _e ( 'months', 'dbem' )?>
115
- </span>
116
- </p>
117
- <p class="alternate-selector" id="weekly-selector">
118
- <?php
119
- $saved_bydays = ($EM_Event->is_recurring()) ? explode ( ",", $EM_Event->byday ) : array();
120
- em_checkbox_items ( 'recurrence_bydays[]', $days_names, $saved_bydays );
121
- ?>
122
- </p>
123
- <p class="alternate-selector" id="monthly-selector">
124
- <?php _e ( 'Every', 'dbem' )?>
125
- <select id="monthly-modifier" name="recurrence_byweekno">
126
- <?php
127
- $weekno_options = array ("1" => __ ( 'first', 'dbem' ), '2' => __ ( 'second', 'dbem' ), '3' => __ ( 'third', 'dbem' ), '4' => __ ( 'fourth', 'dbem' ), '-1' => __ ( 'last', 'dbem' ) );
128
- em_option_items ( $weekno_options, $EM_Event->byweekno );
129
- ?>
130
- </select>
131
- <select id="recurrence-weekday" name="recurrence_byday">
132
- <?php em_option_items ( $days_names, $EM_Event->byday ); ?>
133
- </select>
134
- &nbsp;
135
- </p>
136
- </div>
137
- <p id="recurrence-tip">
138
- <?php _e ( 'Check if your event happens more than once according to a regular pattern', 'dbem' )?>
139
- </p>
140
- <?php elseif( $EM_Event->is_recurrence() ) : ?>
141
- <p>
142
- <?php echo $EM_Event->get_recurrence_description(); ?>
143
- <br />
144
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $EM_Event->recurrence_id; ?>">
145
- <?php _e ( 'Reschedule', 'dbem' ); ?>
146
- </a>
147
- <input type="hidden" name="recurrence_id" value="<?php echo $EM_Event->recurrence_id; ?>" />
148
- </p>
149
- <?php else : ?>
150
- <p><?php _e ( 'This is\'t a recurrent event', 'dbem' ) ?></p>
151
- <?php endif; ?>
152
- </div>
153
- </div>
154
- <!-- END recurrence postbox -->
155
- <?php endif; ?>
156
-
157
- <?php if ( current_user_can('edit_others_events') ): ?>
158
- <div class="postbox ">
159
- <div class="handlediv" title="Fare clic per cambiare."><br />
160
- </div>
161
- <h3 class='hndle'><span><?php _e ( 'Event Owner/Contact Person', 'dbem' ); ?></span></h3>
162
- <div class="inside">
163
- <?php
164
- wp_dropdown_users ( array ('name' => 'event_owner', 'show_option_none' => __ ( "Select...", 'dbem' ), 'selected' => $EM_Event->owner ) );
165
- ?>
166
- </div>
167
- </div>
168
- <?php else: ?>
169
- <input type="hidden" name="event_owner" value="<?php get_current_user_id() ?>" />
170
- <?php endif; ?>
171
-
172
- <?php if( empty($EM_Event->id) ): ?>
173
- <?php
174
- $user_groups = array();
175
- if( function_exists('groups_get_user_groups') ){
176
- $group_data = groups_get_user_groups(get_current_user_id());
177
- foreach( $group_data['groups'] as $group_id ){
178
- if( groups_is_user_admin(get_current_user_id(), $group_id) ){
179
- $user_groups[] = groups_get_group( array('group_id'=>$group_id));
180
- }
181
- }
182
- }
183
- ?>
184
- <?php if( count($user_groups) > 0 ): ?>
185
- <!-- START RSVP -->
186
- <div class="postbox " id='group-data'>
187
- <div class="handlediv" title="Fare clic per cambiare."><br />
188
- </div>
189
- <h3 class='hndle'><span><?php _e('Group Ownership','dbem'); ?></span></h3>
190
- <div class="inside">
191
- <p>
192
- <select name="group_id">
193
- <option value="<?php echo $BP_Group->id; ?>">Not a Group Event</option>
194
- <?php
195
- foreach($user_groups as $BP_Group){
196
- ?>
197
- <option value="<?php echo $BP_Group->id; ?>"><?php echo $BP_Group->name; ?></option>
198
- <?php
199
- }
200
- ?>
201
- </select>
202
- <br />
203
- <em><?php _e ( 'Select a group you admin to attach this event to it. Note that all other admins of that group can modify the booking, and you will not be able to unattach the event without deleting it.', 'dbem' )?></em>
204
- </p>
205
- </div>
206
- </div>
207
- <?php endif; ?>
208
- <?php endif; ?>
209
-
210
- <?php if(get_option('dbem_rsvp_enabled')) : ?>
211
- <!-- START RSVP -->
212
- <div class="postbox " id='rsvp-data'>
213
- <div class="handlediv" title="Fare clic per cambiare."><br />
214
- </div>
215
- <h3 class='hndle'><span><?php _e('Bookings Stats','dbem'); ?></span></h3>
216
- <div class="inside">
217
- <div>
218
- <!-- START RSVP Stats -->
219
- <?php
220
- $available_spaces = $EM_Event->get_bookings()->get_available_spaces();
221
- $booked_spaces = $EM_Event->get_bookings()->get_booked_spaces();
222
-
223
- if ( count($EM_Event->get_bookings()->bookings) > 0 ) {
224
- ?>
225
- <div class='wrap'>
226
- <p><strong><?php echo __('Available Spaces','dbem').': '.$EM_Event->get_bookings()->get_available_spaces(); ?></strong></p>
227
- <p><strong><?php echo __('Confirmed Spaces','dbem').': '.$EM_Event->get_bookings()->get_booked_spaces(); ?></strong></p>
228
- <p><strong><?php echo __('Pending Spaces','dbem').': '.$EM_Event->get_bookings()->get_pending_spaces(); ?></strong></p>
229
- </div>
230
-
231
- <br class='clear'/>
232
-
233
- <div id='major-publishing-actions'>
234
- <div id='publishing-action'>
235
- <a id='printable' href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&event_id=".$EM_Event->id ?>'><?php _e('manage bookings','dbem')?></a><br />
236
- <a target='_blank' href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=bookings_report&event_id=".$EM_Event->id ?>'><?php _e('printable view','dbem')?></a>
237
- <a href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=export_csv&event_id=".$EM_Event->id ?>'><?php _e('export csv','dbem')?></a>
238
- <br class='clear'/>
239
- </div>
240
- <br class='clear'/>
241
- </div>
242
- <?php
243
- } else {
244
- ?>
245
- <p><em><?php _e('No responses yet!')?></em></p>
246
- <?php
247
- }
248
- ?>
249
- <!-- END RSVP Stats -->
250
- </div>
251
- </div>
252
- </div>
253
- <!-- END RSVP -->
254
- <?php endif; ?>
255
- <?php if(get_option('dbem_categories_enabled')) :?>
256
- <!-- START Categories -->
257
- <div class="postbox ">
258
- <div class="handlediv" title="Fare clic per cambiare."><br />
259
- </div>
260
- <h3 class='hndle'><span>
261
- <?php _e ( 'Category', 'dbem' ); ?>
262
- </span></h3>
263
- <div class="inside">
264
- <?php $categories = EM_Categories::get(array('orderby'=>'category_name')); ?>
265
- <?php if( count($categories) > 0 ): ?>
266
- <p>
267
- <?php foreach( $categories as $EM_Category ):?>
268
- <label><input type="checkbox" name="event_categories[]" value="<?php echo $EM_Category->id; ?>" <?php if($EM_Event->get_categories()->has($EM_Category->id)) echo 'checked="checked"'; ?> /> <?php echo $EM_Category->name ?></label><br />
269
- <?php endforeach; ?>
270
- </p>
271
- <?php else: ?>
272
- <p><?php sprintf(__('No categories available, <a href="%s">create one here first</a>','dbem'), get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-categories'); ?></p>
273
- <?php endif; ?>
274
- </div>
275
- </div>
276
- <!-- END Categories -->
277
- <?php endif; ?>
278
- <?php do_action('em_admin_event_form_side_footer'); ?>
279
- </div>
280
- </div>
281
- <!-- END OF SIDEBAR -->
282
- <div id="post-body">
283
- <div id="post-body-content">
284
- <?php do_action('em_admin_event_form_header'); ?>
285
- <div id="event_name" class="stuffbox">
286
- <h3>
287
- <?php _e ( 'Name', 'dbem' ); ?>
288
- </h3>
289
- <div class="inside">
290
- <input type="text" name="event_name" id="event-name" value="<?php echo htmlspecialchars($EM_Event->name,ENT_QUOTES); ?>" /><?php echo $required; ?>
291
- <br />
292
- <?php _e ( 'The event name. Example: Birthday party', 'dbem' )?>
293
- <?php $slug_link = __('View Slug','dbem'); ?>
294
- <a href="#" id="event-slug-trigger"><?php echo $slug_link; ?></a>
295
- <script type="text/javascript">
296
- jQuery(document).ready(function($){
297
- $('#event-slug-trigger').click(function(){
298
- if( $(this).text() == '<?php echo $slug_link; ?>'){
299
- $('.event-slug').show();
300
- $(this).text('<?php _e('Hide Slug','dbem'); ?>');
301
- }else{
302
- $('.event-slug').hide();
303
- $(this).text('<?php echo $slug_link; ?>');
304
- }
305
- });
306
- });
307
- </script>
308
- <p class='event-slug' style="display:none">
309
- <?php _e('Event Slug','dbem'); ?>: <input type="text" name="event_slug" id="event-slug" value="<?php echo $EM_Event->slug; ?>" />
310
- <br />
311
- <?php _e ( 'The event slug. If the event slug already exists, a random number will be appended to the end.', 'dbem' )?>
312
- </p>
313
- </div>
314
- </div>
315
- <div id="event_start_date" class="stuffbox">
316
- <h3 id='event-date-title'><?php _e ( 'Event date', 'dbem' ); ?></h3>
317
- <h3 id='recurrence-dates-title'><?php _e ( 'Recurrence dates', 'dbem' ); ?></h3>
318
- <div class="inside">
319
- <input id="em-date-start-loc" type="text" />
320
- <input id="em-date-start" type="hidden" name="event_start_date" value="<?php echo $EM_Event->start_date ?>" />
321
- <input id="em-date-end-loc" type="text" />
322
- <input id="em-date-end" type="hidden" name="event_end_date" value="<?php echo $EM_Event->end_date ?>" />
323
- <br />
324
- <span id='event-date-explanation'>
325
- <?php
326
- _e ( 'The event date.', 'dbem' );
327
- /* Marcus Begin Edit */
328
- echo " ";
329
- _e ( 'When not reoccurring, this event spans between the beginning and end date.', 'dbem' );
330
- /* Marcus End Edit */
331
- ?>
332
- </span>
333
- <span id='recurrence-dates-explanation'>
334
- <?php _e ( 'The recurrence beginning and end date.', 'dbem' ); ?>
335
- </span>
336
- </div>
337
- </div>
338
- <div id="event_end_day" class="stuffbox">
339
- <h3>
340
- <?php _e ( 'Event time', 'dbem' ); ?>
341
- </h3>
342
- <div class="inside">
343
- <input id="start-time" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_locale_regexp, strtotime($EM_Event->start_time) ); ?>" />
344
- -
345
- <input id="end-time" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_locale_regexp, strtotime($EM_Event->end_time) ); ?>" />
346
- <br />
347
- <?php _e ( 'The time of the event beginning and end', 'dbem' )?>.
348
- </div>
349
- </div>
350
- <div id="location_coordinates" class="stuffbox" style='display: none;'>
351
- <h3>
352
- <?php _e ( 'Coordinates', 'dbem' ); ?>
353
- </h3>
354
- <div class="inside">
355
- <input id='location-latitude' name='location_latitude' type='text' value='<?php echo $EM_Event->get_location()->latitude; ?>' size='15' />
356
- -
357
- <input id='location-longitude' name='location_longitude' type='text' value='<?php echo $EM_Event->get_location()->longitude; ?>' size='15' />
358
- </div>
359
- </div>
360
- <div id="location_info" class="stuffbox">
361
- <h3>
362
- <?php _e ( 'Location', 'dbem' ); ?>
363
- </h3>
364
- <div class="inside">
365
- <table id="dbem-location-data">
366
- <tr>
367
- <td style="padding-right:20px; width:100%;">
368
- <table>
369
- <?php if($use_select_for_locations) : ?>
370
- <tr>
371
- <th><?php _e('Location:','dbem') ?></th>
372
- <td>
373
- <select name="location_id" id='location-select-id' size="1">
374
- <?php
375
- $locations = EM_Locations::get();
376
- foreach($locations as $location) {
377
- $selected = "";
378
- if ($EM_Event->get_location()->id == $location->id){
379
- $selected = "selected='selected' ";
380
- }
381
- ?>
382
- <option value="<?php echo $location->id ?>" title="<?php echo "{$location->latitude},{$location->longitude}" ?>" <?php echo $selected ?>><?php echo $location->name; ?></option>
383
- <?php
384
- }
385
- ?>
386
- </select>
387
- <p><?php _e ( 'The name of the location where the event takes place. You can use the name of a venue, a square, etc', 'dbem' )?></p>
388
- </td>
389
- </tr>
390
- <?php else : ?>
391
- <tr>
392
- <th><?php _e ( 'Name:' )?></th>
393
- <td>
394
- <input id='location-id' name='location_id' type='hidden' value='<?php echo $EM_Event->get_location()->id; ?>' size='15' />
395
- <input id="location-name" type="text" name="location_name" value="<?php echo htmlspecialchars($EM_Event->location->name, ENT_QUOTES); ?>" /><?php echo $required; ?>
396
- <p><em><?php _e ( 'Create a location or start typing to search a previously created location.', 'dbem' )?></em></p>
397
- </td>
398
- </tr>
399
- <tr>
400
- <th><?php _e ( 'Address:' )?>&nbsp;</th>
401
- <td>
402
- <input id="location-address" type="text" name="location_address" value="<?php echo htmlspecialchars($EM_Event->location->address, ENT_QUOTES); ; ?>" /><?php echo $required; ?>
403
- </td>
404
- </tr>
405
- <tr>
406
- <th><?php _e ( 'City/Town:' )?>&nbsp;</th>
407
- <td>
408
- <input id="location-town" type="text" name="location_town" value="<?php echo htmlspecialchars($EM_Event->location->town, ENT_QUOTES); ?>" /><?php echo $required; ?>
409
- <input id="location-town-wpnonce" type="hidden" value="<?php echo wp_create_nonce('search_town'); ?>" />
410
- </td>
411
- </tr>
412
- <tr>
413
- <th><?php _e ( 'State/County:' )?>&nbsp;</th>
414
- <td>
415
- <input id="location-state" type="text" name="location_state" value="<?php echo htmlspecialchars($EM_Event->location->state, ENT_QUOTES); ?>" />
416
- <input id="location-state-wpnonce" type="hidden" value="<?php echo wp_create_nonce('search_states'); ?>" />
417
- </td>
418
- </tr>
419
- <tr>
420
- <th><?php _e ( 'Postcode:' )?>&nbsp;</th>
421
- <td>
422
- <input id="location-postcode" type="text" name="location_postcode" value="<?php echo htmlspecialchars($EM_Event->location->postcode, ENT_QUOTES); ?>" />
423
- </td>
424
- </tr>
425
- <tr>
426
- <th><?php _e ( 'Region:' )?>&nbsp;</th>
427
- <td>
428
- <input id="location-region" type="text" name="location_region" value="<?php echo htmlspecialchars($EM_Event->location->region, ENT_QUOTES); ?>" />
429
- <input id="location-region-wpnonce" type="hidden" value="<?php echo wp_create_nonce('search_regions'); ?>" />
430
- </td>
431
- </tr>
432
- <tr>
433
- <th><?php _e ( 'Country:' )?>&nbsp;</th>
434
- <td>
435
- <select id="location-country" name="location_country">
436
- <option value="0" <?php echo ( $EM_Event->location->country == '' && $EM_Event->location->id == '' && get_option('dbem_location_default_country') == '' ) ? 'selected="selected"':''; ?>><?php _e('none selected','dbem'); ?></option>
437
- <?php foreach(em_get_countries() as $country_key => $country_name): ?>
438
- <option value="<?php echo $country_key; ?>" <?php echo ( $EM_Event->location->country == $country_key || ($EM_Event->location->country == '' && $EM_Event->location->id == '' && get_option('dbem_location_default_country')==$country_key) ) ? 'selected="selected"':''; ?>><?php echo $country_name; ?></option>
439
- <?php endforeach; ?>
440
- </select><?php echo $required; ?>
441
- <!-- <p><em><?php _e('Filling this in first will allow you to quickly find previously filled states and regions for the country.','dbem'); ?></em></p> -->
442
- </td>
443
- </tr>
444
- <?php endif; ?>
445
- </table>
446
- </td>
447
- <?php if ( get_option ( 'dbem_gmap_is_active' ) ) : ?>
448
- <td width="400">
449
- <div id='em-map-404' style='width: 400px; vertical-align:middle; text-align: center;'>
450
- <p><em><?php _e ( 'Location not found', 'dbem' ); ?></em></p>
451
- </div>
452
- <div id='em-map' style='width: 400px; height: 300px; display: none;'></div>
453
- </td>
454
- <?php endif; ?>
455
- </tr>
456
- </table>
457
- </div>
458
- </div>
459
- <div id="event_notes" class="stuffbox">
460
- <h3>
461
- <?php _e ( 'Details', 'dbem' ); ?>
462
- </h3>
463
- <div class="inside">
464
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
465
- <?php the_editor($EM_Event->notes ); ?>
466
- </div>
467
- <br />
468
- <?php _e ( 'Details about the event', 'dbem' )?>
469
- </div>
470
- </div>
471
-
472
- <div id="event-image" class="stuffbox">
473
- <h3>
474
- <?php _e ( 'Event image', 'dbem' ); ?>
475
- </h3>
476
- <div class="inside" style="padding:10px;">
477
- <?php if ($EM_Event->get_image_url() != '') : ?>
478
- <img src='<?php echo $EM_Event->image_url; ?>' alt='<?php echo $EM_Event->name ?>'/>
479
- <?php else : ?>
480
- <?php _e('No image uploaded for this event yet', 'debm') ?>
481
- <?php endif; ?>
482
- <br /><br />
483
- <label for='event_image'><?php _e('Upload/change picture', 'dbem') ?></label> <input id='event-image' name='event_image' id='event_image' type='file' size='40' />
484
- </div>
485
- </div>
486
-
487
- <?php if(get_option('dbem_rsvp_enabled')) : ?>
488
- <div id="event-bookings" class="stuffbox">
489
- <h3><span><?php _e('Bookings/Registration','dbem'); ?></span></h3>
490
- <div class="inside">
491
- <div class="wrap">
492
- <div id="event-rsvp-box">
493
- <input id="event-rsvp" name='event_rsvp' value='1' type='checkbox' <?php echo ($EM_Event->rsvp) ? 'checked="checked"' : ''; ?> />
494
- &nbsp;&nbsp;
495
- <?php _e ( 'Enable registration for this event', 'dbem' )?>
496
- </div>
497
- <div id="event-tickets" style="<?php echo ($EM_Event->rsvp) ? '':'display:none;' ?>">
498
- <?php
499
- //get tickets here and if there are none, create a blank ticket
500
- $EM_Tickets = $EM_Event->get_bookings()->get_tickets();
501
- if( count($EM_Tickets->tickets) == 0 ){
502
- $EM_Tickets->tickets[] = new EM_Ticket();
503
- $delete_temp_ticket = true;
504
- }
505
- if( get_option('dbem_bookings_tickets_single') ){
506
- $EM_Ticket = $EM_Tickets->get_first();
507
- include( em_locate_template('forms/ticket-form.php') );
508
- }else{
509
- ?>
510
- <p><strong><?php _e('Tickets','dbem'); ?></strong></p>
511
- <p><em><?php _e('You have single or multiple tickets, where certain tickets become availalble under certain conditions, e.g. early bookings, group discounts, maximum bookings per ticket, etc.', 'dbem'); ?></em></p>
512
- <table class="form-table">
513
- <thead>
514
- <tr valign="top">
515
- <th class="ticket-status">&nbsp;</th>
516
- <th><?php _e('Ticket Name','dbem'); ?></th>
517
- <th><?php _e('Price','dbem'); ?></th>
518
- <th><?php _e('Min/Max','dbem'); ?></th>
519
- <th><?php _e('Start/End','dbem'); ?></th>
520
- <th><?php _e('Avail. Spaces','dbem'); ?></th>
521
- <th><?php _e('Booked Spaces','dbem'); ?></th>
522
- <th>&nbsp;</th>
523
- </tr>
524
- </thead>
525
- <tfoot>
526
- <tr valign="top">
527
- <td colspan="6">
528
- <a href="#" id="em-tickets-add" rel="#em-tickets-form"><?php _e('Add new ticket','dbem'); ?></a>
529
- </td>
530
- </tr>
531
- </tfoot>
532
- <tbody id="em-tickets-body">
533
- <?php
534
- $count = 1;
535
- foreach( $EM_Tickets->tickets as $EM_Ticket){
536
- ?>
537
- <tr valign="top" id="em-tickets-row-<?php echo $count ?>" class="em-tickets-row">
538
- <td class="ticket-status"><span class="<?php echo ($EM_Ticket->is_available()) ? 'ticket_on':'ticket_off'; ?>"></span></td>
539
- <td class="ticket-name"><span class="ticket_name"><?php echo $EM_Ticket->name ?></span><br /><span class="ticket_description"></span></td>
540
- <td class="ticket-price">
541
- <span class="ticket_price"><?php echo ($EM_Ticket->price) ? $EM_Ticket->price : __('Free','dbem'); ?></span>
542
- </td>
543
- <td class="ticket-limit">
544
- <span class="ticket_min">
545
- <?php echo ( !empty($EM_Ticket->min) ) ? $EM_Ticket->min:'-'; ?>
546
- </span> /
547
- <span class="ticket_max"><?php echo ( !empty($EM_Ticket->max) ) ? $EM_Ticket->max:'-'; ?></span>
548
- </td>
549
- <td class="ticket-time">
550
- <span class="ticket_start"><?php echo ( !empty($EM_Ticket->start) ) ? date($localised_date_format, $EM_Ticket->start_timestamp):''; ?></span> -
551
- <span class="ticket_end"><?php echo ( !empty($EM_Ticket->end) ) ? date($localised_date_format, $EM_Ticket->end_timestamp):''; ?></span>
552
- </td>
553
- <td class="ticket-qty">
554
- <span class="ticket_available_spaces"><?php echo $EM_Ticket->get_available_spaces(); ?></span>/
555
- <span class="ticket_spaces">
556
- <?php
557
- if( $EM_Ticket->get_spaces() ){
558
- echo $EM_Ticket->get_spaces();
559
- echo ($EM_Ticket->spaces_limit) ? '':'*';
560
- }else{
561
- echo '-';
562
- }
563
- ?>
564
- </span>
565
- </td>
566
- <td class="ticket-booked-spaces">
567
- <span class="ticket_booked_spaces"><?php echo $EM_Ticket->get_booked_spaces(); ?></span>
568
- </td>
569
- <td class="ticket-actions">
570
- <a href="#" class="ticket-actions-edit"><?php _e('Edit','dbem'); ?></a>
571
- <?php if( count($EM_Ticket->get_bookings()->bookings) == 0 ): ?>
572
- | <a href="<?php bloginfo('wpurl'); ?>/wp-load.php" class="ticket-actions-delete"><?php _e('Delete','dbem'); ?></a>
573
- <?php else: ?>
574
- | <a href="<?php bloginfo('wpurl'); ?>/wp-admin/admin.php?page=events-manager-bookings&ticket_id=<?php echo $EM_Ticket->id ?>"><?php _e('View Bookings','dbem'); ?></a>
575
- <?php endif; ?>
576
- <input type="hidden" class="ticket_id" name="em_tickets[<?php echo $count; ?>][ticket_id]" value="<?php echo $EM_Ticket->id ?>" />
577
- <input type="hidden" class="ticket_name" name="em_tickets[<?php echo $count; ?>][ticket_name]" value="<?php echo $EM_Ticket->name ?>" />
578
- <input type="hidden" name="em_tickets[<?php echo $count; ?>][ticket_description]" value="<?php echo $EM_Ticket->description ?>" />
579
- <input type="hidden" class="ticket_price" name="em_tickets[<?php echo $count; ?>][ticket_price]" value="<?php echo $EM_Ticket->price ?>" />
580
- <input type="hidden" class="ticket_spaces" name="em_tickets[<?php echo $count; ?>][ticket_spaces]" value="<?php echo $EM_Ticket->spaces ?>" />
581
- <input type="hidden" class="ticket_start" name="em_tickets[<?php echo $count; ?>][ticket_start]" value="<?php echo ( !empty($EM_Ticket->start) ) ? date("Y-m-d H:i", $EM_Ticket->start_timestamp):''; ?>" />
582
- <input type="hidden" class="ticket_end" name="em_tickets[<?php echo $count; ?>][ticket_end]" value="<?php echo ( !empty($EM_Ticket->end) ) ? date("Y-m-d H:i", $EM_Ticket->end_timestamp):''; ?>" />
583
- <input type="hidden" class="ticket_min" name="em_tickets[<?php echo $count; ?>][ticket_min]" value="<?php echo $EM_Ticket->min ?>" />
584
- <input type="hidden" class="ticket_max" name="em_tickets[<?php echo $count; ?>][ticket_max]" value="<?php echo $EM_Ticket->max ?>" />
585
- </td>
586
- </tr>
587
- <?php
588
- $count++;
589
- }
590
- if( !empty($delete_temp_ticket) ){
591
- array_pop($EM_Tickets->tickets);
592
- }
593
- ?>
594
- </tbody>
595
- </table>
596
- <?php } ?>
597
- </div>
598
- </div>
599
- </div>
600
- </div>
601
- <?php endif; ?>
602
-
603
- <?php if(get_option('dbem_attributes_enabled')) : ?>
604
- <div id="event-attributes" class="stuffbox">
605
- <h3>
606
- <?php _e ( 'Attributes', 'dbem' ); ?>
607
- </h3>
608
- <div class="inside">
609
- <?php
610
- $attributes = em_get_attributes();
611
- $has_depreciated = false;
612
- ?>
613
- <div class="wrap">
614
- <?php if( !empty($attributes['names']) && count( $attributes['names'] ) > 0 ) : ?>
615
- <table class="form-table">
616
- <thead>
617
- <tr valign="top">
618
- <td><strong>Attribute Name</strong></td>
619
- <td><strong>Value</strong></td>
620
- </tr>
621
- </thead>
622
- <tbody id="mtm_body">
623
- <?php
624
- $count = 1;
625
- foreach( $attributes['names'] as $name){
626
- ?>
627
- <tr valign="top" id="em_attribute_<?php echo $count ?>">
628
- <td scope="row"><?php echo $name ?></td>
629
- <td>
630
- <?php if( count($attributes['values'][$name]) > 0 ): ?>
631
- <select name="em_attributes[<?php echo $name ?>]">
632
- <option><?php echo __('No Value','dbem'); ?></option>
633
- <?php foreach($attributes['values'][$name] as $attribute_val): ?>
634
- <?php if( array_key_exists($name, $EM_Event->attributes) && $EM_Event->attributes[$name]==$attribute_val ): ?>
635
- <option selected="selected"><?php echo $attribute_val; ?></option>
636
- <?php else: ?>
637
- <option><?php echo $attribute_val; ?></option>
638
- <?php endif; ?>
639
- <?php endforeach; ?>
640
- </select>
641
- <?php else: ?>
642
- <input type="text" name="em_attributes[<?php echo $name ?>]" value="<?php echo array_key_exists($name, $EM_Event->attributes) ? htmlspecialchars($EM_Event->attributes[$name], ENT_QUOTES):''; ?>" />
643
- <?php endif; ?>
644
- </td>
645
- </tr>
646
- <?php
647
- $count++;
648
- }
649
- if($count == 1){
650
- ?>
651
- <tr><td colspan="2"><?php echo sprintf(__("You don't have any custom attributes defined in any of your Events Manager template settings. Please add them the <a href='%s'>settings page</a>",'dbem'),get_bloginfo('wpurl')."/wp-admin/admin.php?page=events-manager-options"); ?></td></tr>
652
- <?php
653
- }
654
- ?>
655
- </tbody>
656
- </table>
657
- <?php if( count(array_diff(array_keys($EM_Event->attributes), $attributes['names'])) > 0 ): ?>
658
- <p><strong><?php _e('Depreciated Attributes')?></strong></p>
659
- <p><em><?php _e("If you see any attributes under here, that means they're not used in Events Manager anymore. To add them, you need to add the custom attribute again to a formatting option in the settings page. To remove any of these depreciated attributes, give it a blank value and save.") ?></em></p>
660
- <table class="form-table">
661
- <thead>
662
- <tr valign="top">
663
- <td><strong>Attribute Name</strong></td>
664
- <td><strong>Value</strong></td>
665
- </tr>
666
- </thead>
667
- <tbody id="mtm_body">
668
- <?php
669
- if( is_array($EM_Event->attributes) and count($EM_Event->attributes) > 0){
670
- foreach( $EM_Event->attributes as $name => $value){
671
- if( !in_array($name, $attributes['names']) ){
672
- ?>
673
- <tr valign="top" id="em_attribute_<?php echo $count ?>">
674
- <td scope="row"><?php echo $name ?></td>
675
- <td>
676
- <input type="text" name="em_attributes[<?php echo $name ?>]" value="<?php echo htmlspecialchars($value, ENT_QUOTES); ?>" />
677
- </td>
678
- </tr>
679
- <?php
680
- $count++;
681
- }
682
- }
683
- }
684
- ?>
685
- </tbody>
686
- </table>
687
- <?php endif; ?>
688
- <?php else : ?>
689
- <p>
690
- <?php _e('In order to use attributes, you must define some in your templates, otherwise they\'ll never show. Go to Events > Settings to add attribute placeholders.', 'dbem'); ?>
691
- </p>
692
- <script>
693
- jQuery(document).ready(function($){ $('#event_attributes').addClass('closed'); });
694
- </script>
695
- <?php endif; ?>
696
- </div>
697
- </div>
698
- </div>
699
- <?php endif; ?>
700
- <?php do_action('em_admin_event_form_footer'); ?>
701
- </div>
702
- <p class="submit">
703
- <input type="submit" name="events_update" value="<?php _e ( 'Submit Event', 'dbem' ); ?> &raquo;" />
704
- </p>
705
- <input type="hidden" name="p" value="<?php echo ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:''; ?>" /><a>
706
- <input type="hidden" name="scope" value="<?php echo ( !empty($_REQUEST['scope']) ) ? $_REQUEST['scope']:'' ?>" /></a>
707
- <input type="hidden" name="event_id" value="<?php echo $EM_Event->id; ?>" />
708
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('wpnonce_event_save'); ?>" />
709
- <input type="hidden" name="action" value="event_save" />
710
- </div>
711
- </div>
712
- </div>
713
- </form>
714
- <?php em_locate_template('forms/tickets-form.php', true); //put here as it can't be in the add event form ?>
715
- <script type="text/javascript">
716
- jQuery(document).ready( function($) {
717
- <?php if( $EM_Event->is_recurring() ): ?>
718
- //Recurrence Warnings
719
- $('#event_form').submit( function(event){
720
- confirmation = confirm('<?php _e('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.', 'dbem'); ?>');
721
- if( confirmation == false ){
722
- event.preventDefault();
723
- }
724
- });
725
- <?php endif; ?>
726
- <?php if( get_option('dbem_rsvp_enabled') ): ?>
727
- //RSVP Warning
728
- $('#event-rsvp').click( function(event){
729
- if( !this.checked ){
730
- confirmation = confirm('<?php _e('Are you sure you want to disable bookings? If you do this and save, you will lose all previous bookings. If you wish to prevent further bookings, reduce the number of spaces available to the amount of bookings you currently have', 'dbem'); ?>');
731
- if( confirmation == false ){
732
- event.preventDefault();
733
- }else{
734
- $('#event-tickets').hide();
735
- $("div#rsvp-data").hide();
736
- }
737
- }else{
738
- $('#event-tickets').fadeIn();
739
- $("div#rsvp-data").fadeIn();
740
- }
741
- });
742
-
743
- if($('input#event-rsvp').attr("checked")) {
744
- $("div#rsvp-data").fadeIn();
745
- } else {
746
- $("div#rsvp-data").hide();
747
- }
748
- <?php endif; ?>
749
- });
750
- </script>
751
- <?php
752
- }
753
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-events.php DELETED
@@ -1,236 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Determines whether to show event page or events page, and saves any updates to the event or events
5
- * @return null
6
- */
7
- function em_admin_events_page() {
8
- //TODO Simplify panel for events, use form flags to detect certain actions (e.g. submitted, etc)
9
- global $wpdb, $EM_Notices, $EM_Event;
10
-
11
- $action = ( !empty($_REQUEST ['action']) ) ? $_REQUEST ['action']:'';
12
- $order = ( !empty($_REQUEST ['order']) ) ? $_REQUEST ['order']:'ASC';
13
- $limit = ( !empty($_REQUEST['limit']) ) ? $_REQUEST['limit'] : 20;//Default limit
14
- $page = ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
15
- $offset = ( $page > 1 ) ? ($page-1)*$limit : 0;
16
- $search = ( !empty($_REQUEST['em_search']) ) ? $_REQUEST['em_search']:'';
17
- $scope_names = em_get_scopes();
18
- $scope = ( !empty($_REQUEST ['scope']) && array_key_exists($_REQUEST ['scope'], $scope_names) ) ? $_REQUEST ['scope']:'future';
19
- $selectedEvents = ( !empty($_REQUEST ['events']) ) ? $_REQUEST ['events']:'';
20
-
21
- $args = array('scope'=>$scope, 'limit'=>0, 'order'=>$order, 'search'=>$search );
22
-
23
- if( !current_user_can('edit_others_events') ){
24
- $args['owner'] = get_current_user_id();
25
- }
26
- //Figure out what status to search for
27
- $args['status'] = ( isset($_REQUEST['status']) && is_numeric($_REQUEST['status']) ) ? $_REQUEST['status'] : false;
28
-
29
- $events = EM_Events::get( $args );
30
- $events_count = count ( $events );
31
- $pending_count = EM_Events::count( array('status'=>0, 'scope'=>$scope) );
32
- $approved_count = EM_Events::count( array('status'=> 1, 'scope'=>$scope) );
33
- $total_count = EM_Events::count( array('status'=> false, 'scope'=>$scope) );
34
-
35
- $use_events_end = get_option('dbem_use_event_end');
36
- echo $EM_Notices;
37
- ?>
38
- <div class="wrap">
39
- <div id="icon-events" class="icon32"><br />
40
- </div>
41
- <h2>
42
- <?php echo $scope_names[$scope]; ?>
43
- <a href="admin.php?page=events-manager-event" class="button add-new-h2"><?php _e('Add New','dbem'); ?></a>
44
- </h2>
45
- <?php
46
- $link = array ();
47
- $link ['past'] = "<a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=past&amp;order=desc'>" . __ ( 'Past events', 'dbem' ) . "</a>";
48
- $link ['all'] = " <a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=all&amp;order=desc'>" . __ ( 'All events', 'dbem' ) . "</a>";
49
- $link ['future'] = " <a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=future'>" . __ ( 'Future events', 'dbem' ) . "</a>";
50
- ?>
51
- <?php if ( !empty($_REQUEST['error']) ) : ?>
52
- <div id='message' class='error'>
53
- <p><?php echo $_REQUEST['error']; ?></p>
54
- </div>
55
- <?php endif; ?>
56
- <?php if ( !empty($_REQUEST['message']) ) : ?>
57
- <div id='message' class='updated fade'>
58
- <p><?php echo $_REQUEST['message']; ?></p>
59
- </div>
60
- <?php endif; ?>
61
- <form id="posts-filter" action="" method="get"><input type='hidden' name='page' value='events-manager' />
62
- <ul class="subsubsub">
63
- <li><a href='<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager&amp;scope=<?php echo $scope; ?>' <?php echo ( !isset($_REQUEST['status']) ) ? 'class="current"':''; ?>><?php _e ( 'Total', 'dbem' ); ?> <span class="count">(<?php echo $total_count; ?>)</span></a></li>
64
- <?php if( current_user_can('publish_events') ): ?>
65
- <li>| <a href='<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager&amp;scope=<?php echo $scope; ?>&amp;status=1' <?php echo ( isset($_REQUEST['status']) && $_REQUEST['status']=='1' ) ? 'class="current"':''; ?>><?php _e ( 'Approved', 'dbem' ); ?> <span class="count">(<?php echo $approved_count; ?>)</span></a></li>
66
- <li>| <a href='<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager&amp;scope=<?php echo $scope; ?>&amp;status=0' <?php echo ( isset($_REQUEST['status']) && $_REQUEST['status']=='0' ) ? 'class="current"':''; ?>><?php _e ( 'Pending', 'dbem' ); ?> <span class="count">(<?php echo $pending_count; ?>)</span></a></li>
67
- <?php endif; ?>
68
- </ul>
69
- <p class="search-box">
70
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Events','dbem'); ?>:</label>
71
- <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_REQUEST['em_search'])) ? $_REQUEST['em_search']:''; ?>" />
72
- <input type="submit" value="<?php _e('Search Events','dbem'); ?>" class="button" />
73
- </p>
74
- <div class="tablenav">
75
-
76
- <div class="alignleft actions">
77
- <select name="action">
78
- <option value="-1" selected="selected"><?php _e ( 'Bulk Actions' ); ?></option>
79
- <option value="event_delete"><?php _e ( 'Delete selected','dbem' ); ?></option>
80
- </select>
81
- <input type="submit" value="<?php _e ( 'Apply' ); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
82
- <select name="scope">
83
- <?php
84
- foreach ( $scope_names as $key => $value ) {
85
- $selected = "";
86
- if ($key == $scope)
87
- $selected = "selected='selected'";
88
- echo "<option value='$key' $selected>$value</option> ";
89
- }
90
- ?>
91
- </select>
92
- <input id="post-query-submit" class="button-secondary" type="submit" value="<?php _e ( 'Filter' )?>" />
93
- </div>
94
- <!--
95
- <div class="view-switch">
96
- <a href="/wp-admin/edit.php?mode=list"><img class="current" id="view-switch-list" src="http://wordpress.lan/wp-includes/images/blank.gif" width="20" height="20" title="List View" alt="List View" name="view-switch-list" /></a> <a href="/wp-admin/edit.php?mode=excerpt"><img id="view-switch-excerpt" src="http://wordpress.lan/wp-includes/images/blank.gif" width="20" height="20" title="Excerpt View" alt="Excerpt View" name="view-switch-excerpt" /></a>
97
- </div>
98
- -->
99
- <?php
100
- if ( $events_count >= $limit ) {
101
- $events_nav = em_admin_paginate( $events_count, $limit, $page);
102
- echo $events_nav;
103
- }
104
- ?>
105
- <br class="clear" />
106
- </div>
107
-
108
- <?php
109
- if (empty ( $events )) {
110
- // TODO localize
111
- _e ( 'no events','dbem' );
112
- } else {
113
- ?>
114
-
115
- <table class="widefat events-table">
116
- <thead>
117
- <tr>
118
- <th class='manage-column column-cb check-column' scope='col'>
119
- <input class='select-all' type="checkbox" value='1' />
120
- </th>
121
- <th><?php _e ( 'Name', 'dbem' ); ?></th>
122
- <th>&nbsp;</th>
123
- <th><?php _e ( 'Location', 'dbem' ); ?></th>
124
- <th colspan="2"><?php _e ( 'Date and time', 'dbem' ); ?></th>
125
- </tr>
126
- </thead>
127
- <tbody>
128
- <?php
129
- $rowno = 0;
130
- $event_count = 0;
131
- foreach ( $events as $event ) {
132
- /* @var $event EM_Event */
133
- if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
134
- $rowno++;
135
- $class = ($rowno % 2) ? 'alternate' : '';
136
- // FIXME set to american
137
- $localised_start_date = date_i18n('D d M Y', $event->start);
138
- $localised_end_date = date_i18n('D d M Y', $event->end);
139
- $style = "";
140
- $today = date ( "Y-m-d" );
141
- $location_summary = "<b>" . $event->location->name . "</b><br/>" . $event->location->address . " - " . $event->location->town;
142
-
143
- if ($event->start_date < $today && $event->end_date < $today){
144
- $class .= " past";
145
- }
146
- //Check pending approval events
147
- if ( !$event->status ){
148
- $class .= " pending";
149
- }
150
- ?>
151
- <tr class="event <?php echo trim($class); ?>" <?php echo $style; ?> id="event_<?php echo $event->id ?>">
152
- <td>
153
- <input type='checkbox' class='row-selector' value='<?php echo $event->id; ?>' name='events[]' />
154
- </td>
155
- <td>
156
- <strong>
157
- <a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $event->id ?>&amp;scope=<?php echo $scope ?>&amp;pno=<?php echo $page ?>"><?php echo ($event->name); ?></a>
158
- </strong>
159
- <?php
160
- if( get_option('dbem_rsvp_enabled') == 1 && $event->rsvp == 1 ){
161
- ?>
162
- <br/>
163
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $event->id ?>"><?php echo __("Bookings",'dbem'); ?></a> &ndash;
164
- <?php _e("Booked",'dbem'); ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces(); ?>
165
- <?php if( get_option('dbem_bookings_approval') == 1 ): ?>
166
- | <?php _e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?>
167
- <?php endif;
168
- }
169
- ?>
170
- <div class="row-actions">
171
- <span class="trash"><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager&amp;action=event_delete&amp;event_id=<?php echo $event->id ?>&amp;scope=<?php echo $scope ?>&amp;pno=<?php echo $page ?>" class="em-event-delete"><?php _e('Delete','dbem'); ?></a></span>
172
- <?php if( !$event->status && $event->can_manage('publish_events','publish_others_events') ): ?>
173
- | <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager&amp;action=event_approve&amp;event_id=<?php echo $event->id ?>&amp;scope=<?php echo $scope ?>&amp;pno=<?php echo $page ?>" class="em-event-approve" style="color:green"><?php _e('Approve','dbem'); ?></a>
174
- <?php endif; ?>
175
- </div>
176
- </td>
177
- <td>
178
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;action=event_duplicate&amp;event_id=<?php echo $event->id; ?>&amp;scope=<?php echo $scope ?>&amp;pno=<?php echo $page ?>" title="<?php _e ( 'Duplicate this event', 'dbem' ); ?>">
179
- <strong>+</strong>
180
- </a>
181
- </td>
182
- <td>
183
- <?php echo $location_summary; ?>
184
- </td>
185
-
186
- <td>
187
- <?php echo $localised_start_date; ?>
188
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
189
- <br />
190
- <?php
191
- //TODO Should 00:00 - 00:00 be treated as an all day event?
192
- echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );
193
- ?>
194
- </td>
195
- <td>
196
- <?php
197
- if ( $event->is_recurrence() ) {
198
- ?>
199
- <strong>
200
- <?php echo $event->get_recurrence_description(); ?> <br />
201
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $event->recurrence_id ?>&amp;scope=<?php echo $scope ?>&amp;pno=<?php echo $page ?>"><?php _e ( 'Reschedule', 'dbem' ); ?></a>
202
- </strong>
203
- <?php
204
- }
205
- ?>
206
- </td>
207
- </tr>
208
- <?php
209
- }
210
- $event_count++;
211
- }
212
- ?>
213
- </tbody>
214
- </table>
215
- <?php
216
- } // end of table
217
- ?>
218
- <div class='tablenav'>
219
- <div class="alignleft actions">
220
- <br class='clear' />
221
- </div>
222
- <?php if ( $events_count >= $limit ) : ?>
223
- <div class="tablenav-pages">
224
- <?php
225
- echo $events_nav;
226
- ?>
227
- </div>
228
- <?php endif; ?>
229
- <br class='clear' />
230
- </div>
231
- </form>
232
- </div>
233
- <?php
234
- }
235
-
236
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-help.php CHANGED
@@ -8,22 +8,39 @@ function em_admin_help_page(){
8
  <div class="wrap">
9
  <div id="icon-events" class="icon32"><br /></div>
10
  <h2><?php _e('Getting Help for Events Manager','dbem'); ?></h2>
11
- <p>
12
- For further information on using this plugin, please view the <a href="http://wp-events-plugin.com/documentation/">documentation pages</a>. If you can't find what you're looking for in the documentation, you may find help on our <a href="http://wp-events-plugin.com/forums/">support forums</a>.
13
- </p>
14
  <div class="em-docs">
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  <h2><?php _e('Placeholders for customizing event pages','dbem'); ?></h2>
16
- <p><?php echo sprintf( __("In the <a href='%s'>settings page</a>, you'll find various textboxes where you can edit how event information looks, such as for event and location lists. Using the placeholders below, you can choose what information should be displayed.",'dbem'), 'admin.php?page=events-manager-options'); ?></p>
17
- <h3><a name="event-placeholders"><?php _e('Event Related Placeholders','dbem'); ?></a></h3>
 
18
  <?php echo em_docs_placeholders( array('type'=>'events') ); ?>
19
- <h3><a name="category-placeholders"><?php _e('Category Related Placeholders','dbem'); ?></a></h3>
 
20
  <?php echo em_docs_placeholders( array('type'=>'categories') ); ?>
21
- <h3><a name="location-placeholders"><?php _e('Location Related Placeholders','dbem'); ?></a></h3>
 
 
 
22
  <?php echo em_docs_placeholders( array('type'=>'locations') ); ?>
23
- <h3><a name="booking-placeholders"><?php _e('Booking Related Placeholders','dbem'); ?></a></h3>
 
24
  <?php echo em_docs_placeholders( array('type'=>'bookings') ); ?>
25
  </div>
26
  <?php
 
27
  //Is this a previously imported installation?
28
  $old_table_name = $wpdb->prefix.'dbem_events';
29
  if( $wpdb->get_var("SHOW TABLES LIKE '$old_table_name'") == $old_table_name ){
@@ -35,7 +52,7 @@ function em_admin_help_page(){
35
  <p>If something went wrong with the update to version 3 read on:</p>
36
  <h4>Scenario 1: the plugin is working, but for some reason the old events weren't imported</h4>
37
  <p>You can safely reimport your old events from the previous tables without any risk of deleting them. However, if you click the link below <b>YOU WILL OVERWRITE ANY NEW EVENTS YOU CREATED IN VERSION 3</b></p>
38
- <p><a onclick="return confirm('Are you sure you want to do this? Any new changes made since updating will be overwritten by your old ones, and this cannot be undone');" href="<?php echo wp_nonce_url( get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-help&em_reimport=1', 'em_reimport' ) ?>">Reimport Events from version 2</a></p>
39
  <h4>Scenario 2: the plugin is not working, I want to go back to version 2!</h4>
40
  <p>You can safely downgrade and will not lose any information.</p>
41
  <ol>
8
  <div class="wrap">
9
  <div id="icon-events" class="icon32"><br /></div>
10
  <h2><?php _e('Getting Help for Events Manager','dbem'); ?></h2>
 
 
 
11
  <div class="em-docs">
12
+ <h2>Where To Get Help</h3>
13
+ <p>
14
+ This page is only a small portion of the event documentation which is here for quick reference. If you're just starting out, we recommend you visit the following places for further support:
15
+ </p>
16
+ <ol>
17
+ <li>New users are strongly encouraged to have a look at our <a href="http://wp-events-plugin.com/documentation/getting-started/">getting started page</a>.</li>
18
+ <li>Browse the other documentation pages and <a href="http://wp-events-plugin.com/tutorials/">tutorials</a>.</li>
19
+ <li>View the <a href="http://wp-events-plugin.com/documentation/faq/">FAQ</a> for general questions and <a href="http://wp-events-plugin.com/documentation/troubleshooting/">Troubleshooting</a> for common issues. These are regularly updated with recent issues.</li>
20
+ <li>Rather than trying to contact us directly, we request you use the <a href="http://wordpress.org/tags/events-manager?forum_id=10">support forums</a> as others may be experiencing the same issues as you. For faster support via private member forums and extra features please consider <a href="http://wp-events-plugin.com/events-manager-pro/">upgrading to pro</a>.</li>
21
+ </ol>
22
+ <p>
23
+ If you can't find what you're looking for in the documentation, you may find help on our <a href="http://wp-events-plugin.com/forums/">support forums</a>.
24
+ </p>
25
  <h2><?php _e('Placeholders for customizing event pages','dbem'); ?></h2>
26
+ <p><?php echo sprintf( __("In the <a href='%s'>settings page</a>, you'll find various textboxes where you can edit how event information looks, such as for event and location lists. Using the placeholders below, you can choose what information should be displayed.",'dbem'), EM_ADMIN_URL .'&amp;events-manager-options'); ?></p>
27
+ <a name="event-placeholders"></a>
28
+ <h3 style="margin-top:20px;"><?php _e('Event Related Placeholders','dbem'); ?></h3>
29
  <?php echo em_docs_placeholders( array('type'=>'events') ); ?>
30
+ <a name="category-placeholders"></a>
31
+ <h3><?php _e('Category Related Placeholders','dbem'); ?></h3>
32
  <?php echo em_docs_placeholders( array('type'=>'categories') ); ?>
33
+ <h3><?php _e('Tag Related Placeholders','dbem'); ?></h3>
34
+ <?php echo em_docs_placeholders( array('type'=>'tags') ); ?>
35
+ <a name="location-placeholders"></a>
36
+ <h3><?php _e('Location Related Placeholders','dbem'); ?></h3>
37
  <?php echo em_docs_placeholders( array('type'=>'locations') ); ?>
38
+ <a name="booking-placeholders"></a>
39
+ <h3><?php _e('Booking Related Placeholders','dbem'); ?></h3>
40
  <?php echo em_docs_placeholders( array('type'=>'bookings') ); ?>
41
  </div>
42
  <?php
43
+
44
  //Is this a previously imported installation?
45
  $old_table_name = $wpdb->prefix.'dbem_events';
46
  if( $wpdb->get_var("SHOW TABLES LIKE '$old_table_name'") == $old_table_name ){
52
  <p>If something went wrong with the update to version 3 read on:</p>
53
  <h4>Scenario 1: the plugin is working, but for some reason the old events weren't imported</h4>
54
  <p>You can safely reimport your old events from the previous tables without any risk of deleting them. However, if you click the link below <b>YOU WILL OVERWRITE ANY NEW EVENTS YOU CREATED IN VERSION 3</b></p>
55
+ <p><a onclick="return confirm('Are you sure you want to do this? Any new changes made since updating will be overwritten by your old ones, and this cannot be undone');" href="<?php echo wp_nonce_url( EM_ADMIN_URL .'&amp;events-manager-help&em_reimport=1', 'em_reimport' ) ?>">Reimport Events from version 2</a></p>
56
  <h4>Scenario 2: the plugin is not working, I want to go back to version 2!</h4>
57
  <p>You can safely downgrade and will not lose any information.</p>
58
  <ol>
admin/em-locations-search.php CHANGED
@@ -8,7 +8,7 @@ require_once('../../../../wp-load.php');
8
  global $wpdb;
9
 
10
  $locations_table = EM_LOCATIONS_TABLE;
11
- $location_cond = ( !current_user_can('edit_others_locations') ) ? "AND location_owner=".get_current_user_id() : '';
12
 
13
  $term = (isset($_GET['term'])) ? '%'.$_GET['term'].'%' : '%'.$_GET['q'].'%';
14
  $sql = $wpdb->prepare("
@@ -19,6 +19,7 @@ $sql = $wpdb->prepare("
19
  location_address AS `address`,
20
  location_town AS `town`,
21
  location_state AS `state`,
 
22
  location_postcode AS `postcode`,
23
  location_country AS `country`
24
  FROM $locations_table
8
  global $wpdb;
9
 
10
  $locations_table = EM_LOCATIONS_TABLE;
11
+ $location_cond = ( !current_user_can('edit_others_locations') && !current_user_can('read_others_locations') ) ? "AND location_owner=".get_current_user_id() : '';
12
 
13
  $term = (isset($_GET['term'])) ? '%'.$_GET['term'].'%' : '%'.$_GET['q'].'%';
14
  $sql = $wpdb->prepare("
19
  location_address AS `address`,
20
  location_town AS `town`,
21
  location_state AS `state`,
22
+ location_region AS `region`,
23
  location_postcode AS `postcode`,
24
  location_country AS `country`
25
  FROM $locations_table
admin/em-locations.php DELETED
@@ -1,282 +0,0 @@
1
- <?php
2
- /**
3
- * Looks at the request values, saves/updates and then displays the right menu in the admin
4
- * @return null
5
- */
6
- function em_admin_locations_page() {
7
- //TODO EM_Location is globalized, use it fully here
8
- global $EM_Location;
9
- //Take actions
10
- if( (!empty($_REQUEST['action']) && ( ($_REQUEST['action'] == "edit" && !empty($_REQUEST['location_id'])) || $_REQUEST['action'] == "add")) ) {
11
- em_admin_location();
12
- } elseif( !empty($_REQUEST['action']) && $_REQUEST['action'] == "location_save" ) {
13
- em_admin_location();
14
- } else {
15
- // no action, just a locations list
16
- em_admin_locations();
17
- }
18
- }
19
-
20
- function em_admin_locations($message='', $fill_fields = false) {
21
- global $EM_Notices;
22
- $limit = ( !empty($_REQUEST['limit']) ) ? $_REQUEST['limit'] : 20;//Default limit
23
- $page = ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
24
- $offset = ( $page > 1 ) ? ($page-1)*$limit : 0;
25
- if( !empty($_REQUEST['owner']) && current_user_can('read_others_locations') ){
26
- $locations = EM_Locations::get(array('blog'=>false));
27
- $locations_mine_count = EM_Locations::count( array('owner'=>get_current_user_id()) );
28
- $locations_all_count = count($locations);
29
- }else{
30
- $locations = EM_Locations::get( array('owner'=>get_current_user_id(), 'blog'=>false) );
31
- $locations_mine_count = count($locations);
32
- $locations_all_count = current_user_can('read_others_locations') ? EM_Locations::count(array('blog'=>false)):0;
33
- }
34
- $locations_count = count($locations);
35
- ?>
36
- <div class='wrap'>
37
- <div id='icon-edit' class='icon32'>
38
- <br/>
39
- </div>
40
- <h2>
41
- <?php _e('Locations', 'dbem'); ?>
42
- <a href="admin.php?page=events-manager-locations&action=add" class="button add-new-h2"><?php _e('Add New') ?></a>
43
- </h2>
44
-
45
- <?php echo $EM_Notices; ?>
46
-
47
- <form id='locations-filter' method='post' action=''>
48
- <input type='hidden' name='page' value='locations'/>
49
- <input type='hidden' name='limit' value='<?php echo $limit ?>' />
50
- <input type='hidden' name='p' value='<?php echo $page ?>' />
51
- <div class="subsubsub">
52
- <a href='admin.php?page=events-manager-locations' <?php echo (empty($_REQUEST['owner'])) ? 'class="current"':''; ?>><?php echo sprintf( __( 'My %s', 'dbem' ), __('Locations','dbem')); ?> <span class="count">(<?php echo $locations_mine_count; ?>)</span></a>
53
- <?php if( current_user_can('read_others_locations') ): ?>
54
- &nbsp;|&nbsp;
55
- <a href='admin.php?page=events-manager-locations&amp;owner=all' <?php echo (!empty($_REQUEST['owner'])) ? 'class="current"':''; ?>><?php echo sprintf( __( 'All %s', 'dbem' ), __('Locations','dbem')); ?> <span class="count">(<?php echo $locations_all_count; ?>)</span></a>
56
- <?php endif; ?>
57
- </div>
58
- <?php if ( $locations_count > 0 ) : ?>
59
- <div class='tablenav'>
60
- <div class="alignleft actions">
61
- <select name="action">
62
- <option value="" selected="selected"><?php _e ( 'Bulk Actions' ); ?></option>
63
- <option value="location_delete"><?php _e ( 'Delete selected','dbem' ); ?></option>
64
- </select>
65
- <input type="submit" value="<?php _e ( 'Apply' ); ?>" id="doaction2" class="button-secondary action" />
66
- </div>
67
- <?php
68
- if ( $locations_count >= $limit ) {
69
- $locations_nav = em_admin_paginate( $locations_count, $limit, $page );
70
- echo $locations_nav;
71
- }
72
- ?>
73
- </div>
74
- <table class='widefat'>
75
- <thead>
76
- <tr>
77
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
78
- <th><?php _e('Name', 'dbem') ?></th>
79
- <th><?php _e('Address', 'dbem') ?></th>
80
- <th><?php _e('Town', 'dbem') ?></th>
81
- </tr>
82
- </thead>
83
- <tfoot>
84
- <tr>
85
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
86
- <th><?php _e('Name', 'dbem') ?></th>
87
- <th><?php _e('Address', 'dbem') ?></th>
88
- <th><?php _e('Town', 'dbem') ?></th>
89
- </tr>
90
- </tfoot>
91
- <tbody>
92
- <?php $i = 1; ?>
93
- <?php foreach ($locations as $EM_Location) : ?>
94
- <?php if( $i >= $offset && $i <= $offset+$limit ): ?>
95
- <tr>
96
- <td><input type='checkbox' class ='row-selector' value='<?php echo $EM_Location->id ?>' name='locations[]'/></td>
97
- <td><a href='admin.php?page=events-manager-locations&amp;action=edit&amp;location_id=<?php echo $EM_Location->id ?>'><?php echo $EM_Location->name ?></a></td>
98
- <td><?php echo $EM_Location->address ?></td>
99
- <td><?php echo $EM_Location->town ?></td>
100
- </tr>
101
- <?php endif; ?>
102
- <?php $i++; ?>
103
- <?php endforeach; ?>
104
- </tbody>
105
- </table>
106
- <?php else: ?>
107
- <p><?php _e('No venues have been inserted yet!', 'dbem') ?></p>
108
- <?php endif; ?>
109
- </form>
110
- </div>
111
- <?php
112
- }
113
-
114
- function em_admin_location($message = "") {
115
- global $EM_Location, $EM_Notices;
116
- //check that user can access this page
117
- if( is_object($EM_Location) && !$EM_Location->can_manage('edit_locations','edit_others_locations') ){
118
- ?>
119
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this location.','dbem'); ?></p></div>
120
- <?php
121
- return false;
122
- }
123
- if( empty($EM_Location) || !is_object($EM_Location) ){
124
- $title = __('Add location', 'dbem');
125
- $EM_Location = new EM_Location();
126
- }else{
127
- $title = __('Edit location', 'dbem');
128
- }
129
- $required = "<i>(".__('required','dbem').")</i>";
130
- echo $EM_Notices;
131
- ?>
132
- <form enctype='multipart/form-data' name='editcat' id='location-form' method='post' action='admin.php?page=events-manager-locations' class='validate'>
133
- <input type='hidden' name='action' value='location_save' />
134
- <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('location_save'); ?>' />
135
- <input type='hidden' name='location_id' value='<?php echo $EM_Location->id ?>'/>
136
- <div class='wrap'>
137
- <div id='icon-edit' class='icon32'>
138
- <br/>
139
- </div>
140
- <h2><?php echo $title ?></h2>
141
-
142
- <?php global $EM_Notices; echo $EM_Notices; ?>
143
- <div id='ajax-response'></div>
144
-
145
- <div id="poststuff" class="metabox-holder">
146
- <div id="post-body">
147
- <div id="post-body-content">
148
- <div id="location_name" class="stuffbox">
149
- <h3>
150
- <?php _e ( 'Location Name', 'dbem' ); ?>
151
- </h3>
152
- <div class="inside">
153
- <input name='location_name' id='location-name' type='text' value='<?php echo htmlspecialchars($EM_Location->name, ENT_QUOTES); ?>' size='40' />
154
- <br />
155
- <?php _e('The name of the location', 'dbem') ?>
156
- </div>
157
- </div>
158
- <div id="location_owner" class="stuffbox">
159
- <h3>
160
- <?php _e ( 'Location Owner', 'dbem' ); ?>
161
- </h3>
162
- <div class="inside">
163
- <?php
164
- wp_dropdown_users ( array ('name' => 'location_owner', 'show_option_none' => __ ( "Select...", 'dbem' ), 'selected' => $EM_Location->owner ) );
165
- ?>
166
- </div>
167
- </div>
168
- <div id="location_coordinates" class="stuffbox" style='display: none;'>
169
- <h3>
170
- <?php _e ( 'Coordinates', 'dbem' ); ?>
171
- </h3>
172
- <div class="inside">
173
- <input id='location-latitude' name='location_latitude' type='text' value='<?php echo $EM_Location->latitude; ?>' size='15' />
174
- -
175
- <input id='location-longitude' name='location_longitude' type='text' value='<?php echo $EM_Location->longitude; ?>' size='15' />
176
- </div>
177
- </div>
178
- <div id="location_info" class="stuffbox">
179
- <h3>
180
- <?php _e ( 'Location', 'dbem' ); ?>
181
- </h3>
182
- <div class="inside">
183
- <p><?php _e("If you're using the Google Maps, the more detail you provide, the more accurate Google can be at finding your location. If your address isn't being found, please <a='http://maps.google.com'>try it on maps.google.com</a> by adding all the fields below seperated by commas.",'dbem')?></p>
184
- <table id="dbem-location-data">
185
- <tr>
186
- <td style="padding-right:20px; width:100%;">
187
- <table>
188
- <tr>
189
- <th><?php _e ( 'Address:' )?>&nbsp;</th>
190
- <td>
191
- <input id="location-address" type="text" name="location_address" value="<?php echo htmlspecialchars($EM_Location->address, ENT_QUOTES); ; ?>" /> <?php echo $required; ?>
192
- </td>
193
- </tr>
194
- <tr>
195
- <th><?php _e ( 'City/Town:' )?>&nbsp;</th>
196
- <td>
197
- <input id="location-town" type="text" name="location_town" value="<?php echo htmlspecialchars($EM_Location->town, ENT_QUOTES); ?>" /> <?php echo $required; ?>
198
- </td>
199
- </tr>
200
- <tr>
201
- <th><?php _e ( 'State/County:' )?>&nbsp;</th>
202
- <td>
203
- <input id="location-state" type="text" name="location_state" value="<?php echo htmlspecialchars($EM_Location->state, ENT_QUOTES); ?>" />
204
- </td>
205
- </tr>
206
- <tr>
207
- <th><?php _e ( 'Postcode:' )?>&nbsp;</th>
208
- <td>
209
- <input id="location-postcode" type="text" name="location_postcode" value="<?php echo htmlspecialchars($EM_Location->postcode, ENT_QUOTES); ?>" />
210
- </td>
211
- </tr>
212
- <tr>
213
- <th><?php _e ( 'Region:' )?>&nbsp;</th>
214
- <td>
215
- <input id="location-region" type="text" name="location_region" value="<?php echo htmlspecialchars($EM_Location->region, ENT_QUOTES); ?>" />
216
- <input id="location-region-wpnonce" type="hidden" value="<?php echo wp_create_nonce('search_regions'); ?>" />
217
- </td>
218
- </tr>
219
- <tr>
220
- <th><?php _e ( 'Country:' )?>&nbsp;</th>
221
- <td>
222
- <select id="location-country" name="location_country">
223
- <?php foreach(em_get_countries(__('none selected','dbem')) as $country_key => $country_name): ?>
224
- <option value="<?php echo $country_key; ?>" <?php echo ( $EM_Location->country === $country_key || ($EM_Location->country == '' && $EM_Location->id == '' && get_option('dbem_location_default_country')==$country_key) ) ? 'selected="selected"':''; ?>><?php echo $country_name; ?></option>
225
- <?php endforeach; ?>
226
- </select> <?php echo $required; ?>
227
- </td>
228
- </tr>
229
- </table>
230
- </td>
231
- <?php if ( get_option ( 'dbem_gmap_is_active' ) ) : ?>
232
- <td width="400">
233
- <div id='em-map-404' style='width: 400px; vertical-align:middle; text-align: center;'>
234
- <p><em><?php _e ( 'Location not found', 'dbem' ); ?></em></p>
235
- </div>
236
- <div id='em-map' style='width: 400px; height: 300px; display: none;'></div>
237
- </td>
238
- <?php endif; ?>
239
- </tr>
240
- </table>
241
- </div>
242
- </div>
243
-
244
- <div id="location_description" class="postbox">
245
- <h3>
246
- <?php _e ( 'Details', 'dbem' ); ?>
247
- </h3>
248
- <div class="inside">
249
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
250
- <?php the_editor($EM_Location->description ); ?>
251
- </div>
252
- <br />
253
- <?php _e ( 'Details about the location', 'dbem' )?>
254
- </div>
255
- </div>
256
-
257
- <div id="location_description" class="stuffbox">
258
- <h3>
259
- <?php _e ( 'Location image', 'dbem' ); ?>
260
- </h3>
261
- <div class="inside" style="padding:10px;">
262
- <?php if ($EM_Location->get_image_url() != '') : ?>
263
- <img src='<?php echo $EM_Location->image_url; ?>' alt='<?php echo $EM_Location->name ?>'/>
264
- <?php else : ?>
265
- <?php _e('No image uploaded for this location yet', 'debm') ?>
266
- <?php endif; ?>
267
- <br /><br />
268
- <label for='location_image'><?php _e('Upload/change picture', 'dbem') ?></label> <input id='location-image' name='location_image' id='location_image' type='file' size='40' />
269
- </div>
270
- </div>
271
- <?php do_action('em_admin_location_form_footer'); ?>
272
-
273
- </div>
274
- </div>
275
- </div>
276
- <p class='submit'><input type='submit' class='button-primary' name='submit' value='<?php _e('Update location', 'dbem') ?>' /></p>
277
- </div>
278
- </form>
279
- <?php
280
- }
281
-
282
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-ms-locations.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Looks at the request values, saves/updates and then displays the right menu in the admin
4
+ * @return null
5
+ */
6
+ function em_admin_ms_locations() {
7
+ //TODO EM_Location is globalized, use it fully here
8
+ global $EM_Location;
9
+ //Take actions
10
+ if( !empty($_REQUEST['action']) && ($_REQUEST['action'] == "edit" || $_REQUEST['action'] == "location_save")) {
11
+ em_admin_location();
12
+ } else {
13
+ // no action, just a locations list
14
+ em_admin_locations();
15
+ }
16
+ }
17
+
18
+ function em_admin_locations($message='', $fill_fields = false) {
19
+ global $current_site;
20
+ ?>
21
+ <div class='wrap'>
22
+ <div id='icon-edit' class='icon32'>
23
+ <br/>
24
+ </div>
25
+ <h2>
26
+ <?php _e('Locations', 'dbem'); ?>
27
+ </h2>
28
+ <?php em_locations_admin(array('url' => $_SERVER['REQUEST_URI'])); ?>
29
+ </div>
30
+ <?php
31
+ }
32
+
33
+ function em_admin_location($message = "") {
34
+ global $EM_Location;
35
+ if( empty($EM_Location) || !is_object($EM_Location) ){
36
+ $title = __('Add location', 'dbem');
37
+ $EM_Location = new EM_Location();
38
+ }else{
39
+ $title = __('Edit location', 'dbem');
40
+ }
41
+ ?>
42
+ <div class='wrap'>
43
+ <div id='icon-edit' class='icon32'>
44
+ <br/>
45
+ </div>
46
+ <h2><?php echo $title ?></h2>
47
+ <?php em_location_form(); ?>
48
+ </div>
49
+ <?php
50
+ }
51
+
52
+ ?>
admin/em-ms-options.php ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function em_ms_upgrade( $blog_id ){
3
+ ?>
4
+ <div class="wrap">
5
+ <div id='icon-options-general' class='icon32'><br /></div>
6
+ <h2><?php esc_html_e('Update Network','dbem'); ?></h2>
7
+ <?php
8
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'upgrade' && check_admin_referer('em_ms_ugrade_'.get_current_user_id()) ){
9
+ global $current_site,$wpdb;
10
+ $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->id);
11
+ foreach($blog_ids as $blog_id){
12
+ $plugin_basename = plugin_basename(dirname(dirname(__FILE__)).'/events-manager.php');
13
+ if( in_array( $plugin_basename, (array) get_blog_option($blog_id, 'active_plugins', array() ) ) || is_plugin_active_for_network($plugin_basename) ){
14
+ if( EM_VERSION > get_blog_option($blog_id, 'dbem_version', 0) ){
15
+ switch_to_blog($blog_id);
16
+ require_once( dirname(__FILE__).'/../em-install.php');
17
+ em_install();
18
+ echo "<p>Upgraded - ".get_bloginfo('blogname')."</p>";
19
+ restore_current_blog();
20
+ }else{
21
+ echo "<p>&quot;".get_blog_option($blog_id, 'blogname')."&quot; is up to date.</p>";
22
+ }
23
+ }else{
24
+ echo "<p>&quot;".get_blog_option($blog_id, 'blogname')."&quot; does not have Events Manager activated.</p>";
25
+ }
26
+ }
27
+ echo "<p>Done Upgrading</p>";
28
+ }else{
29
+ ?>
30
+ <form action="" method="post">
31
+ <p><?php esc_html_e('To update your network blogs with the latest Events Manager automatically, click the update button below.','dbem'); ?></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','dbem'); ?>" />
35
+ </form>
36
+ <?php
37
+ }
38
+ ?>
39
+ </div>
40
+ <?php
41
+ }
42
+
43
+ /**
44
+ * Displays network-related options in the network admin section
45
+ * @uses em_options_save() to save settings
46
+ */
47
+ function em_ms_admin_options_page() {
48
+ global $wpdb,$EM_Notices;
49
+ //Check for uninstall/reset request
50
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' ){
51
+ em_admin_options_uninstall_page();
52
+ return;
53
+ }
54
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' ){
55
+ em_admin_options_reset_page();
56
+ return;
57
+ }
58
+ //TODO place all options into an array
59
+ $events_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
60
+ $locations_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
61
+ $bookings_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
62
+ $categories_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#category-placeholders">'. __('Category Related Placeholders','dbem') .'</a>';
63
+ $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
64
+ $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
65
+ $categories_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $categories_placeholders);
66
+ $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
67
+
68
+ global $save_button;
69
+ $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes', 'dbem') .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
70
+ //Do some multisite checking here for reuse
71
+ ?>
72
+ <script type="text/javascript" charset="utf-8"><?php include(EM_DIR.'/includes/js/admin-settings.js'); ?></script>
73
+ <script type="text/javascript" charset="utf-8">
74
+ jQuery(document).ready(function($){
75
+ //events
76
+ $('input[name="dbem_ms_global_events"]').change(function(){
77
+ if( $('input:radio[name="dbem_ms_global_events"]:checked').val() == 1 ){
78
+ $("tr#dbem_ms_global_events_links_row").show();
79
+ $('input:radio[name="dbem_ms_global_events_links"]:checked').trigger('change');
80
+ }else{
81
+ $("tr#dbem_ms_global_events_links_row, tr#dbem_ms_events_slug_row").hide();
82
+ }
83
+ }).first().trigger('change');
84
+ $('input[name="dbem_ms_global_events_links"]').change(function(){
85
+ if( $('input:radio[name="dbem_ms_global_events_links"]:checked').val() == 1 ){
86
+ $("tr#dbem_ms_events_slug_row").hide();
87
+ }else{
88
+ $("tr#dbem_ms_events_slug_row").show();
89
+ }
90
+ }).first().trigger('change');
91
+ //locations
92
+ $('input[name="dbem_ms_mainblog_locations"]').change(function(){
93
+ if( $('input:radio[name="dbem_ms_mainblog_locations"]:checked').val() == 1 ){
94
+ $("tbody.em-global-locations").hide();
95
+ }else{
96
+ $("tbody.em-global-locations").show();
97
+ }
98
+ }).first().trigger('change');
99
+ $('input[name="dbem_ms_global_locations"]').change(function(){
100
+ if( $('input:radio[name="dbem_ms_global_locations"]:checked').val() == 1 ){
101
+ $("tr#dbem_ms_global_locations_links_row").show();
102
+ $('input:radio[name="dbem_ms_global_locations_links"]:checked').trigger('change');
103
+ }else{
104
+ $("tr#dbem_ms_global_locations_links_row, tr#dbem_ms_locations_slug_row").hide();
105
+ }
106
+ }).first().trigger('change');
107
+ $('input[name="dbem_ms_global_locations_links"]').change(function(){
108
+ if( $('input:radio[name="dbem_ms_global_locations_links"]:checked').val() == 1 ){
109
+ $("tr#dbem_ms_locations_slug_row").hide();
110
+ }else{
111
+ $("tr#dbem_ms_locations_slug_row").show();
112
+ }
113
+ });
114
+ //MS Mode selection hiders
115
+ $('input[name="dbem_ms_global_table"]').change(function(){ //global
116
+ if( $('input:radio[name="dbem_ms_global_table"]:checked').val() == 1 ){
117
+ $("tbody.em-global-options").show();
118
+ $('input:radio[name="dbem_ms_mainblog_locations"]:checked').trigger('change');
119
+ }else{
120
+ $("tbody.em-global-options").hide();
121
+ }
122
+ }).first().trigger('change');
123
+ });
124
+ </script>
125
+ <style type="text/css">.postbox h3 { cursor:pointer; }</style>
126
+ <div class="wrap">
127
+ <div id='icon-options-general' class='icon32'><br /></div>
128
+ <h2 class="nav-tab-wrapper">
129
+ <a href="#" id="em-menu-general" class="nav-tab nav-tab-active"><?php esc_html_e('General','dbem'); ?></a>
130
+ </h2>
131
+ <h3 id="em-options-title"><?php _e ( 'Event Manager Options', 'dbem' ); ?></h3>
132
+ <?php echo $EM_Notices; ?>
133
+ <form id="em-options-form" method="post" action="">
134
+ <div class="metabox-holder">
135
+ <!-- // TODO Move style in css -->
136
+ <div class='postbox-container' style='width: 99.5%'>
137
+ <div id="">
138
+
139
+ <div class="em-menu-general em-menu-group">
140
+ <div class="postbox " id="em-opt-ms-options" >
141
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Multi Site Options', 'dbem' ); ?></span></h3>
142
+ <div class="inside">
143
+ <table class="form-table">
144
+ <?php
145
+ em_options_radio_binary ( __( 'Enable global tables mode?', 'dbem'), 'dbem_ms_global_table', __( 'Setting this to yes will make all events save in the main site event tables (EM must also be activated). This allows you to share events across different blogs, such as showing events in your network whilst allowing users to display and manage their events within their own blog. Bear in mind that activating this will mean old events created on the sub-blogs will not be accessible anymore, and if you switch back they will be but new events created during global events mode will only remain on the main site.','dbem' ) );
146
+ ?>
147
+ <tbody class="em-global-options">
148
+ <?php
149
+ global $current_site;
150
+ $global_slug_tip = __('%s belonging to other sub-sites will have an extra slug preppended to it so that your main site can differentiate between its own %s and those belonging to other sites in your network.','dbem');
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.','dbem' );
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.','dbem');
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.','dbem');
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','dbem'),__('Event','dbem')); ?></h4></td></tr><?php
156
+ em_options_radio_binary ( sprintf(__( 'Display global events on main blog?', 'dbem'), __('events','dbem')), 'dbem_ms_global_events', sprintf($global_post_tip, __('events','dbem'), __('events','dbem')) );
157
+ em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'dbem'), __('events','dbem')), 'dbem_ms_global_events_links', sprintf($global_link_tip, __('events','dbem'), __('event','dbem')).sprintf($global_link_tip2, __('event','dbem'), $options_page_link) );
158
+ em_options_input_text ( sprintf(__( 'Global %s slug', 'dbem' ),__('event','dbem')), 'dbem_ms_events_slug', sprintf($global_slug_tip, __('Events','dbem'), __('events','dbem')).__('Example:','dbem').'<code>http://yoursite.com/events/<strong>event</strong>/subsite-event-slug/', EM_EVENT_SLUG );
159
+ ?><tr class="em-header"><td><h4><?php echo sprintf(__('%s Options','dbem'),__('Location','dbem')); ?></h4></td></tr><?php
160
+ em_options_radio_binary ( sprintf(__( 'Locations on main blog?', 'dbem'), __('locations','dbem')), 'dbem_ms_mainblog_locations', __('If you would prefer all your locations to belong to your main blog, users in sub-sites will still be able to create locations, but the actual locations are created and reside in the main blog.','dbem') );
161
+ ?>
162
+ </tbody>
163
+ <tbody class="em-global-options em-global-locations">
164
+ <?php
165
+ em_options_radio_binary ( sprintf(__( 'Display global %s on main blog?', 'dbem'), __('locations','dbem')), 'dbem_ms_global_locations', sprintf($global_post_tip, __('locations','dbem'), __('locations','dbem')) );
166
+ em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'dbem'), __('locations','dbem')), 'dbem_ms_global_locations_links', sprintf($global_link_tip, __('locations','dbem'), __('location','dbem')).sprintf($global_link_tip2, __('location','dbem'), $options_page_link) );
167
+ em_options_input_text ( sprintf(__( 'Global %s slug', 'dbem' ),__('location','dbem')), 'dbem_ms_locations_slug', sprintf($global_slug_tip, __('Locations','dbem'), __('locations','dbem')).__('Example:','dbem').'<code>http://yoursite.com/locations/<strong>location</strong>/subsite-location-slug/', EM_LOCATION_SLUG );
168
+ ?>
169
+ </tbody>
170
+ <?php echo $save_button; ?>
171
+ </table>
172
+
173
+ </div> <!-- . inside -->
174
+ </div> <!-- .postbox -->
175
+
176
+ <?php
177
+ //including shared MS/non-MS boxes
178
+ em_admin_option_box_caps();
179
+ em_admin_option_box_image_sizes();
180
+ em_admin_option_box_email();
181
+ em_admin_option_box_uninstall();
182
+ ?>
183
+
184
+ <?php do_action('em_ms_options_page_footer'); ?>
185
+ </div> <!-- .em-menu-general -->
186
+
187
+ <div class="em-menu-pages em-menu-group" style="display:none;">
188
+
189
+ </div> <!-- .em-menu-pages -->
190
+
191
+ <p class="submit">
192
+ <input type="submit" id="dbem_options_submit" name="Submit" value="<?php esc_attr_e( 'Save Changes' )?>" />
193
+ <input type="hidden" name="em-submitted" value="1" />
194
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('events-manager-options'); ?>" />
195
+ </p>
196
+
197
+ </div> <!-- .metabox-sortables -->
198
+ </div> <!-- .postbox-container -->
199
+
200
+ </div> <!-- .metabox-holder -->
201
+ </form>
202
+ </div>
203
+ <?php
204
+ }
205
+ ?>
admin/em-options.php CHANGED
@@ -2,251 +2,713 @@
2
 
3
  //Function composing the options subpanel
4
  function em_options_save(){
 
5
  /*
6
  * Here's the idea, we have an array of all options that need super admin approval if in multi-site mode
7
  * since options are only updated here, its one place fit all
8
  */
9
- if( current_user_can('activate_plugins') && !empty($_POST['em-submitted']) ){
10
  //Build the array of options here
11
  $post = $_POST;
12
  foreach ($_POST as $postKey => $postValue){
13
  if( substr($postKey, 0, 5) == 'dbem_' ){
14
  //TODO some more validation/reporting
15
  $numeric_options = array('dbem_locations_default_limit','dbem_events_default_limit');
 
16
  if( in_array($postKey,$numeric_options) && !is_numeric($postValue) ){
17
  //Do nothing, keep old setting.
 
 
18
  }else{
19
  //TODO slashes being added?
20
- //$postValue = EM_Object::sanitize($postValue)
21
- update_option($postKey, stripslashes($postValue));
 
 
 
 
22
  }
23
  }
24
  }
25
-
26
  //set capabilities
27
  if( !empty($_POST['em_capabilities']) && is_array($_POST['em_capabilities']) && (!is_multisite() || is_multisite() && is_super_admin()) ){
28
  global $em_capabilities_array, $wp_roles;
29
- foreach( $wp_roles->role_objects as $role_name => $role ){
30
- foreach( array_keys($em_capabilities_array) as $capability){
31
- if( !empty($_POST['em_capabilities'][$role_name][$capability]) ){
32
- $role->add_cap($capability);
33
- }else{
34
- $role->remove_cap($capability);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  }
37
  }
38
  }
 
39
  do_action('em_options_save');
40
- function em_options_saved_notice(){
41
- ?>
42
- <div class="updated"><p><strong><?php _e('Changes saved.'); ?></strong></p></div>
43
- <?php
 
 
 
 
 
 
 
44
  }
45
- add_action ( 'admin_notices', 'em_options_saved_notice' );
46
- if( get_option('dbem_debug') ){
47
- include_once( WP_PLUGIN_DIR.'/events-manager/em-debug.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
- add_action('admin_head', 'em_options_save');
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  function em_admin_options_page() {
56
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  //TODO place all options into an array
58
- $events_placeholders = '<a href="admin.php?page=events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
59
- $locations_placeholders = '<a href="admin.php?page=events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
60
- $bookings_placeholders = '<a href="admin.php?page=events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
61
- $categories_placeholders = '<a href="admin.php?page=events-manager-help#category-placeholders">'. __('Category Related Placeholders','dbem') .'</a>';
 
62
  $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
63
  $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
64
  $categories_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $categories_placeholders);
65
  $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
66
 
67
- $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes' ) .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
68
- //Do some multisite checking here for reuse
69
- $multisite_view = (is_multisite() && is_super_admin()) ? ' - ('.__('Only Network Admins see this','dbem').')':'';
70
- ?>
71
- <script type="text/javascript" charset="utf-8">
72
- jQuery(document).ready(function($){
73
- var close_text = '<?php _e('Collapse All','dbem'); ?>';
74
- var open_text = '<?php _e('Expand All','dbem'); ?>';
75
- var open_close = $('<a href="#" style="display:block; float:right; clear:right; margin:10px;">'+close_text+'</a>');
76
- $('#icon-options-general').after(open_close);
77
- open_close.click( function(e){
78
- e.preventDefault();
79
- if($(this).text() == close_text){
80
- $(".postbox").addClass('closed');
81
- $(this).text(open_text);
82
- }else{
83
- $(".postbox").removeClass('closed');
84
- $(this).text(close_text);
85
- }
86
- });
87
- //For rewrite titles
88
- $('input:radio[name=dbem_disable_title_rewrites]').live('change',function(){
89
- checked_check = $('input:radio[name=dbem_disable_title_rewrites]:checked');
90
- if( checked_check.val() == 1 ){
91
- $('#dbem_title_html_row').show();
92
- }else{
93
- $('#dbem_title_html_row').hide();
94
- }
95
- });
96
- $('input:radio[name=dbem_disable_title_rewrites]').trigger('change');
97
- $(".postbox").addClass('closed'); //Let's start off closing everything for now.
98
- });
99
- </script>
100
- <div class="wrap">
101
- <div id='icon-options-general' class='icon32'><br />
102
- </div>
103
- <h2><?php _e ( 'Event Manager Options', 'dbem' ); ?></h2>
104
- <?php
105
- /*
106
- * START MIGRATION BIT
107
- */
108
- if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'bookings_migrate' ){
109
- require_once(dirname(__FILE__).'/../em-install.php');
110
- em_migrate_bookings();
111
- }elseif( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'bookings_migrate_delete'){
112
- require_once( dirname(__FILE__).'/../em-install.php');
113
- em_migrate_bookings_delete();
114
- }
115
- ?>
116
- <?php if( $wpdb->get_var("SHOW TABLES LIKE '".EM_PEOPLE_TABLE."'") == EM_PEOPLE_TABLE ): ?>
117
- <?php if( $wpdb->get_var('SELECT COUNT(*) FROM '.EM_TICKETS_BOOKINGS_TABLE) > 0 ): ?>
118
- <div class='updated'>
119
- <p>
120
- It looks like you've already tried reimporting some bookings into the new version (or new bookings have been made since you installed).
121
- If everything looks correct, you can
122
- <a href="admin.php?page=events-manager-options&amp;_wpnonce=<?php echo wp_create_nonce('bookings_migrate_delete'); ?>&amp;action=bookings_migrate_delete">delete the unused tables</a>,
123
- or you can also safely try
124
- <a href="admin.php?page=events-manager-options&amp;_wpnonce=<?php echo wp_create_nonce('bookings_migrate'); ?>&amp;action=bookings_migrate">re-importing again</a>.
125
- </p>
126
- </div>
127
- <?php else: ?>
128
- <div class='updated'>
129
- <p>It looks like you've upgraded from Events Manager version 3.0, meaning your old bookings won't work until you re-import them.
130
- Events Manager 3.0 kept booking user info in a simple database table, whereas now people that make bookings get a subscriber account so
131
- they can access private booking information. You have to choice to
132
- <a href="admin.php?page=events-manager-options&amp;_wpnonce=<?php echo wp_create_nonce('bookings_migrate'); ?>&amp;action=bookings_migrate">import all your old bookings</a>
133
- and create wordpress accounts for bookers, or you can also start afresh and
134
- <a href="admin.php?page=events-manager-options&amp;_wpnonce=<?php echo wp_create_nonce('bookings_migrate_delete'); ?>&amp;action=bookings_migrate_delete">delete the old bookings</a>.
135
- </p>
136
- </div>
137
  <?php endif; ?>
138
- <?php endif; ?>
139
- <?php
140
- /*
141
- * END MIGRATION BIT
142
- */
143
- ?>
144
- <form id="dbem_options_form" method="post" action="">
145
-
146
  <div class="metabox-holder">
147
  <!-- // TODO Move style in css -->
148
  <div class='postbox-container' style='width: 99.5%'>
149
- <div id="" class="meta-box-sortables" >
150
 
151
- <?php if ( is_multisite() && is_super_admin() ) : ?>
152
- <div class="postbox " >
153
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Multi Site Options', 'dbem' ); ?> <?php echo $multisite_view; ?></span></h3>
 
 
154
  <div class="inside">
155
  <table class="form-table">
156
- <?php
157
- em_options_radio_binary ( __( 'Enable global tables mode?' ), 'dbem_ms_global_table', __( 'Setting this to yes will make all events save in the main site event tables (EM must also be activated). This allows you to share events across different blogs, such as showing events in your network whilst allowing users to display and manage their events within their own blog. Bear in mind that activating this will mean old events created on the sub-blogs will not be accessible anymore, and if you switch back they will be but new events created during global events mode will only remain on the main site.','dbem' ) );
158
- em_options_radio_binary ( __( 'Display global events on main blog?' ), 'dbem_ms_global_events', __( 'Displays events from all sites on the network by default. You can still restrict events by blog using shortcodes and template tags coupled with the <code>blog</code> attribute. Requires global tables to be turned on.','dbem' ) );
159
- em_options_radio_binary ( __( 'Link sub-site events directly to sub-site?' ), 'dbem_ms_global_events_links', __( 'When displaying global events on the main site you have the option of users viewing the event details on the main site or being directed to the sub-site.','dbem' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  echo $save_button;
161
  ?>
162
  </table>
163
 
164
  </div> <!-- . inside -->
165
- </div> <!-- .postbox -->
166
- <?php endif; ?>
167
-
168
- <div class="postbox " >
169
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'General options', 'dbem' ); ?> </span></h3>
170
- <div class="inside">
171
- <table class="form-table">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  <?php
173
- em_options_radio_binary ( __( 'Use dropdown for locations?' ), 'dbem_use_select_for_locations', __( 'Select yes to select location from a drow-down menu; location selection will be faster, but you will lose the ability to insert locations with events','dbem' ) );
174
- em_options_radio_binary ( __( 'Use recurrence?' ), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','dbem' ) );
175
- em_options_radio_binary ( __( 'Enable bookings?' ), 'dbem_rsvp_enabled', __( 'Select yes to allow bookings and tickets for events.','dbem' ) );
176
- em_options_radio_binary ( __( 'Use categories?' ), 'dbem_categories_enabled', __( 'Select yes to enable the category features','dbem' ) );
177
- em_options_radio_binary ( __( 'Use event attributes?' ), 'dbem_attributes_enabled', __( 'Select yes to enable the attributes feature','dbem' ) );
178
-
179
- /*default category*/
180
- $category_options = array();
181
- $category_options[0] = __('no default category','dbem');
182
- $EM_Categories = EM_Categories::get();
183
- foreach($EM_Categories as $EM_Category){
184
- $category_options[$EM_Category->id] = $EM_Category->name;
185
- }
186
- em_options_select ( __( 'Default Category' ), 'dbem_default_category', $category_options, __( 'This option allows you to select the default category when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
187
-
188
- /*default location*/
189
- $location_options = array();
190
- $location_options[0] = __('no default location','dbem');
191
- $EM_Locations = EM_Locations::get();
192
- foreach($EM_Locations as $EM_Location){
193
- $location_options[$EM_Location->id] = $EM_Location->name;
194
- }
195
- em_options_select ( __( 'Default Location' ), 'dbem_default_location', $location_options, __( 'This option allows you to select the default location when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
196
-
197
- /*default location country*/
198
- em_options_select ( __( 'Default Location Country' ), 'dbem_location_default_country', em_get_countries(__('no default country', 'dbem')), __('If you select a default country, that will be pre-selected when creating a new location.','dbem') );
199
-
200
- em_options_textarea ( __( 'Event Attributes', 'dbem' ), 'dbem_placeholders_custom', sprintf(__( "You can also add event attributes here, one per line in this format <code>#_ATT{key}</code>. They will not appear on event pages unless you insert them into another template below, but you may want to store extra information about an event for other uses. <a href='%s'>More information on placeholders.</a>", 'dbem' ), 'wp-events-plugin.com/documentation/event-attributes/') );
201
-
202
- echo $save_button;
203
  ?>
204
- </table>
205
-
206
- </div> <!-- . inside -->
207
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
- <div class="postbox " >
210
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Events page', 'dbem' ); ?> </span></h3>
211
- <div class="inside">
212
- <table class="form-table">
213
- <?php
214
- //Wordpress Pages
215
- global $em_disable_filter; //Using a flag here instead
216
- $em_disable_filter = true;
217
- $get_pages = get_pages();
218
- $events_page_options = array();
219
- $events_page_options[0] = __('[No Events Page]');
220
- //TODO Add the hierarchy style ddm, like when choosing page parents
221
- foreach($get_pages as $page){
222
- $events_page_options[$page->ID] = $page->post_title;
223
- }
224
- em_options_select ( __( 'Events page' ), 'dbem_events_page', $events_page_options, __( 'This option allows you to select which page to use as an events page','dbem' ) );
225
- $em_disable_filter = false;
226
- //Rest
227
- em_options_radio_binary ( __( 'Show events page in lists?', 'dbem' ), 'dbem_list_events_page', __( 'Check this option if you want the events page to appear together with other pages in pages lists.', 'dbem' ) );
228
- em_options_radio_binary ( __( 'Display calendar in events page?', 'dbem' ), 'dbem_display_calendar_in_events_page', __( 'This options allows to display the calendar in the events page, instead of the default list. It is recommended not to display both the calendar widget and a calendar page.','dbem' ).' '.__('If you would like to show events that span over more than one day, see the Calendar section on this page.','dbem') );
229
- em_options_radio_binary ( __( 'Disable title rewriting?', 'dbem' ), 'dbem_disable_title_rewrites', __( "Some wordpress themes don't follow best practices when generating navigation menus, and so the automatic title rewriting feature may cause problems, if your menus aren't working correctly on the event pages, try setting this to 'Yes', and provide an appropriate HTML title format below.",'dbem' ) );
230
- em_options_input_text ( __( 'Event Manager titles', 'dbem' ), 'dbem_title_html', __( "This only setting only matters if you selected 'Yes' to above. You will notice the events page titles aren't being rewritten, and you have a new title underneath the default page name. This is where you control the HTML of this title. Make sure you keep the #_PAGETITLE placeholder here, as that's what is rewritten by events manager. To control what's rewritten in this title, see settings further down for page titles.", 'dbem' ) );
231
- em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_events_default_limit', __( "This will control how many events are shown on one list by default.", 'dbem' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  em_options_radio_binary ( __( 'Are current events past events?', 'dbem' ), 'dbem_events_current_are_past', __( "By default, events that are have an end date later than today will be included in searches, set this to yes to consider events that started 'yesterday' as past.", 'dbem' ) );
233
- em_options_radio_binary ( __( 'Show events search?', 'dbem' ), 'dbem_events_page_search', __( "If set to yes, a search form will appear just above your list of events.", 'dbem' ) );
234
  ?>
 
 
 
 
 
 
235
  <tr valign="top" id='dbem_events_default_orderby_row'>
236
  <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
237
  <td>
238
  <select name="dbem_events_default_orderby" >
239
  <?php
240
  $orderby_options = apply_filters('em_settings_events_default_orderby_ddm', array(
241
- 'start_date,start_time,name' => __('Order by start date, start time, then event name','dbem'),
242
- 'name,start_date,start_time' => __('Order by name, start date, then start time','dbem'),
243
- 'name,end_date,end_time' => __('Order by name, end date, then end time','dbem'),
244
- 'end_date,end_time,name' => __('Order by end date, end time, then event name','dbem'),
245
  ));
246
  ?>
247
  <?php foreach($orderby_options as $key => $value) : ?>
248
- <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_default_orderby')) ? "selected='selected'" : ''; ?>>
249
- <?php echo $value; ?>
250
  </option>
251
  <?php endforeach; ?>
252
  </select>
@@ -266,328 +728,1275 @@ function em_admin_options_page() {
266
  ));
267
  ?>
268
  <?php foreach( $order_options as $key => $value) : ?>
269
- <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_default_order')) ? "selected='selected'" : ''; ?>>
270
- <?php echo $value; ?>
271
  </option>
272
  <?php endforeach; ?>
273
  </select>
274
  <br/>
275
  <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
276
  </td>
277
- </tr>
278
- <tr valign="top" id='dbem_events_display_time_limit'>
279
- <th scope="row"><?php _e('Event list scope','dbem'); ?></th>
280
- <td>
281
- <select name="dbem_events_page_scope" >
282
- <?php foreach( em_get_scopes() as $key => $value) : ?>
283
- <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_page_scope')) ? "selected='selected'" : ''; ?>>
284
- <?php echo $value; ?>
285
- </option>
286
- <?php endforeach; ?>
287
- </select>
288
- <br />
289
- <em><?php _e('Only show events starting within a certain time limit on the events page. Default is future events with no end time limit.','dbem'); ?></em>
290
- </td>
291
- </tr>
292
  <?php
 
 
293
  echo $save_button;
294
- ?>
295
- </table>
296
- </div> <!-- . inside -->
297
- </div> <!-- .postbox -->
298
-
299
- <div class="postbox " >
300
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Events format', 'dbem' ); ?> </span></h3>
301
- <div class="inside">
302
- <table class="form-table">
303
- <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Events','dbem')); ?></strong></td></tr>
304
- <?php
305
- em_options_input_text ( __( 'Events page title', 'dbem' ), 'dbem_events_page_title', __( 'The title on the multiple events page.', 'dbem' ) );
306
- em_options_textarea ( __( 'Default event list format header', 'dbem' ), 'dbem_event_list_item_format_header', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
307
- em_options_textarea ( __( 'Default event list format', 'dbem' ), 'dbem_event_list_item_format', __( 'The format of any events in a list.', 'dbem' ).$events_placeholder_tip );
308
- em_options_textarea ( __( 'Default event list format footer', 'dbem' ), 'dbem_event_list_item_format_footer', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
309
- em_options_input_text ( __( 'No events message', 'dbem' ), 'dbem_no_events_message', __( 'The message displayed when no events are available.', 'dbem' ) );
310
- em_options_input_text ( __( 'List events by date title', 'dbem' ), 'dbem_list_date_title', __( 'If viewing a page for events on a specific date, this is the title that would show up. To insert date values, use <a href="http://www.php.net/manual/en/function.date.php">PHP time format characters</a> with a <code>#</code> symbol before them, i.e. <code>#m</code>, <code>#M</code>, <code>#j</code>, etc.<br/>', 'dbem' ) );
311
- ?>
312
- <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Event','dbem')); ?></strong></td></tr>
313
- <?php
314
- em_options_input_text ( __( 'Single event page title format', 'dbem' ), 'dbem_event_page_title_format', __( 'The format of a single event page title.', 'dbem' ).$events_placeholder_tip );
315
- em_options_textarea ( __( 'Default single event format', 'dbem' ), 'dbem_single_event_format', __( 'The format of a single event page.', 'dbem' ).$events_placeholder_tip );
316
- echo $save_button;
317
- ?>
318
- </table>
319
- </div> <!-- . inside -->
320
- </div> <!-- .postbox -->
321
-
322
- <div class="postbox " >
323
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Calendar format', 'dbem' ); ?></span></h3>
324
- <div class="inside">
325
- <table class="form-table">
326
- <?php
327
- em_options_input_text ( __( 'Small calendar title', 'dbem' ), 'dbem_small_calendar_event_title_format', __( 'The format of the title, corresponding to the text that appears when hovering on an eventful calendar day.', 'dbem' ).$events_placeholder_tip );
328
- em_options_input_text ( __( 'Small calendar title separator', 'dbem' ), 'dbem_small_calendar_event_title_separator', __( 'The separator appearing on the above title when more than one events are taking place on the same day.', 'dbem' ) );
329
- em_options_input_text ( __( 'Full calendar events format', 'dbem' ), 'dbem_full_calendar_event_format', __( 'The format of each event when displayed in the full calendar. Remember to include <code>li</code> tags before and after the event.', 'dbem' ).$events_placeholder_tip );
330
- em_options_radio_binary ( __( 'Show long events on calendar pages?', 'dbem' ), 'dbem_full_calendar_long_events', __( "If you are showing a calendar on the events page (see Events format section on this page), you have the option of showing events that span over days on each day it occurs.",'dbem' ) );
331
- em_options_radio_binary ( __( 'Show list on day with single event?', 'dbem' ), 'dbem_display_calendar_day_single', __( "By default, if a calendar day only has one event, it display a single event when clicking on the link of that calendar date. If you select Yes here, you will get always see a list of events.",'dbem' ) );
332
- echo $save_button;
333
- ?>
334
- </table>
335
- </div> <!-- . inside -->
336
- </div> <!-- .postbox -->
337
-
338
- <div class="postbox " >
339
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Locations format', 'dbem' ); ?> </span></h3>
340
- <div class="inside">
341
- <table class="form-table">
342
- <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Locations','dbem')); ?></strong></td></tr>
343
- <?php
344
- em_options_input_text ( sprintf(__('%s page title','dbem'),__('Locations','dbem')), 'dbem_locations_page_title', sprintf(__( 'The title on the multiple %s page.', 'dbem' ), __('locations','dbem')) );
345
- em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('locations','dbem')) );
346
- em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('locations','dbem')).$locations_placeholder_tip );
347
- em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('locations','dbem')) );
348
- em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Locations','dbem')), 'dbem_no_locations_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('locations','dbem')) );
349
- ?>
350
- <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Location','dbem')); ?></strong></td></tr>
351
- <?php
352
- em_options_input_text (sprintf( __( 'Single %s title format', 'dbem' ),__('location','dbem')), 'dbem_location_page_title_format', __( 'The format of a single location page title.', 'dbem' ).$locations_placeholder_tip );
353
- em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('location','dbem')), 'dbem_single_location_format', __( 'The format of a single location page.', 'dbem' ).$locations_placeholder_tip );
354
- em_options_textarea ( __( 'Default location balloon format', 'dbem' ), 'dbem_location_baloon_format', __( 'The format of of the text appearing in the baloon describing the location a single location map.', 'dbem' ).$locations_placeholder_tip );
355
- em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_location_event_list_item_format', __( 'The format of the events the list inserted in the location page through the <code>#_NEXTEVENTS</code>, <code>#_PASTEVENTS</code> and <code>#_ALLEVENTS</code> element.', 'dbem' ).$locations_placeholder_tip );
356
- em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_location_no_events_message', __( 'The message to be displayed in the list generated by <code>#_NEXTEVENTS</code>, <code>#_PASTEVENTS</code> and <code>#_ALLEVENTS</code> when no events are available.', 'dbem' ) );
357
- echo $save_button;
358
- ?>
359
- </table>
360
- </div> <!-- . inside -->
361
- </div> <!-- .postbox -->
362
-
363
- <div class="postbox " >
364
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Categories format', 'dbem' ); ?> </span></h3>
365
- <div class="inside">
366
- <table class="form-table">
367
- <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Categories','dbem')); ?></strong></td></tr>
368
- <?php
369
- em_options_input_text ( sprintf(__('%s page title','dbem'),__('Categories','dbem')), 'dbem_categories_page_title', sprintf(__( 'The title on the multiple %s page.', 'dbem' ), __('categories','dbem')) );
370
- em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('categories','dbem')) );
371
- em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('categories','dbem')).$categories_placeholder_tip );
372
- em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('categories','dbem')) );
373
- em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Categories','dbem')), 'dbem_no_categories_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('categories','dbem')) );
374
- ?>
375
- <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Category','dbem')); ?></strong></td></tr>
376
- <?php
377
- em_options_input_text ( sprintf(__( 'Single %s title format', 'dbem' ),__('category','dbem')), 'dbem_category_page_title_format', __( 'The format of a single category page title.', 'dbem' ).$categories_placeholder_tip );
378
- em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('category','dbem')), 'dbem_category_page_format', __( 'The format of a single category page.', 'dbem' ).$categories_placeholder_tip );
379
- echo $save_button;
380
- ?>
381
- </table>
382
- </div> <!-- . inside -->
383
- </div> <!-- .postbox -->
384
-
385
- <div class="postbox " >
386
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'RSS feed format', 'dbem' ); ?> </span></h3>
387
- <div class="inside">
388
- <table class="form-table">
389
- <?php
390
- em_options_input_text ( __( 'RSS main title', 'dbem' ), 'dbem_rss_main_title', __( 'The main title of your RSS events feed.', 'dbem' ).$events_placeholder_tip );
391
- em_options_input_text ( __( 'RSS main description', 'dbem' ), 'dbem_rss_main_description', __( 'The main description of your RSS events feed.', 'dbem' ) );
392
- em_options_input_text ( __( 'RSS title format', 'dbem' ), 'dbem_rss_title_format', __( 'The format of the title of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
393
- em_options_input_text ( __( 'RSS description format', 'dbem' ), 'dbem_rss_description_format', __( 'The format of the description of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
394
- echo $save_button;
395
  ?>
396
- </table>
397
- </div> <!-- . inside -->
398
- </div> <!-- .postbox -->
399
-
400
- <div class="postbox " >
401
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Maps and geotagging', 'dbem' ); ?> </span></h3>
402
- <div class="inside">
403
- <table class='form-table'>
404
- <?php $gmap_is_active = get_option ( 'dbem_gmap_is_active' ); ?>
405
- <tr valign="top">
406
- <th scope="row"><?php _e ( 'Enable Google Maps integration?', 'dbem' ); ?></th>
407
  <td>
408
- <?php _e ( 'Yes' ); ?> <input id="dbem_gmap_is_active_yes" name="dbem_gmap_is_active" type="radio" value="1" <?php echo ($gmap_is_active) ? "checked='checked'":''; ?> />
409
- <?php _e ( 'No' ); ?> <input name="dbem_gmap_is_active" type="radio" value="0" <?php echo ($gmap_is_active) ? '':"checked='checked'"; ?> /><br />
410
- <em><?php _e ( 'Check this option to enable Goggle Map integration.', 'dbem' )?></em>
411
  </td>
412
  </tr>
413
- <?php
414
- em_options_textarea ( __( 'Map text format', 'dbem' ), 'dbem_map_text_format', __( 'The text format inside the map balloons.', 'dbem' ).$events_placeholder_tip );
415
- echo $save_button;
416
- ?>
417
- </table>
418
- </div> <!-- . inside -->
419
- </div> <!-- .postbox -->
420
-
421
- <div class="postbox " >
422
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Booking and Ticketing Options', 'dbem' ); ?> </span></h3>
423
- <div class="inside">
424
- <table class='form-table'>
425
  <?php
426
- em_options_radio_binary ( __( 'Approval Required?', 'dbem' ), 'dbem_bookings_approval', __( 'Bookings will not be confirmed until the event administrator approves it.', 'dbem' ) );
427
- em_options_select ( __( 'Currency', 'dbem' ), 'dbem_bookings_currency', em_get_currencies()->names, __( 'Choose your currency for displaying event pricing.', 'dbem' ) );
428
- em_options_radio_binary ( __( 'Single ticket mode?', 'dbem' ), 'dbem_bookings_tickets_single', __( 'In single ticket mode, users can only create one ticket per booking (and will not see options to add more tickets).', 'dbem' ) );
429
- em_options_radio_binary ( __( 'Show unavailable tickets?', 'dbem' ), 'dbem_bookings_tickets_show_unavailable', __( 'You can choose whether or not to show unavailable tickets to visitors.', 'dbem' ) );
430
- em_options_radio_binary ( __( 'Reserved unconfirmed spaces?', 'dbem' ), 'dbem_bookings_approval_reserved', __( 'By default, event spaces become unavailable once there are enough CONFIRMED bookings. To reserve spaces even if unnapproved, choose yes.', 'dbem' ) );
431
- em_options_radio_binary ( __( 'Show multiple tickets if logged out?', 'dbem' ), 'dbem_bookings_tickets_show_loggedout', __( 'If logged out, a user will be asked to register in order to book. However, we can show available tickets if you have more than one ticket.', 'dbem' ) );
432
- em_options_radio_binary ( __( 'Allow overbooking when approving?', 'dbem' ), 'dbem_bookings_approval_overbooking', __( 'If you get a lot of pending bookings and you decide to allow more bookings than spaces allow, setting this to yes will allow you to override the event space limit when manually approving.', 'dbem' ) );
433
- em_options_radio_binary ( __( 'Allow guest bookings?', 'dbem' ), 'dbem_bookings_anonymous', __( 'If enabled, guest visitors can supply an email address and a user account will automatically be created for them along with their booking. They will be also be able to log back in with that newly created account.', 'dbem' ) );
434
- echo $save_button;
435
- ?>
436
- </table>
437
- </div> <!-- . inside -->
438
- </div> <!-- .postbox -->
439
-
440
- <div class="postbox " >
441
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Booking Email Templates', 'dbem' ); ?> </span></h3>
442
- <div class="inside">
443
- <table class='form-table'>
444
- <?php
445
- em_options_select ( __( 'Default contact person', 'dbem' ), 'dbem_default_contact_person', em_get_wp_users (), __( 'Select the default contact person. This user will be employed whenever a contact person is not explicitly specified for an event', 'dbem' ) );
446
- em_options_input_text ( __( 'Email events admin?', 'dbem' ), 'dbem_bookings_notify_admin', __( "If you would like every event booking confirmation email sent to an administrator write their email here (leave blank to not send an email).", 'dbem' ) );
447
- em_options_radio_binary ( __( 'Email contact person?', 'dbem' ), 'dbem_bookings_contact_email', __( 'Check this option if you want the event contact to receive an email when someone books places. An email will be sent when a booking is first made (regardless if confirmed or pending)', 'dbem' ) );
448
- ?>
449
- <tr><td colspan='2'><h4><?php _e('Contact person booking confirmed','dbem') ?></h4></td></tr>
450
- <tr><td colspan='2'><?php echo __('An email will be sent to the event contact when a booking is first made.','dbem').$bookings_placeholder_tip ?></td></tr>
451
- <?php
452
- em_options_input_text ( __( 'Contact person email subject', 'dbem' ), 'dbem_bookings_contact_email_subject', '' );
453
- em_options_textarea ( __( 'Contact person email', 'dbem' ), 'dbem_bookings_contact_email_body', '' );
454
  ?>
455
- <tr><td colspan='2'><h4><?php _e('Contact person booking cancelled','dbem') ?></h4></td></tr>
456
- <tr><td colspan='2'><?php echo __('An email will be sent to the event contact if someone cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
457
- <?php
458
- em_options_input_text ( __( 'Contact person cancellation subject', 'dbem' ), 'dbem_contactperson_email_cancelled_subject', '' );
459
- em_options_textarea ( __( 'Contact person cancellation email', 'dbem' ), 'dbem_contactperson_email_cancelled_body', '' );
460
- ?>
461
- <tr><td colspan='2'><h4><?php _e('Confirmed booking email','dbem') ?></h4></td></tr>
462
- <tr><td colspan='2'><?php echo __('This is sent when a person\'s booking is confirmed. This will be sent automatically if approvals are required and the booking is approved. If approvals are disabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
463
- <?php
464
- em_options_input_text ( __( 'Booking confirmed email subject', 'dbem' ), 'dbem_bookings_email_confirmed_subject', '' );
465
- em_options_textarea ( __( 'Booking confirmed email', 'dbem' ), 'dbem_bookings_email_confirmed_body', '' );
466
- ?>
467
- <tr><td colspan='2'><h4><?php _e('Pending booking email','dbem') ?></h4></td></tr>
468
- <tr><td colspan='2'><?php echo __( 'This will be sent to the person when they first submit their booking. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
469
- <?php
470
- em_options_input_text ( __( 'Booking pending email subject', 'dbem' ), 'dbem_bookings_email_pending_subject', '');
471
- em_options_textarea ( __( 'Booking pending email', 'dbem' ), 'dbem_bookings_email_pending_body','') ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  ?>
473
- <tr><td colspan='2'><h4><?php _e('Rejected booking email','dbem') ?></h4></td></tr>
474
- <tr><td colspan='2'><?php echo __( 'This will be sent automatically when a booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  <?php
476
- em_options_input_text ( __( 'Booking rejected email subject', 'dbem' ), 'dbem_bookings_email_rejected_subject', __( "The subject of the email sent to the person making a booking that is awaiting administrator approval. Not relevant if bookings don't require approval.", 'dbem' ).$bookings_placeholder_tip );
477
- em_options_textarea ( __( 'Booking rejected email', 'dbem' ), 'dbem_bookings_email_rejected_body', __( 'The body of the email which will be sent to the person if the booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip );
478
- echo $save_button;
479
  ?>
480
- <tr><td colspan='2'><h4><?php _e('Booking cancelled','dbem') ?></h4></td></tr>
481
- <tr><td colspan='2'><?php echo __('This will be sent when a user cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  <?php
483
- em_options_input_text ( __( 'Booking cancelled email subject', 'dbem' ), 'dbem_bookings_email_cancelled_subject', '' );
484
- em_options_textarea ( __( 'Booking cancelled email', 'dbem' ), 'dbem_bookings_email_cancelled_body', '' );
485
  ?>
486
- </table>
487
- </div> <!-- . inside -->
488
- </div> <!-- .postbox -->
489
-
490
- <?php if ( !is_multisite() || (is_multisite() && is_super_admin()) ) : ?>
491
- <div class="postbox " >
492
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Email Settings', 'dbem' ); ?> <?php echo $multisite_view; ?></span></h3>
493
- <div class="inside">
494
- <table class='form-table'>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
495
  <?php
496
- em_options_input_text ( __( 'Notification sender name', 'dbem' ), 'dbem_mail_sender_name', __( "Insert the display name of the notification sender.", 'dbem' ) );
497
- em_options_input_text ( __( 'Notification sender address', 'dbem' ), 'dbem_mail_sender_address', __( "Insert the address of the notification sender.", 'dbem' ) );
498
- em_options_input_text ( 'Mail sending port', 'dbem_rsvp_mail_port', __( "The port through which you e-mail notifications will be sent. Make sure the firewall doesn't block this port", 'dbem' ) );
499
- em_options_select ( __( 'Mail sending method', 'dbem' ), 'dbem_rsvp_mail_send_method', array ('smtp' => 'SMTP', 'mail' => __( 'PHP mail function', 'dbem' ), 'sendmail' => 'Sendmail', 'qmail' => 'Qmail', 'wp_mail' => 'WP Mail' ), __( 'Select the method to send email notification.', 'dbem' ) );
500
- em_options_radio_binary ( __( 'Use SMTP authentication?', 'dbem' ), 'dbem_rsvp_mail_SMTPAuth', __( 'SMTP authentication is often needed. If you use GMail, make sure to set this parameter to Yes', 'dbem' ) );
501
- em_options_input_text ( 'SMTP host', 'dbem_smtp_host', __( "The SMTP host. Usually it corresponds to 'localhost'. If you use GMail, set this value to 'ssl://smtp.gmail.com:465'.", 'dbem' ) );
502
- em_options_input_text ( __( 'SMTP username', 'dbem' ), 'dbem_smtp_username', __( "Insert the username to be used to access your SMTP server.", 'dbem' ) );
503
- em_options_input_password ( __( 'SMTP password', 'dbem' ), "dbem_smtp_password", __( "Insert the password to be used to access your SMTP server", 'dbem' ) );
504
- echo $save_button;
505
  ?>
506
- </table>
507
- </div> <!-- . inside -->
508
- </div> <!-- .postbox -->
509
-
510
- <div class="postbox " >
511
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Images size', 'dbem' ); ?> <?php echo $multisite_view; ?> </span></h3>
512
- <div class="inside">
513
- <table class='form-table'>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  <?php
515
- em_options_input_text ( __( 'Maximum width (px)', 'dbem' ), 'dbem_image_max_width', __( 'The maximum allowed width for images uploades', 'dbem' ) );
516
- em_options_input_text ( __( 'Maximum height (px)', 'dbem' ), 'dbem_image_max_height', __( "The maximum allowed height for images uploaded, in pixels", 'dbem' ) );
517
- em_options_input_text ( __( 'Maximum size (bytes)', 'dbem' ), 'dbem_image_max_size', __( "The maximum allowed size for images uploaded, in pixels", 'dbem' ) );
518
- echo $save_button;
519
  ?>
520
- </table>
521
- </div> <!-- . inside -->
522
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
 
524
- <div class="postbox" >
525
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'User Capabilities', 'dbem' ); ?> <?php echo $multisite_view; ?></span></h3>
526
- <div class="inside">
527
- <table class="form-table">
528
- <tr><td colspan="2">
529
- <strong><?php _e('Warning: Changing these values may result in exposing previously hidden information to all users.')?></strong><br />
530
- </td></tr>
531
- <?php
532
- global $wp_roles;
533
- global $em_capabilities_array;
534
- ?>
535
- <tr><td colspan="2">
536
- <p><em><?php _e('You can now give fine grained control with regards to what your users can do with events. Each user role can have perform different sets of actions.','dbem'); ?></em></p>
537
- <table class="em-caps-table" style="width:auto;" cellspacing="0" cellpadding="0">
538
- <thead>
539
- <tr>
540
- <td>&nbsp;</td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541
  <?php
542
- $odd = 0;
543
- $cap_docs = array(
544
- 'publish_events' => __('Users can publish events and skip any admin approval.','dbem'),
545
- 'edit_categories' => __('User can edit the global categories.','dbem'),
546
- 'delete_others_events' => __('User can delete other users events.','dbem'),
547
- 'delete_others_locations' => __('User can delete other users locations.','dbem'),
548
- 'edit_others_locations' => __('User can edit other users locations.','dbem'),
549
- 'manage_others_bookings' => __('User can manage other users individual bookings and event booking settings.','dbem'),
550
- 'edit_others_events' => __('User can edit other users events.','dbem'),
551
- 'delete_locations' => __('User can delete their own locations.','dbem'),
552
- 'delete_events' => __('User can delete their events.','dbem'),
553
- 'edit_locations' => __('User can edit their locations.','dbem'),
554
- 'manage_bookings' => __('User can use and manage bookings with their events.','dbem'),
555
- 'read_others_locations' => __('User can view other users locations, to make locations shared by all users allow all event user roles to view all locations.','dbem'),
556
- 'edit_recurrences' => __('User can create recurrent events.','dbem'),
557
- 'edit_events' => __('User can create and edit their events.','dbem')
558
- );
559
- foreach(array_keys($em_capabilities_array) as $capability){
560
- ?><th class="<?php echo $capability ?> <?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>">&nbsp;<a href="#" title="<?php echo $cap_docs[$capability]; ?>">?</a></th><?php
561
- $odd++;
562
- }
563
  ?>
564
- </tr>
565
- </thead>
566
- <tbody>
567
- <?php foreach($wp_roles->role_objects as $role): ?>
568
- <tr>
569
- <td class="cap"><strong><?php echo $role->name; ?></strong></td>
 
570
  <?php
571
- $odd = 0;
572
- foreach(array_keys($em_capabilities_array) as $capability){
573
- ?><td class="<?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>"><input type="checkbox" name="em_capabilities[<?php echo $role->name; ?>][<?php echo $capability ?>]" value="1" <?php echo $role->has_cap($capability) ? 'checked="checked"':''; ?> /></td><?php
574
- $odd++;
575
- }
 
 
 
576
  ?>
577
- </tr>
578
- <?php endforeach; ?>
579
- </tbody>
580
- </table>
581
- </td></tr>
582
- <?php echo $save_button; ?>
583
- </table>
584
- </div> <!-- . inside -->
585
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
  <?php endif; ?>
587
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588
  <?php /*
589
  <div class="postbox " >
590
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Debug Modes', 'dbem' ); ?> </span></h3>
591
  <div class="inside">
592
  <table class='form-table'>
593
  <?php
@@ -598,12 +2007,11 @@ function em_admin_options_page() {
598
  </div> <!-- . inside -->
599
  </div> <!-- .postbox -->
600
  */ ?>
601
-
602
- <?php do_action('em_options_page_footer'); ?>
603
 
604
  <p class="submit">
605
- <input type="submit" id="dbem_options_submit" name="Submit" value="<?php _e ( 'Save Changes' )?>" />
606
  <input type="hidden" name="em-submitted" value="1" />
 
607
  </p>
608
 
609
  </div> <!-- .metabox-sortables -->
@@ -614,4 +2022,260 @@ function em_admin_options_page() {
614
  </div>
615
  <?php
616
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  ?>
2
 
3
  //Function composing the options subpanel
4
  function em_options_save(){
5
+ global $EM_Notices;
6
  /*
7
  * Here's the idea, we have an array of all options that need super admin approval if in multi-site mode
8
  * since options are only updated here, its one place fit all
9
  */
10
+ if( current_user_can('list_users') && !empty($_POST['em-submitted']) && check_admin_referer('events-manager-options','_wpnonce') ){
11
  //Build the array of options here
12
  $post = $_POST;
13
  foreach ($_POST as $postKey => $postValue){
14
  if( substr($postKey, 0, 5) == 'dbem_' ){
15
  //TODO some more validation/reporting
16
  $numeric_options = array('dbem_locations_default_limit','dbem_events_default_limit');
17
+ if( in_array($postKey, array('dbem_bookings_notify_admin','dbem_event_submitted_email_admin','dbem_js_limit_events_form','dbem_js_limit_search','dbem_js_limit_general','dbem_css_limit_include','dbem_css_limit_exclude','dbem_search_form_geo_distance_options')) ){ $postValue = str_replace(' ', '', $postValue); } //clean up comma seperated emails, no spaces needed
18
  if( in_array($postKey,$numeric_options) && !is_numeric($postValue) ){
19
  //Do nothing, keep old setting.
20
+ }elseif( $postKey == 'dbem_category_default_color' && !preg_match("/^#([abcdef0-9]{3}){1,2}?$/i",$postValue)){
21
+ $EM_Notices->add_error( sprintf(esc_html_x('Colors must be in a valid %s format, such as #FF00EE.', 'hex format', 'dbem'), '<a href="http://en.wikipedia.org/wiki/Web_colors">hex</a>').' '. esc_html__('This setting was not changed.', 'dbem'), true);
22
  }else{
23
  //TODO slashes being added?
24
+ if( is_array($postValue) ){
25
+ foreach($postValue as $postValue_key=>$postValue_val) $postValue[$postValue_key] = stripslashes($postValue_val);
26
+ }else{
27
+ $postValue = stripslashes($postValue);
28
+ }
29
+ update_option($postKey, $postValue);
30
  }
31
  }
32
  }
 
33
  //set capabilities
34
  if( !empty($_POST['em_capabilities']) && is_array($_POST['em_capabilities']) && (!is_multisite() || is_multisite() && is_super_admin()) ){
35
  global $em_capabilities_array, $wp_roles;
36
+ if( is_multisite() && is_network_admin() && $_POST['dbem_ms_global_caps'] == 1 ){
37
+ //apply_caps_to_blog
38
+ global $current_site,$wpdb;
39
+ $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->id);
40
+ foreach($blog_ids as $blog_id){
41
+ switch_to_blog($blog_id);
42
+ //normal blog role application
43
+ foreach( $wp_roles->role_objects as $role_name => $role ){
44
+ foreach( array_keys($em_capabilities_array) as $capability){
45
+ if( !empty($_POST['em_capabilities'][$role_name][$capability]) ){
46
+ $role->add_cap($capability);
47
+ }else{
48
+ $role->remove_cap($capability);
49
+ }
50
+ }
51
+ }
52
+ restore_current_blog();
53
+ }
54
+ }elseif( !is_network_admin() ){
55
+ //normal blog role application
56
+ foreach( $wp_roles->role_objects as $role_name => $role ){
57
+ foreach( array_keys($em_capabilities_array) as $capability){
58
+ if( !empty($_POST['em_capabilities'][$role_name][$capability]) ){
59
+ $role->add_cap($capability);
60
+ }else{
61
+ $role->remove_cap($capability);
62
+ }
63
  }
64
  }
65
  }
66
  }
67
+ update_option('dbem_flush_needed',1);
68
  do_action('em_options_save');
69
+ $EM_Notices->add_confirm('<strong>'.__('Changes saved.', 'dbem').'</strong>', true);
70
+ wp_redirect(wp_get_referer());
71
+ exit();
72
+ }
73
+ //Migration
74
+ if( !empty($_GET['em_migrate_images']) && check_admin_referer('em_migrate_images','_wpnonce') && get_option('dbem_migrate_images') ){
75
+ include(plugin_dir_path(__FILE__).'../em-install.php');
76
+ $result = em_migrate_uploads();
77
+ if($result){
78
+ $failed = ( $result['fail'] > 0 ) ? $result['fail'] . ' images failed to migrate.' : '';
79
+ $EM_Notices->add_confirm('<strong>'.$result['success'].' images migrated successfully. '.$failed.'</strong>');
80
  }
81
+ wp_redirect(admin_url().'edit.php?post_type=event&page=events-manager-options&em_migrate_images');
82
+ }elseif( !empty($_GET['em_not_migrate_images']) && check_admin_referer('em_not_migrate_images','_wpnonce') ){
83
+ delete_option('dbem_migrate_images_nag');
84
+ delete_option('dbem_migrate_images');
85
+ }
86
+ //Uninstall
87
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' && current_user_can('activate_plugins') && !empty($_REQUEST['confirmed']) && check_admin_referer('em_uninstall_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
88
+ if( check_admin_referer('em_uninstall_'.get_current_user_id().'_confirmed','_wpnonce2') ){
89
+ //We have a go to uninstall
90
+ global $wpdb;
91
+ //delete EM posts
92
+ remove_action('before_delete_post',array('EM_Location_Post_Admin','before_delete_post'),10,1);
93
+ remove_action('before_delete_post',array('EM_Event_Post_Admin','before_delete_post'),10,1);
94
+ remove_action('before_delete_post',array('EM_Event_Recurring_Post_Admin','before_delete_post'),10,1);
95
+ $post_ids = $wpdb->get_col('SELECT ID FROM '.$wpdb->posts." WHERE post_type IN ('".EM_POST_TYPE_EVENT."','".EM_POST_TYPE_LOCATION."','event-recurring')");
96
+ foreach($post_ids as $post_id){
97
+ wp_delete_post($post_id);
98
+ }
99
+ //delete categories
100
+ $cat_terms = get_terms(EM_TAXONOMY_CATEGORY, array('hide_empty'=>false));
101
+ foreach($cat_terms as $cat_term){
102
+ wp_delete_term($cat_term->term_id, EM_TAXONOMY_CATEGORY);
103
+ }
104
+ $tag_terms = get_terms(EM_TAXONOMY_TAG, array('hide_empty'=>false));
105
+ foreach($tag_terms as $tag_term){
106
+ wp_delete_term($tag_term->term_id, EM_TAXONOMY_TAG);
107
+ }
108
+ //delete EM tables
109
+ $wpdb->query('DROP TABLE '.EM_EVENTS_TABLE);
110
+ $wpdb->query('DROP TABLE '.EM_BOOKINGS_TABLE);
111
+ $wpdb->query('DROP TABLE '.EM_LOCATIONS_TABLE);
112
+ $wpdb->query('DROP TABLE '.EM_TICKETS_TABLE);
113
+ $wpdb->query('DROP TABLE '.EM_TICKETS_BOOKINGS_TABLE);
114
+ $wpdb->query('DROP TABLE '.EM_RECURRENCE_TABLE);
115
+ $wpdb->query('DROP TABLE '.EM_CATEGORIES_TABLE);
116
+ $wpdb->query('DROP TABLE '.EM_META_TABLE);
117
+
118
+ //delete options
119
+ $wpdb->query('DELETE FROM '.$wpdb->options.' WHERE option_name LIKE \'em_%\' OR option_name LIKE \'dbem_%\'');
120
+ //deactivate and go!
121
+ deactivate_plugins(array('events-manager/events-manager.php','events-manager-pro/events-manager-pro.php'), true);
122
+ wp_redirect(admin_url('plugins.php?deactivate=true'));
123
+ exit();
124
  }
125
+ }
126
+ //Reset
127
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' && !empty($_REQUEST['confirmed']) && check_admin_referer('em_reset_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
128
+ if( check_admin_referer('em_reset_'.get_current_user_id().'_confirmed','_wpnonce2') ){
129
+ //We have a go to uninstall
130
+ global $wpdb;
131
+ //delete options
132
+ $wpdb->query('DELETE FROM '.$wpdb->options.' WHERE option_name LIKE \'em_%\' OR option_name LIKE \'dbem_%\'');
133
+ //reset capabilities
134
+ global $em_capabilities_array, $wp_roles;
135
+ foreach( $wp_roles->role_objects as $role_name => $role ){
136
+ foreach( array_keys($em_capabilities_array) as $capability){
137
+ $role->remove_cap($capability);
138
+ }
139
+ }
140
+ //go back to plugin options page
141
+ $EM_Notices->add_confirm(__('Settings have been reset back to default. Your events, locations and categories have not been modified.','dbem'), true);
142
+ wp_redirect(EM_ADMIN_URL.'&page=events-manager-options');
143
+ exit();
144
+ }
145
+ }
146
+ //Force Update Recheck - Workaround for now
147
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'recheck_updates' && check_admin_referer('em_recheck_updates_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
148
+ //force recheck of plugin updates, to refresh dl links
149
+ delete_transient('update_plugins');
150
+ delete_site_transient('update_plugins');
151
+ $EM_Notices->add_confirm(__('If there are any new updates, you should now see them in your Plugins or Updates admin pages.','dbem'), true);
152
+ wp_redirect(wp_get_referer());
153
+ exit();
154
+ }
155
+ //Flag version checking to look at trunk, not tag
156
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'check_devs' && check_admin_referer('em_check_devs_wpnonce') && is_super_admin() ){
157
+ //delete transients, and add a flag to recheck dev version next time round
158
+ delete_transient('update_plugins');
159
+ delete_site_transient('update_plugins');
160
+ update_option('em_check_dev_version', true);
161
+ $EM_Notices->add_confirm(__('Checking for dev versions.','dbem').' '. __('If there are any new updates, you should now see them in your Plugins or Updates admin pages.','dbem'), true);
162
+ wp_redirect(wp_get_referer());
163
+ exit();
164
+ }
165
+
166
  }
167
+ add_action('admin_init', 'em_options_save');
168
 
169
+ function em_admin_email_test_ajax(){
170
+ if( wp_verify_nonce($_REQUEST['_check_email_nonce'],'check_email') && current_user_can('activate_plugins') ){
171
+ $subject = __("Events Manager Test Email",'dbem');
172
+ $content = __('Congratulations! Your email settings work.','dbem');
173
+ $current_user = get_user_by('id', get_current_user_id());
174
+ //add filters for options used in EM_Mailer so the current supplied ones are used
175
+ ob_start();
176
+ add_filter('pre_option_dbem_mail_sender_name', create_function('$args', "return '".$_REQUEST['dbem_mail_sender_name']."';"));
177
+ add_filter('pre_option_dbem_mail_sender_address', create_function('$args', "return '{$_REQUEST['dbem_mail_sender_address']}';"));
178
+ add_filter('pre_option_dbem_rsvp_mail_send_method', create_function('$args', "return '{$_REQUEST['dbem_rsvp_mail_send_method']}';"));
179
+ add_filter('pre_option_dbem_smtp_html', create_function('$args', "return '{$_REQUEST['dbem_smtp_html']}';"));
180
+ add_filter('pre_option_dbem_smtp_html_br', create_function('$args', "return '{$_REQUEST['dbem_smtp_html_br']}';"));
181
+ add_filter('pre_option_dbem_rsvp_mail_port', create_function('$args', "return '{$_REQUEST['dbem_rsvp_mail_port']}';"));
182
+ add_filter('pre_option_dbem_rsvp_mail_SMTPAuth', create_function('$args', "return '{$_REQUEST['dbem_rsvp_mail_SMTPAuth']}';"));
183
+ add_filter('pre_option_dbem_smtp_host', create_function('$args', "return '{$_REQUEST['dbem_smtp_host']}';"));
184
+ add_filter('pre_option_dbem_smtp_username', create_function('$args', "return '{$_REQUEST['dbem_smtp_username']}';"));
185
+ add_filter('pre_option_dbem_smtp_password', create_function('$args', "return '{$_REQUEST['dbem_smtp_password']}';"));
186
+ ob_clean(); //remove any php errors/warnings output
187
+ $EM_Event = new EM_Event();
188
+ if( $EM_Event->email_send($subject,$content,$current_user->user_email) ){
189
+ $result = array(
190
+ 'result' => true,
191
+ 'message' => sprintf(__('Email sent succesfully to %s','dbem'),$current_user->user_email)
192
+ );
193
+ }else{
194
+ $result = array(
195
+ 'result' => false,
196
+ 'message' => __('Email not sent.','dbem')." <ul><li>".implode('</li><li>',$EM_Event->get_errors()).'</li></ul>'
197
+ );
198
+ }
199
+ echo EM_Object::json_encode($result);
200
+ }
201
+ exit();
202
+ }
203
+ add_action('wp_ajax_em_admin_test_email','em_admin_email_test_ajax');
204
 
205
+ function em_admin_options_reset_page(){
206
+ if( check_admin_referer('em_reset_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
207
+ ?>
208
+ <div class="wrap">
209
+ <div id='icon-options-general' class='icon32'><br /></div>
210
+ <h2><?php _e('Reset Events Manager','dbem'); ?></h2>
211
+ <p style="color:red; font-weight:bold;"><?php _e('Are you sure you want to reset Events Manager?','dbem')?></p>
212
+ <p style="font-weight:bold;"><?php _e('All your settings, including email templates and template formats for Events Manager will be deleted.','dbem')?></p>
213
+ <p>
214
+ <a href="<?php echo add_query_arg(array('_wpnonce2' => wp_create_nonce('em_reset_'.get_current_user_id().'_confirmed'), 'confirmed'=>1)); ?>" class="button-primary"><?php _e('Reset Events Manager','dbem'); ?></a>
215
+ <a href="<?php echo wp_get_referer(); ?>" class="button-secondary"><?php _e('Cancel','dbem'); ?></a>
216
+ </p>
217
+ </div>
218
+ <?php
219
+ }
220
+ }
221
+ function em_admin_options_uninstall_page(){
222
+ if( check_admin_referer('em_uninstall_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
223
+ ?>
224
+ <div class="wrap">
225
+ <div id='icon-options-general' class='icon32'><br /></div>
226
+ <h2><?php _e('Uninstall Events Manager','dbem'); ?></h2>
227
+ <p style="color:red; font-weight:bold;"><?php _e('Are you sure you want to uninstall Events Manager?','dbem')?></p>
228
+ <p style="font-weight:bold;"><?php _e('All your settings and events will be permanently deleted. This cannot be undone.','dbem')?></p>
229
+ <p><?php echo sprintf(__('If you just want to deactivate the plugin, <a href="%s">go to your plugins page</a>.','dbem'), wp_nonce_url(admin_url('plugins.php'))); ?></p>
230
+ <p>
231
+ <a href="<?php echo add_query_arg(array('_wpnonce2' => wp_create_nonce('em_uninstall_'.get_current_user_id().'_confirmed'), 'confirmed'=>1)); ?>" class="button-primary"><?php _e('Uninstall and Deactivate','dbem'); ?></a>
232
+ <a href="<?php echo wp_get_referer(); ?>" class="button-secondary"><?php _e('Cancel','dbem'); ?></a>
233
+ </p>
234
+ </div>
235
+ <?php
236
+ }
237
+ }
238
 
239
  function em_admin_options_page() {
240
+ global $wpdb, $EM_Notices;
241
+ //Check for uninstall/reset request
242
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' ){
243
+ em_admin_options_uninstall_page();
244
+ return;
245
+ }
246
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' ){
247
+ em_admin_options_reset_page();
248
+ return;
249
+ }
250
+ //substitute dropdowns with input boxes for some situations to improve speed, e.g. if there 1000s of locations or users
251
+ $total_users = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->users};");
252
+ if( $total_users > 100 && !defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') ){ define('EM_OPTIMIZE_SETTINGS_PAGE_USERS',true); }
253
+ $total_locations = EM_Locations::count();
254
+ if( $total_locations > 100 && !defined('EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS') ){ define('EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS',true); }
255
  //TODO place all options into an array
256
+ global $events_placeholder_tip, $locations_placeholder_tip, $categories_placeholder_tip, $bookings_placeholder_tip;
257
+ $events_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
258
+ $locations_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
259
+ $bookings_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
260
+ $categories_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#category-placeholders">'. __('Category Related Placeholders','dbem') .'</a>';
261
  $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
262
  $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
263
  $categories_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $categories_placeholders);
264
  $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
265
 
266
+ global $save_button;
267
+ $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" class="button-primary" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes', 'dbem') .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
268
+ ?>
269
+ <script type="text/javascript" charset="utf-8"><?php include(EM_DIR.'/includes/js/admin-settings.js'); ?></script>
270
+ <style type="text/css">.postbox h3 { cursor:pointer; }</style>
271
+ <div class="wrap">
272
+ <div id='icon-options-general' class='icon32'><br /></div>
273
+ <h2 class="nav-tab-wrapper">
274
+ <a href="#general" id="em-menu-general" class="nav-tab nav-tab-active"><?php _e('General','dbem'); ?></a>
275
+ <a href="#pages" id="em-menu-pages" class="nav-tab"><?php _e('Pages','dbem'); ?></a>
276
+ <a href="#formats" id="em-menu-formats" class="nav-tab"><?php _e('Formatting','dbem'); ?></a>
277
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
278
+ <a href="#bookings" id="em-menu-bookings" class="nav-tab"><?php _e('Bookings','dbem'); ?></a>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  <?php endif; ?>
280
+ <a href="#emails" id="em-menu-emails" class="nav-tab"><?php _e('Emails','dbem'); ?></a>
281
+ </h2>
282
+ <h3 id="em-options-title"><?php _e ( 'Event Manager Options', 'dbem' ); ?></h3>
283
+ <form id="em-options-form" method="post" action="">
 
 
 
 
284
  <div class="metabox-holder">
285
  <!-- // TODO Move style in css -->
286
  <div class='postbox-container' style='width: 99.5%'>
287
+ <div id="">
288
 
289
+ <div class="em-menu-general em-menu-group">
290
+
291
+ <!-- GENERAL OPTIONS -->
292
+ <div class="postbox " id="em-opt-general" >
293
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'General Options', 'dbem' ); ?> </span></h3>
294
  <div class="inside">
295
  <table class="form-table">
296
+ <?php em_options_radio_binary ( __( 'Disable thumbnails?', 'dbem' ), 'dbem_thumbnails_enabled', __( 'Select yes to disable Events Manager from enabling thumbnails (some themes may already have this enabled, which we cannot be turned off here).','dbem' ) ); ?>
297
+ <tr class="em-header">
298
+ <td colspan="2">
299
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Event','dbem')); ?></h4>
300
+ </td>
301
+ </tr>
302
+ <?php
303
+ em_options_radio_binary ( __( 'Enable recurrence?', 'dbem' ), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','dbem' ) );
304
+ em_options_radio_binary ( __( 'Enable bookings?', 'dbem' ), 'dbem_rsvp_enabled', __( 'Select yes to allow bookings and tickets for events.','dbem' ) );
305
+ em_options_radio_binary ( __( 'Enable tags?', 'dbem' ), 'dbem_tags_enabled', __( 'Select yes to enable the tag features','dbem' ) );
306
+ if( !(EM_MS_GLOBAL && !is_main_site()) ){
307
+ em_options_radio_binary ( __( 'Enable categories?', 'dbem' ), 'dbem_categories_enabled', __( 'Select yes to enable the category features','dbem' ) );
308
+ if( get_option('dbem_categories_enabled') ){
309
+ /*default category*/
310
+ $category_options = array();
311
+ $category_options[0] = __('no default category','dbem');
312
+ $EM_Categories = EM_Categories::get();
313
+ foreach($EM_Categories as $EM_Category){
314
+ $category_options[$EM_Category->id] = $EM_Category->name;
315
+ }
316
+ echo "<tr><th>".__( 'Default Category', 'dbem' )."</th><td>";
317
+ wp_dropdown_categories(array( 'hide_empty' => 0, 'name' => 'dbem_default_category', 'hierarchical' => true, 'taxonomy' => EM_TAXONOMY_CATEGORY, 'selected' => get_option('dbem_default_category'), 'show_option_none' => __('None','dbem'), 'class'=>''));
318
+ echo "</br><em>" .__( 'This option allows you to select the default category when adding an event.','dbem' ).' '.__('If an event does not have a category assigned when editing, this one will be assigned automatically.','dbem')."</em>";
319
+ echo "</td></tr>";
320
+ }
321
+ }
322
+ em_options_radio_binary ( sprintf(__( 'Enable %s attributes?', 'dbem' ),__('event','dbem')), 'dbem_attributes_enabled', __( 'Select yes to enable the attributes feature','dbem' ) );
323
+ em_options_radio_binary ( sprintf(__( 'Enable %s custom fields?', 'dbem' ),__('event','dbem')), 'dbem_cp_events_custom_fields', __( 'Custom fields are the same as attributes, except you cannot restrict specific values, users can add any kind of custom field name/value pair. Only available in the WordPress admin area.','dbem' ) );
324
+ if( get_option('dbem_attributes_enabled') ){
325
+ em_options_textarea ( sprintf(__( '%s Attributes', 'dbem' ),__('Event','dbem')), 'dbem_placeholders_custom', sprintf(__( "You can also add event attributes here, one per line in this format <code>#_ATT{key}</code>. They will not appear on event pages unless you insert them into another template below, but you may want to store extra information about an event for other uses. <a href='%s'>More information on placeholders.</a>", 'dbem' ), EM_ADMIN_URL .'&amp;page=events-manager-help') );
326
+ }
327
+ if( get_option('dbem_locations_enabled') ){
328
+ /*default location*/
329
+ if( defined('EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS') && EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS ){
330
+ em_options_input_text( __( 'Default Location', 'dbem' ), 'dbem_default_location', __('Please enter your Location ID, or leave blank for no location.','dbem').' '.__( 'This option allows you to select the default location when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
331
+ }else{
332
+ $location_options = array();
333
+ $location_options[0] = __('no default location','dbem');
334
+ $EM_Locations = EM_Locations::get();
335
+ foreach($EM_Locations as $EM_Location){
336
+ $location_options[$EM_Location->location_id] = $EM_Location->location_name;
337
+ }
338
+ em_options_select ( __( 'Default Location', 'dbem' ), 'dbem_default_location', $location_options, __('Please enter your Location ID.','dbem').' '.__( 'This option allows you to select the default location when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
339
+ }
340
+
341
+ /*default location country*/
342
+ em_options_select ( __( 'Default Location Country', 'dbem' ), 'dbem_location_default_country', em_get_countries(__('no default country', 'dbem')), __('If you select a default country, that will be pre-selected when creating a new location.','dbem') );
343
+ }
344
+ ?>
345
+ <tr class="em-header">
346
+ <td colspan="2">
347
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Location','dbem')); ?></h4>
348
+ </td>
349
+ </tr>
350
+ <?php
351
+ em_options_radio_binary ( __( 'Enable locations?', 'dbem' ), 'dbem_locations_enabled', __( 'If you disable locations, bear in mind that you should remove your location page, shortcodes and related placeholders from your <a href="#formats" class="nav-tab-link" rel="#em-menu-formats">formats</a>.','dbem' ) );
352
+ if( get_option('dbem_locations_enabled') ){
353
+ em_options_radio_binary ( __( 'Require locations for events?', 'dbem' ), 'dbem_require_location', __( 'Setting this to no will allow you to submit events without locations. You can use the <code>{no_location}...{/no_location}</code> or <code>{has_location}..{/has_location}</code> conditional placeholder to selectively display location information.','dbem' ) );
354
+ em_options_radio_binary ( __( 'Use dropdown for locations?', 'dbem' ), 'dbem_use_select_for_locations', __( 'Select yes to select location from a drop-down menu; location selection will be faster, but you will lose the ability to insert locations with events','dbem' ) );
355
+ em_options_radio_binary ( sprintf(__( 'Enable %s attributes?', 'dbem' ),__('location','dbem')), 'dbem_location_attributes_enabled', __( 'Select yes to enable the attributes feature','dbem' ) );
356
+ em_options_radio_binary ( sprintf(__( 'Enable %s custom fields?', 'dbem' ),__('location','dbem')), 'dbem_cp_locations_custom_fields', __( 'Custom fields are the same as attributes, except you cannot restrict specific values, users can add any kind of custom field name/value pair. Only available in the WordPress admin area.','dbem' ) );
357
+ if( get_option('dbem_location_attributes_enabled') ){
358
+ em_options_textarea ( sprintf(__( '%s Attributes', 'dbem' ),__('Location','dbem')), 'dbem_location_placeholders_custom', sprintf(__( "You can also add location attributes here, one per line in this format <code>#_LATT{key}</code>. They will not appear on location pages unless you insert them into another template below, but you may want to store extra information about an event for other uses. <a href='%s'>More information on placeholders.</a>", 'dbem' ), EM_ADMIN_URL .'&amp;page=events-manager-help') );
359
+ }
360
+ }
361
+ ?>
362
+ <tr class="em-header">
363
+ <td colspan="2">
364
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Other','dbem')); ?></h4>
365
+ </td>
366
+ </tr>
367
+ <?php
368
+ em_options_radio_binary ( __('Show some love?','dbem'), 'dbem_credits', __( 'Hundreds of free hours have gone into making this free plugin, show your support and add a small link to the plugin website at the bottom of your event pages.','dbem' ) );
369
  echo $save_button;
370
  ?>
371
  </table>
372
 
373
  </div> <!-- . inside -->
374
+ </div> <!-- .postbox -->
375
+
376
+ <?php if ( !is_multisite() ){ em_admin_option_box_image_sizes(); } ?>
377
+
378
+ <?php if ( !is_multisite() || (is_super_admin() && !get_site_option('dbem_ms_global_caps')) ){ em_admin_option_box_caps(); } ?>
379
+
380
+ <div class="postbox" id="em-opt-event-submissions" >
381
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Event Submission Forms', 'dbem' ); ?></span></h3>
382
+ <div class="inside">
383
+ <table class="form-table">
384
+ <tr><td colspan="2" class="em-boxheader">
385
+ <?php echo sprintf(__('You can allow users to publicly submit events on your blog by using the %s shortcode, and enabling anonymous submissions below.','dbem'), '<code>[event_form]</code>'); ?>
386
+ </td></tr>
387
+ <?php
388
+ em_options_radio_binary ( __( 'Use Visual Editor?', 'dbem' ), 'dbem_events_form_editor', __( 'Users can now use the WordPress editor for easy HTML entry in the submission form.', 'dbem' ) );
389
+ em_options_radio_binary ( __( 'Show form again?', 'dbem' ), 'dbem_events_form_reshow', __( 'When a user submits their event, you can display a new event form again.', 'dbem' ) );
390
+ em_options_textarea ( __( 'Success Message', 'dbem' ), 'dbem_events_form_result_success', __( 'Customize the message your user sees when they submitted their event.', 'dbem' ).$events_placeholder_tip );
391
+ em_options_textarea ( __( 'Successfully Updated Message', 'dbem' ), 'dbem_events_form_result_success_updated', __( 'Customize the message your user sees when they resubmit/update their event.', 'dbem' ).$events_placeholder_tip );
392
+ ?>
393
+ <tr class="em-header"><td colspan="2">
394
+ <h4><?php echo sprintf(__('Anonymous event submissions','dbem'), '<code>[event_form]</code>'); ?></h4>
395
+ </td></tr>
396
+ <?php
397
+ em_options_radio_binary ( __( 'Allow anonymous event submissions?', 'dbem' ), 'dbem_events_anonymous_submissions', __( 'Would you like to allow users to submit bookings anonymously? If so, you can use the new [event_form] shortcode or <code>em_event_form()</code> template tag with this enabled.', 'dbem' ) );
398
+ if( defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') && EM_OPTIMIZE_SETTINGS_PAGE_USERS ){
399
+ em_options_input_text( __('Guest Default User', 'dbem'), 'dbem_events_anonymous_user', __('Please add a User ID.','dbem').' '.__( 'Events require a user to own them. In order to allow events to be submitted anonymously you need to assign that event a specific user. We recommend you create a "Anonymous" subscriber with a very good password and use that. Guests will have the same event permissions as this user when submitting.', 'dbem' ) );
400
+ }else{
401
+ em_options_select ( __('Guest Default User', 'dbem'), 'dbem_events_anonymous_user', em_get_wp_users (), __( 'Events require a user to own them. In order to allow events to be submitted anonymously you need to assign that event a specific user. We recommend you create a "Anonymous" subscriber with a very good password and use that. Guests will have the same event permissions as this user when submitting.', 'dbem' ) );
402
+ }
403
+ em_options_textarea ( __( 'Success Message', 'dbem' ), 'dbem_events_anonymous_result_success', __( 'Anonymous submitters cannot see or modify their event once submitted. You can customize the success message they see here.', 'dbem' ).$events_placeholder_tip );
404
+ ?>
405
+ <?php echo $save_button; ?>
406
+ </table>
407
+ </div> <!-- . inside -->
408
+ </div> <!-- .postbox -->
409
+
410
+ <?php do_action('em_options_page_footer'); ?>
411
+
412
+ <?php /*
413
+ <div class="postbox" id="em-opt-geo" >
414
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Geo APIs', 'dbem' ); ?> <em>(Beta)</em></span></h3>
415
+ <div class="inside">
416
+ <p><?php esc_html_e('Geocoding is the process of converting addresses into geographic coordinates, which can be used to find events and locations near a specific coordinate.','dbem'); ?></p>
417
+ <table class="form-table">
418
+ <?php
419
+ em_options_radio_binary ( __( 'Enable Geocoding Features?', 'dbem' ), 'dbem_geo', '', '', '.em-settings-geocoding');
420
+ ?>
421
+ </table>
422
+ <div class="em-settings-geocoding">
423
+ <h4>GeoNames API (geonames.org)</h4>
424
+ <p>We make use of the <a href="http://www.geonames.org">GeoNames</a> web service to suggest locations/addresses to users when searching, and converting these into coordinates.</p>
425
+ <p>To be able to use these services, you must <a href="http://www.geonames.org/login">register an account</a>, activate the free webservice and enter your username below. You are allowed up to 30,000 requests per day, if you require more you can purchase credits from your account.</p>
426
+ <table class="form-table">
427
+ <?php em_options_input_text ( __( 'GeoNames Username', 'dbem' ), 'dbem_geonames_username', __('If left blank, this service will not be used.','dbem')); ?>
428
+ </table>
429
+ </div>
430
+ <table class="form-table"><?php echo $save_button; ?></table>
431
+ </div> <!-- . inside -->
432
+ </div> <!-- .postbox -->
433
+ */ ?>
434
+
435
+ <div class="postbox" id="em-opt-performance-optimization" >
436
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Performance Optimization', 'dbem' ); ?> (<?php _e('Advanced','dbem'); ?>)</span></h3>
437
+ <div class="inside">
438
  <?php
439
+ $performance_opt_page_instructions = __('In the boxes below, you are expected to write the page IDs. For multiple pages, use comma-seperated values e.g. 1,2,3. Entering 0 means EVERY page, -1 means the home page.','dbem');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  ?>
441
+ <div class="em-boxheader">
442
+ <p><?php _e('This section allows you to configure parts of this plugin that will improve performance on your site and increase page speeds by reducing extra files from being unnecessarily included on pages as well as reducing server loads where possible. This only applies to pages outside the admin area.','dbem'); ?></p>
443
+ <p><strong><?php _e('Warning!','dbem'); ?></strong> <?php echo sprintf(__('This is for advanced users, you should know what you\'re doing here or things will not work properly. For more information on how these options work see our <a href="%s" target="_blank">optimization recommendations</a>','dbem'), 'http://wp-events-plugin.com/documentation/optimization-recommendations/'); ?></p>
444
+ </div>
445
+ <table class="form-table">
446
+ <tr class="em-header"><td colspan="2">
447
+ <h4><?php _e('JavaScript Files','dbem'); ?></h4>
448
+ <p><?php echo sprintf(__('If you are not using it already, we recommend you try the <a href="%s" target="_blank">Use Google Libraries</a> plugin, because without further optimization options below it already significantly reduces the number of files needed to display your Event pages and will most likely speed up your overall website loading time.' ,'dbem'),'http://wordpress.org/extend/plugins/use-google-libraries/'); ?>
449
+ </td></tr>
450
+ <?php
451
+ em_options_radio_binary ( __( 'Limit JS file loading?', 'dbem' ), 'dbem_js_limit', __( 'Prevent unnecessary loading of JavaScript files on pages where they are not needed.', 'dbem' ) );
452
+ ?>
453
+ <tbody id="dbem-js-limit-options">
454
+ <tr class="em-subheader"><td colspan="2">
455
+ <?php
456
+ _e('Aside from pages we automatically generate and include certain jQuery files, if you are using Widgets, Shortcode or PHP to display specific items you may need to tell us where you are using them for them to work properly. Below are options for you to include specific jQuery dependencies only on certain pages.','dbem');
457
+ echo $performance_opt_page_instructions;
458
+ ?>
459
+ </td></tr>
460
+ <?php
461
+ em_options_input_text( __( 'General JS', 'dbem' ), 'dbem_js_limit_general', __( 'Loads our own JS file if no other dependencies are already loaded, which is still needed for many items generated by EM using JavaScript such as Calendars, Maps and Booking Forms/Buttons', 'dbem' ), 0 );
462
+ em_options_input_text( __( 'Search Forms', 'dbem' ), 'dbem_js_limit_search', __( 'Include pages where you use shortcodes or widgets to display event search forms.', 'dbem' ) );
463
+ em_options_input_text( __( 'Event Edit and Submission Forms', 'dbem' ), 'dbem_js_limit_events_form', __( 'Include pages where you use shortcode or PHP to display event submission forms.', 'dbem' ) );
464
+ em_options_input_text( __( 'Booking Management Pages', 'dbem' ), 'dbem_js_limit_edit_bookings', __( 'Include pages where you use shortcode or PHP to display event submission forms.', 'dbem' ) );
465
+ ?>
466
+ </tbody>
467
+ <tr class="em-header"><td colspan="2">
468
+ <h4><?php _e('CSS File','dbem'); ?></h4>
469
+ </td></tr>
470
+ <?php
471
+ em_options_radio_binary ( __( 'Limit loading of our CSS files?', 'dbem' ), 'dbem_css_limit', __( 'Enabling this will prevent us from loading our CSS file on every page, and will only load on specific pages generated by Events Manager.', 'dbem' ) );
472
+ ?>
473
+ <tbody id="dbem-css-limit-options">
474
+ <tr class="em-subheader"><td colspan="2">
475
+ <?php echo $performance_opt_page_instructions; ?>
476
+ </td></tr>
477
+ <?php
478
+ em_options_input_text( __( 'Include on', 'dbem' ), 'dbem_css_limit_include', __( 'Our CSS file will only be INCLUDED on all of these pages.', 'dbem' ), 0 );
479
+ em_options_input_text( __( 'Exclude on', 'dbem' ), 'dbem_css_limit_exclude', __( 'Our CSS file will be EXCLUDED on all of these pages. Takes precedence over inclusion rules.', 'dbem' ), 0 );
480
+ ?>
481
+ </tbody>
482
+ <?php
483
+ ?>
484
+ <tr class="em-header"><td colspan="2">
485
+ <h4><?php _e('Thumbnails','dbem'); ?></h4>
486
+ </td></tr>
487
+ <?php
488
+ em_options_radio_binary ( __( 'Disable WordPress Thumbnails?', 'dbem' ), 'dbem_disable_thumbnails', __( 'If set to yes, full sized images will be used and HTML width and height attributes will be used to determine the size.', 'dbem' ).' '.sprintf(__('Setting this to yes will also make your images crop efficiently with the %s feature in the %s plugin.','dbem'), '<a href="http://jetpack.me/support/photon/">Photon</a>','<a href="https://wordpress.org/plugins/jetpack/">JetPack</a>') );
489
+ ?>
490
+ <?php echo $save_button; ?>
491
+ </table>
492
+ <script type="text/javascript">
493
+ jQuery(document).ready(function($){
494
+ $('input:radio[name="dbem_js_limit"]').change(function(){
495
+ if( $('input:radio[name="dbem_js_limit"]:checked').val() == 1 ){
496
+ $('tbody#dbem-js-limit-options').show();
497
+ }else{
498
+ $('tbody#dbem-js-limit-options').hide();
499
+ }
500
+ }).trigger('change');
501
+
502
+ $('input:radio[name="dbem_css_limit"]').change(function(){
503
+ if( $('input:radio[name="dbem_css_limit"]:checked').val() == 1 ){
504
+ $('tbody#dbem-css-limit-options').show();
505
+ }else{
506
+ $('tbody#dbem-css-limit-options').hide();
507
+ }
508
+ }).trigger('change');
509
+ });
510
+ </script>
511
+ </div> <!-- . inside -->
512
+ </div> <!-- .postbox -->
513
+
514
+ <div class="postbox" id="em-opt-style-options" >
515
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Styling Options', 'dbem' ); ?> (<?php _e('Advanced','dbem'); ?>) <em>(Beta)</em></span></h3>
516
+ <div class="inside">
517
+ <p class="em-boxheader">
518
+ <?php _e('Events Manager imposes a minimal amount of styling on websites so that your themes can take over.','dbem'); ?>
519
+ <?php _e('Below are some additional options for individual pages and sections, which you can turn on to enforce custom styling provided by the plugin or off if you want to do your own custom styling.','dbem'); ?>
520
+ </p>
521
+ <table class="form-table">
522
+ <?php
523
+ em_options_radio_binary ( __( 'Search forms', 'dbem' ), 'dbem_css_search');
524
+ ?>
525
+ <tr class="em-subheader"><td colspan="2">The options below currently have no effect, but are there so you know what may be added in future updates. You can leave them on if you want furture styling to take effect, or turn them off to keep your current styles as is.</td><tr>
526
+ <?php
527
+ em_options_radio_binary ( __( 'Event/Location admin pages', 'dbem' ), 'dbem_css_editors' );
528
+ em_options_radio_binary ( __( 'Booking admin pages', 'dbem' ), 'dbem_css_rsvpadmin' );
529
+ em_options_radio_binary ( __( 'Events list page', 'dbem' ), 'dbem_css_evlist' );
530
+ em_options_radio_binary ( __( 'Locations list page', 'dbem' ), 'dbem_css_loclist' );
531
+ em_options_radio_binary ( __( 'Event booking forms', 'dbem' ), 'dbem_css_rsvp' );
532
+ em_options_radio_binary ( __( 'Categories list page', 'dbem' ), 'dbem_css_catlist' );
533
+ em_options_radio_binary ( __( 'Tags list page', 'dbem' ), 'dbem_css_taglist' );
534
+ echo $save_button;
535
+ ?>
536
+ </table>
537
+ </div> <!-- . inside -->
538
+ </div> <!-- .postbox -->
539
+
540
+ <?php if ( !is_multisite() ) { em_admin_option_box_uninstall(); } ?>
541
+
542
+ <?php if( get_option('dbem_migrate_images') ): ?>
543
+ <div class="postbox " >
544
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span>Migrate Images From Version 4</span></h3>
545
+ <div class="inside">
546
+ <?php /* Not translating as it's temporary */ //EM4 ?>
547
+ <p>You have the option of migrating images from version 4 so they become the equivalent of 'featured images' like with regular WordPress posts and pages and are also available in your media library.</p>
548
+ <p>Your event and location images will still display correctly on the front-end even if you don't migrate, but will not show up within your edit location/event pages in the admin area.</p>
549
+ <p>
550
+ <a href="<?php echo $_SERVER['REQUEST_URI'] ?>&amp;em_migrate_images=1&amp;_wpnonce=<?php echo wp_create_nonce('em_migrate_images'); ?>" />Migrate Images</a><br />
551
+ <a href="<?php echo $_SERVER['REQUEST_URI'] ?>&amp;em_not_migrate_images=1&amp;_wpnonce=<?php echo wp_create_nonce('em_not_migrate_images'); ?>" />Do Not Migrate Images</a>
552
+ </p>
553
+ </div> <!-- . inside -->
554
+ </div> <!-- .postbox -->
555
+ <?php endif; ?>
556
+ </div> <!-- .em-menu-general -->
557
 
558
+ <!-- PAGE OPTIONS -->
559
+ <div class="em-menu-pages em-menu-group" style="display:none;">
560
+ <?php
561
+ $template_page_tip = __( "Many themes display extra meta information on post pages such as 'posted by' or 'post date' information, which may not be desired. Usually, page templates contain less clutter.", 'dbem' );
562
+ $template_page_tip .= ' '. __("If you choose 'Pages' then %s will be shown using your theme default page template, alternatively choose from page templates that come with your specific theme.",'dbem');
563
+ $template_page_tip .= ' '. str_replace('#','http://codex.wordpress.org/Post_Types#Template_Files',__("Be aware that some themes will not work with this option, if so (or you want to make your own changes), you can create a file named <code>single-%s.php</code> <a href='#'>as shown on the wordpress codex</a>, and leave this set to Posts.", 'dbem'));
564
+ $body_class_tip = __('If you would like to add extra classes to your body html tag when a single %s page is displayed, enter it here. May be useful or necessary if your theme requires special class names for specific templates.','dbem');
565
+ $post_class_tip = __('Same concept as the body classes option, but some themes also use the <code>post_class()</code> function within page content to differentiate styling between post types.','dbem');
566
+ $format_override_tip = __("By using formats, you can control how your %s are displayed from within the Events Manager <a href='#formats' class='nav-tab-link' rel='#em-menu-formats'>Formatting</a> tab above without having to edit your theme files.",'dbem');
567
+ $page_templates = array(''=>__('Posts'), 'page' => __('Pages'), __('Theme Templates','dbem') => array_flip(get_page_templates()));
568
+ ?>
569
+ <div class="postbox" id="em-opt-permalinks" >
570
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('Permalink Slugs','dbem')); ?></span></h3>
571
+ <div class="inside">
572
+ <p class="em-boxheader"><?php _e('You can change the permalink structure of your events, locations, categories and tags here. Be aware that you may want to set up redirects if you change your permalink structures to maintain SEO rankings.','dbem'); ?></p>
573
+ <table class="form-table">
574
+ <?php
575
+ em_options_input_text ( __( 'Events', 'dbem' ), 'dbem_cp_events_slug', sprintf(__('e.g. %s - you can use / Separators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_cp_events_slug',EM_POST_TYPE_EVENT_SLUG).'</code>/2012-olympics/</strong>'), EM_POST_TYPE_EVENT_SLUG );
576
+ if( get_option('dbem_locations_enabled') && !(EM_MS_GLOBAL && get_site_option('dbem_ms_mainblog_locations') && !is_main_site()) ){
577
+ em_options_input_text ( __( 'Locations', 'dbem' ), 'dbem_cp_locations_slug', sprintf(__('e.g. %s - you can use / Separators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_cp_locations_slug',EM_POST_TYPE_LOCATION_SLUG).'</code>/wembley-stadium/</strong>'), EM_POST_TYPE_LOCATION_SLUG );
578
+ }
579
+ if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_site()) ){
580
+ em_options_input_text ( __( 'Event Categories', 'dbem' ), 'dbem_taxonomy_category_slug', sprintf(__('e.g. %s - you can use / Separators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_taxonomy_category_slug',EM_TAXONOMY_CATEGORY_SLUG).'</code>/sports/</strong>'), EM_TAXONOMY_CATEGORY_SLUG );
581
+ }
582
+ if( get_option('dbem_tags_enabled') ){
583
+ em_options_input_text ( __( 'Event Tags', 'dbem' ), 'dbem_taxonomy_tag_slug', sprintf(__('e.g. %s - you can use / Separators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_taxonomy_tag_slug',EM_TAXONOMY_TAG_SLUG).'</code>/running/</strong>'), EM_TAXONOMY_TAG_SLUG );
584
+ }
585
+ echo $save_button;
586
+ ?>
587
+ </table>
588
+ </div> <!-- . inside -->
589
+ </div> <!-- .postbox -->
590
+
591
+ <div class="postbox " id="em-opt-event-pages" >
592
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s Pages','dbem'),__('Event','dbem')); ?></span></h3>
593
+ <div class="inside">
594
+ <table class="form-table">
595
+ <?php
596
+ //em_options_radio_binary ( sprintf(__( 'Display %s as', 'dbem' ),__('events','dbem')), 'dbem_cp_events_template_page', sprintf($template_page_tip, EM_POST_TYPE_EVENT), array(__('Posts'),__('Pages')) );
597
+ em_options_select( sprintf(__( 'Display %s as', 'dbem' ),__('events','dbem')), 'dbem_cp_events_template', $page_templates, sprintf($template_page_tip, __('events','dbem'), EM_POST_TYPE_EVENT) );
598
+ em_options_input_text( __('Body Classes','dbem'), 'dbem_cp_events_body_class', sprintf($body_class_tip, __('event','dbem')) );
599
+ em_options_input_text( __('Post Classes','dbem'), 'dbem_cp_events_post_class', $post_class_tip );
600
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_events_formats', sprintf($format_override_tip,__('events','dbem')));
601
+ em_options_radio_binary ( __( 'Enable Comments?', 'dbem' ), 'dbem_cp_events_comments', sprintf(__('If you would like to disable comments entirely, disable this, otherwise you can disable comments on each single %s. Note that %s with comments enabled will still be until you resave them.','dbem'),__('event','dbem'),__('events','dbem')));
602
+ echo $save_button;
603
+ ?>
604
+ </table>
605
+ </div> <!-- . inside -->
606
+ </div> <!-- .postbox -->
607
+
608
+ <div class="postbox " id="em-opt-event-archives" >
609
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives','dbem'),__('Event','dbem')); ?></span></h3>
610
+ <div class="inside">
611
+ <table class="form-table">
612
+ <tr>
613
+ <th><?php echo sprintf(__( 'Events page', 'dbem' )); ?></th>
614
+ <td>
615
+ <?php wp_dropdown_pages(array('name'=>'dbem_events_page', 'selected'=>get_option('dbem_events_page'), 'show_option_none'=>sprintf(__('[No %s Page]', 'dbem'),__('Events','dbem')) )); ?>
616
+ <br />
617
+ <em><?php echo __( 'This option allows you to select which page to use as an events page. If you do not select an events page, to display event lists you can enable event archives or use the appropriate shortcodes and/or template tags.','dbem' ); ?></em>
618
+ </td>
619
+ </tr>
620
+ <tbody class="em-event-page-options">
621
+ <?php
622
+ em_options_radio_binary ( __( 'Show events search?', 'dbem' ), 'dbem_events_page_search_form', __( "If set to yes, a search form will appear just above your list of events.", 'dbem' ) );
623
+ em_options_radio_binary ( __( 'Display calendar in events page?', 'dbem' ), 'dbem_display_calendar_in_events_page', __( 'This options allows to display the calendar in the events page, instead of the default list. It is recommended not to display both the calendar widget and a calendar page.','dbem' ).' '.__('If you would like to show events that span over more than one day, see the Calendar section on this page.','dbem') );
624
+ em_options_radio_binary ( __( 'Disable title rewriting?', 'dbem' ), 'dbem_disable_title_rewrites', __( "Some WordPress themes don't follow best practices when generating navigation menus, and so the automatic title rewriting feature may cause problems, if your menus aren't working correctly on the event pages, try setting this to 'Yes', and provide an appropriate HTML title format below.",'dbem' ) );
625
+ em_options_input_text ( __( 'Event Manager titles', 'dbem' ), 'dbem_title_html', __( "This only setting only matters if you selected 'Yes' to above. You will notice the events page titles aren't being rewritten, and you have a new title underneath the default page name. This is where you control the HTML of this title. Make sure you keep the #_PAGETITLE placeholder here, as that's what is rewritten by events manager. To control what's rewritten in this title, see settings further down for page titles.", 'dbem' ) );
626
+ ?>
627
+ </tbody>
628
+ <tr class="em-header">
629
+ <td colspan="2">
630
+ <h4><?php echo sprintf(__('WordPress %s Archives','dbem'), __('Event','dbem')); ?></h4>
631
+ <p><?php echo sprintf(__('%s custom post types can have archives, just like normal WordPress posts. If enabled, should you visit your base slug url %s and you will see an post-formatted archive of previous %s', 'dbem'), __('Event','dbem'), '<code>'.home_url().'/'.get_option('dbem_cp_events_slug',EM_POST_TYPE_EVENT_SLUG).'/</code>', __('events','dbem')); ?></p>
632
+ <p><?php echo sprintf(__('Note that assigning a %s page above will override this archive if the URLs collide (which is the default setting, and is recommended for maximum plugin compatibility). You can have both at the same time, but you must ensure that your page and %s slugs are different.','dbem'), __('events','dbem'), __('event','dbem')); ?></p>
633
+ </td>
634
+ </tr>
635
+ <tbody class="em-event-archive-options">
636
+ <?php
637
+ em_options_radio_binary ( __( 'Enable Archives?', 'dbem' ), 'dbem_cp_events_has_archive', __( "Allow WordPress post-style archives.", 'dbem' ) );
638
+ ?>
639
+ </tbody>
640
+ <tbody class="em-event-archive-options em-event-archive-sub-options">
641
+ <tr valign="top">
642
+ <th scope="row"><?php _e('Default event archive ordering','dbem'); ?></th>
643
+ <td>
644
+ <select name="dbem_events_default_archive_orderby" >
645
+ <?php
646
+ $event_archive_orderby_options = apply_filters('em_settings_events_default_archive_orderby_ddm', array(
647
+ '_start_ts' => __('Order by start date, start time','dbem'),
648
+ 'title' => __('Order by name','dbem')
649
+ ));
650
+ ?>
651
+ <?php foreach($event_archive_orderby_options as $key => $value) : ?>
652
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
653
+ <?php echo esc_html($value); ?>
654
+ </option>
655
+ <?php endforeach; ?>
656
+ </select>
657
+ <select name="dbem_events_default_archive_order" >
658
+ <?php
659
+ $ascending = __('Ascending','dbem');
660
+ $descending = __('Descending','dbem');
661
+ $event_archive_order_options = apply_filters('em_settings_events_default_archive_order_ddm', array(
662
+ 'ASC' => __('Ascending','dbem'),
663
+ 'DESC' => __('Descending','dbem')
664
+ ));
665
+ ?>
666
+ <?php foreach( $event_archive_order_options as $key => $value) : ?>
667
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_archive_order')) ? "selected='selected'" : ''; ?>>
668
+ <?php echo esc_html($value); ?>
669
+ </option>
670
+ <?php endforeach; ?>
671
+ </select>
672
+ <br/>
673
+ <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
674
+ </td>
675
+ </tr>
676
+ <?php
677
+ em_options_select( __('Event archives scope','dbem'), 'dbem_events_archive_scope', em_get_scopes() );
678
+ ?>
679
+ </tbody>
680
+ <tr class="em-header">
681
+ <td colspan="2">
682
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
683
+ </td>
684
+ </tr>
685
+ <?php
686
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_events_archive_formats', sprintf($format_override_tip,__('events','dbem')));
687
+ em_options_radio_binary ( __( 'Override Excerpts with Formats?', 'dbem' ), 'dbem_cp_events_excerpt_formats', sprintf($format_override_tip,__('events','dbem')));
688
  em_options_radio_binary ( __( 'Are current events past events?', 'dbem' ), 'dbem_events_current_are_past', __( "By default, events that are have an end date later than today will be included in searches, set this to yes to consider events that started 'yesterday' as past.", 'dbem' ) );
689
+ em_options_radio_binary ( __( 'Include in WordPress Searches?', 'dbem' ), 'dbem_cp_events_search_results', sprintf(__( "Allow %s to appear in the built-in search results.", 'dbem' ),__('events','dbem')) );
690
  ?>
691
+ <tr class="em-header">
692
+ <td colspan="2">
693
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('event','dbem')); ?></h4>
694
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
695
+ </td>
696
+ </tr>
697
  <tr valign="top" id='dbem_events_default_orderby_row'>
698
  <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
699
  <td>
700
  <select name="dbem_events_default_orderby" >
701
  <?php
702
  $orderby_options = apply_filters('em_settings_events_default_orderby_ddm', array(
703
+ 'event_start_date,event_start_time,event_name' => __('Order by start date, start time, then event name','dbem'),
704
+ 'event_name,event_start_date,event_start_time' => __('Order by name, start date, then start time','dbem'),
705
+ 'event_name,event_end_date,event_end_time' => __('Order by name, end date, then end time','dbem'),
706
+ 'event_end_date,event_end_time,event_name' => __('Order by end date, end time, then event name','dbem'),
707
  ));
708
  ?>
709
  <?php foreach($orderby_options as $key => $value) : ?>
710
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_orderby')) ? "selected='selected'" : ''; ?>>
711
+ <?php echo esc_html($value); ?>
712
  </option>
713
  <?php endforeach; ?>
714
  </select>
728
  ));
729
  ?>
730
  <?php foreach( $order_options as $key => $value) : ?>
731
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_events_default_order')) ? "selected='selected'" : ''; ?>>
732
+ <?php echo esc_html($value); ?>
733
  </option>
734
  <?php endforeach; ?>
735
  </select>
736
  <br/>
737
  <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
738
  </td>
739
+ </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
  <?php
741
+ em_options_select( __('Event list scope','dbem'), 'dbem_events_page_scope', em_get_scopes(), __('Only show events starting within a certain time limit on the events page. Default is future events with no end time limit.','dbem') );
742
+ em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_events_default_limit', __( "This will control how many events are shown on one list by default.", 'dbem' ) );
743
  echo $save_button;
744
+ ?>
745
+ </table>
746
+ </div> <!-- . inside -->
747
+ </div> <!-- .postbox -->
748
+
749
+ <?php if( get_option('dbem_locations_enabled') ): ?>
750
+ <div class="postbox " id="em-opt-location-pages" >
751
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s Pages','dbem'),__('Location','dbem')); ?></span></h3>
752
+ <div class="inside">
753
+ <table class="form-table">
754
+ <?php
755
+ //em_options_radio_binary ( sprintf(__( 'Display %s as', 'dbem' ),__('locations','dbem')), 'dbem_cp_locations_template_page', sprintf($template_page_tip, EM_POST_TYPE_LOCATION), array(__('Posts'),__('Pages')) );
756
+ em_options_select( sprintf(__( 'Display %s as', 'dbem' ),__('locations','dbem')), 'dbem_cp_locations_template', $page_templates, sprintf($template_page_tip, __('locations','dbem'), EM_POST_TYPE_LOCATION) );
757
+ em_options_input_text( __('Body Classes','dbem'), 'dbem_cp_locations_body_class', sprintf($body_class_tip, __('location','dbem')) );
758
+ em_options_input_text( __('Post Classes','dbem'), 'dbem_cp_locations_post_class', $post_class_tip );
759
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_locations_formats', sprintf($format_override_tip,__('locations','dbem')));
760
+ em_options_radio_binary ( __( 'Enable Comments?', 'dbem' ), 'dbem_cp_locations_comments', sprintf(__('If you would like to disable comments entirely, disable this, otherwise you can disable comments on each single %s. Note that %s with comments enabled will still be until you resave them.','dbem'),__('location','dbem'),__('locations','dbem')));
761
+ em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_location_event_list_limit', sprintf(__( "Controls how many events being held at a location are shown per page when using placeholders such as %s. Leave blank for no limit.", 'dbem' ), '<code>#_LOCATIONNEXTEVENTS</code>') );
762
+ echo $save_button;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
763
  ?>
764
+ </table>
765
+ </div> <!-- . inside -->
766
+ </div> <!-- .postbox -->
767
+
768
+ <div class="postbox " id="em-opt-location-archives" >
769
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives','dbem'),__('Location','dbem')); ?></span></h3>
770
+ <div class="inside">
771
+ <table class="form-table">
772
+ <tr>
773
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Locations','dbem')); ?></th>
 
774
  <td>
775
+ <?php wp_dropdown_pages(array('name'=>'dbem_locations_page', 'selected'=>get_option('dbem_locations_page'), 'show_option_none'=>sprintf(__('[No %s Page]', 'dbem'),__('Locations','dbem')) )); ?>
776
+ <br />
777
+ <em><?php echo sprintf(__( 'This option allows you to select which page to use as the %s page. If you do not select a %s page, to display lists you can enable archives or use the appropriate shortcodes and/or template tags.','dbem' ),__('locations','dbem'),__('locations','dbem')); ?></em>
778
  </td>
779
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
780
  <?php
781
+ em_options_radio_binary ( __( 'Show locations search?', 'dbem' ), 'dbem_locations_page_search_form', __( "If set to yes, a search form will appear just above your list of locations.", 'dbem' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
782
  ?>
783
+ <tr class="em-header">
784
+ <td colspan="2">
785
+ <h4><?php echo sprintf(__('WordPress %s Archives','dbem'), __('Location','dbem')); ?></h4>
786
+ <p><?php echo sprintf(__('%s custom post types can have archives, just like normal WordPress posts. If enabled, should you visit your base slug url %s and you will see an post-formatted archive of previous %s', 'dbem'), __('Location','dbem'), '<code>'.home_url().'/'.get_option('dbem_cp_events_slug',EM_POST_TYPE_LOCATION_SLUG).'/</code>', __('locations','dbem')); ?></p>
787
+ <p><?php echo sprintf(__('Note that assigning a %s page above will override this archive if the URLs collide (which is the default settings, and is recommended for maximum plugin compatibility). You can have both at the same time, but you must ensure that your page and %s slugs are different.','dbem'), __('locations','dbem'), __('location','dbem')); ?></p>
788
+ </td>
789
+ </tr>
790
+ <tbody class="em-location-archive-options">
791
+ <?php
792
+ em_options_radio_binary ( __( 'Enable Archives?', 'dbem' ), 'dbem_cp_locations_has_archive', __( "Allow WordPress post-style archives.", 'dbem' ) );
793
+ ?>
794
+ </tbody>
795
+ <tbody class="em-location-archive-options em-location-archive-sub-options">
796
+ <tr valign="top">
797
+ <th scope="row"><?php _e('Default archive ordering','dbem'); ?></th>
798
+ <td>
799
+ <select name="dbem_locations_default_archive_orderby" >
800
+ <?php
801
+ $orderby_options = apply_filters('em_settings_locations_default_archive_orderby_ddm', array(
802
+ '_country' => sprintf(__('Order by %s','dbem'),__('Country','dbem')),
803
+ '_town' => sprintf(__('Order by %s','dbem'),__('Town','dbem')),
804
+ 'title' => sprintf(__('Order by %s','dbem'),__('Name','dbem'))
805
+ ));
806
+ ?>
807
+ <?php foreach($orderby_options as $key => $value) : ?>
808
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_locations_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
809
+ <?php echo esc_html($value) ?>
810
+ </option>
811
+ <?php endforeach; ?>
812
+ </select>
813
+ <select name="dbem_locations_default_archive_order" >
814
+ <?php
815
+ $ascending = __('Ascending','dbem');
816
+ $descending = __('Descending','dbem');
817
+ $order_options = apply_filters('em_settings_locations_default_archive_order_ddm', array(
818
+ 'ASC' => __('Ascending','dbem'),
819
+ 'DESC' => __('Descending','dbem')
820
+ ));
821
+ ?>
822
+ <?php foreach( $order_options as $key => $value) : ?>
823
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_locations_default_archive_order')) ? "selected='selected'" : ''; ?>>
824
+ <?php echo esc_html($value) ?>
825
+ </option>
826
+ <?php endforeach; ?>
827
+ </select>
828
+ </td>
829
+ </tr>
830
+ </tbody>
831
+ <tr class="em-header">
832
+ <td colspan="2">
833
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
834
+ </td>
835
+ </tr>
836
+ <?php
837
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_locations_archive_formats', sprintf($format_override_tip,__('locations','dbem')));
838
+ em_options_radio_binary ( __( 'Override Excerpts with Formats?', 'dbem' ), 'dbem_cp_locations_excerpt_formats', sprintf($format_override_tip,__('locations','dbem')));
839
+ em_options_radio_binary ( __( 'Include in WordPress Searches?', 'dbem' ), 'dbem_cp_locations_search_results', sprintf(__( "Allow %s to appear in the built-in search results.", 'dbem' ),__('locations','dbem')) );
840
  ?>
841
+ <tr class="em-header">
842
+ <td colspan="2">
843
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('location','dbem')); ?></h4>
844
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
845
+ </td>
846
+ </tr>
847
+ <tr valign="top" id='dbem_locations_default_orderby_row'>
848
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
849
+ <td>
850
+ <select name="dbem_locations_default_orderby" >
851
+ <?php
852
+ $orderby_options = apply_filters('em_settings_locations_default_orderby_ddm', array(
853
+ 'location_country' => sprintf(__('Order by %s','dbem'),__('Country','dbem')),
854
+ 'location_town' => sprintf(__('Order by %s','dbem'),__('Town','dbem')),
855
+ 'location_name' => sprintf(__('Order by %s','dbem'),__('Name','dbem'))
856
+ ));
857
+ ?>
858
+ <?php foreach($orderby_options as $key => $value) : ?>
859
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_locations_default_orderby')) ? "selected='selected'" : ''; ?>>
860
+ <?php echo esc_html($value) ?>
861
+ </option>
862
+ <?php endforeach; ?>
863
+ </select>
864
+ <select name="dbem_locations_default_order" >
865
+ <?php
866
+ $ascending = __('Ascending','dbem');
867
+ $descending = __('Descending','dbem');
868
+ $order_options = apply_filters('em_settings_locations_default_order_ddm', array(
869
+ 'ASC' => __('Ascending','dbem'),
870
+ 'DESC' => __('Descending','dbem')
871
+ ));
872
+ ?>
873
+ <?php foreach( $order_options as $key => $value) : ?>
874
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_locations_default_order')) ? "selected='selected'" : ''; ?>>
875
+ <?php echo esc_html($value) ?>
876
+ </option>
877
+ <?php endforeach; ?>
878
+ </select>
879
+ </td>
880
+ </tr>
881
  <?php
882
+ em_options_input_text ( __( 'List Limits', 'dbem' ), 'dbem_locations_default_limit', sprintf(__( "This will control how many %s are shown on one list by default.", 'dbem' ),__('locations','dbem')) );
883
+ echo $save_button;
 
884
  ?>
885
+ </table>
886
+ </div> <!-- . inside -->
887
+ </div> <!-- .postbox -->
888
+ <?php endif; ?>
889
+
890
+ <?php if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_site()) ): ?>
891
+ <div class="postbox " id="em-opt-categories-pages" >
892
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo __('Event Categories','dbem'); ?></span></h3>
893
+ <div class="inside">
894
+ <div class="em-boxheader">
895
+ <p>
896
+ <?php echo sprintf(__('%s are a <a href="%s" target="_blank">WordPress custom taxonomy</a>.','dbem'), __('Event Categories','dbem'), 'http://codex.wordpress.org/Taxonomies');?>
897
+ <?php echo sprintf(__('%s can be displayed just like normal WordPress custom taxonomies in an archive-style format, however Events Manager by default allows you to completely change the standard look of these archives and use our own <a href="%s">custom formatting</a> methods.','dbem'), __('Event Categories','dbem'), EM_ADMIN_URL .'&amp;page=events-manager-help#event-placeholders'); ?>
898
+ </p>
899
+ <p>
900
+ <?php echo sprintf(__('Due to how we change how this custom taxonomy is displayed when overriding with formats it is strongly advised that you assign a %s page below, which increases comatability with various plugins and themes.','dbem'), __('categories','dbem')); ?>
901
+ <?php sprintf(__('<a href="%s">See some more information</a> on how %s work when overriding with formats.','dbem'), '#', __('categories','dbem')); //not ready yet, but make translatable ?>
902
+ </p>
903
+ </div>
904
+ <table class="form-table">
905
+ <tr>
906
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Categories','dbem')); ?></th>
907
+ <td>
908
+ <?php wp_dropdown_pages(array('name'=>'dbem_categories_page','selected'=>get_option('dbem_categories_page'), 'show_option_none'=>sprintf(__('[No %s Page]', 'dbem'),__('Categories','dbem')) )); ?>
909
+ <br />
910
+ <em><?php echo sprintf(__( 'This option allows you to select which page to use as the %s page.','dbem' ),__('categories','dbem')); ?></em>
911
+ </td>
912
+ </tr>
913
+ <tr class="em-header">
914
+ <td colspan="2">
915
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
916
+ </td>
917
+ </tr>
918
  <?php
919
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_categories_formats', sprintf($format_override_tip,__('categories','dbem'))." ".__('Setting this to yes will make categories display as a page rather than an archive.', 'dbem'));
 
920
  ?>
921
+ <tr valign="top">
922
+ <th scope="row"><?php _e('Default archive ordering','dbem'); ?></th>
923
+ <td>
924
+ <select name="dbem_categories_default_archive_orderby" >
925
+ <?php foreach($event_archive_orderby_options as $key => $value) : ?>
926
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_categories_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
927
+ <?php echo esc_html($value) ?>
928
+ </option>
929
+ <?php endforeach; ?>
930
+ </select>
931
+ <select name="dbem_categories_default_archive_order" >
932
+ <?php foreach( $event_archive_order_options as $key => $value) : ?>
933
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_categories_default_archive_order')) ? "selected='selected'" : ''; ?>>
934
+ <?php echo esc_html($value) ?>
935
+ </option>
936
+ <?php endforeach; ?>
937
+ </select>
938
+ <br /><?php echo __('When listing events for a category, this order is applied.', 'dbem'); ?>
939
+ </td>
940
+ </tr>
941
+ <tr class="em-header">
942
+ <td colspan="2">
943
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('category','dbem')); ?></h4>
944
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
945
+ </td>
946
+ </tr>
947
+ <tr valign="top" id='dbem_categories_default_orderby_row'>
948
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
949
+ <td>
950
+ <select name="dbem_categories_default_orderby" >
951
+ <?php
952
+ $orderby_options = apply_filters('em_settings_categories_default_orderby_ddm', array(
953
+ 'id' => sprintf(__('Order by %s','dbem'),__('ID','dbem')),
954
+ 'count' => sprintf(__('Order by %s','dbem'),__('Count','dbem')),
955
+ 'name' => sprintf(__('Order by %s','dbem'),__('Name','dbem')),
956
+ 'slug' => sprintf(__('Order by %s','dbem'),__('Slug','dbem')),
957
+ 'term_group' => sprintf(__('Order by %s','dbem'),'term_group'),
958
+ ));
959
+ ?>
960
+ <?php foreach($orderby_options as $key => $value) : ?>
961
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_categories_default_orderby')) ? "selected='selected'" : ''; ?>>
962
+ <?php echo esc_html($value) ?>
963
+ </option>
964
+ <?php endforeach; ?>
965
+ </select>
966
+ <select name="dbem_categories_default_order" >
967
+ <?php
968
+ $ascending = __('Ascending','dbem');
969
+ $descending = __('Descending','dbem');
970
+ $order_options = apply_filters('em_settings_categories_default_order_ddm', array(
971
+ 'ASC' => __('Ascending','dbem'),
972
+ 'DESC' => __('Descending','dbem')
973
+ ));
974
+ ?>
975
+ <?php foreach( $order_options as $key => $value) : ?>
976
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_categories_default_order')) ? "selected='selected'" : ''; ?>>
977
+ <?php echo esc_html($value) ?>
978
+ </option>
979
+ <?php endforeach; ?>
980
+ </select>
981
+ <br /><?php echo __('When listing categories, this order is applied.', 'dbem'); ?>
982
+ </td>
983
+ </tr>
984
  <?php
985
+ em_options_input_text ( __( 'List Limits', 'dbem' ), 'dbem_categories_default_limit', sprintf(__( "This will control how many %s are shown on one list by default.", 'dbem' ),__('categories','dbem')) );
986
+ em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_category_event_list_limit', sprintf(__( "Controls how many events belonging to a category are shown per page when using placeholders such as %s. Leave blank for no limit.", 'dbem' ), '<code>#_CATEGORYNEXTEVENTS</code>') );
987
+ echo $save_button;
 
 
 
 
 
 
988
  ?>
989
+ </table>
990
+ </div> <!-- . inside -->
991
+ </div> <!-- .postbox -->
992
+ <?php endif; ?>
993
+
994
+ <?php if( get_option('dbem_tags_enabled') ): //disabled for now, will add tag stuff later ?>
995
+ <div class="postbox " id="em-opt-tags-pages" >
996
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo __('Event Tags','dbem'); ?></span></h3>
997
+ <div class="inside">
998
+ <div class="em-boxheader">
999
+ <p>
1000
+ <?php echo sprintf(__('%s are a <a href="%s" target="_blank">WordPress custom taxonomy</a>.','dbem'), __('Event Tags','dbem'), 'http://codex.wordpress.org/Taxonomies');?>
1001
+ <?php echo sprintf(__('%s can be displayed just like normal WordPress custom taxonomies in an archive-style format, however Events Manager by default allows you to completely change the standard look of these archives and use our own <a href="%s">custom formatting</a> methods.','dbem'), __('Event Tags','dbem'), EM_ADMIN_URL .'&amp;page=events-manager-help#event-placeholders'); ?>
1002
+ </p>
1003
+ <p>
1004
+ <?php echo sprintf(__('Due to how we change how this custom taxonomy is displayed when overriding with formats it is strongly advised that you assign a %s page below, which increases comatability with various plugins and themes.','dbem'), __('tags','dbem')); ?>
1005
+ <?php sprintf(__('<a href="%s">See some more information</a> on how %s work when overriding with formats.','dbem'), '#', __('tags','dbem')); //not ready yet, but make translatable ?>
1006
+ </p>
1007
+ </div>
1008
+ <table class="form-table">
1009
+ <tr>
1010
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Tags','dbem')); ?></th>
1011
+ <td>
1012
+ <?php wp_dropdown_pages(array('name'=>'dbem_tags_page','selected'=>get_option('dbem_tags_page'), 'show_option_none'=>sprintf(__('[No %s Page]', 'dbem'),__('Tags','dbem')) )); ?>
1013
+ <br />
1014
+ <em><?php echo sprintf(__( 'This option allows you to select which page to use as the %s page.','dbem' ),__('tags','dbem'),__('tags','dbem')); ?></em>
1015
+ </td>
1016
+ </tr>
1017
+ <tr class="em-header">
1018
+ <td colspan="2">
1019
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
1020
+ </td>
1021
+ </tr>
1022
+ <?php
1023
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_tags_formats', sprintf($format_override_tip,__('tags','dbem')));
1024
+ ?>
1025
+ <tr valign="top">
1026
+ <th scope="row"><?php _e('Default archive ordering','dbem'); ?></th>
1027
+ <td>
1028
+ <select name="dbem_tags_default_archive_orderby" >
1029
+ <?php foreach($event_archive_orderby_options as $key => $value) : ?>
1030
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_tags_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
1031
+ <?php echo esc_html($value) ?>
1032
+ </option>
1033
+ <?php endforeach; ?>
1034
+ </select>
1035
+ <select name="dbem_tags_default_archive_order" >
1036
+ <?php foreach( $event_archive_order_options as $key => $value) : ?>
1037
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_tags_default_archive_order')) ? "selected='selected'" : ''; ?>>
1038
+ <?php echo esc_html($value) ?>
1039
+ </option>
1040
+ <?php endforeach; ?>
1041
+ </select>
1042
+ </td>
1043
+ </tr>
1044
+ <tr class="em-header">
1045
+ <td colspan="2">
1046
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('tag','dbem')); ?></h4>
1047
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
1048
+ </td>
1049
+ </tr>
1050
+ <tr valign="top" id='dbem_tags_default_orderby_row'>
1051
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
1052
+ <td>
1053
+ <select name="dbem_tags_default_orderby" >
1054
+ <?php
1055
+ $orderby_options = apply_filters('em_settings_tags_default_orderby_ddm', array(
1056
+ 'id' => sprintf(__('Order by %s','dbem'),__('ID','dbem')),
1057
+ 'count' => sprintf(__('Order by %s','dbem'),__('Count','dbem')),
1058
+ 'name' => sprintf(__('Order by %s','dbem'),__('Name','dbem')),
1059
+ 'slug' => sprintf(__('Order by %s','dbem'),__('Slug','dbem')),
1060
+ 'term_group' => sprintf(__('Order by %s','dbem'),'term_group'),
1061
+ ));
1062
+ ?>
1063
+ <?php foreach($orderby_options as $key => $value) : ?>
1064
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_tags_default_orderby')) ? "selected='selected'" : ''; ?>>
1065
+ <?php echo esc_html($value) ?>
1066
+ </option>
1067
+ <?php endforeach; ?>
1068
+ </select>
1069
+ <select name="dbem_tags_default_order" >
1070
+ <?php
1071
+ $ascending = __('Ascending','dbem');
1072
+ $descending = __('Descending','dbem');
1073
+ $order_options = apply_filters('em_settings_tags_default_order_ddm', array(
1074
+ 'ASC' => __('Ascending','dbem'),
1075
+ 'DESC' => __('Descending','dbem')
1076
+ ));
1077
+ ?>
1078
+ <?php foreach( $order_options as $key => $value) : ?>
1079
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_tags_default_order')) ? "selected='selected'" : ''; ?>>
1080
+ <?php echo esc_html($value) ?>
1081
+ </option>
1082
+ <?php endforeach; ?>
1083
+ </select>
1084
+ <br /><?php echo __('When listing tags, this order is applied.', 'dbem'); ?>
1085
+ </td>
1086
+ </tr>
1087
+ <?php
1088
+ em_options_input_text ( __( 'List Limits', 'dbem' ), 'dbem_tags_default_limit', sprintf(__( "This will control how many %s are shown on one list by default.", 'dbem' ),__('tags','dbem')) );
1089
+ em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_tag_event_list_limit', sprintf(__( "Controls how many events belonging to a tag are shown per page when using placeholders such as %s. Leave blank for no limit.", 'dbem' ), '<code>#_TAGNEXTEVENTS</code>') );
1090
+ echo $save_button; ?>
1091
+ </table>
1092
+ </div> <!-- . inside -->
1093
+ </div> <!-- .postbox -->
1094
+ <?php endif; ?>
1095
+
1096
+ <div class="postbox " id="em-opt-other-pages" >
1097
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s Pages','dbem'),__('Other','dbem')); ?></span></h3>
1098
+ <div class="inside">
1099
+ <p class="em-boxheader"><?php _e('These pages allow you to provide an event management interface outside the admin area on whatever page you want on your website. Bear in mind that this is overriden by BuddyPress if activated.', 'dbem'); ?></p>
1100
+ <table class="form-table">
1101
  <?php
1102
+ $other_pages_tip = 'Using the %s shortcode, you can allow users to manage %s outside the admin area.';
 
 
 
1103
  ?>
1104
+ <tr class="em-header">
1105
+ <td colspan="2">
1106
+ <h4><?php _e('My Bookings','dbem'); ?></h4>
1107
+ <p><?php _e('This page is where people that have made bookings for an event can go and view their previous bookings.','dbem'); ?>
1108
+ </td>
1109
+ </tr>
1110
+ <tr>
1111
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('My bookings','dbem')); ?>
1112
+ </th>
1113
+ <td>
1114
+ <?php wp_dropdown_pages(array('name'=>'dbem_my_bookings_page', 'selected'=>get_option('dbem_my_bookings_page'), 'show_option_none'=>'['.__('None', 'dbem').']' )); ?>
1115
+ <br />
1116
+ <em><?php echo sprintf(__('Users can view their bookings for other events on this page.','dbem' ),'<code>[my_bookings]</code>',__('bookings','dbem')); ?></em>
1117
+ </td>
1118
+ </tr>
1119
+ <tr valign="top" id='dbem_bookings_default_orderby_row'>
1120
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
1121
+ <td>
1122
+ <select name="dbem_bookings_default_orderby" >
1123
+ <?php
1124
+ $orderby_options = apply_filters('em_settings_bookings_default_orderby_ddm', array(
1125
+ 'event_name' => sprintf(__('Order by %s','dbem'),__('Event Name','dbem')),
1126
+ 'event_start_date' => sprintf(__('Order by %s','dbem'),__('Start Date','dbem')),
1127
+ 'booking_date' => sprintf(__('Order by %s','dbem'),__('Booking Date','dbem'))
1128
+ ));
1129
+ ?>
1130
+ <?php foreach($orderby_options as $key => $value) : ?>
1131
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_bookings_default_orderby')) ? "selected='selected'" : ''; ?>>
1132
+ <?php echo esc_html($value) ?>
1133
+ </option>
1134
+ <?php endforeach; ?>
1135
+ </select>
1136
+ <select name="dbem_bookings_default_order" >
1137
+ <?php
1138
+ $ascending = __('Ascending','dbem');
1139
+ $descending = __('Descending','dbem');
1140
+ $order_options = apply_filters('em_settings_bookings_default_order_ddm', array(
1141
+ 'ASC' => __('Ascending','dbem'),
1142
+ 'DESC' => __('Descending','dbem')
1143
+ ));
1144
+ ?>
1145
+ <?php foreach( $order_options as $key => $value) : ?>
1146
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_bookings_default_order')) ? "selected='selected'" : ''; ?>>
1147
+ <?php echo esc_html($value) ?>
1148
+ </option>
1149
+ <?php endforeach; ?>
1150
+ </select>
1151
+ </td>
1152
+ </tr>
1153
+ <tr class="em-header">
1154
+ <td colspan="2">
1155
+ <h4><?php _e('Front-end management pages','dbem'); ?></h4>
1156
+ <p><?php _e('Users with the relevant permissions can manage their own events and bookings to these events on the following pages.','dbem'); ?></p>
1157
+ </td>
1158
+ </tr>
1159
+ <tr>
1160
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Edit events','dbem')); ?></th>
1161
+ <td>
1162
+ <?php wp_dropdown_pages(array('name'=>'dbem_edit_events_page', 'selected'=>get_option('dbem_edit_events_page'), 'show_option_none'=>'['.__('None', 'dbem').']' )); ?>
1163
+ <br />
1164
+ <em><?php echo sprintf(__('Users can view, add and edit their %s on this page.','dbem'),__('events','dbem')); ?></em>
1165
+ </td>
1166
+ </tr>
1167
+ <tr>
1168
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Edit locations','dbem')); ?></th>
1169
+ <td>
1170
+ <?php wp_dropdown_pages(array('name'=>'dbem_edit_locations_page', 'selected'=>get_option('dbem_edit_locations_page'), 'show_option_none'=>'['.__('None', 'dbem').']' )); ?>
1171
+ <br />
1172
+ <em><?php echo sprintf(__('Users can view, add and edit their %s on this page.','dbem'),__('locations','dbem')); ?></em>
1173
+ </td>
1174
+ </tr>
1175
+ <tr>
1176
+ <th><?php echo sprintf(__( '%s page', 'dbem' ),__('Manage bookings','dbem')); ?></th>
1177
+ <td>
1178
+ <?php wp_dropdown_pages(array('name'=>'dbem_edit_bookings_page', 'selected'=>get_option('dbem_edit_bookings_page'), 'show_option_none'=>'['.__('None', 'dbem').']' )); ?>
1179
+ <br />
1180
+ <em><?php _e('Users can manage bookings for their events on this page.','dbem'); ?></em>
1181
+ </td>
1182
+ </tr>
1183
+ <?php echo $save_button; ?>
1184
+ </table>
1185
+ </div> <!-- . inside -->
1186
+ </div> <!-- .postbox -->
1187
+
1188
+ <?php do_action('em_options_page_footer_pages'); ?>
1189
+
1190
+ </div> <!-- .em-menu-pages -->
1191
 
1192
+ <!-- FORMAT OPTIONS -->
1193
+ <div class="em-menu-formats em-menu-group" style="display:none;">
1194
+ <div class="postbox " id="em-opt-events-formats" >
1195
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Events', 'dbem' ); ?> </span></h3>
1196
+ <div class="inside">
1197
+ <table class="form-table">
1198
+ <tr class="em-header"><td colspan="2">
1199
+ <h4><?php echo sprintf(__('%s Page','dbem'),__('Events','dbem')); ?></h4>
1200
+ <p><?php _e('These formats will be used on your events page. This will also be used if you do not provide specified formats in other event lists, like in shortcodes.','dbem'); ?></p>
1201
+ </td></tr>
1202
+ <?php
1203
+ $grouby_modes = array(0=>__('None','dbem'), 'yearly'=>__('Yearly','dbem'), 'monthly'=>__('Monthly','dbem'), 'weekly'=>__('Weekly','dbem'), 'daily'=>__('Daily','dbem'));
1204
+ em_options_select(__('Events page grouping','dbem'), 'dbem_event_list_groupby', $grouby_modes, __('If you choose a group by mode, your events page will display events in groups of your chosen time range.','dbem'));
1205
+ em_options_input_text(__('Events page grouping header','dbem'), 'dbem_event_list_groupby_header_format', __('Choose how to format your group headings.','dbem').' '. sprintf(__('#s will be replaced by the date format below', 'dbem'), 'http://codex.wordpress.org/Formatting_Date_and_Time'));
1206
+ em_options_input_text(__('Events page grouping date format','dbem'), 'dbem_event_list_groupby_format', __('Choose how to format your group heading dates. Leave blank for default.','dbem').' '. sprintf(__('Date and Time formats follow the <a href="%s">WordPress time formatting conventions</a>', 'dbem'), 'http://codex.wordpress.org/Formatting_Date_and_Time'));
1207
+ em_options_textarea ( __( 'Default event list format header', 'dbem' ), 'dbem_event_list_item_format_header', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
1208
+ em_options_textarea ( __( 'Default event list format', 'dbem' ), 'dbem_event_list_item_format', __( 'The format of any events in a list.', 'dbem' ).$events_placeholder_tip );
1209
+ em_options_textarea ( __( 'Default event list format footer', 'dbem' ), 'dbem_event_list_item_format_footer', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
1210
+ em_options_input_text ( __( 'No events message', 'dbem' ), 'dbem_no_events_message', __( 'The message displayed when no events are available.', 'dbem' ) );
1211
+ em_options_input_text ( __( 'List events by date title', 'dbem' ), 'dbem_list_date_title', __( 'If viewing a page for events on a specific date, this is the title that would show up. To insert date values, use <a href="http://www.php.net/manual/en/function.date.php">PHP time format characters</a> with a <code>#</code> symbol before them, i.e. <code>#m</code>, <code>#M</code>, <code>#j</code>, etc.<br/>', 'dbem' ) );
1212
+ ?>
1213
+ <tr class="em-header">
1214
+ <td colspan="2">
1215
+ <h4><?php echo sprintf(__('Single %s Page','dbem'),__('Event','dbem')); ?></h4>
1216
+ <em><?php echo sprintf(__('These formats can be used on %s pages or on other areas of your site displaying an %s.','dbem'),__('event','dbem'),__('event','dbem'));?></em>
1217
+ </tr>
1218
+ <?php
1219
+ if( EM_MS_GLOBAL && !get_option('dbem_ms_global_events_links') ){
1220
+ em_options_input_text ( sprintf(__( 'Single %s title format', 'dbem' ),__('event','dbem')), 'dbem_event_page_title_format', sprintf(__( 'The format of a single %s page title.', 'dbem' ),__('event','dbem')).' '.__( 'This is only used when showing events from other blogs.', 'dbem' ).$events_placeholder_tip );
1221
+ }
1222
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('event','dbem')), 'dbem_single_event_format', sprintf(__( 'The format used to display %s content on single pages or elsewhere on your site.', 'dbem' ),__('event','dbem')).$events_placeholder_tip );
1223
+ ?>
1224
+ <tr class="em-header">
1225
+ <td colspan="2">
1226
+ <h4><?php echo sprintf(__('%s Excerpts','dbem'),__('Event','dbem')); ?></h4>
1227
+ <em><?php echo sprintf(__('These formats can be used when WordPress automatically displays %s excerpts on your site and %s is enabled in your %s settings tab.','dbem'),__('event','dbem'),'<strong>'.__( 'Override Excerpts with Formats?', 'dbem' ).'</strong>','<a href="#formats" class="nav-tab-link" rel="#em-menu-pages">'.__('Pages','dbem').' &gt; '.sprintf(__('%s List/Archives','dbem'),__('Event','dbem')).'</a>');?></em>
1228
+ </td>
1229
+ </tr>
1230
+ <?php
1231
+ em_options_textarea ( sprintf(__('%s excerpt', 'dbem' ),__('Event','dbem')), 'dbem_event_excerpt_format', __( 'Used if an excerpt has been defined.', 'dbem' ).$events_placeholder_tip );
1232
+ em_options_textarea ( sprintf(__('%s excerpt fallback', 'dbem' ),__('Event','dbem')), 'dbem_event_excerpt_alt_format', __( 'Used if an excerpt has not been defined.', 'dbem' ).$events_placeholder_tip );
1233
+
1234
+ echo $save_button;
1235
+ ?>
1236
+ </table>
1237
+ </div> <!-- . inside -->
1238
+ </div> <!-- .postbox -->
1239
+
1240
+ <div class="postbox " id="em-opt-search-form" >
1241
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Search Form', 'dbem' ); ?> </span></h3>
1242
+ <div class="inside">
1243
+ <table class="form-table em-search-form-main">
1244
+ <tr class="em-header"><td colspan="2"><h4><?php _e('Main Search Fields','dbem'); ?></h4></td></tr>
1245
+ <tbody class="em-subsection">
1246
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Search', 'dbem' ); ?></h5></td></tr>
1247
+ <?php
1248
+ em_options_radio_binary ( __( 'Show text search?', 'dbem' ), 'dbem_search_form_text', '', '', '#dbem_search_form_text_label_row' );
1249
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_text_label', __('Appears within the input box.','dbem') );
1250
+ ?>
1251
+ </tbody>
1252
+ <tbody class="em-settings-geocoding em-subsection">
1253
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Geolocation Search', 'dbem' ); ?></h5></td></tr>
1254
+ <?php
1255
+ em_options_radio_binary ( __( 'Show geolocation search?', 'dbem' ), 'dbem_search_form_geo', '', '', '#dbem_search_form_geo_label_row, #dbem_search_form_geo_distance_default_row, #dbem_search_form_geo_unit_default_row' );
1256
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_geo_label', __('Appears within the input box.','dbem') );
1257
+ em_options_input_text ( __( 'Default distance', 'dbem' ), 'dbem_search_form_geo_distance_default', __('Enter a number.','dbem'), '');
1258
+ em_options_select ( __( 'Default distance unit', 'dbem' ), 'dbem_search_form_geo_unit_default', array('km'=>'km','mi'=>'mi'), '');
1259
+ ?>
1260
+ </tbody>
1261
+ </table>
1262
+ <table class="form-table">
1263
+ <tr class="em-header"><td colspan="2"><h4><?php _e('Advanced Search Fields','dbem'); ?></h4></td></tr>
1264
+ <?php
1265
+ em_options_radio_binary ( __( 'Enable advanced fields?', 'dbem' ), 'dbem_search_form_advanced', __('Enables additional advanced search fields such as dates, country, etc.','dbem'), '', '.em-search-form-advanced' );
1266
+ ?>
1267
+ <tbody class="em-search-form-advanced">
1268
+ <?php
1269
+ em_options_input_text ( __( 'Search button text', 'dbem' ), 'dbem_search_form_submit', __("If there's no fields to show in the main search section, this button will be used instead at the bottom of the advanced fields.",'dbem'));
1270
+ em_options_radio_binary ( __( 'Hidden by default?', 'dbem' ), 'dbem_search_form_advanced_hidden', __('If set to yes, advanced search fields will be hidden by default and can be revealed by clicking the "Advanced Search" link.','dbem'), '', '#dbem_search_form_advanced_show_row, #dbem_search_form_advanced_hide_row' );
1271
+ em_options_input_text ( __( 'Show label', 'dbem' ), 'dbem_search_form_advanced_show', __('Appears as the label for this search option.','dbem') );
1272
+ em_options_input_text ( __( 'Hide label', 'dbem' ), 'dbem_search_form_advanced_hide', __('Appears as the label for this search option.','dbem') );
1273
+ ?>
1274
+ </tbody>
1275
+ <tbody class="em-search-form-advanced em-subsection">
1276
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Dates', 'dbem' ); ?></h5></td></tr>
1277
+ <?php
1278
+ em_options_radio_binary ( __( 'Show date range?', 'dbem' ), 'dbem_search_form_dates', '', '', '#dbem_search_form_dates_label_row, #dbem_search_form_dates_separator_row' );
1279
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_dates_label', __('Appears as the label for this search option.','dbem') );
1280
+ em_options_input_text ( __( 'Date Separator', 'dbem' ), 'dbem_search_form_dates_separator', sprintf(__( 'For when start/end %s are present, this will seperate the two (include spaces here if necessary).', 'dbem' ), __('dates','dbem')) );
1281
+ ?>
1282
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Category', 'dbem' ); ?></h5></td></tr>
1283
+ <?php
1284
+ em_options_radio_binary ( __( 'Show categories?', 'dbem' ), 'dbem_search_form_categories', '', '', '#dbem_search_form_category_label_row, #dbem_search_form_categories_label_row' );
1285
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_category_label', __('Appears as the label for this search option.','dbem') );
1286
+ em_options_input_text ( __( 'Categories dropdown label', 'dbem' ), 'dbem_search_form_categories_label', __('Appears as the first default search option.','dbem') );
1287
+ ?>
1288
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Geolocation Search', 'dbem' ); ?></h5></td></tr>
1289
+ <?php
1290
+ em_options_radio_binary ( __( 'Show distance options?', 'dbem' ), 'dbem_search_form_geo_units', '', '', '#dbem_search_form_geo_units_label_row, #dbem_search_form_geo_distance_options_row' );
1291
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_geo_units_label', __('Appears as the label for this search option.','dbem') );
1292
+ em_options_input_text ( __( 'Distance Values', 'dbem' ), 'dbem_search_form_geo_distance_options', __('The numerical units shown to those searching by distance. Use comma-seperated numers, such as "25,50,100".','dbem') );
1293
+ ?>
1294
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Country', 'dbem' ); ?></h5></td></tr>
1295
+ <?php
1296
+ em_options_radio_binary ( __( 'Show countries?', 'dbem' ), 'dbem_search_form_countries', '', '', '#dbem_search_form_country_label_row, #dbem_search_form_countries_label_row' );
1297
+ em_options_select ( __( 'Default Country', 'dbem' ), 'dbem_search_form_default_country', em_get_countries(__('no default country', 'dbem')), __('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.','dbem') );
1298
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_country_label', __('Appears as the label for this search option.','dbem') );
1299
+ em_options_input_text ( __( 'All countries text', 'dbem' ), 'dbem_search_form_countries_label', __('Appears as the first default search option.','dbem') );
1300
+ ?>
1301
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'Region', 'dbem' ); ?></h5></td></tr>
1302
+ <?php
1303
+ em_options_radio_binary ( __( 'Show regions?', 'dbem' ), 'dbem_search_form_regions', '', '', '#dbem_search_form_region_label_row, #dbem_search_form_regions_label_row' );
1304
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_region_label', __('Appears as the label for this search option.','dbem') );
1305
+ em_options_input_text ( __( 'All regions text', 'dbem' ), 'dbem_search_form_regions_label', __('Appears as the first default search option.','dbem') );
1306
+ ?>
1307
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'State/County', 'dbem' ); ?></h5></td></tr>
1308
+ <?php
1309
+ em_options_radio_binary ( __( 'Show states?', 'dbem' ), 'dbem_search_form_states', '', '', '#dbem_search_form_state_label_row, #dbem_search_form_states_label_row' );
1310
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_state_label', __('Appears as the label for this search option.','dbem') );
1311
+ em_options_input_text ( __( 'All states text', 'dbem' ), 'dbem_search_form_states_label', __('Appears as the first default search option.','dbem') );
1312
+ ?>
1313
+ <tr class="em-subheader"><td colspan="2"><h5><?php esc_html_e( 'City/Town', 'dbem' ); ?></h5></td></tr>
1314
+ <?php
1315
+ em_options_radio_binary ( __( 'Show towns/cities?', 'dbem' ), 'dbem_search_form_towns', '', '', '#dbem_search_form_town_label_row, #dbem_search_form_towns_label_row' );
1316
+ em_options_input_text ( __( 'Label', 'dbem' ), 'dbem_search_form_town_label', __('Appears as the label for this search option.','dbem') );
1317
+ em_options_input_text ( __( 'All towns/cities text', 'dbem' ), 'dbem_search_form_towns_label', __('Appears as the first default search option.','dbem') );
1318
+ ?>
1319
+ </tbody>
1320
+ <?php echo $save_button; ?>
1321
+ </table>
1322
+ </div> <!-- . inside -->
1323
+ </div> <!-- .postbox -->
1324
+
1325
+ <div class="postbox " id="em-opt-date-time" >
1326
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Date/Time', 'dbem' ); ?> </span></h3>
1327
+ <div class="inside">
1328
+ <p class="em-boxheader"><?php
1329
+ $date_time_format_tip = sprintf(__('Date and Time formats follow the <a href="%s">WordPress time formatting conventions</a>', 'dbem'), 'http://codex.wordpress.org/Formatting_Date_and_Time');
1330
+ echo $date_time_format_tip;
1331
+ ?></p>
1332
+ <table class="form-table">
1333
+ <?php
1334
+ em_options_input_text ( __( 'Date Format', 'dbem' ), 'dbem_date_format', sprintf(__('For use with the %s placeholder','dbem'),'<code>#_EVENTDATES</code>') );
1335
+ em_options_input_text ( __( 'Date Picker Format', 'dbem' ), 'dbem_date_format_js', sprintf(__( 'Same as <em>Date Format</em>, but this is used for the datepickers used by Events Manager. This uses a slightly different format to the others on here, for a list of characters to use, visit the <a href="%s">jQuery formatDate reference</a>', 'dbem' ),'http://docs.jquery.com/UI/Datepicker/formatDate') );
1336
+ em_options_input_text ( __( 'Date Separator', 'dbem' ), 'dbem_dates_separator', sprintf(__( 'For when start/end %s are present, this will seperate the two (include spaces here if necessary).', 'dbem' ), __('dates','dbem')) );
1337
+ em_options_input_text ( __( 'Time Format', 'dbem' ), 'dbem_time_format', sprintf(__('For use with the %s placeholder','dbem'),'<code>#_EVENTTIMES</code>') );
1338
+ em_options_input_text ( __( 'Time Separator', 'dbem' ), 'dbem_times_separator', sprintf(__( 'For when start/end %s are present, this will seperate the two (include spaces here if necessary).', 'dbem' ), __('times','dbem')) );
1339
+ em_options_input_text ( __( 'All Day Message', 'dbem' ), 'dbem_event_all_day_message', sprintf(__( 'If an event lasts all day, this text will show if using the %s placeholder', 'dbem' ), '<code>#_EVENTTIMES</code>') );
1340
+ em_options_radio_binary ( __( 'Use 24h Format?', 'dbem' ), 'dbem_time_24h', __( 'When creating events, would you like your times to be shown in 24 hour format?', 'dbem' ) );
1341
+ echo $save_button;
1342
+ ?>
1343
+ </table>
1344
+ </div> <!-- . inside -->
1345
+ </div> <!-- .postbox -->
1346
+
1347
+ <div class="postbox " id="em-opt-calendar-formats" >
1348
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Calendar', 'dbem' ); ?></span></h3>
1349
+ <div class="inside">
1350
+ <table class="form-table">
1351
+ <?php
1352
+ em_options_radio_binary ( __( 'Link directly to event on day with single event?', 'dbem' ), 'dbem_calendar_direct_links', __( "If a calendar day has only one event, you can force a direct link to the event (recommended to avoid duplicate content).",'dbem' ) );
1353
+ em_options_radio_binary ( __( 'Show list on day with single event?', 'dbem' ), 'dbem_display_calendar_day_single', __( "By default, if a calendar day only has one event, it display a single event when clicking on the link of that calendar date. If you select Yes here, you will get always see a list of events.",'dbem' ) );
1354
+ ?>
1355
+ <tr class="em-header"><td colspan="2"><h4><?php _e('Small Calendar','dbem'); ?></h4></td></tr>
1356
+ <?php
1357
+ em_options_input_text ( __( 'Month format', 'dbem' ), 'dbem_small_calendar_month_format', __('The format of the month/year header of the calendar.','dbem').' '.$date_time_format_tip);
1358
+ em_options_input_text ( __( 'Event titles', 'dbem' ), 'dbem_small_calendar_event_title_format', __( 'The format of the title, corresponding to the text that appears when hovering on an eventful calendar day.', 'dbem' ).$events_placeholder_tip );
1359
+ em_options_input_text ( __( 'Title separator', 'dbem' ), 'dbem_small_calendar_event_title_separator', __( 'The separator appearing on the above title when more than one events are taking place on the same day.', 'dbem' ) );
1360
+ em_options_radio_binary( __( 'Abbreviated weekdays', 'dbem' ), 'dbem_small_calendar_abbreviated_weekdays', __( 'The calendar headings uses abbreviated weekdays','dbem') );
1361
+ em_options_input_text ( __( 'Initial lengths', 'dbem' ), 'dbem_small_calendar_initials_length', __( 'Shorten the calendar headings containing the days of the week, use 0 for the full name.', 'dbem' ).$events_placeholder_tip );
1362
+ ?>
1363
+ <tr class="em-header"><td colspan="2"><h4><?php _e('Full Calendar','dbem'); ?></h4></td></tr>
1364
+ <?php
1365
+ em_options_input_text ( __( 'Month format', 'dbem' ), 'dbem_full_calendar_month_format', __('The format of the month/year header of the calendar.','dbem').' '.$date_time_format_tip);
1366
+ em_options_input_text ( __( 'Event format', 'dbem' ), 'dbem_full_calendar_event_format', __( 'The format of each event when displayed in the full calendar. Remember to include <code>li</code> tags before and after the event.', 'dbem' ).$events_placeholder_tip );
1367
+ em_options_radio_binary( __( 'Abbreviated weekdays?', 'dbem' ), 'dbem_full_calendar_abbreviated_weekdays', __( 'Use abbreviations, e.g. Friday = Fri. Useful for certain languages where abbreviations differ from full names.','dbem') );
1368
+ em_options_input_text ( __( 'Initial lengths', 'dbem' ), 'dbem_full_calendar_initials_length', __( 'Shorten the calendar headings containing the days of the week, use 0 for the full name.', 'dbem' ).$events_placeholder_tip);
1369
+ ?>
1370
+ <tr class="em-header"><td colspan="2"><h4><?php echo __('Calendar Day Event List Settings','dbem'); ?></h4></td></tr>
1371
+ <tr valign="top" id='dbem_display_calendar_orderby_row'>
1372
+ <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
1373
+ <td>
1374
+ <select name="dbem_display_calendar_orderby" >
1375
  <?php
1376
+ $orderby_options = apply_filters('dbem_display_calendar_orderby_ddm', array(
1377
+ 'event_name,event_start_time' => __('Order by event name, then event start time','dbem'),
1378
+ 'event_start_time,event_name' => __('Order by event start time, then event name','dbem')
1379
+ ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1380
  ?>
1381
+ <?php foreach($orderby_options as $key => $value) : ?>
1382
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_display_calendar_orderby')) ? "selected='selected'" : ''; ?>>
1383
+ <?php echo esc_html($value) ?>
1384
+ </option>
1385
+ <?php endforeach; ?>
1386
+ </select>
1387
+ <select name="dbem_display_calendar_order" >
1388
  <?php
1389
+ $ascending = __('Ascending','dbem');
1390
+ $descending = __('Descending','dbem');
1391
+ $order_options = apply_filters('dbem_display_calendar_order_ddm', array(
1392
+ 'ASC' => __('All Ascending','dbem'),
1393
+ 'DESC,ASC' => "$descending, $ascending",
1394
+ 'DESC,DESC' => "$descending, $descending",
1395
+ 'DESC' => __('All Descending','dbem')
1396
+ ));
1397
  ?>
1398
+ <?php foreach( $order_options as $key => $value) : ?>
1399
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_display_calendar_order')) ? "selected='selected'" : ''; ?>>
1400
+ <?php echo esc_html($value) ?>
1401
+ </option>
1402
+ <?php endforeach; ?>
1403
+ </select>
1404
+ <br/>
1405
+ <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
1406
+ </td>
1407
+ </tr>
1408
+ <?php
1409
+ em_options_input_text ( __( 'Calendar events/day limit', 'dbem' ), 'dbem_display_calendar_events_limit', __( 'Limits the number of events on each calendar day. Leave blank for no limit.', 'dbem' ) );
1410
+ em_options_input_text ( __( 'More Events message', 'dbem' ), 'dbem_display_calendar_events_limit_msg', __( 'Text with link to calendar day page with all events for that day if there are more events than the limit above, leave blank for no link as the day number is also a link.', 'dbem' ) );
1411
+ ?>
1412
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('iCal Feed Settings','dbem'),__('Event','dbem')); ?></h4></td></tr>
1413
+ <?php
1414
+ em_options_input_text ( __( 'iCal Title', 'dbem' ), 'dbem_ical_description_format', __( 'The title that will appear in the calendar.', 'dbem' ).$events_placeholder_tip );
1415
+ em_options_input_text ( __( 'iCal Description', 'dbem' ), 'dbem_ical_real_description_format', __( 'The description of the event that will appear in the calendar.', 'dbem' ).$events_placeholder_tip );
1416
+ em_options_input_text ( __( 'iCal Location', 'dbem' ), 'dbem_ical_location_format', __( 'The location information that will appear in the calendar.', 'dbem' ).$events_placeholder_tip );
1417
+ em_options_select( __('iCal Scope','dbem'), 'dbem_ical_scope', em_get_scopes(), __('Choose to show events within a specific time range.','dbem'));
1418
+ em_options_input_text ( __( 'iCal Limit', 'dbem' ), 'dbem_ical_limit', __( 'Limits the number of future events shown (0 = unlimited).', 'dbem' ) );
1419
+ echo $save_button;
1420
+ ?>
1421
+ </table>
1422
+ </div> <!-- . inside -->
1423
+ </div> <!-- .postbox -->
1424
+
1425
+ <?php if( get_option('dbem_locations_enabled') ): ?>
1426
+ <div class="postbox " id="em-opt-locations-formats" >
1427
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Locations', 'dbem' ); ?> </span></h3>
1428
+ <div class="inside">
1429
+ <table class="form-table">
1430
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s Page','dbem'),__('Locations','dbem')); ?></h4></td></tr>
1431
+ <?php
1432
+ em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('locations','dbem')) );
1433
+ em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('locations','dbem')).$locations_placeholder_tip );
1434
+ em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('locations','dbem')) );
1435
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Locations','dbem')), 'dbem_no_locations_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('locations','dbem')) );
1436
+ ?>
1437
+ <tr class="em-header">
1438
+ <td colspan="2">
1439
+ <h4><?php echo sprintf(__('Single %s Page','dbem'),__('Location','dbem')); ?></h4>
1440
+ <em><?php echo sprintf(__('These formats can be used on %s pages or on other areas of your site displaying an %s.','dbem'),__('location','dbem'),__('location','dbem'));?></em>
1441
+ </tr>
1442
+ <?php
1443
+ if( EM_MS_GLOBAL && get_option('dbem_ms_global_location_links') ){
1444
+ em_options_input_text (sprintf( __( 'Single %s title format', 'dbem' ),__('location','dbem')), 'dbem_location_page_title_format', sprintf(__( 'The format of a single %s page title.', 'dbem' ),__('location','dbem')).$locations_placeholder_tip );
1445
+ }
1446
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('location','dbem')), 'dbem_single_location_format', sprintf(__( 'The format of a single %s page.', 'dbem' ),__('location','dbem')).$locations_placeholder_tip );
1447
+ ?>
1448
+ <tr class="em-header">
1449
+ <td colspan="2">
1450
+ <h4><?php echo sprintf(__('%s Excerpts','dbem'),__('Location','dbem')); ?></h4>
1451
+ <em><?php echo sprintf(__('These formats can be used when WordPress automatically displays %s excerpts on your site and %s is enabled in your %s settings tab.','dbem'),__('location','dbem'),'<strong>'.__( 'Override Excerpts with Formats?', 'dbem' ).'</strong>','<a href="#formats" class="nav-tab-link" rel="#em-menu-pages">'.__('Pages','dbem').' &gt; '.sprintf(__('%s List/Archives','dbem'),__('Location','dbem')).'</a>');?></em>
1452
+ </td>
1453
+ </tr>
1454
+ <?php
1455
+ em_options_textarea ( sprintf(__('%s excerpt', 'dbem' ),__('Location','dbem')), 'dbem_location_excerpt_format', __( 'Used if an excerpt has been defined.', 'dbem' ).$locations_placeholder_tip );
1456
+ em_options_textarea ( sprintf(__('%s excerpt fallback', 'dbem' ),__('Location','dbem')), 'dbem_location_excerpt_alt_format', __( 'Used if an excerpt has not been defined.', 'dbem' ).$locations_placeholder_tip );
1457
+ ?>
1458
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s List Formats','dbem'),__('Event','dbem')); ?></h4></td></tr>
1459
+ <?php
1460
+ em_options_input_text ( __( 'Default event list format header', 'dbem' ), 'dbem_location_event_list_item_header_format', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
1461
+ em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_location_event_list_item_format', sprintf(__( 'The format of the events the list inserted in the location page through the %s element.', 'dbem' ).$events_placeholder_tip, '<code>#_LOCATIONNEXTEVENTS</code>, <code>#_LOCATIONPASTEVENTS</code>, <code>#_LOCATIONALLEVENTS</code>') );
1462
+ em_options_input_text ( __( 'Default event list format footer', 'dbem' ), 'dbem_location_event_list_item_footer_format', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
1463
+ em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_location_no_events_message', sprintf(__( 'The message to be displayed in the list generated by %s when no events are available.', 'dbem' ), '<code>#_LOCATIONNEXTEVENTS</code>, <code>#_LOCATIONPASTEVENTS</code>, <code>#_LOCATIONALLEVENTS</code>') );
1464
+ ?>
1465
+ <tr class="em-header"><td colspan="2">
1466
+ <h4><?php echo sprintf(__('Single %s Format','dbem'),__('Event','dbem')); ?></h4>
1467
+ <p><?php echo sprintf(__('The settings below are used when using the %s placeholder','dbem'), '<code>#_LOCATIONNEXTEVENT</code>'); ?></p>
1468
+ </td></tr>
1469
+ <?php
1470
+ em_options_input_text ( __( 'Next event format', 'dbem' ), 'dbem_location_event_single_format', sprintf(__( 'The format of the next upcoming event in this %s.', 'dbem' ),__('location','dbem')).$events_placeholder_tip );
1471
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_location_no_event_message', sprintf(__( 'The message to be displayed in the list generated by %s when no events are available.', 'dbem' ), '<code>#_LOCATIONNEXTEVENT</code>') );
1472
+ echo $save_button;
1473
+ ?>
1474
+ </table>
1475
+ </div> <!-- . inside -->
1476
+ </div> <!-- .postbox -->
1477
+ <?php endif; ?>
1478
+
1479
+ <?php if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_site()) ): ?>
1480
+ <div class="postbox " id="em-opt-categories-formats" >
1481
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Event Categories', 'dbem' ); ?> </span></h3>
1482
+ <div class="inside">
1483
+ <table class="form-table">
1484
+ <?php
1485
+ em_options_input_text(sprintf(esc_html__('Default %s color','dbem'), esc_html__('category','dbem')), 'dbem_category_default_color', sprintf(esc_html_x('Colors must be in a valid %s format, such as #FF00EE.', 'hex format', 'dbem'), '<a href="http://en.wikipedia.org/wiki/Web_colors">hex</a>'));
1486
+ ?>
1487
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s Page','dbem'),__('Categories','dbem')); ?></h4></td></tr>
1488
+ <?php
1489
+ em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('categories','dbem')) );
1490
+ em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('categories','dbem')).$categories_placeholder_tip );
1491
+ em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('categories','dbem')) );
1492
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Categories','dbem')), 'dbem_no_categories_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('categories','dbem')) );
1493
+ ?>
1494
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('Single %s Page','dbem'),__('Category','dbem')); ?></h4></td></tr>
1495
+ <?php
1496
+ em_options_input_text ( sprintf(__( 'Single %s title format', 'dbem' ),__('category','dbem')), 'dbem_category_page_title_format', __( 'The format of a single category page title.', 'dbem' ).$categories_placeholder_tip );
1497
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('category','dbem')), 'dbem_category_page_format', sprintf(__( 'The format of a single %s page.', 'dbem' ),__('category','dbem')).$categories_placeholder_tip );
1498
+ ?>
1499
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s List Formats','dbem'),__('Event','dbem')); ?></h4></td></tr>
1500
+ <?php
1501
+ em_options_input_text ( __( 'Default event list format header', 'dbem' ), 'dbem_category_event_list_item_header_format', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
1502
+ em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_category_event_list_item_format', sprintf(__( 'The format of the events the list inserted in the category page through the %s element.', 'dbem' ).$events_placeholder_tip, '<code>#_CATEGORYPASTEVENTS</code>, <code>#_CATEGORYNEXTEVENTS</code>, <code>#_CATEGORYALLEVENTS</code>') );
1503
+ em_options_input_text ( __( 'Default event list format footer', 'dbem' ), 'dbem_category_event_list_item_footer_format', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
1504
+ em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_category_no_events_message', sprintf(__( 'The message to be displayed in the list generated by %s when no events are available.', 'dbem' ), '<code>#_CATEGORYPASTEVENTS</code>, <code>#_CATEGORYNEXTEVENTS</code>, <code>#_CATEGORYALLEVENTS</code>') );
1505
+ ?>
1506
+ <tr class="em-header"><td colspan="2">
1507
+ <h4><?php echo sprintf(__('Single %s Format','dbem'),__('Event','dbem')); ?></h4>
1508
+ <p><?php echo sprintf(__('The settings below are used when using the %s placeholder','dbem'), '<code>#_CATEGORYNEXTEVENT</code>'); ?></p>
1509
+ </td></tr>
1510
+ <?php
1511
+ em_options_input_text ( __( 'Next event format', 'dbem' ), 'dbem_category_event_single_format', sprintf(__( 'The format of the next upcoming event in this %s.', 'dbem' ),__('category','dbem')).$events_placeholder_tip );
1512
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_category_no_event_message', sprintf(__( 'The message to be displayed in the list generated by %s when no events are available.', 'dbem' ), '<code>#_CATEGORYNEXTEVENT</code>') );
1513
+ echo $save_button;
1514
+ ?>
1515
+ </table>
1516
+ </div> <!-- . inside -->
1517
+ </div> <!-- .postbox -->
1518
+ <?php endif; ?>
1519
+
1520
+ <?php if( get_option('dbem_tags_enabled') ): ?>
1521
+ <div class="postbox " id="em-opt-tags-formats" >
1522
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Event Tags', 'dbem' ); ?> </span></h3>
1523
+ <div class="inside">
1524
+ <table class="form-table">
1525
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s Page','dbem'),__('Tags','dbem')); ?></h4></td></tr>
1526
+ <?php
1527
+ em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Tags','dbem')), 'dbem_tags_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('tags','dbem')) );
1528
+ em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Tags','dbem')), 'dbem_tags_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('tags','dbem')).$categories_placeholder_tip );
1529
+ em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Tags','dbem')), 'dbem_tags_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('tags','dbem')) );
1530
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Tags','dbem')), 'dbem_no_tags_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('tags','dbem')) );
1531
+ ?>
1532
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('Single %s Page','dbem'),__('Tag','dbem')); ?></h4></td></tr>
1533
+ <?php
1534
+ em_options_input_text ( sprintf(__( 'Single %s title format', 'dbem' ),__('tag','dbem')), 'dbem_tag_page_title_format', __( 'The format of a single tag page title.', 'dbem' ).$categories_placeholder_tip );
1535
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('tag','dbem')), 'dbem_tag_page_format', sprintf(__( 'The format of a single %s page.', 'dbem' ),__('tag','dbem')).$categories_placeholder_tip );
1536
+ ?>
1537
+ <tr class="em-header"><td colspan="2"><h4><?php echo sprintf(__('%s List Formats','dbem'),__('Event','dbem')); ?></h4></td></tr>
1538
+ <?php
1539
+ em_options_input_text ( __( 'Default event list format header', 'dbem' ), 'dbem_tag_event_list_item_header_format', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
1540
+ em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_tag_event_list_item_format', __( 'The format of the events the list inserted in the tag page through the <code>#_TAGNEXTEVENTS</code>, <code>#_TAGNEXTEVENTS</code> and <code>#_TAGALLEVENTS</code> element.', 'dbem' ).$categories_placeholder_tip );
1541
+ em_options_input_text ( __( 'Default event list format footer', 'dbem' ), 'dbem_tag_event_list_item_footer_format', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
1542
+ em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_tag_no_events_message', __( 'The message to be displayed in the list generated by <code>#_TAGNEXTEVENTS</code>, <code>#_TAGNEXTEVENTS</code> and <code>#_TAGALLEVENTS</code> when no events are available.', 'dbem' ) );
1543
+ ?>
1544
+ <tr class="em-header"><td colspan="2">
1545
+ <h4><?php echo sprintf(__('Single %s Format','dbem'),__('Event','dbem')); ?></h4>
1546
+ <p><?php echo sprintf(__('The settings below are used when using the %s placeholder','dbem'), '<code>#_TAGNEXTEVENT</code>'); ?></p>
1547
+ </td></tr>
1548
+ <?php
1549
+ em_options_input_text ( __( 'Next event format', 'dbem' ), 'dbem_tag_event_single_format', sprintf(__( 'The format of the next upcoming event in this %s.', 'dbem' ),__('tag','dbem')).$events_placeholder_tip );
1550
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_tag_no_event_message', sprintf(__( 'The message to be displayed in the list generated by %s when no events are available.', 'dbem' ), '<code>#_CATEGORYNEXTEVENT</code>') );
1551
+ echo $save_button;
1552
+ ?>
1553
+ </table>
1554
+ </div> <!-- . inside -->
1555
+ </div> <!-- .postbox -->
1556
+ <?php endif; ?>
1557
+
1558
+ <div class="postbox " id="em-opt-rss-formats" >
1559
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'RSS', 'dbem' ); ?> </span></h3>
1560
+ <div class="inside">
1561
+ <table class="form-table">
1562
+ <?php
1563
+ em_options_input_text ( __( 'RSS main title', 'dbem' ), 'dbem_rss_main_title', __( 'The main title of your RSS events feed.', 'dbem' ).$events_placeholder_tip );
1564
+ em_options_input_text ( __( 'RSS main description', 'dbem' ), 'dbem_rss_main_description', __( 'The main description of your RSS events feed.', 'dbem' ) );
1565
+ em_options_input_text ( __( 'RSS title format', 'dbem' ), 'dbem_rss_title_format', __( 'The format of the title of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
1566
+ em_options_input_text ( __( 'RSS description format', 'dbem' ), 'dbem_rss_description_format', __( 'The format of the description of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
1567
+ em_options_input_text ( __( 'RSS limit', 'dbem' ), 'dbem_rss_limit', __( 'Limits the number of future events shown (0 = unlimited).', 'dbem' ) );
1568
+ em_options_select( __('RSS Scope','dbem'), 'dbem_rss_scope', em_get_scopes(), __('Choose to show events within a specific time range.','dbem'));
1569
+ ?>
1570
+ <tr valign="top" id='dbem_rss_orderby_row'>
1571
+ <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
1572
+ <td>
1573
+ <select name="dbem_rss_orderby" >
1574
+ <?php
1575
+ $orderby_options = apply_filters('em_settings_events_default_orderby_ddm', array(
1576
+ 'event_start_date,event_start_time,event_name' => __('Order by start date, start time, then event name','dbem'),
1577
+ 'event_name,event_start_date,event_start_time' => __('Order by name, start date, then start time','dbem'),
1578
+ 'event_name,event_end_date,event_end_time' => __('Order by name, end date, then end time','dbem'),
1579
+ 'event_end_date,event_end_time,event_name' => __('Order by end date, end time, then event name','dbem'),
1580
+ ));
1581
+ ?>
1582
+ <?php foreach($orderby_options as $key => $value) : ?>
1583
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_rss_orderby')) ? "selected='selected'" : ''; ?>>
1584
+ <?php echo esc_html($value); ?>
1585
+ </option>
1586
+ <?php endforeach; ?>
1587
+ </select>
1588
+ <select name="dbem_rss_order" >
1589
+ <?php
1590
+ $ascending = __('Ascending','dbem');
1591
+ $descending = __('Descending','dbem');
1592
+ $order_options = apply_filters('em_settings_events_default_order_ddm', array(
1593
+ 'ASC' => __('All Ascending','dbem'),
1594
+ 'DESC,ASC,ASC' => __("$descending, $ascending, $ascending",'dbem'),
1595
+ 'DESC,DESC,ASC' => __("$descending, $descending, $ascending",'dbem'),
1596
+ 'DESC' => __('All Descending','dbem'),
1597
+ 'ASC,DESC,ASC' => __("$ascending, $descending, $ascending",'dbem'),
1598
+ 'ASC,DESC,DESC' => __("$ascending, $descending, $descending",'dbem'),
1599
+ 'ASC,ASC,DESC' => __("$ascending, $ascending, $descending",'dbem'),
1600
+ 'DESC,ASC,DESC' => __("$descending, $ascending, $descending",'dbem'),
1601
+ ));
1602
+ ?>
1603
+ <?php foreach( $order_options as $key => $value) : ?>
1604
+ <option value='<?php echo esc_attr($key) ?>' <?php echo ($key == get_option('dbem_rss_order')) ? "selected='selected'" : ''; ?>>
1605
+ <?php echo esc_html($value); ?>
1606
+ </option>
1607
+ <?php endforeach; ?>
1608
+ </select>
1609
+ <br/>
1610
+ <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
1611
+ </td>
1612
+ </tr>
1613
+ <?php
1614
+ echo $save_button;
1615
+ ?>
1616
+ </table>
1617
+ </div> <!-- . inside -->
1618
+ </div> <!-- .postbox -->
1619
+
1620
+ <div class="postbox " id="em-opt-maps-formats" >
1621
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Maps', 'dbem' ); ?> </span></h3>
1622
+ <div class="inside">
1623
+ <p class="em-boxheader"><?php echo sprintf(__('You can use Google Maps to show where your events are located. For more information on using maps, <a href="%s">see our documentation</a>.','dbem'),'http://wp-events-plugin.com/documentation/google-maps/'); ?>
1624
+ <table class='form-table'>
1625
+ <?php $gmap_is_active = get_option ( 'dbem_gmap_is_active' ); ?>
1626
+ <tr valign="top">
1627
+ <th scope="row"><?php _e ( 'Enable Google Maps integration?', 'dbem' ); ?></th>
1628
+ <td>
1629
+ <?php _e ( 'Yes' ); ?> <input id="dbem_gmap_is_active_yes" name="dbem_gmap_is_active" type="radio" value="1" <?php echo ($gmap_is_active) ? "checked='checked'":''; ?> />
1630
+ <?php _e ( 'No' ); ?> <input name="dbem_gmap_is_active" type="radio" value="0" <?php echo ($gmap_is_active) ? '':"checked='checked'"; ?> /><br />
1631
+ <em><?php _e ( 'Check this option to enable Goggle Map integration.', 'dbem' )?></em>
1632
+ </td>
1633
+ <?php em_options_input_text(__('Default map width','dbem'), 'dbem_map_default_width', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'dbem'), '<code>100%</code>', '<code>100px</code>')); ?>
1634
+ <?php em_options_input_text(__('Default map height','dbem'), 'dbem_map_default_height', sprintf(__('Can be in form of pixels or a percentage such as %s or %s.', 'dbem'), '<code>100%</code>', '<code>100px</code>')); ?>
1635
+ </tr>
1636
+ <tr class="em-header"><td colspan="2">
1637
+ <h4><?php _e('Global Map Format','dbem'); ?></h4>
1638
+ <p><?php echo sprintf(__('If you use the %s <a href="%s">shortcode</a>, you can display a map of all your locations and events, the settings below will be used.','dbem'), '<code>[locations_map]</code>','http://wp-events-plugin.com/documentation/shortcodes/'); ?></p>
1639
+ </td></tr>
1640
+ <?php
1641
+ em_options_textarea ( __( 'Location balloon format', 'dbem' ), 'dbem_map_text_format', __( 'The format of of the text appearing in the balloon describing the location.', 'dbem' ).' '.__( 'Event.', 'dbem' ).$locations_placeholder_tip );
1642
+ ?>
1643
+ <tr class="em-header"><td colspan="2">
1644
+ <h4><?php _e('Single Location/Event Map Format','dbem'); ?></h4>
1645
+ <p><?php echo sprintf(_e('If you use the <code>#_LOCATIONMAP</code> <a href="%s">placeholder</a> when displaying individual event and location information, the settings below will be used.','dbem'), '<code>[locations_map]</code>','http://wp-events-plugin.com/documentation/placeholders/'); ?></p>
1646
+ </td></tr>
1647
+ <?php
1648
+ em_options_textarea ( __( 'Location balloon format', 'dbem' ), 'dbem_location_baloon_format', __( 'The format of of the text appearing in the balloon describing the location.', 'dbem' ).$events_placeholder_tip );
1649
+ echo $save_button;
1650
+ ?>
1651
+ </table>
1652
+ </div> <!-- . inside -->
1653
+ </div> <!-- .postbox -->
1654
+
1655
+ <?php do_action('em_options_page_footer_formats'); ?>
1656
+
1657
+ </div> <!-- .em-menu-formats -->
1658
+
1659
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
1660
+ <!-- BOOKING OPTIONS -->
1661
+ <div class="em-menu-bookings em-menu-group" style="display:none;">
1662
+
1663
+ <div class="postbox " id="em-opt-bookings-general" >
1664
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('General','dbem')); ?> </span></h3>
1665
+ <div class="inside">
1666
+ <table class='form-table'>
1667
+ <?php
1668
+ em_options_radio_binary ( __( 'Allow guest bookings?', 'dbem' ), 'dbem_bookings_anonymous', __( 'If enabled, guest visitors can supply an email address and a user account will automatically be created for them along with their booking. They will be also be able to log back in with that newly created account.', 'dbem' ) );
1669
+ em_options_radio_binary ( __( 'Approval Required?', 'dbem' ), 'dbem_bookings_approval', __( 'Bookings will not be confirmed until the event administrator approves it.', 'dbem' ).' '.__( 'This setting is not applicable when using payment gateways, see individual gateways for approval settings.', 'dbem' ));
1670
+ em_options_radio_binary ( __( 'Reserved unconfirmed spaces?', 'dbem' ), 'dbem_bookings_approval_reserved', __( 'By default, event spaces become unavailable once there are enough CONFIRMED bookings. To reserve spaces even if unnapproved, choose yes.', 'dbem' ) );
1671
+ em_options_radio_binary ( __( 'Can users cancel their booking?', 'dbem' ), 'dbem_bookings_user_cancellation', __( 'If enabled, users can cancel their bookings themselves from their bookings page.', 'dbem' ) );
1672
+ em_options_radio_binary ( __( 'Allow overbooking when approving?', 'dbem' ), 'dbem_bookings_approval_overbooking', __( 'If you get a lot of pending bookings and you decide to allow more bookings than spaces allow, setting this to yes will allow you to override the event space limit when manually approving.', 'dbem' ) );
1673
+ em_options_radio_binary ( __( 'Allow double bookings?', 'dbem' ), 'dbem_bookings_double', __( 'If enabled, users can book an event more than once.', 'dbem' ) );
1674
+ echo $save_button;
1675
+ ?>
1676
+ </table>
1677
+ </div> <!-- . inside -->
1678
+ </div> <!-- .postbox -->
1679
+
1680
+ <div class="postbox " id="em-opt-pricing-options" >
1681
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Pricing','dbem')); ?> </span></h3>
1682
+ <div class="inside">
1683
+ <table class='form-table'>
1684
+ <?php
1685
+ /* Tax & Currency */
1686
+ em_options_select ( __( 'Currency', 'dbem' ), 'dbem_bookings_currency', em_get_currencies()->names, __( 'Choose your currency for displaying event pricing.', 'dbem' ) );
1687
+ em_options_input_text ( __( 'Thousands Separator', 'dbem' ), 'dbem_bookings_currency_thousands_sep', '<code>'.get_option('dbem_bookings_currency_thousands_sep')." = ".em_get_currency_symbol().'100<strong>'.get_option('dbem_bookings_currency_thousands_sep').'</strong>000<strong>'.get_option('dbem_bookings_currency_decimal_point').'</strong>00</code>' );
1688
+ em_options_input_text ( __( 'Decimal Point', 'dbem' ), 'dbem_bookings_currency_decimal_point', '<code>'.get_option('dbem_bookings_currency_decimal_point')." = ".em_get_currency_symbol().'100<strong>'.get_option('dbem_bookings_currency_decimal_point').'</strong>00</code>' );
1689
+ em_options_input_text ( __( 'Currency Format', 'dbem' ), 'dbem_bookings_currency_format', __('Choose how prices are displayed. <code>@</code> will be replaced by the currency symbol, and <code>#</code> will be replaced by the number.','dbem').' <code>'.get_option('dbem_bookings_currency_format')." = ".em_get_currency_formatted('10000000').'</code>');
1690
+ em_options_input_text ( __( 'Tax Rate', 'dbem' ), 'dbem_bookings_tax', __( 'Add a tax rate to your ticket prices (entering 10 will add 10% to the ticket price).', 'dbem' ) );
1691
+ em_options_radio_binary ( __( 'Add tax to ticket price?', 'dbem' ), 'dbem_bookings_tax_auto_add', __( 'When displaying ticket prices and booking totals, include the tax automatically?', 'dbem' ) );
1692
+ echo $save_button;
1693
+ ?>
1694
+ </table>
1695
+ </div> <!-- . inside -->
1696
+ </div> <!-- .postbox -->
1697
+
1698
+ <div class="postbox " id="em-opt-booking-feedbacks" >
1699
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e( 'Customize Feedback Messages', 'dbem' ); ?> </span></h3>
1700
+ <div class="inside">
1701
+ <p><?php _e('Below you will find texts that will be displayed to users in various areas during the bookings process, particularly on booking forms.','dbem'); ?></p>
1702
+ <table class='form-table'>
1703
+ <tr class="em-header"><td colspan='2'><h4><?php _e('My Bookings messages','dbem') ?></h4></td></tr>
1704
+ <?php
1705
+ em_options_input_text ( __( 'Booking Cancelled', 'dbem' ), 'dbem_booking_feedback_cancelled', __( 'When a user cancels their booking, this message will be displayed confirming the cancellation.', 'dbem' ) );
1706
+ em_options_input_text ( __( 'Booking Cancellation Warning', 'dbem' ), 'dbem_booking_warning_cancel', __( 'When a user chooses to cancel a booking, this warning is displayed for them to confirm.', 'dbem' ) );
1707
+ ?>
1708
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Booking form texts/messages','dbem') ?></h4></td></tr>
1709
+ <?php
1710
+ em_options_input_text ( __( 'Bookings disabled', 'dbem' ), 'dbem_bookings_form_msg_disabled', __( 'An event with no bookings.', 'dbem' ) );
1711
+ em_options_input_text ( __( 'Bookings closed', 'dbem' ), 'dbem_bookings_form_msg_closed', __( 'Bookings have closed (e.g. event has started).', 'dbem' ) );
1712
+ em_options_input_text ( __( 'Fully booked', 'dbem' ), 'dbem_bookings_form_msg_full', __( 'Event is fully booked.', 'dbem' ) );
1713
+ em_options_input_text ( __( 'Already attending', 'dbem' ), 'dbem_bookings_form_msg_attending', __( 'If already attending and double bookings are disabled, this message will be displayed, followed by a link to the users booking page.', 'dbem' ) );
1714
+ em_options_input_text ( __( 'Manage bookings link text', 'dbem' ), 'dbem_bookings_form_msg_bookings_link', __( 'Link text used for link to user bookings.', 'dbem' ) );
1715
+ ?>
1716
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Booking form feedback messages','dbem') ?></h4></td></tr>
1717
+ <tr><td colspan='2'><?php _e('When a booking is made by a user, a feedback message is shown depending on the result, which can be customized below.','dbem'); ?></td></tr>
1718
+ <?php
1719
+ em_options_input_text ( __( 'Successful booking', 'dbem' ), 'dbem_booking_feedback', __( 'When a booking is registered and confirmed.', 'dbem' ) );
1720
+ em_options_input_text ( __( 'Successful pending booking', 'dbem' ), 'dbem_booking_feedback_pending', __( 'When a booking is registered but pending.', 'dbem' ) );
1721
+ em_options_input_text ( __( 'Not enough spaces', 'dbem' ), 'dbem_booking_feedback_full', __( 'When a booking cannot be made due to lack of spaces.', 'dbem' ) );
1722
+ em_options_input_text ( __( 'Errors', 'dbem' ), 'dbem_booking_feedback_error', __( 'When a booking cannot be made due to an error when filling the form. Below this, there will be a dynamic list of errors.', 'dbem' ) );
1723
+ em_options_input_text ( __( 'Email Exists', 'dbem' ), 'dbem_booking_feedback_email_exists', __( 'When a guest tries to book using an email registered with a user account.', 'dbem' ) );
1724
+ em_options_input_text ( __( 'User must log in', 'dbem' ), 'dbem_booking_feedback_log_in', __( 'When a user must log in before making a booking.', 'dbem' ) );
1725
+ em_options_input_text ( __( 'Error mailing user', 'dbem' ), 'dbem_booking_feedback_nomail', __( 'If a booking is made and an email cannot be sent, this is added to the success message.', 'dbem' ) );
1726
+ em_options_input_text ( __( 'Already booked', 'dbem' ), 'dbem_booking_feedback_already_booked', __( 'If the user made a previous booking and cannot double-book.', 'dbem' ) );
1727
+ em_options_input_text ( __( 'No spaces booked', 'dbem' ), 'dbem_booking_feedback_min_space', __( 'If the user tries to make a booking without requesting any spaces.', 'dbem' ) );$notice_full = __('Sold Out', 'dbem');
1728
+ em_options_input_text ( __( 'Maximum spaces per booking', 'dbem' ), 'dbem_booking_feedback_spaces_limit', __( 'If the user tries to make a booking with spaces that exceeds the maximum number of spaces per booking.', 'dbem' ).' '. __('%d will be replaced by a number.','dbem') );
1729
+ ?>
1730
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Booking button feedback messages','dbem') ?></h4></td></tr>
1731
+ <tr><td colspan='2'><?php echo sprintf(__('When the %s placeholder, the below texts will be used.','dbem'),'<code>#_BOOKINGBUTTON</code>'); ?></td></tr>
1732
+ <?php
1733
+ em_options_input_text ( __( 'User can book', 'dbem' ), 'dbem_booking_button_msg_book', '');
1734
+ em_options_input_text ( __( 'Booking in progress', 'dbem' ), 'dbem_booking_button_msg_booking', '');
1735
+ em_options_input_text ( __( 'Booking complete', 'dbem' ), 'dbem_booking_button_msg_booked', '');
1736
+ em_options_input_text ( __( 'Booking already made', 'dbem' ), 'dbem_booking_button_msg_already_booked', '');
1737
+ em_options_input_text ( __( 'Booking error', 'dbem' ), 'dbem_booking_button_msg_error', '');
1738
+ em_options_input_text ( __( 'Event fully booked', 'dbem' ), 'dbem_booking_button_msg_full', '');
1739
+ em_options_input_text ( __( 'Cancel', 'dbem' ), 'dbem_booking_button_msg_cancel', '');
1740
+ em_options_input_text ( __( 'Cancelation in progress', 'dbem' ), 'dbem_booking_button_msg_canceling', '');
1741
+ em_options_input_text ( __( 'Cancelation complete', 'dbem' ), 'dbem_booking_button_msg_cancelled', '');
1742
+ em_options_input_text ( __( 'Cancelation error', 'dbem' ), 'dbem_booking_button_msg_cancel_error', '');
1743
+
1744
+ echo $save_button;
1745
+ ?>
1746
+ </table>
1747
+ </div> <!-- . inside -->
1748
+ </div> <!-- .postbox -->
1749
+
1750
+ <div class="postbox " id="em-opt-booking-form-options" >
1751
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Booking Form','dbem')); ?> </span></h3>
1752
+ <div class="inside">
1753
+ <table class='form-table'>
1754
+ <?php
1755
+ em_options_radio_binary ( __( 'Display login form?', 'dbem' ), 'dbem_bookings_login_form', __( 'Choose whether or not to display a login form in the booking form area to remind your members to log in before booking.', 'dbem' ) );
1756
+ em_options_input_text ( __( 'Submit button text', 'dbem' ), 'dbem_bookings_submit_button', sprintf(__( 'The text used by the submit button. To use an image instead, enter the full url starting with %s or %s.', 'dbem' ), '<code>http://</code>','<code>https://</code>') );
1757
+ do_action('em_options_booking_form_options');
1758
+ echo $save_button;
1759
+ ?>
1760
+ </table>
1761
+ </div> <!-- . inside -->
1762
+ </div> <!-- .postbox -->
1763
+
1764
+ <div class="postbox " id="em-opt-ticket-options" >
1765
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Ticket','dbem')); ?> </span></h3>
1766
+ <div class="inside">
1767
+ <table class='form-table'>
1768
+ <?php
1769
+ em_options_radio_binary ( __( 'Single ticket mode?', 'dbem' ), 'dbem_bookings_tickets_single', __( 'In single ticket mode, users can only create one ticket per event (and will not see options to add more tickets).', 'dbem' ) );
1770
+ em_options_radio_binary ( __( 'Show ticket table in single ticket mode?', 'dbem' ), 'dbem_bookings_tickets_single_form', __( 'If you prefer a ticket table like with multiple tickets, even for single ticket events, enable this.', 'dbem' ) );
1771
+ em_options_radio_binary ( __( 'Show unavailable tickets?', 'dbem' ), 'dbem_bookings_tickets_show_unavailable', __( 'You can choose whether or not to show unavailable tickets to visitors.', 'dbem' ) );
1772
+ em_options_radio_binary ( __( 'Show member-only tickets?', 'dbem' ), 'dbem_bookings_tickets_show_member_tickets', sprintf(__('%s must be set to yes for this to work.', 'dbem' ), '<strong>'.__( 'Show unavailable tickets?', 'dbem' ).'</strong>').' '.__( 'If there are member-only tickets, you can choose whether or not to show these tickets to guests.','dbem') );
1773
+
1774
+ em_options_radio_binary ( __( 'Show multiple tickets if logged out?', 'dbem' ), 'dbem_bookings_tickets_show_loggedout', __( 'If guests cannot make bookings, they will be asked to register in order to book. However, enabling this will still show available tickets.', 'dbem' ) );
1775
+ $ticket_orders = array(
1776
+ 'ticket_price DESC, ticket_name ASC'=>__('Ticket Price (Descending)','dbem'),
1777
+ 'ticket_price ASC, ticket_name ASC'=>__('Ticket Price (Ascending)','dbem'),
1778
+ 'ticket_name ASC, ticket_price DESC'=>__('Ticket Name (Ascending)','dbem'),
1779
+ 'ticket_name DESC, ticket_price DESC'=>__('Ticket Name (Descending)','dbem')
1780
+ );
1781
+ em_options_select ( __( 'Order Tickets By', 'dbem' ), 'dbem_bookings_tickets_orderby', $ticket_orders, __( 'Choose which order your tickets appear.', 'dbem' ) );
1782
+ echo $save_button;
1783
+ ?>
1784
+ </table>
1785
+ </div> <!-- . inside -->
1786
+ </div> <!-- .postbox -->
1787
+
1788
+ <div class="postbox " id="em-opt-no-user-bookings" >
1789
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e('No-User Booking Mode','dbem'); ?> </span></h3>
1790
+ <div class="inside">
1791
+ <table class='form-table'>
1792
+ <tr><td colspan='2'>
1793
+ <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.','dbem'); ?></p>
1794
+ <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.','dbem'); ?></p>
1795
+ <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.','dbem'); ?></p>
1796
+ <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.','dbem'); ?></p>
1797
+ </td></tr>
1798
+ <?php
1799
+ em_options_radio_binary ( __( 'Enable No-User Booking Mode?', 'dbem' ), 'dbem_bookings_registration_disable', __( 'This disables user registrations for bookings.', 'dbem' ) );
1800
+ em_options_radio_binary ( __( 'Allow bookings with registered emails?', 'dbem' ), '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.', 'dbem' ).'<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.','dbem') );
1801
+ $current_user = array();
1802
+ if( get_option('dbem_bookings_registration_user') ){
1803
+ $user = get_user_by('id',get_option('dbem_bookings_registration_user'));
1804
+ $current_user[$user->ID] = $user->display_name;
1805
+ }
1806
+ if( defined('EM_OPTIMIZE_SETTINGS_PAGE_USERS') && EM_OPTIMIZE_SETTINGS_PAGE_USERS ){
1807
+ em_options_input_text ( __( 'Assign bookings to', 'dbem' ), 'dbem_bookings_registration_user', __('Please add a User ID.','dbem').' '.__( '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.', 'dbem' ) );
1808
+ }else{
1809
+ em_options_select ( __( 'Assign bookings to', 'dbem' ), '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.', 'dbem' ) );
1810
+ }
1811
+ echo $save_button;
1812
+ ?>
1813
+ </table>
1814
+ </div> <!-- . inside -->
1815
+ </div> <!-- .postbox -->
1816
+
1817
+ <?php do_action('em_options_page_footer_bookings'); ?>
1818
+
1819
+ </div> <!-- .em-menu-bookings -->
1820
  <?php endif; ?>
1821
+
1822
+ <!-- EMAIL OPTIONS -->
1823
+ <div class="em-menu-emails em-menu-group" style="display:none;">
1824
+
1825
+ <?php if ( !is_multisite() ) { em_admin_option_box_email(); } ?>
1826
+
1827
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
1828
+ <div class="postbox " id="em-opt-booking-emails">
1829
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Booking Email Templates', 'dbem' ); ?> </span></h3>
1830
+ <div class="inside">
1831
+ <?php do_action('em_options_page_booking_email_templates_options_top'); ?>
1832
+ <table class='form-table'>
1833
+ <?php
1834
+ $email_subject_tip = __('You can disable this email by leaving the subject blank.','dbem');
1835
+ em_options_input_text ( __( 'Email events admin?', 'dbem' ), 'dbem_bookings_notify_admin', __( "If you would like every event booking confirmation email sent to an administrator write their email here (leave blank to not send an email).", 'dbem' ).' '.__('For multiple emails, seperate by commas (e.g. email1@test.com,email2@test.com,etc.)','dbem') );
1836
+ em_options_radio_binary ( __( 'Email event owner?', 'dbem' ), 'dbem_bookings_contact_email', __( 'Check this option if you want the event contact to receive an email when someone books places. An email will be sent when a booking is first made (regardless if confirmed or pending)', 'dbem' ) );
1837
+ ?>
1838
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Event Admin/Owner Emails', 'dbem'); ?></h4></td></tr>
1839
+ <tbody class="em-subsection">
1840
+ <tr class="em-subheader"><td colspan='2'>
1841
+ <h5><?php _e('Confirmed booking email','dbem') ?></h5>
1842
+ <em><?php echo __('This is sent when a person\'s booking is confirmed. This will be sent automatically if approvals are required and the booking is approved. If approvals are disabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></em>
1843
+ </td></tr>
1844
+ <?php
1845
+ em_options_input_text ( __( 'Booking confirmed email subject', 'dbem' ), 'dbem_bookings_contact_email_confirmed_subject', $email_subject_tip );
1846
+ em_options_textarea ( __( 'Booking confirmed email', 'dbem' ), 'dbem_bookings_contact_email_confirmed_body', '' );
1847
+ ?>
1848
+ <tr class="em-subheader"><td colspan='2'>
1849
+ <h5><?php _e('Pending booking email','dbem') ?></h5>
1850
+ <em><?php echo __('This is sent when a person\'s booking is pending. If approvals are enabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></em>
1851
+ </td></tr>
1852
+ <?php
1853
+ em_options_input_text ( __( 'Booking pending email subject', 'dbem' ), 'dbem_bookings_contact_email_pending_subject', $email_subject_tip );
1854
+ em_options_textarea ( __( 'Booking pending email', 'dbem' ), 'dbem_bookings_contact_email_pending_body', '' );
1855
+ ?>
1856
+ <tr class="em-subheader"><td colspan='2'>
1857
+ <h5><?php _e('Booking cancelled','dbem') ?></h5>
1858
+ <em><?php echo __('An email will be sent to the event contact if someone cancels their booking.','dbem').$bookings_placeholder_tip ?></em>
1859
+ </td></tr>
1860
+ <?php
1861
+ em_options_input_text ( __( 'Booking cancelled email subject', 'dbem' ), 'dbem_bookings_contact_email_cancelled_subject', $email_subject_tip );
1862
+ em_options_textarea ( __( 'Booking cancelled email', 'dbem' ), 'dbem_bookings_contact_email_cancelled_body', '' );
1863
+ ?>
1864
+ <tr class="em-subheader"><td colspan='2'>
1865
+ <h5><?php _e('Rejected booking email','dbem') ?></h5>
1866
+ <em><?php echo __( 'This will be sent to event admins when a booking is rejected.', 'dbem' ).$bookings_placeholder_tip ?></em>
1867
+ </td></tr>
1868
+ <?php
1869
+ em_options_input_text ( __( 'Booking rejected email subject', 'dbem' ), 'dbem_bookings_contact_email_rejected_subject', $email_subject_tip );
1870
+ em_options_textarea ( __( 'Booking rejected email', 'dbem' ), 'dbem_bookings_contact_email_rejected_body', '' );
1871
+ ?>
1872
+ </tbody>
1873
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Booked User Emails', 'dbem'); ?></h4></td></tr>
1874
+ <tbody class="em-subsection">
1875
+ <tr class="em-subheader"><td colspan='2'>
1876
+ <h5><?php _e('Confirmed booking email','dbem') ?></h5>
1877
+ <em><?php echo __('This is sent when a person\'s booking is confirmed. This will be sent automatically if approvals are required and the booking is approved. If approvals are disabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></em>
1878
+ </td></tr>
1879
+ <?php
1880
+ em_options_input_text ( __( 'Booking confirmed email subject', 'dbem' ), 'dbem_bookings_email_confirmed_subject', $email_subject_tip );
1881
+ em_options_textarea ( __( 'Booking confirmed email', 'dbem' ), 'dbem_bookings_email_confirmed_body', '' );
1882
+ ?>
1883
+ <tr class="em-subheader"><td colspan='2'>
1884
+ <h5><?php _e('Pending booking email','dbem') ?></h5>
1885
+ <em><?php echo __( 'This will be sent to the person when they first submit their booking. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></em>
1886
+ </td></tr>
1887
+ <?php
1888
+ em_options_input_text ( __( 'Booking pending email subject', 'dbem' ), 'dbem_bookings_email_pending_subject', $email_subject_tip);
1889
+ em_options_textarea ( __( 'Booking pending email', 'dbem' ), 'dbem_bookings_email_pending_body','') ;
1890
+ ?>
1891
+ <tr class="em-subheader"><td colspan='2'>
1892
+ <h5><?php _e('Rejected booking email','dbem') ?></h5>
1893
+ <em><?php echo __( 'This will be sent automatically when a booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></em>
1894
+ </td></tr>
1895
+ <?php
1896
+ em_options_input_text ( __( 'Booking rejected email subject', 'dbem' ), 'dbem_bookings_email_rejected_subject', $email_subject_tip );
1897
+ em_options_textarea ( __( 'Booking rejected email', 'dbem' ), 'dbem_bookings_email_rejected_body', '' );
1898
+ ?>
1899
+ <tr class="em-subheader"><td colspan='2'>
1900
+ <h5><?php _e('Booking cancelled','dbem') ?></h5>
1901
+ <em><?php echo __('This will be sent when a user cancels their booking.','dbem').$bookings_placeholder_tip ?></em>
1902
+ </td></tr>
1903
+ <?php
1904
+ em_options_input_text ( __( 'Booking cancelled email subject', 'dbem' ), 'dbem_bookings_email_cancelled_subject', $email_subject_tip );
1905
+ em_options_textarea ( __( 'Booking cancelled email', 'dbem' ), 'dbem_bookings_email_cancelled_body', '' );
1906
+ ?>
1907
+ </tbody>
1908
+ <?php do_action('em_options_page_booking_email_templates_options_bottom'); ?>
1909
+ <?php echo $save_button; ?>
1910
+ </table>
1911
+ </div> <!-- . inside -->
1912
+ </div> <!-- .postbox -->
1913
+ <?php endif; ?>
1914
+
1915
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
1916
+ <div class="postbox " id="em-opt-registration-emails">
1917
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Registration Email Templates', 'dbem' ); ?> </span></h3>
1918
+ <div class="inside">
1919
+ <p class="em-boxheader">
1920
+ <?php echo sprintf(__('This is only applicable when %s is not active.','dbem'), '<em>'.__('No-User Booking Mode','dbem').'</em>'); ?>
1921
+ <?php _e('When a guest user makes a booking for the first time in Events Manager, a new user account is created for them and they are sent their credentials in a seperate email, which can be modified below.','dbem'); ?>
1922
+ </p>
1923
+ <table class='form-table'>
1924
+ <?php
1925
+ em_options_radio_binary ( __( 'Disable new registration email?', 'dbem' ), '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.', 'dbem' ) );
1926
+
1927
+ em_options_input_text ( __( 'Registration email subject', 'dbem' ), 'dbem_bookings_email_registration_subject' );
1928
+ em_options_textarea ( __( 'Registration email', 'dbem' ), 'dbem_bookings_email_registration_body', sprintf(__('%s is replaced by username and %s is replaced by the user password.','dbem'),'<code>%username%</code>','<code>%password%</code>') );
1929
+ echo $save_button;
1930
+ ?>
1931
+ </table>
1932
+ </div> <!-- . inside -->
1933
+ </div> <!-- .postbox -->
1934
+ <?php endif; ?>
1935
+
1936
+ <div class="postbox " id="em-opt-event-submission-emails" >
1937
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Event Submission Templates', 'dbem' ); ?> </span></h3>
1938
+ <div class="inside">
1939
+ <table class='form-table'>
1940
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Event Admin Emails', 'dbem'); ?></h4></td></tr>
1941
+ <?php
1942
+ em_options_input_text ( __( 'Administrator Email', 'dbem' ), 'dbem_event_submitted_email_admin', __('Event submission notifications will be sent to emails added here.','dbem').' '.__('If left blank, no emails will be sent. Seperate emails with commas for more than one email.','dbem') );
1943
+ ?>
1944
+ <tbody class="em-subsection">
1945
+ <tr class="em-subheader"><td colspan='2'>
1946
+ <h5><?php _e('Event Submitted','dbem') ?></h5>
1947
+ <em><?php echo __('An email will be sent to your administrator emails when an event is submitted and pending approval.','dbem').$bookings_placeholder_tip ?></em>
1948
+ </td></tr>
1949
+ <?php
1950
+ em_options_input_text ( __( 'Event submitted subject', 'dbem' ), 'dbem_event_submitted_email_subject', __('If left blank, this email will not be sent.','dbem') );
1951
+ em_options_textarea ( __( 'Event submitted email', 'dbem' ), 'dbem_event_submitted_email_body', '' );
1952
+ ?>
1953
+ <tr class="em-subheader"><td colspan='2'>
1954
+ <h5><?php _e('Event Re-Submitted','dbem') ?></h5>
1955
+ <em><?php echo __('When a user modifies a previously published event, it will be put back into pending review status and will not be publisehd until you re-approve it.','dbem').$bookings_placeholder_tip ?></em>
1956
+ </td></tr>
1957
+ <?php
1958
+ em_options_input_text ( __( 'Event resubmitted subject', 'dbem' ), 'dbem_event_resubmitted_email_subject', __('If left blank, this email will not be sent.','dbem') );
1959
+ em_options_textarea ( __( 'Event resubmitted email', 'dbem' ), 'dbem_event_resubmitted_email_body', '' );
1960
+ ?>
1961
+ <tr class="em-subheader"><td colspan='2'>
1962
+ <h5><?php _e('Event Published','dbem') ?></h5>
1963
+ <em><?php echo __('An email will be sent to an administrator of your choice when an event is published by users who are not administrators.','dbem').$bookings_placeholder_tip ?>
1964
+ </td></tr>
1965
+ <?php
1966
+ em_options_input_text ( __( 'Event published subject', 'dbem' ), 'dbem_event_published_email_subject', __('If left blank, this email will not be sent.','dbem') );
1967
+ em_options_textarea ( __( 'Event published email', 'dbem' ), 'dbem_event_published_email_body', '' );
1968
+ ?>
1969
+ </tbody>
1970
+ <tr class="em-header"><td colspan='2'><h4><?php _e('Event Submitter Emails', 'dbem'); ?></h4></td></tr>
1971
+ <tbody class="em-subsection">
1972
+ <tr class="em-subheader"><td colspan='2'>
1973
+ <h5><?php _e('Event Approved','dbem') ?></h5>
1974
+ <em><?php echo __('An email will be sent to the event owner when their event is approved. Users requiring event approval do not have the <code>publish_events</code> capability.','dbem').$bookings_placeholder_tip ?>
1975
+ </td></tr>
1976
+ <?php
1977
+ em_options_input_text ( __( 'Event approved subject', 'dbem' ), 'dbem_event_approved_email_subject', __('If left blank, this email will not be sent.','dbem') );
1978
+ em_options_textarea ( __( 'Event approved email', 'dbem' ), 'dbem_event_approved_email_body', '' );
1979
+ ?>
1980
+ <tr class="em-subheader"><td colspan='2'>
1981
+ <h5><?php _e('Event Reapproved','dbem') ?></h5>
1982
+ <?php echo __('When a user modifies a previously published event, it will be put back into pending review status and will not be publisehd until you re-approve it.','dbem').$bookings_placeholder_tip ?>
1983
+ </td></tr>
1984
+ <?php
1985
+ em_options_input_text ( __( 'Event reapproved subject', 'dbem' ), 'dbem_event_reapproved_email_subject', __('If left blank, this email will not be sent.','dbem') );
1986
+ em_options_textarea ( __( 'Event reapproved email', 'dbem' ), 'dbem_event_reapproved_email_body', '' );
1987
+ ?>
1988
+ </tbody>
1989
+ <?php echo $save_button; ?>
1990
+ </table>
1991
+ </div> <!-- . inside -->
1992
+ </div> <!-- .postbox -->
1993
+
1994
+ <?php do_action('em_options_page_footer_emails'); ?>
1995
+
1996
+ </div><!-- .em-group-emails -->
1997
  <?php /*
1998
  <div class="postbox " >
1999
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Debug Modes', 'dbem' ); ?> </span></h3>
2000
  <div class="inside">
2001
  <table class='form-table'>
2002
  <?php
2007
  </div> <!-- . inside -->
2008
  </div> <!-- .postbox -->
2009
  */ ?>
 
 
2010
 
2011
  <p class="submit">
2012
+ <input type="submit" id="dbem_options_submit" class="button-primary" name="Submit" value="<?php esc_attr_e( 'Save Changes', 'dbem' ); ?>" />
2013
  <input type="hidden" name="em-submitted" value="1" />
2014
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('events-manager-options'); ?>" />
2015
  </p>
2016
 
2017
  </div> <!-- .metabox-sortables -->
2022
  </div>
2023
  <?php
2024
  }
2025
+
2026
+ /**
2027
+ * Meta options box for image sizes. Shared in both MS and Normal options page, hence it's own function
2028
+ */
2029
+ function em_admin_option_box_image_sizes(){
2030
+ global $save_button;
2031
+ ?>
2032
+ <div class="postbox " id="em-opt-image-sizes" >
2033
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Image Sizes', 'dbem' ); ?> </span></h3>
2034
+ <div class="inside">
2035
+ <p class="em-boxheader"><?php _e('These settings will only apply to the image uploading if using our front-end forms. In your WP admin area, images are handled by WordPress.','dbem'); ?></p>
2036
+ <table class='form-table'>
2037
+ <?php
2038
+ em_options_input_text ( __( 'Maximum width (px)', 'dbem' ), 'dbem_image_max_width', __( 'The maximum allowed width for images uploads', 'dbem' ) );
2039
+ em_options_input_text ( __( 'Minimum width (px)', 'dbem' ), 'dbem_image_min_width', __( 'The minimum allowed width for images uploads', 'dbem' ) );
2040
+ em_options_input_text ( __( 'Maximum height (px)', 'dbem' ), 'dbem_image_max_height', __( "The maximum allowed height for images uploaded, in pixels", 'dbem' ) );
2041
+ em_options_input_text ( __( 'Minimum height (px)', 'dbem' ), 'dbem_image_min_height', __( "The minimum allowed height for images uploaded, in pixels", 'dbem' ) );
2042
+ em_options_input_text ( __( 'Maximum size (bytes)', 'dbem' ), 'dbem_image_max_size', __( "The maximum allowed size for images uploaded, in bytes", 'dbem' ) );
2043
+ echo $save_button;
2044
+ ?>
2045
+ </table>
2046
+ </div> <!-- . inside -->
2047
+ </div> <!-- .postbox -->
2048
+ <?php
2049
+ }
2050
+
2051
+ /**
2052
+ * Meta options box for email settings. Shared in both MS and Normal options page, hence it's own function
2053
+ */
2054
+ function em_admin_option_box_email(){
2055
+ global $save_button;
2056
+ $current_user = get_user_by('id', get_current_user_id());
2057
+ ?>
2058
+ <div class="postbox " id="em-opt-email-settings">
2059
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Email Settings', 'dbem' ); ?></span></h3>
2060
+ <div class="inside em-email-form">
2061
+ <p class="em-email-settings-check em-boxheader">
2062
+ <em><?php _e('Before you save your changes, you can quickly send yourself a test email by clicking this button.','dbem'); ?>
2063
+ <?php echo sprintf(__('A test email will be sent to your account email - %s','dbem'), $current_user->user_email . ' <a href="'.admin_url( 'profile.php' ).'">'.__('edit','dbem').'</a>'); ?></em><br />
2064
+ <input type="button" id="em-admin-check-email" class="secondary-button" value="<?php esc_attr_e('Test Email Settings','dbem'); ?>" />
2065
+ <input type="hidden" name="_check_email_nonce" value="<?php echo wp_create_nonce('check_email'); ?>" />
2066
+ <span id="em-email-settings-check-status"></span>
2067
+ </p>
2068
+ <table class="form-table">
2069
+ <?php
2070
+ em_options_input_text ( __( 'Notification sender name', 'dbem' ), 'dbem_mail_sender_name', __( "Insert the display name of the notification sender.", 'dbem' ) );
2071
+ em_options_input_text ( __( 'Notification sender address', 'dbem' ), 'dbem_mail_sender_address', __( "Insert the address of the notification sender.", 'dbem' ) );
2072
+ em_options_select ( __( 'Mail sending method', 'dbem' ), 'dbem_rsvp_mail_send_method', array ('smtp' => 'SMTP', 'mail' => __( 'PHP mail function', 'dbem' ), 'sendmail' => 'Sendmail', 'qmail' => 'Qmail', 'wp_mail' => 'WP Mail' ), __( 'Select the method to send email notification.', 'dbem' ) );
2073
+ em_options_radio_binary ( __( 'Send HTML Emails?', 'dbem' ), 'dbem_smtp_html', __( 'If set to yes, your emails will be sent in HTML format, otherwise plaintext.', 'dbem' ).' '.__( 'Depending on server settings, some sending methods may ignore this settings.', 'dbem' ) );
2074
+ em_options_radio_binary ( __( 'Add br tags to HTML emails?', 'dbem' ), 'dbem_smtp_html_br', __( 'If HTML emails are enabled, br tags will automatically be added for new lines.', 'dbem' ) );
2075
+ ?>
2076
+ <tbody class="em-email-settings-smtp">
2077
+ <?php
2078
+ em_options_input_text ( 'Mail sending port', 'dbem_rsvp_mail_port', __( "The port through which you e-mail notifications will be sent. Make sure the firewall doesn't block this port", 'dbem' ) );
2079
+ em_options_radio_binary ( __( 'Use SMTP authentication?', 'dbem' ), 'dbem_rsvp_mail_SMTPAuth', __( 'SMTP authentication is often needed. If you use GMail, make sure to set this parameter to Yes', 'dbem' ) );
2080
+ em_options_input_text ( 'SMTP host', 'dbem_smtp_host', __( "The SMTP host. Usually it corresponds to 'localhost'. If you use GMail, set this value to 'ssl://smtp.gmail.com:465'.", 'dbem' ) );
2081
+ em_options_input_text ( __( 'SMTP username', 'dbem' ), 'dbem_smtp_username', __( "Insert the username to be used to access your SMTP server.", 'dbem' ) );
2082
+ em_options_input_password ( __( 'SMTP password', 'dbem' ), "dbem_smtp_password", __( "Insert the password to be used to access your SMTP server", 'dbem' ) );
2083
+ ?>
2084
+ </tbody>
2085
+ <?php
2086
+ echo $save_button;
2087
+ ?>
2088
+ </table>
2089
+ <script type="text/javascript" charset="utf-8">
2090
+ jQuery(document).ready(function($){
2091
+ $('#dbem_rsvp_mail_send_method_row select').change(function(){
2092
+ el = $(this);
2093
+ if( el.find(':selected').val() == 'smtp' ){
2094
+ $('.em-email-settings-smtp').show();
2095
+ }else{
2096
+ $('.em-email-settings-smtp').hide();
2097
+ }
2098
+ }).trigger('change');
2099
+ $('input#em-admin-check-email').click(function(e,el){
2100
+ var email_data = $('.em-email-form input, .em-email-form select').serialize();
2101
+ $.ajax({
2102
+ url: EM.ajaxurl,
2103
+ dataType: 'json',
2104
+ data: email_data+"&action=em_admin_test_email",
2105
+ success: function(data){
2106
+ if(data.result && data.message){
2107
+ $('#em-email-settings-check-status').css({'color':'green','display':'block'}).html(data.message);
2108
+ }else{
2109
+ var msg = (data.message) ? data.message:'Email not sent';
2110
+ $('#em-email-settings-check-status').css({'color':'red','display':'block'}).html(msg);
2111
+ }
2112
+ },
2113
+ error: function(){ $('#em-email-settings-check-status').css({'color':'red','display':'block'}).html('Server Error'); },
2114
+ beforeSend: function(){ $('input#em-admin-check-email').val('<?php _e('Checking...','dbem') ?>'); },
2115
+ complete: function(){ $('input#em-admin-check-email').val('<?php _e('Test Email Settings','dbem'); ?>'); }
2116
+ });
2117
+ });
2118
+ });
2119
+ </script>
2120
+ </div> <!-- . inside -->
2121
+ </div> <!-- .postbox -->
2122
+ <?php
2123
+ }
2124
+
2125
+ /**
2126
+ * Meta options box for user capabilities. Shared in both MS and Normal options page, hence it's own function
2127
+ */
2128
+ function em_admin_option_box_caps(){
2129
+ global $save_button, $wpdb;
2130
+ ?>
2131
+ <div class="postbox" id="em-opt-user-caps" >
2132
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'User Capabilities', 'dbem' ); ?></span></h3>
2133
+ <div class="inside">
2134
+ <table class="form-table">
2135
+ <tr><td colspan="2" class="em-boxheader">
2136
+ <p><strong><?php _e('Warning: Changing these values may result in exposing previously hidden information to all users.', 'dbem')?></strong></p>
2137
+ <p><em><?php _e('You can now give fine grained control with regards to what your users can do with events. Each user role can have perform different sets of actions.','dbem'); ?></em></p>
2138
+ </td></tr>
2139
+ <?php
2140
+ global $wp_roles;
2141
+ $cap_docs = array(
2142
+ sprintf(__('%s Capabilities','dbem'),__('Event','dbem')) => array(
2143
+ /* Event Capabilities */
2144
+ 'publish_events' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('events','dbem')),
2145
+ 'delete_others_events' => sprintf(__('User can delete other users %s','dbem'),__('events','dbem')),
2146
+ 'edit_others_events' => sprintf(__('User can edit other users %s','dbem'),__('events','dbem')),
2147
+ 'delete_events' => sprintf(__('User can delete their own %s','dbem'),__('events','dbem')),
2148
+ 'edit_events' => sprintf(__('User can create and edit %s','dbem'),__('events','dbem')),
2149
+ 'read_private_events' => sprintf(__('User can view private %s','dbem'),__('events','dbem')),
2150
+ /*'read_events' => sprintf(__('User can view %s','dbem'),__('events','dbem')),*/
2151
+ ),
2152
+ sprintf(__('%s Capabilities','dbem'),__('Recurring Event','dbem')) => array(
2153
+ /* Recurring Event Capabilties */
2154
+ 'publish_recurring_events' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('recurring events','dbem')),
2155
+ 'delete_others_recurring_events' => sprintf(__('User can delete other users %s','dbem'),__('recurring events','dbem')),
2156
+ 'edit_others_recurring_events' => sprintf(__('User can edit other users %s','dbem'),__('recurring events','dbem')),
2157
+ 'delete_recurring_events' => sprintf(__('User can delete their own %s','dbem'),__('recurring events','dbem')),
2158
+ 'edit_recurring_events' => sprintf(__('User can create and edit %s','dbem'),__('recurring events','dbem'))
2159
+ ),
2160
+ sprintf(__('%s Capabilities','dbem'),__('Location','dbem')) => array(
2161
+ /* Location Capabilities */
2162
+ 'publish_locations' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('locations','dbem')),
2163
+ 'delete_others_locations' => sprintf(__('User can delete other users %s','dbem'),__('locations','dbem')),
2164
+ 'edit_others_locations' => sprintf(__('User can edit other users %s','dbem'),__('locations','dbem')),
2165
+ 'delete_locations' => sprintf(__('User can delete their own %s','dbem'),__('locations','dbem')),
2166
+ 'edit_locations' => sprintf(__('User can create and edit %s','dbem'),__('locations','dbem')),
2167
+ 'read_private_locations' => sprintf(__('User can view private %s','dbem'),__('locations','dbem')),
2168
+ 'read_others_locations' => __('User can use other user locations for their events.','dbem'),
2169
+ /*'read_locations' => sprintf(__('User can view %s','dbem'),__('locations','dbem')),*/
2170
+ ),
2171
+ sprintf(__('%s Capabilities','dbem'),__('Other','dbem')) => array(
2172
+ /* Category Capabilities */
2173
+ 'delete_event_categories' => sprintf(__('User can delete %s categories and tags.','dbem'),__('event','dbem')),
2174
+ 'edit_event_categories' => sprintf(__('User can edit %s categories and tags.','dbem'),__('event','dbem')),
2175
+ /* Booking Capabilities */
2176
+ 'manage_others_bookings' => __('User can manage other users individual bookings and event booking settings.','dbem'),
2177
+ 'manage_bookings' => __('User can use and manage bookings with their events.','dbem'),
2178
+ 'upload_event_images' => __('User can upload images along with their events and locations.','dbem')
2179
+ )
2180
+ );
2181
+ ?>
2182
+ <?php
2183
+ if( is_multisite() && is_network_admin() ){
2184
+ echo em_options_radio_binary(__('Apply global capabilities?','dbem'), 'dbem_ms_global_caps', __('If set to yes the capabilities will be applied all your network blogs and you will not be able to set custom capabilities each blog. You can select no later and visit specific blog settings pages to add/remove capabilities.','dbem') );
2185
+ }
2186
+ ?>
2187
+ <tr><td colspan="2">
2188
+ <table class="em-caps-table" style="width:auto;" cellspacing="0" cellpadding="0">
2189
+ <thead>
2190
+ <tr>
2191
+ <td>&nbsp;</td>
2192
+ <?php
2193
+ $odd = 0;
2194
+ foreach(array_keys($cap_docs) as $capability_group){
2195
+ ?><th class="<?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>"><?php echo $capability_group ?></th><?php
2196
+ $odd++;
2197
+ }
2198
+ ?>
2199
+ </tr>
2200
+ </thead>
2201
+ <tbody>
2202
+ <?php foreach($wp_roles->role_objects as $role): ?>
2203
+ <tr>
2204
+ <td class="cap"><strong><?php echo $role->name; ?></strong></td>
2205
+ <?php
2206
+ $odd = 0;
2207
+ foreach($cap_docs as $capability_group){
2208
+ ?>
2209
+ <td class="<?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>">
2210
+ <?php foreach($capability_group as $cap => $cap_help){ ?>
2211
+ <input type="checkbox" name="em_capabilities[<?php echo $role->name; ?>][<?php echo $cap ?>]" value="1" id="<?php echo $role->name.'_'.$cap; ?>" <?php echo $role->has_cap($cap) ? 'checked="checked"':''; ?> />
2212
+ &nbsp;<label for="<?php echo $role->name.'_'.$cap; ?>"><?php echo $cap; ?></label>&nbsp;<a href="#" title="<?php echo $cap_help; ?>">?</a>
2213
+ <br />
2214
+ <?php } ?>
2215
+ </td>
2216
+ <?php
2217
+ $odd++;
2218
+ }
2219
+ ?>
2220
+ </tr>
2221
+ <?php endforeach; ?>
2222
+ </tbody>
2223
+ </table>
2224
+ </td></tr>
2225
+ <?php echo $save_button; ?>
2226
+ </table>
2227
+ </div> <!-- . inside -->
2228
+ </div> <!-- .postbox -->
2229
+ <?php
2230
+ }
2231
+
2232
+ function em_admin_option_box_uninstall(){
2233
+ global $save_button;
2234
+ if( is_multisite() ){
2235
+ $uninstall_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
2236
+ $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');
2237
+ $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');
2238
+ $check_devs = admin_url().'network/admin.php?page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
2239
+ }else{
2240
+ $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');
2241
+ $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');
2242
+ $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');
2243
+ $check_devs = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=check_devs&amp;_wpnonce='.wp_create_nonce('em_check_devs_wpnonce');
2244
+ }
2245
+ ?>
2246
+ <div class="postbox" id="em-opt-admin-tools" >
2247
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Admin Tools', 'dbem' ); ?> (<?php _e ( 'Advanced', 'dbem' ); ?>)</span></h3>
2248
+ <div class="inside">
2249
+ <table class="form-table">
2250
+ <tr class="em-header"><td colspan="2">
2251
+ <h4><?php _e ( 'Development Versions &amp; Updates', 'dbem' ); ?></h4>
2252
+ <p><?php _e('We\'re always making improvements, adding features and fixing bugs between releases. We incrementally make these changes in between updates and make it available as a development version. You can download these manually, but we\'ve made it easy for you. <strong>Warning:</strong> Development versions are not always fully tested before release, use wisely!','dbem'); ?></p>
2253
+ </td></tr>
2254
+ <?php em_options_radio_binary ( __( 'Enable Dev Updates?', 'dbem' ), 'dbem_pro_dev_updates', __('If enabled, the latest dev version will always be checked instead of the latest stable version of the plugin.', 'dbem') ); ?>
2255
+ <tr>
2256
+ <th style="text-align:right;"><a href="<?php echo $recheck_updates_url; ?>" class="button-secondary"><?php _e('Re-Check Updates','dbem'); ?></a></th>
2257
+ <td><?php _e('If you would like to check and see if there is a new stable update.','dbem'); ?></td>
2258
+ </tr>
2259
+ <tr>
2260
+ <th style="text-align:right;"><a href="<?php echo $check_devs; ?>" class="button-secondary"><?php _e('Check Dev Versions','dbem'); ?></a></th>
2261
+ <td><?php _e('If you would like to download a dev version, but just as a one-off, you can force a dev version check by clicking the button below. If there is one available, it should appear in your plugin updates page as a regular update.','dbem'); ?></td>
2262
+ </tr>
2263
+ </table>
2264
+
2265
+ <table class="form-table">
2266
+ <tr class="em-header"><td colspan="2">
2267
+ <h4><?php _e ( 'Uninstall/Reset', 'dbem' ); ?></h4>
2268
+ <p><?php _e('Use the buttons below to uninstall Events Manager completely from your system or reset Events Manager to original settings and keep your event data.','dbem'); ?></p>
2269
+ </td></tr>
2270
+ <tr><td colspan="2">
2271
+ <a href="<?php echo $uninstall_url; ?>" class="button-secondary"><?php _e('Uninstall','dbem'); ?></a>
2272
+ <a href="<?php echo $reset_url; ?>" class="button-secondary"><?php _e('Reset','dbem'); ?></a>
2273
+ </td></tr>
2274
+ </table>
2275
+ <?php do_action('em_options_page_panel_admin_tools'); ?>
2276
+ <?php echo $save_button; ?>
2277
+ </div>
2278
+ </div>
2279
+ <?php
2280
+ }
2281
  ?>
admin/em-people.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
-
3
- function em_printable_booking_report() {
4
- global $EM_Event;
5
- //check that user can access this page
6
- if( isset($_GET['page']) && $_GET['page']=='events-manager-bookings' && isset($_GET['action']) && $_GET['action'] == 'bookings_report' && is_object($EM_Event)){
7
- if( is_object($EM_Event) && !$EM_Event->can_manage('edit_events','edit_others_events') ){
8
- ?>
9
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
10
- <?php
11
- return false;
12
- }
13
- ?>
14
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
15
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
16
- <html>
17
- <head>
18
- <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
19
- <title>Bookings for <?php echo $EM_Event->name; ?></title>
20
- <link rel="stylesheet" href="<?php echo bloginfo('wpurl') ?>/wp-content/plugins/events-manager/includes/css/events_manager.css" type="text/css" media="screen" />
21
- </head>
22
- <body id="printable">
23
- <div id="container">
24
- <h1>Bookings for <?php echo $EM_Event->name; ?></h1>
25
- <p><?php echo $EM_Event->output("#d #M #Y"); ?></p>
26
- <p><?php echo $EM_Event->output("#_LOCATION, #_ADDRESS, #_TOWN"); ?></p>
27
- <h2><?php _e('Bookings data', 'dbem');?></h2>
28
- <table id="bookings-table">
29
- <tr>
30
- <th scope='col'><?php _e('Name', 'dbem')?></th>
31
- <th scope='col'><?php _e('E-mail', 'dbem')?></th>
32
- <th scope='col'><?php _e('Phone number', 'dbem')?></th>
33
- <th scope='col'><?php _e('Spaces', 'dbem')?></th>
34
- <th scope='col'><?php _e('Comment', 'dbem')?></th>
35
- </tr>
36
- <?php foreach($EM_Event->get_bookings()->bookings as $EM_Booking) { ?>
37
- <tr>
38
-
39
- <td><?php echo $EM_Booking->person->display_name ?></td>
40
- <td><?php echo $EM_Booking->person->user_email ?></td>
41
- <td><?php echo $EM_Booking->person->phone ?></td>
42
- <td class='spaces-number'><?php echo $EM_Booking->get_spaces() ?></td>
43
- <td><?php echo $EM_Booking->comment ?></td>
44
- </tr>
45
- <?php } ?>
46
- <tr id='booked-spaces'>
47
- <td colspan='3'>&nbsp;</td>
48
- <td class='total-label'><?php _e('Booked', 'dbem')?>:</td>
49
- <td class='spaces-number'><?php echo $EM_Event->get_bookings()->get_booked_spaces(); ?></td>
50
- </tr>
51
- <tr id='available-spaces'>
52
- <td colspan='3'>&nbsp;</td>
53
- <td class='total-label'><?php _e('Available', 'dbem')?>:</td>
54
- <td class='spaces-number'><?php echo $EM_Event->get_bookings()->get_available_spaces(); ?></td>
55
- </tr>
56
- </table>
57
- </div>
58
- </body>
59
- </html>
60
- <?php
61
- die();
62
- }
63
- }
64
- add_action('admin_init', 'em_printable_booking_report');
65
-
66
- /**
67
- * Adds phone number to contact info of users, compatible with previous phone field method
68
- * @param $array
69
- * @return array
70
- */
71
- function em_contact_methods($array){
72
- $array['dbem_phone'] = __('Phone','dbem') . ' <span class="description">('. __('Events Manager','dbem') .')</span>';
73
- return $array;
74
- }
75
- add_filter( 'user_contactmethods' , 'em_contact_methods' , 10 , 1 );
76
-
77
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/wpfc-admin.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adds a note to the event post type in the admin area, so it's obvious EM is interfering.
4
+ */
5
+ function wpfc_admin_options_post_type_event(){
6
+ echo " - <i>powered by Events Manager</i>";
7
+ }
8
+ add_action('wpfc_admin_options_post_type_event','wpfc_admin_options_post_type_event');
9
+
10
+ function wpfc_em_admin_notice(){
11
+ if( !empty($_REQUEST['page']) && $_REQUEST['page'] == 'wp-fullcalendar'){
12
+ ?>
13
+ <div class="updated"><p><?php echo sprintf(__('If you choose the Event post type whilst Events Manager is activated, you can also visit the <a href="%s">Events Manager settings page</a> for a few more options when displaying event information on your calendar.','dbem'), admin_url('edit.php?post_type='.EM_POST_TYPE_EVENT.'&page=events-manager-options')); ?></p></div>
14
+ <?php
15
+ }
16
+ }
17
+ add_action('admin_notices', 'wpfc_em_admin_notice');
18
+
19
+ function wpfc_em_admin_options(){
20
+ ?>
21
+ <div class="postbox " >
22
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Full Calendar Options', 'dbem' ); ?> </span></h3>
23
+ <div class="inside">
24
+ <p class="em-boxheader"><?php echo sprintf(__('Looking for the rest of the FullCalendar Options? They\'ve moved <a href="%s">here</a>, the options below are for overriding specific bits relevant to Events Manager.','dbem'), admin_url('options-general.php?page=wp-fullcalendar')); ?></p>
25
+ <table class='form-table'>
26
+ <?php
27
+ global $events_placeholder_tip, $save_button;
28
+ em_options_radio_binary ( __( 'Override calendar on events page?', 'dbem' ), 'dbem_emfc_override_calendar', __( 'If set to yes, the FullCalendar will be used instead of the standard calendar on the events page.', 'dbem' ) );
29
+ em_options_radio_binary ( __( 'Override calendar shortcode?', 'dbem' ), 'dbem_emfc_override_shortcode', __( 'Overrides the default calendar shortcode. You can also use [events_fullcalendar] instead.','dbem' ) );
30
+ em_options_input_text ( __( 'Event title format', 'dbem' ), 'dbem_emfc_full_calendar_event_format', __('HTML is not accepted.','dbem').' '.$events_placeholder_tip, '#_EVENTNAME' );
31
+ em_options_textarea( __( 'Event tooltips format', 'dbem' ), 'dbem_emfc_qtips_format', __('If you enable tips, this information will be shown, which can include HTML.','dbem').' '.$events_placeholder_tip, '#_EVENTNAME' );$positions_options = array();
32
+ ?>
33
+ </table>
34
+ <?php echo $save_button; ?>
35
+ </div> <!-- . inside -->
36
+ </div> <!-- .postbox -->
37
+ <?php
38
+ }
39
+ add_action('em_options_page_footer', 'wpfc_em_admin_options');
40
+
41
+ function wpfc_em_install(){
42
+ //check for updates - try adding one option, if it works then it's a first time install so add more
43
+ if( current_user_can('list_users') && add_option('dbem_emfc_full_calendar_event_format','#_EVENTTIMES - #_EVENTNAME') ){
44
+ add_option('dbem_emfc_qtips_format', '{has_image}<div style="float:left; margin:0px 5px 5px 0px;">#_EVENTIMAGE{75,75}</div>{/has_image}#_EVENTEXCERPT');
45
+ }
46
+ }
47
+ add_action('init', 'wpfc_em_install');
buddypress/bp-em-activity.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
 
 
2
  /**
3
  * bp_em_record_activity()
4
  *
5
  * If the activity stream component is installed, this function will record activity items for your
6
  * component.
7
- *
8
- * You must pass the function an associated array of arguments:
9
- *
10
- * $args = array(
11
- * REQUIRED PARAMS
12
- * 'action' => For em: "Andy high-fived John", "Andy posted a new update".
13
- * 'type' => The type of action being carried out, for em 'new_friendship', 'joined_group'. This should be unique within your component.
14
- *
15
- * OPTIONAL PARAMS
16
- * 'id' => The ID of an existing activity item that you want to update.
17
- * 'content' => The content of your activity, if it has any, for em a photo, update content or blog post excerpt.
18
- * 'component' => The slug of the component.
19
- * 'primary_link' => The link for the title of the item when appearing in RSS feeds (defaults to the activity permalink)
20
- * 'item_id' => The ID of the main piece of data being recorded, for em a group_id, user_id, forum_post_id - useful for filtering and deleting later on.
21
- * 'user_id' => The ID of the user that this activity is being recorded for. Pass false if it's not for a user.
22
- * 'recorded_time' => (optional) The time you want to set as when the activity was carried out (defaults to now)
23
- * 'hide_sitewide' => Should this activity item appear on the site wide stream?
24
- * 'secondary_item_id' => (optional) If the activity is more complex you may need a second ID. For em a group forum post may need the group_id AND the forum_post_id.
25
- * )
26
- *
27
- * Events usage would be:
28
- *
29
- * bp_em_record_activity( array( 'type' => 'new_highfive', 'action' => 'Andy high-fived John', 'user_id' => $bp->loggedin_user->id, 'item_id' => $bp->displayed_user->id ) );
30
- *
31
  */
32
  function bp_em_record_activity( $args = '' ) {
33
  if ( !function_exists( 'bp_activity_add' ) )
@@ -49,10 +27,96 @@ function bp_em_record_activity( $args = '' ) {
49
 
50
  $r = wp_parse_args( $args, $defaults );
51
  extract( $r );
52
-
53
  return bp_activity_add( array( 'id' => $id, 'user_id' => $user_id, 'action' => $action, 'content' => $content, 'primary_link' => $primary_link, 'component' => $component, 'type' => $type, 'item_id' => $item_id, 'secondary_item_id' => $secondary_item_id, 'recorded_time' => $recorded_time, 'hide_sitewide' => $hide_sitewide ) );
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  /**
57
  * Records new events to the activity stream.
58
  * @param unknown_type $result
@@ -60,15 +124,30 @@ function bp_em_record_activity( $args = '' ) {
60
  * @return unknown
61
  */
62
  function bp_em_record_activity_event_save( $result, $EM_Event ){
63
- if( $result && $EM_Event->status == 1 && ($EM_Event->previous_status == 0 || !empty($EM_Event->is_new)) ){
64
- $user = get_userdata($EM_Event->owner);
65
- bp_em_record_activity( array(
66
- 'user_id' => $user->ID,
67
- 'action' => sprintf(__('%s added a the event %s','dbem'), "<a href='".get_bloginfo('wpurl').'/'.BP_MEMBERS_SLUG.'/'.$user->user_login."/'>".$user->display_name."</a>", $EM_Event->output('#_EVENTLINK') ),
68
- 'primary_link' => $EM_Event->output('#_EVENTURL'),
69
- 'type' => 'new_event',
70
- 'item_id' => $EM_Event->id,
71
- ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
  return $result;
74
  }
@@ -80,28 +159,60 @@ add_filter('em_event_save','bp_em_record_activity_event_save', 10, 2);
80
  * @return boolean
81
  */
82
  function bp_em_record_activity_booking_save( $result, $EM_Booking ){
83
- if( $result ){
84
- $user = $EM_Booking->person;
85
- $user_link = "<a href='".get_bloginfo('wpurl').'/'.BP_MEMBERS_SLUG.'/'.$user->user_login."/'>".$user->display_name."</a>";
 
 
86
  $event_link = $EM_Booking->get_event()->output('#_EVENTLINK');
87
- $status = $EM_Booking->status;
88
- if( $status == 1 || (!get_option('dbem_bookings_approval') && $status < 2) ){
89
- $action = sprintf(__('%s is attending %s.','dbem'), $user_link, $event_link );
90
- }elseif( ($EM_Booking->previous_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->previous_status < 2)) && ($status > 1 || empty($status) || (!get_option('dbem_bookings_approval') && $status != 1)) ){
91
- $action = sprintf(__('%s will not be attending %s anymore.','dbem'), $user_link, $event_link );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
  if( !empty($action) ){
94
- bp_em_record_activity( array(
95
- 'user_id' => $EM_Booking->person->ID,
96
- 'action' => $action,
97
- 'primary_link' => $EM_Booking->get_event()->output('#_EVENTURL'),
98
- 'type' => 'new_booking',
99
- 'item_id' => $EM_Event->id,
100
- 'secondary_item_id' => $EM_Booking->id
101
- ));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  }
103
  }
104
  return $result;
105
  }
106
- add_filter('em_booking_save','bp_em_record_activity_booking_save', 10, 2);
107
- add_filter('em_booking_delete','bp_em_record_activity_booking_save', 10, 2);
 
1
  <?php
2
+ // This file handles hooks/filter requiring activity stream publications
3
+
4
  /**
5
  * bp_em_record_activity()
6
  *
7
  * If the activity stream component is installed, this function will record activity items for your
8
  * component.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  */
10
  function bp_em_record_activity( $args = '' ) {
11
  if ( !function_exists( 'bp_activity_add' ) )
27
 
28
  $r = wp_parse_args( $args, $defaults );
29
  extract( $r );
 
30
  return bp_activity_add( array( 'id' => $id, 'user_id' => $user_id, 'action' => $action, 'content' => $content, 'primary_link' => $primary_link, 'component' => $component, 'type' => $type, 'item_id' => $item_id, 'secondary_item_id' => $secondary_item_id, 'recorded_time' => $recorded_time, 'hide_sitewide' => $hide_sitewide ) );
31
  }
32
 
33
+ function em_bp_register_activity_actions() {
34
+
35
+ if ( !bp_is_active( 'events' ) ) {
36
+ return false;
37
+ }
38
+
39
+ $bp = buddypress();
40
+
41
+ // @todo - Figure out why adding a second bp_activity_set_action creates two 'Bookings' actions in backend and different booking status front-end e.g. when friendships created/accepted do not
42
+ bp_activity_set_action(
43
+ $bp->events->id,
44
+ 'new_booking',
45
+ __( 'Bookings', 'dbem' ),
46
+ 'em_bp_events_format_activity_action_bookings',
47
+ __( 'Bookings', 'dbem' ),
48
+ array( 'activity', 'member' )
49
+ );
50
+ /*
51
+ bp_activity_set_action(
52
+ $bp->events->id,
53
+ 'booking_cancelled',
54
+ __( 'Booking Cancelled', 'dbem' ),
55
+ 'em_bp_events_format_activity_action_bookings',
56
+ __( 'Bookings', 'dbem' ),
57
+ array( 'activity', 'member' )
58
+ );
59
+ */
60
+
61
+ bp_activity_set_action(
62
+ $bp->events->id,
63
+ 'new_event',
64
+ __('New Event','dbem'),
65
+ 'em_bp_events_format_activity_action_events',
66
+ __( 'Events', 'dbem' ),
67
+ array( 'activity', 'member' )
68
+ );
69
+ }
70
+ add_action( 'bp_register_activity_actions', 'em_bp_register_activity_actions' );
71
+
72
+ /**
73
+ * Not yet used fully - formats booking-related actions
74
+ * @param string $action
75
+ * @param object $activity
76
+ * @return string
77
+ */
78
+ function em_bp_events_format_activity_action_bookings( $action, $activity ) {
79
+ return '';
80
+ $member_link = bp_core_get_userlink( $activity->user_id );
81
+ $EM_Booking = em_get_booking( $activity->item );
82
+
83
+ $action = '';
84
+ switch ($activity->type){
85
+ case 'new_booking':
86
+ if( $activity->component == 'groups' ){
87
+ $action = sprintf(__('%s is attending %s of the group %s.','dbem'), $member_link, $event_link, $group_link );
88
+ }else{
89
+ $action = sprintf(__('%s is attending %s.','dbem'), $member_link, $event_link );
90
+ }
91
+ break;
92
+ case 'cancelled_booking':
93
+ if( $activity->component == 'groups' ){
94
+ $action = sprintf(__('%s will not be attending %s of group %s anymore.','dbem'), $user_link, $event_link, $group_link );
95
+ }else{
96
+ $action = sprintf(__('%s will not be attending %s anymore.','dbem'), $user_link, $event_link );
97
+ }
98
+ break;
99
+ }
100
+
101
+ return apply_filters( 'bp_events_format_activity_action_bookings', $action, $activity );
102
+ }
103
+
104
+ /**
105
+ * Not yet used fully - formats event-related actions
106
+ * @param string $action
107
+ * @param object $activity
108
+ * @return string
109
+ */
110
+ function em_bp_events_format_activity_action_events( $action, $activity ) {
111
+ return '';
112
+ $member_link = bp_core_get_userlink( $activity->user_id );
113
+ $EM_Event = em_get_event( $activity->item_id );
114
+
115
+ $action = sprintf(__('%s added the event %s','dbem'), $member_link, $EM_Event->output('#_EVENTLINK') );
116
+
117
+ return apply_filters( 'bp_events_format_activity_action_events', $action, $activity );
118
+ }
119
+
120
  /**
121
  * Records new events to the activity stream.
122
  * @param unknown_type $result
124
  * @return unknown
125
  */
126
  function bp_em_record_activity_event_save( $result, $EM_Event ){
127
+ if( $result && $EM_Event->event_status == 1 && $EM_Event->get_previous_status() != 1 ){
128
+ $user = get_userdata($EM_Event->event_owner);
129
+ $member_link = bp_core_get_user_domain($user->ID);
130
+ if( empty($EM_Event->group_id) ){
131
+ bp_em_record_activity( array(
132
+ 'user_id' => $user->ID,
133
+ 'action' => sprintf(__('%s added the event %s','dbem'), "<a href='".$member_link."'>".$user->display_name."</a>", $EM_Event->output('#_EVENTLINK') ),
134
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
135
+ 'type' => 'new_event',
136
+ 'item_id' => $EM_Event->event_id,
137
+ 'hide_sitewide' => $EM_Event->event_private
138
+ ));
139
+ }else{
140
+ //tis a group event
141
+ $group = new BP_Groups_Group($EM_Event->group_id);
142
+ bp_em_record_activity( array(
143
+ 'user_id' => $user->ID,
144
+ 'action' => sprintf(__('%s added the event %s to %s.','dbem'), "<a href='".$member_link."'>".$user->display_name."</a>", $EM_Event->output('#_EVENTLINK'), '<a href="'.bp_get_group_permalink($group).'">'.bp_get_group_name($group).'</a>' ),
145
+ 'component' => 'groups',
146
+ 'type' => 'new_event',
147
+ 'item_id' => $EM_Event->group_id,
148
+ 'hide_sitewide' => $EM_Event->event_private
149
+ ));
150
+ }
151
  }
152
  return $result;
153
  }
159
  * @return boolean
160
  */
161
  function bp_em_record_activity_booking_save( $result, $EM_Booking ){
162
+ if( !empty($EM_Booking->event_id) && $result ){
163
+ $rejected_statuses = array(0,2,3); //these statuses apply to rejected/cancelled bookings
164
+ $user = $EM_Booking->get_person();
165
+ $member_link = bp_core_get_user_domain($user->ID);
166
+ $user_link = "<a href='".$member_link."/'>".$user->display_name."</a>";
167
  $event_link = $EM_Booking->get_event()->output('#_EVENTLINK');
168
+ $status = $EM_Booking->booking_status;
169
+ $EM_Event = $EM_Booking->get_event();
170
+ $action_type = 'new_booking';
171
+ if( empty($EM_Event->group_id) ){
172
+ if( $status == 1 || (!get_option('dbem_bookings_approval') && $status < 2) ){
173
+ $action = sprintf(__('%s is attending %s.','dbem'), $user_link, $event_link );
174
+ }elseif( ($EM_Booking->previous_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->previous_status < 2)) && in_array($status, $rejected_statuses) ){
175
+ $action = sprintf(__('%s will not be attending %s anymore.','dbem'), $user_link, $event_link );
176
+ //$action_type = 'cancelled_booking';
177
+ }
178
+ }else{
179
+ $group = new BP_Groups_Group($EM_Event->group_id);
180
+ $group_link = '<a href="'.bp_get_group_permalink($group).'">'.bp_get_group_name($group).'</a>';
181
+ if( $status == 1 || (!get_option('dbem_bookings_approval') && $status < 2) ){
182
+ $action = sprintf(__('%s is attending %s of the group %s.','dbem'), $user_link, $event_link, $group_link );
183
+ }elseif( ($EM_Booking->previous_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->previous_status < 2)) && in_array($status, $rejected_statuses) ){
184
+ $action = sprintf(__('%s will not be attending %s of group %s anymore.','dbem'), $user_link, $event_link, $group_link );
185
+ //$action_type = 'cancelled_booking';
186
+ }
187
  }
188
  if( !empty($action) ){
189
+ if( empty($EM_Event->group_id) ){
190
+ bp_em_record_activity( array(
191
+ 'user_id' => $EM_Booking->person->ID,
192
+ 'action' => $action,
193
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
194
+ 'type' => $action_type,
195
+ 'item_id' => $EM_Event->event_id,
196
+ 'secondary_item_id' => $EM_Booking->booking_id,
197
+ 'hide_sitewide' => $EM_Event->event_private
198
+ ));
199
+ }else{
200
+ //tis a group event
201
+ bp_em_record_activity( array(
202
+ 'component' => 'groups',
203
+ 'user_id' => $EM_Booking->person->ID,
204
+ 'action' => $action,
205
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
206
+ 'type' => $action_type,
207
+ 'item_id' => $EM_Event->group_id,
208
+ 'secondary_item_id' => $EM_Booking->booking_id,
209
+ 'hide_sitewide' => $EM_Event->event_private
210
+ ));
211
+ }
212
  }
213
  }
214
  return $result;
215
  }
216
+ add_filter('em_booking_set_status','bp_em_record_activity_booking_save', 100, 2);
217
+ add_filter('em_booking_save','bp_em_record_activity_booking_save', 100, 2);
218
+ add_filter('em_booking_delete','bp_em_record_activity_booking_save', 100, 2);
buddypress/bp-em-admin.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
-
3
- /***
4
- * This file is used to add site administration menus to the WordPress backend.
5
- *
6
- * If you need to provide configuration options for your component that can only
7
- * be modified by a site administrator, this is the best place to do it.
8
- *
9
- * However, if your component has settings that need to be configured on a user
10
- * by user basis - it's best to hook into the front end "Settings" menu.
11
- */
12
-
13
- /**
14
- * bp_em_admin()
15
- *
16
- * Checks for form submission, saves component settings and outputs admin screen HTML.
17
- */
18
- function bp_em_admin() {
19
- global $bp;
20
-
21
- /* If the form has been submitted and the admin referrer checks out, save the settings */
22
- if ( isset( $_POST['submit'] ) && check_admin_referer('em-settings') ) {
23
- update_option( 'em-setting-one', $_POST['em-setting-one'] );
24
- update_option( 'em-setting-two', $_POST['em-setting-two'] );
25
-
26
- $updated = true;
27
- }
28
-
29
- $setting_one = get_option( 'em-setting-one' );
30
- $setting_two = get_option( 'em-setting-two' );
31
- ?>
32
- <div class="wrap">
33
- <h2><?php _e( 'Events Admin', 'bp-em' ) ?></h2>
34
- <br />
35
-
36
- <?php if ( isset($updated) ) : ?><?php echo "<div id='message' class='updated fade'><p>" . __( 'Settings Updated.', 'bp-em' ) . "</p></div>" ?><?php endif; ?>
37
-
38
- <form action="<?php echo site_url() . '/wp-admin/admin.php?page=bp-em-settings' ?>" name="em-settings-form" id="em-settings-form" method="post">
39
-
40
- <table class="form-table">
41
- <tr valign="top">
42
- <th scope="row"><label for="target_uri"><?php _e( 'Option One', 'bp-em' ) ?></label></th>
43
- <td>
44
- <input name="em-setting-one" type="text" id="em-setting-one" value="<?php echo attribute_escape( $setting_one ); ?>" size="60" />
45
- </td>
46
- </tr>
47
- <th scope="row"><label for="target_uri"><?php _e( 'Option Two', 'bp-em' ) ?></label></th>
48
- <td>
49
- <input name="em-setting-two" type="text" id="em-setting-two" value="<?php echo attribute_escape( $setting_two ); ?>" size="60" />
50
- </td>
51
- </tr>
52
- </table>
53
- <p class="submit">
54
- <input type="submit" name="submit" value="<?php _e( 'Save Settings', 'bp-em' ) ?>"/>
55
- </p>
56
-
57
- <?php
58
- /* This is very important, don't leave it out. */
59
- wp_nonce_field( 'em-settings' );
60
- ?>
61
- </form>
62
- </div>
63
- <?php
64
- }
65
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
buddypress/bp-em-core.php CHANGED
@@ -1,241 +1,330 @@
1
  <?php
2
- // Define a slug constant that will be used to view this components pages
3
- if ( !defined( 'BP_EM_SLUG' ) )
4
- define ( 'BP_EM_SLUG', 'events' );
5
-
6
- //Include component files
7
- require ( dirname( __FILE__ ) . '/bp-em-activity.php' ); /* The notifications file should contain functions to send email notifications on specific user actions */
8
- require ( dirname( __FILE__ ) . '/bp-em-templatetags.php' ); /* The templatetags file should contain classes and functions designed for use in template files */
9
- require ( dirname( __FILE__ ) . '/bp-em-notifications.php' ); /* The notifications file should contain functions to send email notifications on specific user actions */
10
- require ( dirname( __FILE__ ) . '/bp-em-groups.php' ); /* The notifications file should contain functions to send email notifications on specific user actions */
11
- //Screens
12
- include( dirname( __FILE__ ). '/screens/settings.php');
13
- include( dirname( __FILE__ ). '/screens/profile.php');
14
- include( dirname( __FILE__ ). '/screens/my-events.php');
15
- include( dirname( __FILE__ ). '/screens/my-locations.php');
16
- include( dirname( __FILE__ ). '/screens/attending.php');
17
- include( dirname( __FILE__ ). '/screens/my-bookings.php');
18
- include( dirname( __FILE__ ). '/screens/my-group-events.php');
19
- include( dirname( __FILE__ ). '/screens/group-events.php');
20
-
21
-
22
  /**
23
- * bp_em_setup_globals()
24
- *
25
- * Sets up global variables for your component.
26
  */
27
- function bp_em_setup_globals() {
28
- global $bp, $wpdb;
29
- $bp->events = new stdClass();
30
- $bp->events->id = 'events';
31
- //$bp->events->table_name = $wpdb->base_prefix . 'bp_em';
32
- $bp->events->format_notification_function = 'bp_em_format_notifications';
33
- $bp->events->slug = BP_EM_SLUG;
34
- /* Register this in the active components array */
35
- $bp->active_components[$bp->events->slug] = $bp->events->id;
36
- //quick link shortcut
37
- $bp->events->link = trailingslashit($bp->loggedin_user->domain).'events/';
38
- }
39
- add_action( 'wp', 'bp_em_setup_globals', 2 );
40
- //add_action( 'admin_menu', 'bp_em_setup_globals', 2 );
41
 
42
- /**
43
- * bp_em_setup_nav()
44
- *
45
- * Sets up the user profile navigation items for the component. This adds the top level nav
46
- * item and all the sub level nav items to the navigation array. This is then
47
- * rendered in the template.
48
- */
49
- function bp_em_setup_nav() {
50
- global $bp;
51
- $count = 0;
 
 
 
 
 
 
 
 
 
 
52
 
53
- /* Add 'Events' to the main user profile navigation */
54
- bp_core_new_nav_item( array(
55
- 'name' => __( 'Events', 'bp-em' ),
56
- 'slug' => $bp->events->slug,
57
- 'position' => 80,
58
- 'screen_function' => bp_is_my_profile() ? 'bp_em_my_events':'bp_em_events',
59
- 'default_subnav_slug' => bp_is_my_profile() ? 'my-events':''
60
- ) );
61
 
62
- $em_link = $bp->loggedin_user->domain . $bp->events->slug . '/';
 
 
 
 
 
 
63
 
64
- /* Create two sub nav items for this component */
65
- bp_core_new_subnav_item( array(
66
- 'name' => __( 'My Profile', 'dbem' ),
67
- 'slug' => 'profile',
68
- 'parent_slug' => $bp->events->slug,
69
- 'parent_url' => $em_link,
70
- 'screen_function' => 'bp_em_events',
71
- 'position' => 10,
72
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
73
- ) );
74
-
75
- bp_core_new_subnav_item( array(
76
- 'name' => __( 'Events I\'m Attending', 'dbem' ),
77
- 'slug' => 'attending',
78
- 'parent_slug' => $bp->events->slug,
79
- 'parent_url' => $em_link,
80
- 'screen_function' => 'bp_em_attending',
81
- 'position' => 20,
82
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
83
- ) );
84
 
85
- bp_core_new_subnav_item( array(
86
- 'name' => __( 'My Events', 'dbem' ),
87
- 'slug' => 'my-events',
88
- 'parent_slug' => $bp->events->slug,
89
- 'parent_url' => $em_link,
90
- 'screen_function' => 'bp_em_my_events',
91
- 'position' => 30,
92
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
93
- ) );
94
-
95
- bp_core_new_subnav_item( array(
96
- 'name' => __( 'My Locations', 'dbem' ),
97
- 'slug' => 'my-locations',
98
- 'parent_slug' => $bp->events->slug,
99
- 'parent_url' => $em_link,
100
- 'screen_function' => 'bp_em_my_locations',
101
- 'position' => 40,
102
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
103
- ) );
104
 
105
- bp_core_new_subnav_item( array(
106
- 'name' => __( 'My Event Bookings', 'dbem' ),
107
- 'slug' => 'my-bookings',
108
- 'parent_slug' => $bp->events->slug,
109
- 'parent_url' => $em_link,
110
- 'screen_function' => 'bp_em_my_bookings',
111
- 'position' => 50,
112
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
113
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
- /* Add a nav item for this component under the settings nav item. */
116
- bp_core_new_subnav_item( array(
117
- 'name' => __( 'Events', 'dbem' ),
118
- 'slug' => 'group-events',
119
- 'parent_slug' => $bp->groups->slug,
120
- 'parent_url' => $bp->loggedin_user->domain . $bp->groups->slug . '/',
121
- 'screen_function' => 'bp_em_my_group_events',
122
- 'position' => 60,
123
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
124
- ) );
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- /* Add a nav item for this component under the settings nav item. */
127
- bp_core_new_subnav_item( array(
128
- 'name' => __( 'Events', 'dbem' ),
129
- 'slug' => 'events-settings',
130
- 'parent_slug' => $bp->settings->slug,
131
- 'parent_url' => $bp->loggedin_user->domain . $bp->settings->slug . '/',
132
- 'screen_function' => 'bp_em_screen_settings_menu',
133
- 'position' => 40,
134
- 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
135
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
-
138
- /* Create two sub nav items for this component */
139
- $group_link = $bp->root_domain . '/' . $bp->groups->slug . '/' . $bp->groups->current_group->slug . '/';
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
- if( $bp->current_component == 'groups' ){
142
- $count = EM_Events::count(array('group'=>$bp->groups->current_group->id));
143
- if( empty($count) ) $count = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  }
145
- bp_core_new_subnav_item( array(
146
- 'name' => sprintf(__( 'Events (%s)', 'dbem' ), $count),
147
- 'slug' => 'events',
148
- 'parent_url' => $group_link,
149
- 'parent_slug' => $bp->groups->slug,
150
- 'screen_function' => 'bp_em_group_events',
151
- 'position' => 50,
152
- 'user_has_access' => $bp->groups->current_group->user_has_access,
153
- 'item_css_id' => 'forums'
154
- ) );
155
 
156
- }
157
-
158
- /***
159
- * In versions of BuddyPress 1.2.2 and newer you will be able to use:
160
- * add_action( 'bp_setup_nav', 'bp_example_setup_nav' );
161
- */
162
- add_action( 'wp', 'bp_em_setup_nav', 2 );
163
- add_action( 'admin_menu', 'bp_em_setup_nav', 2 );
164
-
165
-
166
- function em_bp_rewrite_links($replace, $object, $result){
167
- global $bp;
168
- if( is_object($object) && get_class($object)=='EM_Event' ){
169
- switch( $result ){
170
- case '#_EDITEVENTURL':
171
- case '#_EDITEVENTLINK':
172
- if( $object->can_manage('edit_events','edit_others_events') && !is_admin() ){
173
- $replace = $bp->events->link.'my-events/edit/?event_id='.$object->id;
174
- if($result == '#_EDITEVENTLINK'){
175
- $replace = "<a href='".$replace."'>".__('Edit').' '.__('Event', 'dbem')."</a>";
176
- }
177
- }
178
- break;
179
- case '#_BOOKINGSLINK':
180
- case '#_BOOKINGSURL':
181
- if( $object->can_manage('manage_bookings','manage_others_bookings') && !is_admin() ){
182
- $replace = $bp->events->link.'my-bookings/?event_id='.$object->id;
183
- if($result == '#_BOOKINGSLINK'){
184
- $replace = "<a href='{$replace}' title='{$object->name}'>{$object->name}</a>";
185
- }
186
- }
187
- break;
188
  }
189
  }
190
- return $replace;
191
  }
192
- add_filter('em_event_output_placeholder','em_bp_rewrite_links',10,3);
193
-
194
- /**
195
- * bp_em_load_template_filter()
196
- *
197
- * You can define a custom load template filter for your component. This will allow
198
- * you to store and load template files from your plugin directory.
199
- *
200
- * This will also allow users to override these templates in their active theme and
201
- * replace the ones that are stored in the plugin directory.
202
- *
203
- * If you're not interested in using template files, then you don't need this function.
204
- *
205
- * This will become clearer in the function bp_em_screen_one() when you want to load
206
- * a template file.
207
- */
208
- function bp_em_load_template_filter( $found_template, $templates ) {
209
  global $bp;
 
 
 
210
 
211
- /**
212
- * Only filter the template location when we're on the em component pages.
 
213
  */
214
- if ( $bp->current_component != $bp->events->slug )
215
- return $found_template;
216
-
217
- foreach ( (array) $templates as $template ) {
218
- if ( file_exists( STYLESHEETPATH . '/' . $template ) )
219
- $filtered_templates[] = STYLESHEETPATH . '/' . $template;
220
- else
221
- $filtered_templates[] = dirname( __FILE__ ) . '/templates/' . $template;
222
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
- $found_template = $filtered_templates[0];
225
-
226
- return apply_filters( 'bp_em_load_template_filter', $found_template );
 
 
 
 
227
  }
228
- add_filter( 'bp_located_template', 'bp_em_load_template_filter', 10, 2 );
229
 
230
- /**
231
- * Remove a screen notification for a user.
232
- */
233
- function bp_em_remove_screen_notifications() {
234
- global $bp;
235
- bp_core_delete_notifications_for_user_by_type( $bp->loggedin_user->id, $bp->events->slug, 'attending' );
236
  }
237
- add_action( 'bp_em_my_events', 'bp_em_remove_screen_notifications' );
238
- add_action( 'xprofile_screen_display_profile', 'bp_em_remove_screen_notifications' );
239
 
240
  /**
241
  * Delete events when you delete a user.
@@ -247,4 +336,5 @@ function bp_em_remove_data( $user_id ) {
247
  add_action( 'wpmu_delete_user', 'bp_em_remove_data', 1 );
248
  add_action( 'delete_user', 'bp_em_remove_data', 1 );
249
 
 
250
  ?>
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', 'dbem'), 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...', 'dbem' ),__('Events','dbem')),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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
+
166
+ // Prevent debug notices
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.
174
+ $current_blog = $blog_id;
175
+ switch_to_blog(BP_ROOT_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
+ 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', 'dbem' ),
193
+ 'href' => $em_link
194
+ );
195
+
196
+ /* Create SubNav Items */
197
+ $wp_admin_nav[] = array(
198
+ 'parent' => 'my-em-' . $this->id,
199
+ 'id' => 'my-em-' . $this->id .'-profile',
200
+ 'title' => __( 'My Profile', 'dbem' ),
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', 'dbem' ),
208
+ 'href' => $em_link.'attending/'
209
+ );
210
+
211
+ if( $can_manage_events ){
212
+ $wp_admin_nav[] = array(
213
+ 'parent' => 'my-em-' . $this->id,
214
+ 'id' => 'my-em-' . $this->id .'-my-events',
215
+ 'title' => __( 'My Events', 'dbem' ),
216
+ 'href' => $em_link.'my-events/'
217
+ );
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ),
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', 'dbem' ) . " <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' => 'forums'
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.
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
  ?>
buddypress/bp-em-groups.php CHANGED
@@ -1,57 +1,150 @@
1
  <?php
2
  /**
 
3
  * @param EM_Event $EM_Event
4
  */
5
- function bp_em_group_event_save($EM_Event){
6
- if( empty($EM_Event->id) && !empty($_REQUEST['group_id']) ){
7
- //we have been requested an event creation tied to a group, so does this group exist, and does this person have admin rights to it?
8
- if( groups_is_user_admin(get_current_user_id(), $_REQUEST['group_id']) ){
9
- $EM_Event->group_id = $_REQUEST['group_id'];
10
- }
11
- }
12
- return $EM_Event;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
- add_action('em_event_save_pre','bp_em_group_event_save',1,1);
15
 
16
  /**
 
 
17
  * @param boolean $result
18
  * @param EM_Event $EM_Event
19
  */
20
- function bp_em_group_event_can_manage( $result, $EM_Event){
21
- if( !$result && !empty($EM_Event->group_id) ){ //only override if already false, incase it's true
22
- if( groups_is_user_admin(get_current_user_id(),$EM_Event->group_id) && current_user_can('edit_events') ){
 
 
23
  //This user is an admin of the owner's group, so they can edit this event.
24
  return true;
 
 
25
  }
26
  }
27
  return $result;
28
  }
29
- add_action('em_event_can_manage','bp_em_group_event_can_manage',1,2);
30
 
31
 
32
- function bp_em_group_accepted_searches($searches){
33
- $searches[] = 'group';
 
 
34
  return $searches;
35
  }
36
  add_filter('em_accepted_searches','bp_em_group_events_accepted_searches',1,1);
37
 
38
  function bp_em_group_events_get_default_search($searches, $array){
39
- if( !empty($array['group']) && (is_numeric($array['group']) || $array['group'] == 'my') ){
40
- $searches['group'] = $array['group'];
 
 
 
 
 
 
41
  }
42
  return $searches;
43
  }
44
  add_filter('em_events_get_default_search','bp_em_group_events_get_default_search',1,2);
45
 
 
 
 
46
  function bp_em_group_events_build_sql_conditions( $conditions, $args ){
47
  if( !empty($args['group']) && is_numeric($args['group']) ){
48
  $conditions['group'] = "( `group_id`={$args['group']} )";
49
- }elseif( $args['group'] == 'my' ){
50
  $groups = groups_get_user_groups(get_current_user_id());
51
  if( count($groups) > 0 ){
52
  $conditions['group'] = "( `group_id` IN (".implode(',',$groups['groups']).") )";
53
  }
54
  }
 
 
 
 
 
 
 
 
 
 
 
 
55
  return $conditions;
56
  }
57
- add_filter('em_events_build_sql_conditions','bp_em_group_events_build_sql_conditions',1,2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  /**
3
+ * Turns an event private if the event belongs to a private BP Group
4
  * @param EM_Event $EM_Event
5
  */
6
+ function bp_em_group_event_save($result, $EM_Event){
7
+ if( is_object($EM_Event) && !empty($EM_Event->event_id) ){
8
+ if( !empty($_REQUEST['group_id']) && is_numeric($_REQUEST['group_id']) && bp_is_active('groups') ){
9
+ //firstly, we check that the event has been published, otherwise users without publish rights can submit an event at a private group and event is marked private/published immediately
10
+ if( $EM_Event->event_status == 1 ){
11
+ //we have been requested an event creation tied to a group, so does this group exist, and does this person have admin rights to it?
12
+ if( groups_is_user_admin(get_current_user_id(), $_REQUEST['group_id']) ){
13
+ $EM_Event->group_id = $_REQUEST['group_id'];
14
+ }
15
+ if( !empty($EM_Event->group_id) ){
16
+ //if group is private, make it private
17
+ $group = groups_get_group(array('group_id'=>$EM_Event->group_id));
18
+ $is_member = groups_is_user_member(get_current_user_id(), $EM_Event->group_id) || groups_is_user_admin(get_current_user_id(), $EM_Event->group_id) || groups_is_user_mod(get_current_user_id(), $EM_Event->group_id);
19
+ if( $group->status != 'public' && $is_member ){
20
+ //Make sure event status is private and set post status to private
21
+ global $wpdb;
22
+ $EM_Event->event_private = 1;
23
+ $wpdb->update($wpdb->posts, array('post_status'=>'private'), array('ID'=>$EM_Event->post_id));
24
+ $wpdb->update(EM_EVENTS_TABLE, array('event_private'=>1), array('event_id'=>$EM_Event->event_id));
25
+ }
26
+ }
27
+ }
28
+ }else{
29
+ $EM_Event->group_id = null;
30
+ }
31
+ }
32
+ return $result;
33
  }
34
+ add_action('em_event_save','bp_em_group_event_save',1,2);
35
 
36
  /**
37
+ * Overrides the default capability of the user for another owner's event if the user is a group admin and the event belongs to a group.
38
+ * User must have the relevant permissions globally in order to inherit that capability for this event as well.
39
  * @param boolean $result
40
  * @param EM_Event $EM_Event
41
  */
42
+ function bp_em_group_event_can_manage( $result, $EM_Event, $owner_capability, $admin_capability, $user_to_check){
43
+ if( !$result && $EM_Event->event_owner != get_current_user_id() && !empty($EM_Event->group_id) && bp_is_active('groups') ){ //only override if already false, incase it's true
44
+ //if the user is an admin of this group, and actually has the relevant permissions globally, they can manage this event
45
+ $EM_Object = new EM_Object(); //create new object to prevent infinite loop should we call $EM_Event->can_manage();
46
+ if( groups_is_user_admin(get_current_user_id(),$EM_Event->group_id) && $EM_Object->can_manage($owner_capability, $admin_capability, $user_to_check) ){
47
  //This user is an admin of the owner's group, so they can edit this event.
48
  return true;
49
+ }else{
50
+ $EM_Event->add_error($EM_Object->get_errors()); //add any applicable errors
51
  }
52
  }
53
  return $result;
54
  }
55
+ add_filter('em_event_can_manage','bp_em_group_event_can_manage',1,5);
56
 
57
 
58
+ function bp_em_group_events_accepted_searches($searches){
59
+ if( bp_is_active('groups') ){
60
+ $searches[] = 'group';
61
+ }
62
  return $searches;
63
  }
64
  add_filter('em_accepted_searches','bp_em_group_events_accepted_searches',1,1);
65
 
66
  function bp_em_group_events_get_default_search($searches, $array){
67
+ if( !empty($array['group']) && (is_numeric($array['group']) || $array['group'] == 'my' || $array['group'] == 'this') && bp_is_active('groups') ){
68
+ if($array['group'] == 'this'){ //shows current group, if applicable
69
+ if( is_numeric(bp_get_current_group_id()) ){
70
+ $searches['group'] = bp_get_current_group_id();
71
+ }
72
+ }else{
73
+ $searches['group'] = $array['group'];
74
+ }
75
  }
76
  return $searches;
77
  }
78
  add_filter('em_events_get_default_search','bp_em_group_events_get_default_search',1,2);
79
 
80
+ /*
81
+ * Privacy Functions
82
+ */
83
  function bp_em_group_events_build_sql_conditions( $conditions, $args ){
84
  if( !empty($args['group']) && is_numeric($args['group']) ){
85
  $conditions['group'] = "( `group_id`={$args['group']} )";
86
+ }elseif( !empty($args['group']) && $args['group'] == 'my' ){
87
  $groups = groups_get_user_groups(get_current_user_id());
88
  if( count($groups) > 0 ){
89
  $conditions['group'] = "( `group_id` IN (".implode(',',$groups['groups']).") )";
90
  }
91
  }
92
+ //deal with private groups and events
93
+ if( is_user_logged_in() ){
94
+ global $wpdb;
95
+ //find out what private groups they belong to, and don't show private group events not in their memberships
96
+ $group_ids = BP_Groups_Member::get_group_ids(get_current_user_id());
97
+ if( $group_ids['total'] > 0){
98
+ $conditions['group_privacy'] = "(`event_private`=0 OR (`event_private`=1 AND (`group_id` IS NULL OR `group_id` = 0)) OR (`event_private`=1 AND `group_id` IN (".implode(',',$group_ids['groups']).")))";
99
+ }else{
100
+ //find out what private groups they belong to, and don't show private group events not in their memberships
101
+ $conditions['group_privacy'] = "(`event_private`=0 OR (`event_private`=1 AND (`group_id` IS NULL OR `group_id` = 0)))";
102
+ }
103
+ }
104
  return $conditions;
105
  }
106
+ add_filter('em_events_build_sql_conditions','bp_em_group_events_build_sql_conditions',1,2);
107
+
108
+
109
+ /**
110
+ * Checks if the event is private and either belongs to a group or private group, as members of that group should be able to see the post even if not able to see private events.
111
+ * @param string $template
112
+ * @return string
113
+ */
114
+ function bp_em_private_event_check($template){
115
+ global $post, $wpdb, $wp_query, $bp;
116
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
117
+ $EM_Event = em_get_event($post);
118
+ //echo "<pre>"; print_r($EM_Event); echo "</pre>"; die();
119
+ if( !empty($EM_Event->event_private) && !empty($EM_Event->group_id) ){
120
+ if( is_user_logged_in() ){
121
+ //make sure user is a member of this group, whether private or not, private groups just aren't shown to non-members of a group
122
+ $id_lookup = $wpdb->get_var( $wpdb->prepare( "SELECT m.group_id FROM {$bp->groups->table_name_members} m WHERE m.group_id = %s AND m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $EM_Event->group_id, get_current_user_id() ) );
123
+ if($id_lookup != $EM_Event->group_id){
124
+ unset($post);
125
+ $wp_query->set_404();
126
+ $template = locate_template(array('404.php'),false);
127
+ }
128
+ }else{
129
+ unset($post);
130
+ $wp_query->set_404();
131
+ $template = locate_template(array('404.php'),false);
132
+ }
133
+ }
134
+ }
135
+ return $template;
136
+ }
137
+ add_filter('single_template','bp_em_private_event_check',20);
138
+
139
+ /*
140
+ * Admin Meta Boxes
141
+ */
142
+ function bp_em_meta_boxes(){
143
+ add_meta_box('em-event-group', __('Group Ownership','dbem'), 'bp_em_meta_box_group',EM_POST_TYPE_EVENT, 'side','low');
144
+ add_meta_box('em-event-group', __('Group Ownership','dbem'), 'bp_em_meta_box_group','event-recurring', 'side','low');
145
+ }
146
+ add_action('add_meta_boxes', 'bp_em_meta_boxes');
147
+
148
+ function bp_em_meta_box_group(){
149
+ em_locate_template('forms/event/group.php',true);
150
+ }
buddypress/bp-em-notifications.php CHANGED
@@ -1,68 +1,5 @@
1
  <?php
2
-
3
- /********************************************************************************
4
- * Activity & Notification Functions
5
- *
6
- * These functions handle the recording, deleting and formatting of activity and
7
- * notifications for the user and for this specific component.
8
- */
9
- /**
10
- * bp_em_screen_notification_settings()
11
- *
12
- * Adds notification settings for the component, so that a user can turn off email
13
- * notifications set on specific component actions.
14
- */
15
- function bp_em_screen_notification_settings() {
16
- global $current_user;
17
-
18
- /**
19
- * Under Settings > Notifications within a users profile page they will see
20
- * settings to turn off notifications for each component.
21
- *
22
- * You can plug your custom notification settings into this page, so that when your
23
- * component is active, the user will see options to turn off notifications that are
24
- * specific to your component.
25
- */
26
-
27
- /**
28
- * Each option is stored in a posted array notifications[SETTING_NAME]
29
- * When saved, the SETTING_NAME is stored as usermeta for that user.
30
- *
31
- * For em, notifications[notification_friends_friendship_accepted] could be
32
- * used like this:
33
- *
34
- * if ( 'no' == get_usermeta( $bp['loggedin_userid'], 'notification_friends_friendship_accepted' ) )
35
- * // don't send the email notification
36
- * else
37
- * // send the email notification.
38
- */
39
-
40
- ?>
41
- <table class="notification-settings" id="bp-em-notification-settings">
42
- <tr>
43
- <th class="icon"></th>
44
- <th class="title"><?php _e( 'Events', 'bp-em' ) ?></th>
45
- <th class="yes"><?php _e( 'Yes', 'bp-em' ) ?></th>
46
- <th class="no"><?php _e( 'No', 'bp-em' )?></th>
47
- </tr>
48
- <tr>
49
- <td></td>
50
- <td><?php _e( 'Action One', 'bp-em' ) ?></td>
51
- <td class="yes"><input type="radio" name="notifications[notification_em_action_one]" value="yes" <?php if ( !get_usermeta( $current_user->id,'notification_em_action_one') || 'yes' == get_usermeta( $current_user->id,'notification_em_action_one') ) { ?>checked="checked" <?php } ?>/></td>
52
- <td class="no"><input type="radio" name="notifications[notification_em_action_one]" value="no" <?php if ( get_usermeta( $current_user->id,'notification_em_action_one') == 'no' ) { ?>checked="checked" <?php } ?>/></td>
53
- </tr>
54
- <tr>
55
- <td></td>
56
- <td><?php _e( 'Action Two', 'bp-em' ) ?></td>
57
- <td class="yes"><input type="radio" name="notifications[notification_em_action_two]" value="yes" <?php if ( !get_usermeta( $current_user->id,'notification_em_action_two') || 'yes' == get_usermeta( $current_user->id,'notification_em_action_two') ) { ?>checked="checked" <?php } ?>/></td>
58
- <td class="no"><input type="radio" name="notifications[notification_em_action_two]" value="no" <?php if ( 'no' == get_usermeta( $current_user->id,'notification_em_action_two') ) { ?>checked="checked" <?php } ?>/></td>
59
- </tr>
60
-
61
- <?php do_action( 'bp_em_notification_settings' ); ?>
62
- </table>
63
- <?php
64
- }
65
- //add_action( 'bp_notification_settings', 'bp_em_screen_notification_settings' );
66
 
67
  /**
68
  * bp_em_format_notifications()
@@ -83,31 +20,45 @@ function bp_em_format_notifications( $action, $item_id, $secondary_item_id, $tot
83
  case 'pending_booking':
84
  //Count pending bookings
85
  if( get_option('dbem_bookings_approval')){
86
- $EM_Bookings = EM_Bookings::get(array('status'=>0, 'owner'=>get_current_user_id()));
87
- if ( count($EM_Bookings->bookings) > 1 ) {
88
- return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/?event_id" title="' . __( 'My Bookings', 'bp-em' ) . '">' . __('You have a pending booking','dbem'). '</a>', $EM_Bookings );
89
  } else {
90
- return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'bp-em' ) . '">' . sprintf(__('You have %s pending bookings','dbem'), $bookings_pending_count). '</a>', $EM_Bookings );
91
  }
92
  }
93
  break;
94
  case 'confirmed_booking':
95
  //Count pending bookings
96
- $EM_Bookings = EM_Bookings::get(array('status'=>0, 'owner'=>get_current_user_id()));
97
- if ( count($EM_Bookings->bookings) > 1 ) {
98
- return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/?event_id="'.$EM_Bookings->first()->event_id.'" title="' . __( 'My Bookings', 'bp-em' ) . '">' . __('You have a new booking','dbem'). '</a>', $EM_Bookings );
 
 
 
 
 
 
 
99
  } else {
100
- return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'bp-em' ) . '">' . sprintf(__('You have %s new bookings','dbem'), $bookings_pending_count). '</a>', $EM_Bookings );
101
  }
102
  break;
103
  }
104
- die($action);
105
-
106
  do_action( 'bp_em_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
107
 
108
  return false;
109
  }
110
 
 
 
 
 
 
 
 
 
 
 
111
  /**
112
  * Catch booking saves and add a BP notification.
113
  * @param boolean $result
@@ -116,15 +67,15 @@ function bp_em_format_notifications( $action, $item_id, $secondary_item_id, $tot
116
  */
117
  function bp_em_add_booking_notification($result, $EM_Booking){
118
  global $bp;
119
- if( get_option('dbem_bookings_approval') && $EM_Booking->status == 0 ){
120
  $action = 'pending_booking';
121
- }elseif( $EM_Booking->status == 1 || (get_option('dbem_bookings_approval') && $EM_Booking->status == 0) ){
122
  $action = 'confirmed_booking';
123
- }elseif( $EM_Booking->status == 3 ){
124
  $action = 'cancelled_booking';
125
  }
126
  if( !empty($action) ){
127
- bp_core_add_notification( $EM_Booking->id, $EM_Booking->get_event()->owner, 'events', $action );
128
  }
129
  return $result;
130
  }
1
  <?php
2
+ //This file handles hooks requiring notifications
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  /**
5
  * bp_em_format_notifications()
20
  case 'pending_booking':
21
  //Count pending bookings
22
  if( get_option('dbem_bookings_approval')){
23
+ if ( $total_items > 1 ) {
24
+ return '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('You have a pending booking','dbem'). '</a>';
 
25
  } else {
26
+ return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('You have %s pending bookings','dbem'), $total_items). '</a>' );
27
  }
28
  }
29
  break;
30
  case 'confirmed_booking':
31
  //Count pending bookings
32
+ if ( $total_items > 1 ) {
33
+ return apply_filters( 'bp_em_format_confirmed_booking_notifications', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('You have a confirmed booking','dbem'). '</a>' );
34
+ } else {
35
+ return apply_filters( 'bp_em_format_confirmed_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('You have %s confirmed bookings','dbem'), $total_items). '</a>' );
36
+ }
37
+ break;
38
+ case 'cancelled_booking':
39
+ //Count pending bookings
40
+ if ( $total_items > 1 ) {
41
+ return apply_filters( 'bp_em_format_cancelled_booking_notifications', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('A user cancelled a booking','dbem'). '</a>' );
42
  } else {
43
+ return apply_filters( 'bp_em_format_cancelled_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('%s users cancelled bookings.','dbem'), $total_items). '</a>' );
44
  }
45
  break;
46
  }
 
 
47
  do_action( 'bp_em_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
48
 
49
  return false;
50
  }
51
 
52
+ /**
53
+ * Remove a screen notification for a user.
54
+ */
55
+ function bp_em_remove_screen_notifications() {
56
+ global $bp;
57
+ bp_core_delete_notifications_by_type( $bp->loggedin_user->id, $bp->events->slug, 'attending' );
58
+ }
59
+ add_action( 'bp_em_my_events', 'bp_em_remove_screen_notifications' );
60
+ add_action( 'xprofile_screen_display_profile', 'bp_em_remove_screen_notifications' );
61
+
62
  /**
63
  * Catch booking saves and add a BP notification.
64
  * @param boolean $result
67
  */
68
  function bp_em_add_booking_notification($result, $EM_Booking){
69
  global $bp;
70
+ if( get_option('dbem_bookings_approval') && $EM_Booking->get_status() == 0 ){
71
  $action = 'pending_booking';
72
+ }elseif( $EM_Booking->get_status() == 1 || (get_option('dbem_bookings_approval') && $EM_Booking->get_status() == 0) ){
73
  $action = 'confirmed_booking';
74
+ }elseif( $EM_Booking->get_status() == 3 ){
75
  $action = 'cancelled_booking';
76
  }
77
  if( !empty($action) ){
78
+ bp_core_add_notification( $EM_Booking->booking_id, $EM_Booking->get_event()->get_contact()->ID, 'events', $action );
79
  }
80
  return $result;
81
  }
buddypress/bp-em-templatetags.php CHANGED
@@ -1,7 +1,21 @@
1
  <?php
2
-
3
  /**
4
- * In this file you should define template tag functions that end users can add to their template files.
5
- * Each template tag function should echo the final data so that it will output the required information
6
- * just by calling the function name.
7
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
 
2
  /**
3
+ * Echo the Events Manager BuddyPresss component's slug
4
+ * @since 5.0
5
+ */
6
+ function em_bp_slug() {
7
+ echo em_bp_get_slug();
8
+ }
9
+ /**
10
+ * Return the Events Manager BuddyPresss component's slug
11
+ *
12
+ * @since 5.0
13
+ * @uses apply_filters() Filter 'em_bp_get_slug' to change the output
14
+ * @return str $slug The slug from $bp->events->slug, if it exists
15
+ */
16
+ function em_bp_get_slug() {
17
+ global $bp;
18
+ // Avoid PHP warnings, in case the value is not set for some reason
19
+ $slug = !empty( $bp->events->slug ) ? $bp->events->slug : BP_EM_SLUG;
20
+ return apply_filters( 'em_bp_get_slug', $slug );
21
+ }
buddypress/screens/attending.php CHANGED
@@ -20,10 +20,10 @@ function bp_em_attending() {
20
  }
21
 
22
  function bp_em_attending_title() {
23
- _e( 'Events I\'m Attending', 'bp-em' );
24
  }
25
 
26
  function bp_em_attending_content() {
27
  //We can use the same template as the public user interface for non bp sites
28
- em_locate_template('templates/my-bookings.php',true);
29
  }
20
  }
21
 
22
  function bp_em_attending_title() {
23
+ _e( 'Events I\'m Attending', 'dbem' );
24
  }
25
 
26
  function bp_em_attending_content() {
27
  //We can use the same template as the public user interface for non bp sites
28
+ em_my_bookings();
29
  }
buddypress/screens/group-events.php CHANGED
@@ -6,6 +6,9 @@ function bp_em_group_events() {
6
  global $bp;
7
  do_action( 'bp_em_group_events' );
8
 
 
 
 
9
  add_action( 'bp_template_title', 'bp_em_group_events_title' );
10
  add_action( 'bp_template_content', 'bp_em_group_events_content' );
11
 
6
  global $bp;
7
  do_action( 'bp_em_group_events' );
8
 
9
+ //plug into EM admin code (at least for now)
10
+ include_once(EM_DIR.'/admin/em-admin.php');
11
+
12
  add_action( 'bp_template_title', 'bp_em_group_events_title' );
13
  add_action( 'bp_template_content', 'bp_em_group_events_content' );
14
 
buddypress/screens/my-bookings.php CHANGED
@@ -8,13 +8,17 @@ function bp_em_my_bookings() {
8
  global $bp, $EM_Event;
9
 
10
  //assume any notifications here are considered viewed via this page
11
- bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','pending_booking');
12
- bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','confirmed_booking');
13
- bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','cancelled_booking');
14
-
15
- if( !is_object($EM_Event) && !empty($_REQUEST['event_id']) ){
16
- $EM_Event = new EM_Event($_REQUEST['event_id']);
 
 
17
  }
 
 
18
  /**
19
  * If the user has not Accepted or Rejected anything, then the code above will not run,
20
  * we can continue and load the template.
8
  global $bp, $EM_Event;
9
 
10
  //assume any notifications here are considered viewed via this page
11
+ if( function_exists('bp_notifications_delete_notifications_by_type') ){
12
+ bp_notifications_delete_notifications_by_type(get_current_user_id(), 'events','pending_booking');
13
+ bp_notifications_delete_notifications_by_type(get_current_user_id(), 'events','confirmed_booking');
14
+ bp_notifications_delete_notifications_by_type(get_current_user_id(), 'events','cancelled_booking');
15
+ }else{
16
+ bp_core_delete_notifications_by_type(get_current_user_id(), 'events','pending_booking');
17
+ bp_core_delete_notifications_by_type(get_current_user_id(), 'events','confirmed_booking');
18
+ bp_core_delete_notifications_by_type(get_current_user_id(), 'events','cancelled_booking');
19
  }
20
+
21
+ em_load_event();
22
  /**
23
  * If the user has not Accepted or Rejected anything, then the code above will not run,
24
  * we can continue and load the template.
buddypress/screens/my-events.php CHANGED
@@ -10,23 +10,14 @@ function bp_em_my_events() {
10
 
11
  do_action( 'bp_em_my_events' );
12
 
13
- //plug into EM admin code (at least for now)
14
- include_once(EM_DIR.'/admin/em-admin.php');
15
- em_admin_load_scripts();
16
- add_action('wp_head','em_admin_general_script');
17
-
18
  $template_title = 'bp_em_my_events_title';
19
  $template_content = 'bp_em_my_events_content';
20
 
21
- if( count($bp->action_variables) > 0 ){
22
- if( is_object($EM_Event) && !$EM_Event->can_manage('edit_events','edit_others_events') ) return false;
23
- if( !empty($bp->action_variables[0]) ){
24
- switch($bp->action_variables[0]){
25
- case 'edit':
26
- $template_title = 'bp_em_my_events_editor_title';
27
- $template_content = 'bp_em_my_events_editor';
28
- break;
29
- }
30
  }
31
  }
32
 
@@ -52,14 +43,13 @@ function bp_em_my_events_content() {
52
  function bp_em_my_events_editor_title() {
53
  global $EM_Event;
54
  if( is_object($EM_Event) ){
55
- _e( 'Edit Event', 'dbem' );
 
 
 
 
56
  }else{
57
  _e( 'Add Event', 'dbem' );
58
  }
59
  }
60
-
61
- function bp_em_my_events_editor(){
62
- em_locate_template('forms/event-editor.php', true);
63
- }
64
-
65
  ?>
10
 
11
  do_action( 'bp_em_my_events' );
12
 
 
 
 
 
 
13
  $template_title = 'bp_em_my_events_title';
14
  $template_content = 'bp_em_my_events_content';
15
 
16
+ if( !empty($_GET['action']) ){
17
+ switch($_GET['action']){
18
+ case 'edit':
19
+ $template_title = 'bp_em_my_events_editor_title';
20
+ break;
 
 
 
 
21
  }
22
  }
23
 
43
  function bp_em_my_events_editor_title() {
44
  global $EM_Event;
45
  if( is_object($EM_Event) ){
46
+ if($EM_Event->is_recurring()){
47
+ echo __( "Reschedule Events", 'dbem' )." '{$EM_Event->event_name}'";
48
+ }else{
49
+ echo __( "Edit Event", 'dbem' ) . " '" . $EM_Event->event_name . "'";
50
+ }
51
  }else{
52
  _e( 'Add Event', 'dbem' );
53
  }
54
  }
 
 
 
 
 
55
  ?>
buddypress/screens/my-group-events.php CHANGED
@@ -6,6 +6,9 @@ function bp_em_my_group_events() {
6
  global $bp;
7
  do_action( 'bp_em_my_group_events' );
8
 
 
 
 
9
  add_action( 'bp_template_title', 'bp_em_my_group_events_title' );
10
  add_action( 'bp_template_content', 'bp_em_my_group_events_content' );
11
 
6
  global $bp;
7
  do_action( 'bp_em_my_group_events' );
8
 
9
+ //plug into EM admin code (at least for now)
10
+ include_once(EM_DIR.'/admin/em-admin.php');
11
+
12
  add_action( 'bp_template_title', 'bp_em_my_group_events_title' );
13
  add_action( 'bp_template_content', 'bp_em_my_group_events_content' );
14
 
buddypress/screens/my-locations.php CHANGED
@@ -10,30 +10,14 @@ function bp_em_my_locations() {
10
 
11
  do_action( 'bp_em_my_locations' );
12
 
13
- //plug into EM admin code (at least for now)
14
- include_once(EM_DIR.'/admin/em-admin.php');
15
- em_admin_load_scripts();
16
- add_action('wp_head','em_admin_general_script');
17
-
18
  $template_title = 'bp_em_my_locations_title';
19
  $template_content = 'bp_em_my_locations_content';
20
 
21
- if( count($bp->action_variables) > 0 ){
22
- if( is_object($EM_Location) && !$EM_Location->can_manage('edit_locations','edit_others_locations') ) return false;
23
- if( !empty($bp->action_variables[0]) ){
24
- switch($bp->action_variables[0]){
25
- case 'edit':
26
- $template_title = 'bp_em_my_locations_editor_title';
27
- $template_content = 'bp_em_my_locations_editor_content';
28
- break;
29
- default :
30
- $template_title = 'bp_em_my_locations_title';
31
- $template_content = 'bp_em_my_locations_content';
32
- break;
33
- }
34
- }else{
35
- $template_title = 'bp_em_my_locations_title';
36
- $template_content = 'bp_em_my_locations_content';
37
  }
38
  }
39
 
@@ -58,15 +42,10 @@ function bp_em_my_locations_content() {
58
 
59
  function bp_em_my_locations_editor_title() {
60
  global $EM_Location;
61
- if( is_object($EM_Location) ){
62
- _e( 'Edit Location', 'dbem' );
63
  }else{
64
- _e( 'Add Location', 'dbem' );
65
  }
66
  }
67
-
68
- function bp_em_my_locations_editor_content(){
69
- em_locate_template('forms/location-editor.php', true);
70
- }
71
-
72
  ?>
10
 
11
  do_action( 'bp_em_my_locations' );
12
 
 
 
 
 
 
13
  $template_title = 'bp_em_my_locations_title';
14
  $template_content = 'bp_em_my_locations_content';
15
 
16
+ if( !empty($_GET['action']) ){
17
+ switch($_GET['action']){
18
+ case 'edit':
19
+ $template_title = 'bp_em_my_locations_editor_title';
20
+ break;
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
  }
23
 
42
 
43
  function bp_em_my_locations_editor_title() {
44
  global $EM_Location;
45
+ if( empty($EM_Location) || !is_object($EM_Location) ){
46
+ $title = __('Add Location', 'dbem');
47
  }else{
48
+ $title = __('Edit Location', 'dbem');
49
  }
50
  }
 
 
 
 
 
51
  ?>
buddypress/screens/profile.php CHANGED
@@ -24,31 +24,9 @@ function bp_em_events() {
24
  * display the corresponding information. The functions are presented below:
25
  */
26
  function bp_em_events_title() {
27
- _e( 'Events', 'bp-em' );
28
  }
29
 
30
  function bp_em_events_content() {
31
- global $bp, $EM_Notices;
32
- echo $EM_Notices;
33
- ?>
34
- <h4><?php _e('My Events', 'dbem'); ?></h4>
35
- <?php
36
- $events = EM_Events::get(array('owner'=>$bp->displayed_user->id));
37
- if( count($events) > 0 ){
38
- $args = array(
39
- 'format_header' => get_option('dbem_bp_events_list_format_header'),
40
- 'format' => get_option('dbem_bp_events_list_format'),
41
- 'format_footer' => get_option('dbem_bp_events_list_format_footer'),
42
- 'owner' => $bp->displayed_user->id
43
- );
44
- echo EM_Events::output($events, $args);
45
- }else{
46
- ?>
47
- <p><?php _e('No Events', 'dbem'); ?></p>
48
- <?php
49
- }
50
- ?>
51
- <h4><?php _e("Events I'm Attending", 'dbem'); ?></h4>
52
- <?php
53
- bp_em_attending_content();
54
  }
24
  * display the corresponding information. The functions are presented below:
25
  */
26
  function bp_em_events_title() {
27
+ _e( 'Events', 'dbem' );
28
  }
29
 
30
  function bp_em_events_content() {
31
+ em_locate_template('buddypress/profile.php',true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
buddypress/screens/settings.php DELETED
@@ -1,56 +0,0 @@
1
- <?php
2
- function bp_em_screen_settings_menu() {
3
- global $bp, $current_user, $bp_settings_updated, $pass_error;
4
-
5
- if ( isset( $_POST['submit'] ) ) {
6
- /* Check the nonce */
7
- check_admin_referer('bp-em-admin');
8
-
9
- $bp_settings_updated = true;
10
-
11
- /**
12
- * This is when the user has hit the save button on their settings.
13
- * The best place to store these settings is in wp_usermeta.
14
- */
15
- update_usermeta( $bp->loggedin_user->id, 'bp-em-option-one', attribute_escape( $_POST['bp-em-option-one'] ) );
16
- }
17
-
18
- add_action( 'bp_template_content_header', 'bp_em_screen_settings_menu_header' );
19
- add_action( 'bp_template_title', 'bp_em_screen_settings_menu_title' );
20
- add_action( 'bp_template_content', 'bp_em_screen_settings_menu_content' );
21
-
22
- bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
23
- }
24
-
25
- function bp_em_screen_settings_menu_header() {
26
- _e( 'Events Settings Header', 'bp-em' );
27
- }
28
-
29
- function bp_em_screen_settings_menu_title() {
30
- _e( 'Events Settings', 'bp-em' );
31
- }
32
-
33
- function bp_em_screen_settings_menu_content() {
34
- global $bp, $bp_settings_updated; ?>
35
-
36
- <?php if ( $bp_settings_updated ) { ?>
37
- <div id="message" class="updated fade">
38
- <p><?php _e( 'Changes Saved.', 'bp-em' ) ?></p>
39
- </div>
40
- <?php } ?>
41
-
42
- <form action="<?php echo $bp->loggedin_user->domain . 'settings/events-settings/'; ?>" name="bp-em-admin-form" id="account-delete-form" class="bp-em-admin-form" method="post">
43
-
44
- <input type="checkbox" name="bp-em-option-one" id="bp-em-option-one" value="1"<?php if ( '1' == get_usermeta( $bp->loggedin_user->id, 'bp-em-option-one' ) ) : ?> checked="checked"<?php endif; ?> /> <?php _e( 'Do you love clicking checkboxes?', 'bp-em' ); ?>
45
- <p class="submit">
46
- <input type="submit" value="<?php _e( 'Save Settings', 'bp-em' ) ?> &raquo;" id="submit" name="submit" />
47
- </p>
48
-
49
- <?php
50
- /* This is very important, don't leave it out. */
51
- wp_nonce_field( 'bp-em-admin' );
52
- ?>
53
-
54
- </form>
55
- <?php
56
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/em-booking.php CHANGED
@@ -1,29 +1,73 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  class EM_Booking extends EM_Object{
3
  //DB Fields
4
- var $id;
5
  var $event_id;
6
  var $person_id;
7
- var $price;
8
- var $spaces;
9
- var $comment;
10
- var $status = 0;
11
- var $notes = array();
 
 
12
  var $fields = array(
13
  'booking_id' => array('name'=>'id','type'=>'%d'),
14
  'event_id' => array('name'=>'event_id','type'=>'%d'),
15
  'person_id' => array('name'=>'person_id','type'=>'%d'),
16
- 'booking_price' => array('name'=>'price','type'=>'%d'),
17
  'booking_spaces' => array('name'=>'spaces','type'=>'%d'),
18
  'booking_comment' => array('name'=>'comment','type'=>'%s'),
19
- 'booking_status' => array('name'=>'status','type'=>'%d')
 
 
 
20
  );
21
  //Other Vars
 
 
 
 
 
22
  var $timestamp;
23
  var $person;
24
  var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
25
  var $feedback_message = "";
26
  var $errors = array();
 
 
 
 
 
27
  /**
28
  * Contains an array of custom fields for a booking. This is loaded from em_meta, where the booking_custom name contains arrays of data.
29
  * @var array
@@ -33,7 +77,7 @@ class EM_Booking extends EM_Object{
33
  * If saved in this instance, you can see what previous approval status was.
34
  * @var int
35
  */
36
- var $previous_status;
37
  /**
38
  * The booking approval status number corresponds to a state in this array.
39
  * @var unknown_type
@@ -64,32 +108,24 @@ class EM_Booking extends EM_Object{
64
  */
65
  function EM_Booking( $booking_data = false ){
66
  //Get the person for this booking
 
67
  if( $booking_data !== false ){
68
  //Load booking data
69
  $booking = array();
70
  if( is_array($booking_data) ){
71
  $booking = $booking_data;
72
  }elseif( is_numeric($booking_data) ){
73
- //Retreiving from the database
74
- global $wpdb;
75
- $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." LEFT JOIN ". EM_META_TABLE ." ON object_id=booking_id WHERE booking_id ='$booking_data'";
76
  $booking = $wpdb->get_row($sql, ARRAY_A);
77
- //Custom Fields
78
- $custom = $wpdb->get_row("SELECT meta_key, meta_value FROM ". EM_BOOKINGS_TABLE ." LEFT JOIN ". EM_META_TABLE ." ON object_id=booking_id WHERE booking_id ='$booking_data' AND meta_key='booking_custom'");
79
- //Booking notes
80
- $notes = $wpdb->get_results("SELECT * FROM ". EM_META_TABLE ." WHERE meta_key='booking-note' AND object_id ='$booking_data'", ARRAY_A);
81
- foreach($notes as $note){
82
- $this->notes[] = unserialize($note['meta_value']);
83
- }
84
  }
 
 
85
  //Save into the object
86
  $this->to_object($booking);
 
87
  $this->get_person();
88
- $this->timestamp = strtotime($booking['booking_date']);
89
- //Add custom booking data
90
- if( !empty($custom['meta_key']) && $custom['meta_key'] == 'booking_custom' && is_serialized($custom['meta_value']) ){
91
- $this->custom = unserialize($custom['meta_value']);
92
- }
93
  }
94
  //Do it here so things appear in the po file.
95
  $this->status_array = array(
@@ -97,61 +133,91 @@ class EM_Booking extends EM_Object{
97
  1 => __('Approved','dbem'),
98
  2 => __('Rejected','dbem'),
99
  3 => __('Cancelled','dbem'),
100
- 4 => __('Awaiting Online Payment','dbem')
 
101
  );
 
 
 
 
 
 
 
102
  do_action('em_booking', $this, $booking_data);
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  /**
106
  * Saves the booking into the database, whether a new or existing booking
 
107
  * @return boolean
108
  */
109
- function save(){
110
  global $wpdb;
111
  $table = EM_BOOKINGS_TABLE;
112
  do_action('em_booking_save_pre',$this);
113
- if( $this->validate() ){
114
- if( $this->can_manage() ){
115
- $this->person_id = $this->get_person()->ID;
116
- //Step 1. Save the booking
117
- $data = $this->to_array();
118
- if($this->id != ''){
119
- $update = true;
120
- $where = array( 'booking_id' => $this->id );
121
- $result = $wpdb->update($table, $data, $where, $this->get_types($data));
122
- $this->feedback_message = __('Changes saved','dbem');
123
- }else{
124
- $update = false;
125
- $result = $wpdb->insert($table, $data, $this->get_types($data));
126
- $this->id = $wpdb->insert_id;
127
- $this->feedback_message = __('Your booking has been recorded','dbem');
128
- }
129
- if( $result === false ){
130
- $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
131
- $this->errors[] = __('There was a problem saving the booking.', 'dbem');
132
- }else{
133
- //Step 2. Insert ticket bookings for this booking id
134
- $tickets_bookings_result = $this->get_tickets_bookings()->save();
135
- if( !$tickets_bookings_result ){
136
- if( !$update ){
137
- //delete the booking and tickets, instead of a transaction
138
- $this->delete();
139
- }
140
- $this->errors[] = __('There was a problem saving the booking.', 'dbem');
141
- $this->add_errors( $this->get_tickets_bookings()->get_errors() );
142
- }
143
- }
144
- return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
145
  }else{
 
 
 
 
 
 
 
 
 
 
146
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
147
- if( !$this->can_manage() ){
148
- $this->feedback_message = sprintf(__('You cannot manage this %s.', 'dbem'),__('Booking','dbem'));
 
 
 
 
 
 
 
 
149
  }
150
  }
 
 
 
 
 
 
151
  }else{
152
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
153
  if( !$this->can_manage() ){
154
- $this->feedback_message = sprintf(__('You cannot manage this %s.', 'dbem'),__('Booking','dbem'));
155
  }
156
  }
157
  return apply_filters('em_booking_save', false, $this);
@@ -168,7 +234,7 @@ class EM_Booking extends EM_Object{
168
  $conds = array();
169
  foreach($search as $key => $value) {
170
  if( array_key_exists($key, $this->fields) ){
171
- $value = $wpdb->escape($value);
172
  $conds[] = "`$key`='$value'";
173
  }
174
  }
@@ -187,47 +253,58 @@ class EM_Booking extends EM_Object{
187
  * Get posted data and save it into the object (not db)
188
  * @return boolean
189
  */
190
- function get_post(){
191
- $this->tickets_bookings = new EM_Tickets_Bookings($this->id);
 
192
  $result = array();
193
- $this->event_id = $this->get_event()->id;
194
- if( !empty($_POST['em_tickets']) && is_array($_POST['em_tickets']) ){
195
- foreach( $_POST['em_tickets'] as $ticket_id => $values){
196
  //make sure ticket exists
197
- if( !empty($values['spaces']) ){
198
- $args = array('ticket_id'=>$ticket_id, 'ticket_booking_spaces'=>$values['spaces'], 'booking_id'=>$this->id);
199
  if($this->get_event()->get_bookings()->ticket_exists($ticket_id)){
200
- $EM_Ticket_Booking = new EM_Ticket_Booking($args);
201
- $EM_Ticket_Booking->booking = $this;
202
- $this->tickets_bookings->add( $EM_Ticket_Booking );
 
 
203
  }else{
204
  $this->errors[]=__('You are trying to book a non-existent ticket for this event.','dbem');
205
  }
206
  }
207
  }
208
- $this->comment = (!empty($_REQUEST['booking_comment'])) ? $_REQUEST['booking_comment']:'';
209
- $this->get_spaces();
210
- $this->get_price();
 
 
 
 
 
 
211
  $this->get_person();
212
- }
213
- return apply_filters('em_booking_get_post',$this->validate(),$this);
 
 
214
  }
215
 
216
- function validate(){
217
  //step 1, basic info
218
  $basic = (
219
  (empty($this->event_id) || is_numeric($this->event_id)) &&
220
  (empty($this->person_id) || is_numeric($this->person_id)) &&
221
- is_numeric($this->spaces) && $this->spaces > 0
222
  );
223
  //give some errors in step 1
224
- if( $this->spaces == 0 ){
225
- $this->add_error(__('You must request at least one space to book an event.','dbem'));
226
  }
227
  //step 2, tickets bookings info
228
  if( count($this->get_tickets_bookings()) > 0 ){
229
  $ticket_validation = array();
230
- foreach($this->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){
231
  if ( !$EM_Ticket_Booking->validate() ){
232
  $ticket_validation[] = false;
233
  $result = $basic && !in_array(false,$ticket_validation);
@@ -238,7 +315,16 @@ class EM_Booking extends EM_Object{
238
  }else{
239
  $result = false;
240
  }
241
-
 
 
 
 
 
 
 
 
 
242
  return apply_filters('em_booking_validate',$result,$this);
243
  }
244
 
@@ -248,58 +334,236 @@ class EM_Booking extends EM_Object{
248
  * @return mixed
249
  */
250
  function get_spaces( $force_refresh=false ){
251
- if($this->spaces == 0 || $force_refresh == true ){
252
- $this->spaces = $this->get_tickets_bookings()->get_spaces($force_refresh);
253
  }
254
- return apply_filters('em_booking_get_spaces',$this->spaces,$this);
255
  }
256
 
 
 
257
  /**
258
- * Gets the total price for this whole booking. Seting $force_reset to true will recheck spaces, even if previously done so.
259
- * @param boolean $force_refresh
260
- * @return float
 
261
  */
262
- function get_price( $force_refresh=false, $format=false ){
263
- if($force_refresh || $this->price == 0){
264
- $this->price = $this->get_tickets_bookings()->get_price($force_refresh);
 
 
 
265
  }
 
266
  if($format){
267
- return apply_filters('em_booking_get_prices', em_get_currency_symbol().number_format($this->price,2),$this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
- return apply_filters('em_booking_get_prices',$this->price,$this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  }
271
 
 
 
272
  /**
273
  * Gets the event this booking belongs to and saves a refernece in the event property
274
  * @return EM_Event
275
  */
276
  function get_event(){
277
  global $EM_Event;
278
- if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->id == $this->event_id ){
279
  return $this->event;
280
- }elseif( is_object($EM_Event) && ( (is_object($this->event) &&$this->event->id == $this->event_id) || empty($this->id)) ){
281
  $this->event = $EM_Event;
282
  }else{
283
- $this->event = new EM_Event($this->event_id);
284
- }
285
- return apply_filters('em_booking_get_event',$this->event);
286
- }
287
-
288
- /**
289
- * Get custom fields for this booking.
290
- * @return array
291
- */
292
- function get_custom(){
293
- global $wpdb;
294
- if( count($this->custom) == 0 ){
295
- $sql = "SELECT * FROM ". EM_META_TABLE ." WHERE object_id ='{$this->id}' AND (meta_key='booking_custom' OR meta_key IS NULL)";
296
- $booking = $wpdb->get_row($sql, ARRAY_A);
297
- //Add custom booking data
298
- if( !empty($booking['meta_key']) && $booking['meta_key'] == 'booking_custom' && is_serialized($booking['meta_value']) ){
299
- $this->custom = unserialize($booking['meta_value']);
300
- }
301
  }
302
- return $this->custom;
303
  }
304
 
305
  /**
@@ -321,30 +585,144 @@ class EM_Booking extends EM_Object{
321
  */
322
  function get_tickets_bookings(){
323
  global $wpdb;
324
- if( !is_object($this->tickets_bookings) && get_class($this->tickets_bookings)!='EM_Tickets_Bookings'){
325
  $this->tickets_bookings = new EM_Tickets_Bookings($this);
326
  }
327
  return apply_filters('em_booking_get_tickets_bookings', $this->tickets_bookings, $this);
328
  }
329
 
 
 
 
330
  function get_person(){
331
  global $EM_Person;
332
  if( is_object($this->person) && get_class($this->person)=='EM_Person' && ($this->person->ID == $this->person_id || empty($this->person_id) ) ){
333
- return apply_filters('em_booking_get_person', $this->person, $this);
334
- }elseif( is_object($EM_Person) && ($EM_Person->ID === $this->person_id || $this->id == '') ){
335
  $this->person = $EM_Person;
 
336
  }elseif( is_numeric($this->person_id) ){
337
  $this->person = new EM_Person($this->person_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  }
339
  return apply_filters('em_booking_get_person', $this->person, $this);
340
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
  /**
343
  * Returns a string representation of the booking's status
344
  * @return string
345
  */
346
  function get_status(){
347
- return $this->status_array[$this->status];
 
348
  }
349
 
350
  /**
@@ -353,87 +731,115 @@ class EM_Booking extends EM_Object{
353
  */
354
  function delete(){
355
  global $wpdb;
356
- //FIXME ticket logic needed
357
- $sql = $wpdb->prepare("DELETE FROM ". EM_BOOKINGS_TABLE . " WHERE booking_id=%d", $this->id);
358
- $result = $wpdb->query( $sql );
359
- if( $result !== false ){
360
- //delete the tickets too
361
- $this->get_tickets_bookings()->delete();
362
- $this->previous_status = $this->status;
363
- $this->status = false;
364
- $this->feedback_message = sprintf(__('%s deleted', 'dbem'), __('Booking','dbem'));
365
- }else{
366
- $this->add_error(sprintf(__('%s could not be deleted', 'dbem'), __('Booking','dbem')));
 
 
 
367
  }
368
  return apply_filters('em_booking_delete',( $result !== false ), $this);
369
  }
370
 
371
- function cancel(){
372
  if( $this->person->ID == get_current_user_id() ){
373
  $this->manage_override = true; //normally, users can't manage a bookiing, only event owners, so we allow them to mod their booking status in this case only.
374
  }
375
- return $this->set_status(3);
376
  }
377
 
378
  /**
379
  * Approve a booking.
380
  * @return bool
381
  */
382
- function approve(){
383
- return $this->set_status(1);
384
  }
385
  /**
386
  * Reject a booking and save
387
  * @return bool
388
  */
389
- function reject(){
390
- return $this->set_status(2);
391
  }
392
  /**
393
- * Unpprove a booking.
394
  * @return bool
395
  */
396
- function unapprove(){
397
- return $this->set_status(0);
398
  }
399
 
400
  /**
401
  * Change the status of the booking. This will save to the Database too.
402
- * @param unknown_type $status
403
- * @return string
404
  */
405
- function set_status($status){
 
406
  $action_string = strtolower($this->status_array[$status]);
407
  //if we're approving we can't approve a booking if spaces are full, so check before it's approved.
408
- if($status == 1){
409
- if( $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() && !get_option('dbem_bookings_approval_overbooking') ){
410
  $this->feedback_message = sprintf(__('Not approved, spaces full.','dbem'), $action_string);
 
411
  return apply_filters('em_booking_set_status', false, $this);
412
  }
413
  }
414
- $this->previous_status = $this->status;
415
- $this->status = $status;
416
- $result = $this->save();
417
- if($result){
418
  $this->feedback_message = sprintf(__('Booking %s.','dbem'), $action_string);
419
- if( !($this->status == 0 && $this->previous_status > 0) || $this->previous_status == 4 ){
420
- if( $this->email() ){
421
- $this->feedback_message .= " ".__('Mail Sent.','dbem');
422
  }elseif( $this->previous_status == 0 ){
423
  //extra errors may be logged by email() in EM_Object
424
- $this->feedback_message .= ' <span style="color:red">'.__('ERROR : Mail Not Sent.','dbem').'</span>';
425
- $this->add_error(__('ERROR : Mail Not Sent.','dbem'));
426
- $result = false;
427
  }
428
  }
429
  }else{
430
  //errors should be logged by save()
431
  $this->feedback_message = sprintf(__('Booking could not be %s.','dbem'), $action_string);
432
  $this->add_error(sprintf(__('Booking could not be %s.','dbem'), $action_string));
 
433
  }
434
  return apply_filters('em_booking_set_status', $result, $this);
435
  }
436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  /**
438
  * Add a booking note to this booking. returns wpdb result or false if use can't manage this event.
439
  * @param string $note
@@ -442,106 +848,238 @@ class EM_Booking extends EM_Object{
442
  function add_note( $note_text ){
443
  global $wpdb;
444
  if( $this->can_manage() ){
 
445
  $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
446
  $this->notes[] = $note;
447
  $this->feedback_message = __('Booking note successfully added.','dbem');
448
- return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
449
  }
450
  return false;
451
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
 
453
  /**
454
  * @param EM_Booking $EM_Booking
455
  * @param EM_Event $event
456
  * @return boolean
457
  */
458
- function email(){
459
  global $EM_Mailer;
 
 
 
460
  //FIXME ticket logic needed
461
  $EM_Event = $this->get_event(); //We NEED event details here.
 
 
462
  //Make sure event matches booking, and that booking used to be approved.
463
- if( !($this->status == 0 && $this->previous_status > 0) || $this->previous_status == 4 ){
464
- $contact_id = ( $EM_Event->owner != "") ? $EM_Event->owner : get_option('dbem_default_contact_person');
465
-
466
- $contact_subject = get_option('dbem_bookings_contact_email_subject');
467
- $contact_body = get_option('dbem_bookings_contact_email_body');
468
-
469
- if( get_option('dbem_bookings_approval') == 0 && $this->status < 2 || $this->status == 1 ){
470
- $booker_subject = get_option('dbem_bookings_email_confirmed_subject');
471
- $booker_body = get_option('dbem_bookings_email_confirmed_body');
472
- }elseif( $this->status == 0 || $this->previous_status == 4 ){
473
- $booker_subject = get_option('dbem_bookings_email_pending_subject');
474
- $booker_body = get_option('dbem_bookings_email_pending_body');
475
- }elseif( $this->status == 2 ){
476
- $booker_subject = get_option('dbem_bookings_email_rejected_subject');
477
- $booker_body = get_option('dbem_bookings_email_rejected_body');
478
- }elseif( $this->status == 3 ){
479
- $booker_subject = get_option('dbem_bookings_email_cancelled_subject');
480
- $booker_body = get_option('dbem_bookings_email_cancelled_body');
481
- $contact_subject = get_option('dbem_contactperson_email_cancelled_subject');
482
- $contact_body = get_option('dbem_contactperson_email_cancelled_body');
483
- }
484
-
485
- // email specific placeholders
486
- $placeholders = array(
487
- '#_RESPNAME' => '#_BOOKINGNAME',//Depreciated
488
- '#_RESPEMAIL' => '#_BOOKINGEMAIL',//Depreciated
489
- '#_RESPPHONE' => '#_BOOKINGPHONE',//Depreciated
490
- '#_COMMENT' => '#_BOOKINGCOMMENT',//Depreciated
491
- '#_RESERVEDSPACES' => '#_BOOKEDSPACES',//Depreciated
492
- '#_BOOKINGNAME' => $this->person->display_name,
493
- '#_BOOKINGEMAIL' => $this->person->user_email,
494
- '#_BOOKINGPHONE' => $this->person->phone,
495
- '#_BOOKINGSPACES' => $this->get_spaces(),
496
- '#_BOOKINGLISTURL' => em_get_my_bookings_url(),
497
- '#_BOOKINGCOMMENT' => $this->comment,
498
- );
499
- foreach($placeholders as $key => $value) {
500
- $contact_subject = str_replace($key, $value, $contact_subject);
501
- $contact_body = str_replace($key, $value, $contact_body);
502
- $booker_subject = str_replace($key, $value, $booker_subject);
503
- $booker_body = str_replace($key, $value, $booker_body);
504
- }
505
-
506
- $booker_subject = $EM_Event->output($booker_subject, 'email');
507
- $booker_body = $EM_Event->output($booker_body, 'email');
508
-
509
- //Send to the person booking
510
- if( !$this->email_send( $booker_subject,$booker_body, $this->person->user_email) ){
511
- return false;
512
  }
513
 
514
- //Send admin/contact emails
515
- if( (get_option('dbem_bookings_approval') == 0 || $this->status == 0 || $this->status == 3) && (get_option('dbem_bookings_contact_email') == 1 || get_option('dbem_bookings_notify_admin') != '') ){
516
- //Only gets sent if this is a pending booking, unless approvals are disabled.
517
- $contact_subject = $EM_Event->output($contact_subject, 'email');
518
- $contact_body = $EM_Event->output($contact_body, 'email');
519
-
520
- if( get_option('dbem_bookings_contact_email') == 1 ){
521
- if( !$this->email_send( $contact_subject, $contact_body, $EM_Event->contact->user_email) && current_user_can('activate_plugins')){
522
- $this->errors[] = __('Confirmation email could not be sent to contact person. Registrant should have gotten their email (only admin see this warning).','dbem');
523
- return false;
 
 
 
 
 
 
 
 
 
524
  }
525
- }
526
-
527
- if( get_option('dbem_bookings_notify_admin') != '' && preg_match('/^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3}$/', get_option('dbem_bookings_notify_admin')) ){
528
- if( !$this->email_send( $contact_subject, $contact_body, get_option('dbem_bookings_notify_admin')) ){
529
- $this->errors[] = __('Confirmation email could not be sent to admin. Registrant should have gotten their email (only admin see this warning).','dbem');
530
- return false;
 
 
531
  }
532
  }
533
  }
534
- return true;
535
  }
536
- return false;
537
  //TODO need error checking for booking mail send
538
  }
539
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
  /**
541
  * Can the user manage this event?
542
  */
543
- function can_manage(){
544
- return $this->get_event()->can_manage('manage_bookings','manage_others_bookings') || empty($this->id) || !empty($this->manage_override);
545
  }
546
 
547
  /**
1
  <?php
2
+ /**
3
+ * gets a booking in a more db-friendly manner, allows hooking into booking object right after instantiation
4
+ * @param mixed $id
5
+ * @param mixed $search_by
6
+ * @return EM_Booking
7
+ */
8
+ function em_get_booking($id = false) {
9
+ global $EM_Booking;
10
+ //check if it's not already global so we don't instantiate again
11
+ if( is_object($EM_Booking) && get_class($EM_Booking) == 'EM_Booking' ){
12
+ if( is_object($id) && $EM_Booking->booking_id == $id->booking_id ){
13
+ return apply_filters('em_get_booking', $EM_Booking);
14
+ }else{
15
+ if( is_numeric($id) && $EM_Booking->booking_id == $id ){
16
+ return apply_filters('em_get_booking', $EM_Booking);
17
+ }elseif( is_array($id) && !empty($id['booking_id']) && $EM_Booking->booking_id == $id['booking_id'] ){
18
+ return apply_filters('em_get_booking', $EM_Booking);
19
+ }
20
+ }
21
+ }
22
+ if( is_object($id) && get_class($id) == 'EM_Booking' ){
23
+ return apply_filters('em_get_booking', $id);
24
+ }else{
25
+ return apply_filters('em_get_booking', new EM_Booking($id));
26
+ }
27
+ }
28
+ /**
29
+ * Contains all information and relevant functions surrounding a single booking made with Events Manager
30
+ */
31
  class EM_Booking extends EM_Object{
32
  //DB Fields
33
+ var $booking_id;
34
  var $event_id;
35
  var $person_id;
36
+ var $booking_price = null;
37
+ var $booking_spaces;
38
+ var $booking_comment;
39
+ var $booking_status = false;
40
+ var $booking_tax_rate = null;
41
+ var $booking_taxes = null;
42
+ var $booking_meta = array();
43
  var $fields = array(
44
  'booking_id' => array('name'=>'id','type'=>'%d'),
45
  'event_id' => array('name'=>'event_id','type'=>'%d'),
46
  'person_id' => array('name'=>'person_id','type'=>'%d'),
47
+ 'booking_price' => array('name'=>'price','type'=>'%f'),
48
  'booking_spaces' => array('name'=>'spaces','type'=>'%d'),
49
  'booking_comment' => array('name'=>'comment','type'=>'%s'),
50
+ 'booking_status' => array('name'=>'status','type'=>'%d'),
51
+ 'booking_tax_rate' => array('name'=>'tax_rate','type'=>'%f','null'=>1),
52
+ 'booking_taxes' => array('name'=>'taxes','type'=>'%f','null'=>1),
53
+ 'booking_meta' => array('name'=>'meta','type'=>'%s')
54
  );
55
  //Other Vars
56
+ /**
57
+ * array of notes by admins on this booking. loaded from em_meta table in construct
58
+ * @var array
59
+ */
60
+ var $notes;
61
  var $timestamp;
62
  var $person;
63
  var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
64
  var $feedback_message = "";
65
  var $errors = array();
66
+ /**
67
+ * when using EM_Booking::email_send(), this number is updated with sent emails
68
+ * @var int
69
+ */
70
+ var $mails_sent = 0;
71
  /**
72
  * Contains an array of custom fields for a booking. This is loaded from em_meta, where the booking_custom name contains arrays of data.
73
  * @var array
77
  * If saved in this instance, you can see what previous approval status was.
78
  * @var int
79
  */
80
+ var $previous_status = false;
81
  /**
82
  * The booking approval status number corresponds to a state in this array.
83
  * @var unknown_type
108
  */
109
  function EM_Booking( $booking_data = false ){
110
  //Get the person for this booking
111
+ global $wpdb;
112
  if( $booking_data !== false ){
113
  //Load booking data
114
  $booking = array();
115
  if( is_array($booking_data) ){
116
  $booking = $booking_data;
117
  }elseif( is_numeric($booking_data) ){
118
+ //Retreiving from the database
119
+ $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE booking_id ='$booking_data'";
 
120
  $booking = $wpdb->get_row($sql, ARRAY_A);
 
 
 
 
 
 
 
121
  }
122
+ //booking meta
123
+ $booking['booking_meta'] = (!empty($booking['booking_meta'])) ? maybe_unserialize($booking['booking_meta']):array();
124
  //Save into the object
125
  $this->to_object($booking);
126
+ $this->previous_status = $this->booking_status;
127
  $this->get_person();
128
+ $this->timestamp = !empty($booking['booking_date']) ? strtotime($booking['booking_date'], current_time('timestamp')):false;
 
 
 
 
129
  }
130
  //Do it here so things appear in the po file.
131
  $this->status_array = array(
133
  1 => __('Approved','dbem'),
134
  2 => __('Rejected','dbem'),
135
  3 => __('Cancelled','dbem'),
136
+ 4 => __('Awaiting Online Payment','dbem'),
137
+ 5 => __('Awaiting Payment','dbem')
138
  );
139
+ $this->compat_keys(); //depricating in 6.0
140
+ //do some legacy checking here for bookings made prior to 5.4, due to how taxes are calculated
141
+ $this->get_tax_rate();
142
+ if( !empty($this->legacy_tax_rate) ){
143
+ //reset booking_price, it'll be recalculated later (if you're using this property directly, don't, use $this->get_price())
144
+ $this->booking_price = $this->booking_taxes = null;
145
+ }
146
  do_action('em_booking', $this, $booking_data);
147
  }
148
 
149
+ function get_notes(){
150
+ global $wpdb;
151
+ if( !is_array($this->notes) && !empty($this->booking_id) ){
152
+ $notes = $wpdb->get_results("SELECT * FROM ". EM_META_TABLE ." WHERE meta_key='booking-note' AND object_id ='{$this->booking_id}'", ARRAY_A);
153
+ $this->notes = array();
154
+ foreach($notes as $note){
155
+ $this->notes[] = unserialize($note['meta_value']);
156
+ }
157
+ }elseif( empty($this->booking_id) ){
158
+ $this->notes = array();
159
+ }
160
+ return $this->notes;
161
+ }
162
+
163
  /**
164
  * Saves the booking into the database, whether a new or existing booking
165
+ * @param $mail whether or not to email the user and contact people
166
  * @return boolean
167
  */
168
+ function save($mail = true){
169
  global $wpdb;
170
  $table = EM_BOOKINGS_TABLE;
171
  do_action('em_booking_save_pre',$this);
172
+ if( $this->can_manage() ){
173
+ //update prices, spaces, person_id
174
+ $this->get_spaces(true);
175
+ $this->calculate_price();
176
+ $this->person_id = (empty($this->person_id)) ? $this->get_person()->ID : $this->person_id;
177
+ //Step 1. Save the booking
178
+ $data = $this->to_array();
179
+ $data['booking_meta'] = serialize($data['booking_meta']);
180
+ //update or save
181
+ if($this->booking_id != ''){
182
+ $update = true;
183
+ $where = array( 'booking_id' => $this->booking_id );
184
+ $result = $wpdb->update($table, $data, $where, $this->get_types($data));
185
+ $result = ($result !== false);
186
+ $this->feedback_message = __('Changes saved','dbem');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }else{
188
+ $update = false;
189
+ $data_types = $this->get_types($data);
190
+ $data['booking_date'] = current_time('mysql');
191
+ $data_types[] = '%s';
192
+ $result = $wpdb->insert($table, $data, $data_types);
193
+ $this->booking_id = $wpdb->insert_id;
194
+ $this->feedback_message = __('Your booking has been recorded','dbem');
195
+ }
196
+ //Step 2. Insert ticket bookings for this booking id if no errors so far
197
+ if( $result === false ){
198
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
199
+ $this->errors[] = __('There was a problem saving the booking.', 'dbem');
200
+ }else{
201
+ $tickets_bookings_result = $this->get_tickets_bookings()->save();
202
+ if( !$tickets_bookings_result ){
203
+ if( !$update ){
204
+ //delete the booking and tickets, instead of a transaction
205
+ $this->delete();
206
+ }
207
+ $this->errors[] = __('There was a problem saving the booking.', 'dbem');
208
+ $this->add_error( $this->get_tickets_bookings()->get_errors() );
209
  }
210
  }
211
+ //Step 3. email if necessary
212
+ if ( count($this->errors) == 0 && $mail ) {
213
+ $this->email();
214
+ }
215
+ $this->compat_keys();
216
+ return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
217
  }else{
218
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
219
  if( !$this->can_manage() ){
220
+ $this->add_error(sprintf(__('You cannot manage this %s.', 'dbem'),__('Booking','dbem')));
221
  }
222
  }
223
  return apply_filters('em_booking_save', false, $this);
234
  $conds = array();
235
  foreach($search as $key => $value) {
236
  if( array_key_exists($key, $this->fields) ){
237
+ $value = esc_sql($value);
238
  $conds[] = "`$key`='$value'";
239
  }
240
  }
253
  * Get posted data and save it into the object (not db)
254
  * @return boolean
255
  */
256
+ function get_post( $override_availability = false ){
257
+ $this->tickets_bookings = new EM_Tickets_Bookings($this->booking_id);
258
+ do_action('em_booking_get_post_pre',$this);
259
  $result = array();
260
+ $this->event_id = $_REQUEST['event_id'];
261
+ if( isset($_REQUEST['em_tickets']) && is_array($_REQUEST['em_tickets']) && ($_REQUEST['em_tickets'] || $override_availability) ){
262
+ foreach( $_REQUEST['em_tickets'] as $ticket_id => $values){
263
  //make sure ticket exists
264
+ if( !empty($values['spaces']) || $override_availability ){
265
+ $args = array('ticket_id'=>$ticket_id, 'ticket_booking_spaces'=>$values['spaces'], 'booking_id'=>$this->booking_id);
266
  if($this->get_event()->get_bookings()->ticket_exists($ticket_id)){
267
+ $EM_Ticket_Booking = new EM_Ticket_Booking($args);
268
+ $EM_Ticket_Booking->booking = $this;
269
+ if( !$this->tickets_bookings->add( $EM_Ticket_Booking, $override_availability ) ){
270
+ $this->add_error($this->tickets_bookings->get_errors());
271
+ }
272
  }else{
273
  $this->errors[]=__('You are trying to book a non-existent ticket for this event.','dbem');
274
  }
275
  }
276
  }
277
+ $this->booking_comment = (!empty($_REQUEST['booking_comment'])) ? wp_kses_data(stripslashes($_REQUEST['booking_comment'])):'';
278
+ //allow editing of tax rate
279
+ if( !empty($this->booking_id) && $this->can_manage() ){
280
+ $this->booking_tax_rate = (!empty($_REQUEST['booking_tax_rate']) && is_numeric($_REQUEST['booking_tax_rate'])) ? $_REQUEST['booking_tax_rate']:$this->booking_tax_rate;
281
+ }
282
+ //recalculate spaces/price
283
+ $this->get_spaces(true);
284
+ $this->calculate_price();
285
+ //get person
286
  $this->get_person();
287
+ //re-run compatiblity keys function
288
+ $this->compat_keys(); //depricating in 6.0
289
+ }
290
+ return apply_filters('em_booking_get_post',count($this->errors) == 0,$this);
291
  }
292
 
293
+ function validate( $override_availability = false ){
294
  //step 1, basic info
295
  $basic = (
296
  (empty($this->event_id) || is_numeric($this->event_id)) &&
297
  (empty($this->person_id) || is_numeric($this->person_id)) &&
298
+ is_numeric($this->booking_spaces) && $this->booking_spaces > 0
299
  );
300
  //give some errors in step 1
301
+ if( $this->booking_spaces == 0 ){
302
+ $this->add_error(get_option('dbem_booking_feedback_min_space'));
303
  }
304
  //step 2, tickets bookings info
305
  if( count($this->get_tickets_bookings()) > 0 ){
306
  $ticket_validation = array();
307
+ foreach($this->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){ /* @var $EM_Ticket_Booking EM_Ticket_Booking */
308
  if ( !$EM_Ticket_Booking->validate() ){
309
  $ticket_validation[] = false;
310
  $result = $basic && !in_array(false,$ticket_validation);
315
  }else{
316
  $result = false;
317
  }
318
+ //is there enough space overall?
319
+ if( !$override_availability && $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() ){
320
+ $result = false;
321
+ $this->add_error(get_option('dbem_booking_feedback_full'));
322
+ }
323
+ //can we book this amount of spaces at once?
324
+ if( $this->get_event()->event_rsvp_spaces > 0 && $this->get_spaces() > $this->get_event()->event_rsvp_spaces ){
325
+ $result = false;
326
+ $this->add_error( sprintf(get_option('dbem_booking_feedback_spaces_limit'), $this->get_event()->event_rsvp_spaces));
327
+ }
328
  return apply_filters('em_booking_validate',$result,$this);
329
  }
330
 
334
  * @return mixed
335
  */
336
  function get_spaces( $force_refresh=false ){
337
+ if($this->booking_spaces == 0 || $force_refresh == true ){
338
+ $this->booking_spaces = $this->get_tickets_bookings()->get_spaces($force_refresh);
339
  }
340
+ return apply_filters('em_booking_get_spaces',$this->booking_spaces,$this);
341
  }
342
 
343
+ /* Price Calculations */
344
+
345
  /**
346
+ * Gets the total price for this whole booking, including any discounts, taxes, and any other additional items. In other words, what the person has to pay or has supposedly paid.
347
+ * This price shouldn't change once established, unless there's any alteration to the booking itself that'd affect the price, such as a change in ticket numbers, discount, etc.
348
+ * @param boolean $format
349
+ * @return double|string
350
  */
351
+ function get_price( $format = false, $format_depricated = null ){
352
+ if( $format_depricated !== null ) $format = $format_depricated; //support for old parameters, will be depricated soon
353
+ //recalculate price here only if price is not actually set
354
+ if( $this->booking_price === null ){
355
+ $this->calculate_price();
356
+ apply_filters('em_booking_get_price', $this->booking_price, $this);
357
  }
358
+ //return booking_price, formatted or not
359
  if($format){
360
+ return $this->format_price($this->booking_price);
361
+ }
362
+ return $this->booking_price;
363
+ }
364
+
365
+ /**
366
+ * Total of tickets without taxes, discounts or any other modification. No filter given here for that very reason!
367
+ * @param boolean $format
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
+ }
375
+ return $price;
376
+ }
377
+
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);
385
+ return $price;
386
+ }
387
+
388
+ /**
389
+ * Gets price AFTER taxes and post-tax discounts have also been added
390
+ * @param boolean $format
391
+ * @return double|string
392
+ */
393
+ function get_price_post_taxes( $format = false ){
394
+ //get price before taxes
395
+ $price = $this->get_price_pre_taxes();
396
+ //add taxes to price
397
+ if( $this->get_tax_rate() > 0 ){
398
+ $this->booking_taxes = $price * ($this->get_tax_rate()/100); //calculate and save tax amount
399
+ $price += $this->booking_taxes; //add taxes
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);
407
+ return $price;
408
+ }
409
+
410
+ /**
411
+ * Get amount of taxes applied to this booking price.
412
+ * @param boolean $format
413
+ * @return double|string
414
+ */
415
+ function get_price_taxes( $format=false ){
416
+ if( $this->booking_taxes !== null ){
417
+ $this->booking_taxes; //taxes already calculated
418
+ }else{
419
+ $this->calculate_price(); //recalculate price and taxes
420
+ }
421
+ //return amount of taxes applied, formatted or not
422
+ if( $format ){
423
+ return $this->format_price($this->booking_taxes);
424
+ }
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
435
+ */
436
+ function calculate_price(){
437
+ //reset price and taxes calculations
438
+ $this->booking_price = $this->booking_taxes = null;
439
+ //get post-tax price and save it to booking_price
440
+ $this->booking_price = apply_filters('em_booking_calculate_price', $this->get_price_post_taxes(), $this);
441
+ return $this->booking_price;
442
+ }
443
+
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
453
+ //no tax applied yet to an existing booking, or tax possibly applied (but handled seperately in EM_Tickets_Bookings but in legacy < v5.4
454
+ //sort out MultiSite nuances
455
+ if( EM_MS_GLOBAL && $this->get_event()->blog_id != get_current_blog_id() ){
456
+ //MultiSite AND Global tables enabled AND this event belongs to another blog - get settings for blog that published the event
457
+ $this->booking_tax_rate = get_blog_option($this->get_event()->blog_id, 'dbem_legacy_bookings_tax');
458
+ }else{
459
+ //get booking from current site, whether or not we're in MultiSite
460
+ $this->booking_tax_rate = get_option('dbem_legacy_bookings_tax');
461
+ }
462
+ $this->legacy_tax_rate = true;
463
+ }else{
464
+ //first time we're applying tax rate
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.
531
+ */
532
+ function get_price_summary_array(){
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).'%', '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
  /**
554
  * Gets the event this booking belongs to and saves a refernece in the event property
555
  * @return EM_Event
556
  */
557
  function get_event(){
558
  global $EM_Event;
559
+ if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->event_id == $this->event_id ){
560
  return $this->event;
561
+ }elseif( is_object($EM_Event) && ( (is_object($this->event) && $this->event->event_id == $this->event_id) || empty($this->booking_id)) ){
562
  $this->event = $EM_Event;
563
  }else{
564
+ $this->event = new EM_Event($this->event_id, 'event_id');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
565
  }
566
+ return apply_filters('em_booking_get_event',$this->event, $this);
567
  }
568
 
569
  /**
585
  */
586
  function get_tickets_bookings(){
587
  global $wpdb;
588
+ if( !is_object($this->tickets_bookings) || get_class($this->tickets_bookings)!='EM_Tickets_Bookings'){
589
  $this->tickets_bookings = new EM_Tickets_Bookings($this);
590
  }
591
  return apply_filters('em_booking_get_tickets_bookings', $this->tickets_bookings, $this);
592
  }
593
 
594
+ /**
595
+ * @return EM_Person
596
+ */
597
  function get_person(){
598
  global $EM_Person;
599
  if( is_object($this->person) && get_class($this->person)=='EM_Person' && ($this->person->ID == $this->person_id || empty($this->person_id) ) ){
600
+ //This person is already included, so don't do anything
601
+ }elseif( is_object($EM_Person) && ($EM_Person->ID === $this->person_id || $this->booking_id == '') ){
602
  $this->person = $EM_Person;
603
+ $this->person_id = $this->person->ID;
604
  }elseif( is_numeric($this->person_id) ){
605
  $this->person = new EM_Person($this->person_id);
606
+ }else{
607
+ $this->person = new EM_Person(0);
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){
615
+ $this->person->$key = $value;
616
+ }
617
+ }
618
+ $this->person->user_email = ( !empty($this->booking_meta['registration']['user_email']) ) ? $this->booking_meta['registration']['user_email']:$this->person->user_email;
619
+ if( !empty($this->booking_meta['registration']['user_name']) ){
620
+ $name_string = explode(' ',$this->booking_meta['registration']['user_name']);
621
+ $this->booking_meta['registration']['first_name'] = array_shift($name_string);
622
+ $this->booking_meta['registration']['last_name'] = implode(' ', $name_string);
623
+ }
624
+ $this->person->user_firstname = ( !empty($this->booking_meta['registration']['first_name']) ) ? $this->booking_meta['registration']['first_name']:__('Guest User','dbem');
625
+ $this->person->first_name = $this->person->user_firstname;
626
+ $this->person->user_lastname = ( !empty($this->booking_meta['registration']['last_name']) ) ? $this->booking_meta['registration']['last_name']:'';
627
+ $this->person->last_name = $this->person->user_lastname;
628
+ $this->person->phone = ( !empty($this->booking_meta['registration']['dbem_phone']) ) ? $this->booking_meta['registration']['dbem_phone']:__('Not Supplied','dbem');
629
+ //build display name
630
+ $full_name = $this->person->user_firstname . " " . $this->person->user_lastname ;
631
+ $full_name = trim($full_name);
632
+ $display_name = ( empty($full_name) ) ? __('Guest User','dbem'):$full_name;
633
+ $this->person->display_name = $display_name;
634
+ $this->person->loaded_no_user = $this->booking_id;
635
  }
636
  return apply_filters('em_booking_get_person', $this->person, $this);
637
  }
638
+
639
+ /**
640
+ * Gets personal information from the $_REQUEST array and saves it to the $EM_Booking->booking_meta['registration'] array
641
+ * @return boolean
642
+ */
643
+ function get_person_post(){
644
+ $user_data = array();
645
+ $registration = true;
646
+ if( empty($this->booking_meta['registration']) ) $this->booking_meta['registration'] = array();
647
+ // Check the e-mail address
648
+ if ( $_REQUEST['user_email'] == '' ) {
649
+ $registration = false;
650
+ $this->add_error(__( '<strong>ERROR</strong>: Please type your e-mail address.', 'dbem') );
651
+ } elseif ( !is_email( $_REQUEST['user_email'] ) ) {
652
+ $registration = false;
653
+ $this->add_error( __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.', 'dbem') );
654
+ }elseif(email_exists( $_REQUEST['user_email'] ) && !get_option('dbem_bookings_registration_disable_user_emails') ){
655
+ $registration = false;
656
+ $this->add_error( get_option('dbem_booking_feedback_email_exists') );
657
+ }else{
658
+ $user_data['user_email'] = $_REQUEST['user_email'];
659
+ }
660
+ //Check the user name
661
+ if( !empty($_REQUEST['user_name']) ){
662
+ //split full name up and save full, first and last names
663
+ $user_data['user_name'] = wp_kses($_REQUEST['user_name'], array());
664
+ $name_string = explode(' ',$user_data['user_name']);
665
+ $user_data['first_name'] = array_shift($name_string);
666
+ $user_data['last_name'] = implode(' ', $name_string);
667
+ }else{
668
+ //Check the first/last name
669
+ $name_string = array();
670
+ if( !empty($_REQUEST['first_name']) ){
671
+ $user_data['first_name'] = $name_string[] = wp_kses($_REQUEST['first_name'], array());
672
+ }
673
+ if( !empty($_REQUEST['last_name']) ){
674
+ $user_data['last_name'] = $name_string[] = wp_kses($_REQUEST['last_name'], array());
675
+ }
676
+ if( !empty($name_string) ) $user_data['user_name'] = implode(' ', $name_string);
677
+ }
678
+ //Save full name
679
+ if( !empty($user_data['first_name']) || !empty($user_data['last_name']) )
680
+ //Check the phone
681
+ if( !empty($_REQUEST['dbem_phone']) ){
682
+ $user_data['dbem_phone'] = wp_kses($_REQUEST['dbem_phone'], array());
683
+ }
684
+ //Add booking meta
685
+ if( $registration ){
686
+ $this->booking_meta['registration'] = array_merge($this->booking_meta['registration'], $user_data); //in case someone else added stuff
687
+ }
688
+ $registration = apply_filters('em_booking_get_person_post', $registration, $this);
689
+ if( $registration ){
690
+ $this->feedback_message = __('Personal details have successfully been modified.', 'dbem');
691
+ }
692
+ return $registration;
693
+ }
694
+
695
+ /**
696
+ * Displays a form containing user fields, used in no-user booking mode for editing guest users within a booking
697
+ * @return string
698
+ */
699
+ function get_person_editor(){
700
+ ob_start();
701
+ $name = $this->get_person()->get_name();
702
+ $email = $this->get_person()->user_email;
703
+ $phone = ($this->get_person()->phone != __('Not Supplied','dbem')) ? $this->get_person()->phone:'';
704
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'booking_modify_person' ){
705
+ $name = !empty($_REQUEST['user_name']) ? $_REQUEST['user_name']:$name;
706
+ $email = !empty($_REQUEST['user_email']) ? $_REQUEST['user_email']:$email;
707
+ $phone = !empty($_REQUEST['dbem_phone']) ? $_REQUEST['dbem_phone']:$phone;
708
+ }
709
+ ?>
710
+ <table class="em-form-fields">
711
+ <tr><th><?php _e('Name','dbem'); ?> : </th><td><input type="text" name="user_name" value="<?php echo esc_attr($name); ?>" /></td></tr>
712
+ <tr><th><?php _e('Email','dbem'); ?> : </th><td><input type="text" name="user_email" value="<?php echo esc_attr($email); ?>" /></td></tr>
713
+ <tr><th><?php _e('Phone','dbem'); ?> : </th><td><input type="text" name="dbem_phone" value="<?php echo esc_attr($phone); ?>" /></td></tr>
714
+ </table>
715
+ <?php
716
+ return apply_filters('em_booking_get_person_editor', ob_get_clean(), $this);
717
+ }
718
 
719
  /**
720
  * Returns a string representation of the booking's status
721
  * @return string
722
  */
723
  function get_status(){
724
+ $status = ($this->booking_status == 0 && !get_option('dbem_bookings_approval') ) ? 1:$this->booking_status;
725
+ return apply_filters('em_booking_get_status', $this->status_array[$status], $this);
726
  }
727
 
728
  /**
731
  */
732
  function delete(){
733
  global $wpdb;
734
+ $result = false;
735
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
736
+ $sql = $wpdb->prepare("DELETE FROM ". EM_BOOKINGS_TABLE . " WHERE booking_id=%d", $this->booking_id);
737
+ $result = $wpdb->query( $sql );
738
+ if( $result !== false ){
739
+ //delete the tickets too
740
+ $this->get_tickets_bookings()->delete();
741
+ $this->previous_status = $this->booking_status;
742
+ $this->booking_status = false;
743
+ $this->feedback_message = sprintf(__('%s deleted', 'dbem'), __('Booking','dbem'));
744
+ $wpdb->delete( EM_META_TABLE, array('meta_key'=>'booking-note', 'object_id' => $this->booking_id), array('%s','%d'));
745
+ }else{
746
+ $this->add_error(sprintf(__('%s could not be deleted', 'dbem'), __('Booking','dbem')));
747
+ }
748
  }
749
  return apply_filters('em_booking_delete',( $result !== false ), $this);
750
  }
751
 
752
+ function cancel($email = true){
753
  if( $this->person->ID == get_current_user_id() ){
754
  $this->manage_override = true; //normally, users can't manage a bookiing, only event owners, so we allow them to mod their booking status in this case only.
755
  }
756
+ return $this->set_status(3, $email);
757
  }
758
 
759
  /**
760
  * Approve a booking.
761
  * @return bool
762
  */
763
+ function approve($email = true, $ignore_spaces = false){
764
+ return $this->set_status(1, $email, $ignore_spaces);
765
  }
766
  /**
767
  * Reject a booking and save
768
  * @return bool
769
  */
770
+ function reject($email = true){
771
+ return $this->set_status(2, $email);
772
  }
773
  /**
774
+ * Unapprove a booking.
775
  * @return bool
776
  */
777
+ function unapprove($email = true){
778
+ return $this->set_status(0, $email);
779
  }
780
 
781
  /**
782
  * Change the status of the booking. This will save to the Database too.
783
+ * @param int $status
784
+ * @return boolean
785
  */
786
+ function set_status($status, $email = true, $ignore_spaces = false){
787
+ global $wpdb;
788
  $action_string = strtolower($this->status_array[$status]);
789
  //if we're approving we can't approve a booking if spaces are full, so check before it's approved.
790
+ if(!$ignore_spaces && $status == 1){
791
+ if( !$this->is_reserved() && $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() && !get_option('dbem_bookings_approval_overbooking') ){
792
  $this->feedback_message = sprintf(__('Not approved, spaces full.','dbem'), $action_string);
793
+ $this->add_error($this->feedback_message);
794
  return apply_filters('em_booking_set_status', false, $this);
795
  }
796
  }
797
+ $this->previous_status = $this->booking_status;
798
+ $this->booking_status = $status;
799
+ $result = $wpdb->query($wpdb->prepare('UPDATE '.EM_BOOKINGS_TABLE.' SET booking_status=%d WHERE booking_id=%d', array($status, $this->booking_id)));
800
+ if($result !== false){
801
  $this->feedback_message = sprintf(__('Booking %s.','dbem'), $action_string);
802
+ if( $email ){
803
+ if( $this->email() && $this->mails_sent > 0 ){
804
+ $this->feedback_message .= " ".__('Email Sent.','dbem');
805
  }elseif( $this->previous_status == 0 ){
806
  //extra errors may be logged by email() in EM_Object
807
+ $this->feedback_message .= ' <span style="color:red">'.__('ERROR : Email Not Sent.','dbem').'</span>';
808
+ $this->add_error(__('ERROR : Email Not Sent.','dbem'));
 
809
  }
810
  }
811
  }else{
812
  //errors should be logged by save()
813
  $this->feedback_message = sprintf(__('Booking could not be %s.','dbem'), $action_string);
814
  $this->add_error(sprintf(__('Booking could not be %s.','dbem'), $action_string));
815
+ $result = false;
816
  }
817
  return apply_filters('em_booking_set_status', $result, $this);
818
  }
819
 
820
+ /**
821
+ * Returns true if booking is reserving a space at this event, whether confirmed or not
822
+ */
823
+ function is_reserved(){
824
+ $result = false;
825
+ if( $this->booking_status == 0 && get_option('dbem_bookings_approval_reserved') ){
826
+ $result = true;
827
+ }elseif( $this->booking_status == 0 && !get_option('dbem_bookings_approval') ){
828
+ $result = true;
829
+ }elseif( $this->booking_status == 1 ){
830
+ $result = true;
831
+ }
832
+ return apply_filters('em_booking_is_reserved', $result, $this);
833
+ }
834
+
835
+ /**
836
+ * Returns true if booking is either pending or reserved but not confirmed (which is assumed pending)
837
+ */
838
+ function is_pending(){
839
+ $result = ($this->is_reserved() || $this->booking_status == 0) && $this->booking_status != 1;
840
+ return apply_filters('em_booking_is_pending', $result, $this);
841
+ }
842
+
843
  /**
844
  * Add a booking note to this booking. returns wpdb result or false if use can't manage this event.
845
  * @param string $note
848
  function add_note( $note_text ){
849
  global $wpdb;
850
  if( $this->can_manage() ){
851
+ $this->get_notes();
852
  $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
853
  $this->notes[] = $note;
854
  $this->feedback_message = __('Booking note successfully added.','dbem');
855
+ return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->booking_id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
856
  }
857
  return false;
858
  }
859
+
860
+ function get_admin_url(){
861
+ if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){
862
+ $my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page'));
863
+ $bookings_link = em_add_get_params($my_bookings_page, array('event_id'=>$this->event_id, 'booking_id'=>'booking_id'), false);
864
+ }else{
865
+ if( $this->get_event()->blog_id != get_current_blog_id() ){
866
+ $bookings_link = get_admin_url($this->get_event()->blog_id, 'edit.php?post_type='.EM_POST_TYPE_EVENT."&page=events-manager-bookings&event_id=".$this->event_id."&booking_id=".$this->booking_id);
867
+ }else{
868
+ $bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&event_id=".$this->event_id."&booking_id=".$this->booking_id;
869
+ }
870
+ }
871
+ return apply_filters('em_booking_get_bookings_url', $bookings_link, $this);
872
+ }
873
+
874
+ function output($format, $target="html") {
875
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([^}]+)})?/", $format, $placeholders);
876
+ foreach( $this->get_tickets() as $EM_Ticket){ /* @var $EM_Ticket EM_Ticket */ break; } //Get first ticket for single ticket placeholders
877
+ $output_string = $format;
878
+ $replaces = array();
879
+ foreach($placeholders[1] as $key => $result) {
880
+ $replace = '';
881
+ $full_result = $placeholders[0][$key];
882
+ switch( $result ){
883
+ case '#_BOOKINGID':
884
+ $replace = $this->booking_id;
885
+ break;
886
+ case '#_RESPNAME' : //Depreciated
887
+ case '#_BOOKINGNAME':
888
+ $replace = $this->get_person()->get_name();
889
+ break;
890
+ case '#_RESPEMAIL' : //Depreciated
891
+ case '#_BOOKINGEMAIL':
892
+ $replace = $this->get_person()->user_email;
893
+ break;
894
+ case '#_RESPPHONE' : //Depreciated
895
+ case '#_BOOKINGPHONE':
896
+ $replace = $this->get_person()->phone;
897
+ break;
898
+ case '#_BOOKINGSPACES':
899
+ $replace = $this->get_spaces();
900
+ break;
901
+ case '#_BOOKINGDATE':
902
+ $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format'), $this->timestamp):'n/a';
903
+ break;
904
+ case '#_BOOKINGTIME':
905
+ $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_time_format'), $this->timestamp):'n/a';
906
+ break;
907
+ case '#_BOOKINGDATETIME':
908
+ $replace = ( $this->timestamp ) ? date_i18n(get_option('dbem_date_format').' '.get_option('dbem_time_format'), $this->timestamp):'n/a';
909
+ break;
910
+ case '#_BOOKINGLISTURL':
911
+ $replace = em_get_my_bookings_url();
912
+ break;
913
+ case '#_COMMENT' : //Depreciated
914
+ case '#_BOOKINGCOMMENT':
915
+ $replace = $this->booking_comment;
916
+ break;
917
+ $replace = $this->get_price(true); //if there's tax, it'll be added here
918
+ break;
919
+ case '#_BOOKINGPRICEWITHOUTTAX':
920
+ $replace = $this->format_price($this->get_price() - $this->get_price_taxes());
921
+ break;
922
+ case '#_BOOKINGPRICETAX':
923
+ $replace = $this->get_price_taxes(true);
924
+ break;
925
+ case '#_BOOKINGPRICEWITHTAX':
926
+ case '#_BOOKINGPRICE':
927
+ $replace = $this->get_price(true);
928
+ break;
929
+ case '#_BOOKINGTICKETNAME':
930
+ $replace = $EM_Ticket->name;
931
+ break;
932
+ case '#_BOOKINGTICKETDESCRIPTION':
933
+ $replace = $EM_Ticket->description;
934
+ break;
935
+ case '#_BOOKINGTICKETPRICEWITHTAX':
936
+ $replace = $this->format_price( $EM_Ticket->get_price_without_tax() * (1+$this->get_tax_rate()/100) );
937
+ break;
938
+ case '#_BOOKINGTICKETPRICEWITHOUTTAX':
939
+ $replace = $EM_Ticket->get_price_without_tax(true);
940
+ break;
941
+ case '#_BOOKINGTICKETTAX':
942
+ $replace = $this->format_price( $EM_Ticket->get_price_without_tax() * ($this->get_tax_rate()/100) );
943
+ break;
944
+ case '#_BOOKINGTICKETPRICE':
945
+ $replace = $EM_Ticket->get_price(true);
946
+ break;
947
+ case '#_BOOKINGTICKETS':
948
+ ob_start();
949
+ em_locate_template('emails/bookingtickets.php', true, array('EM_Booking'=>$this));
950
+ $replace = ob_get_clean();
951
+ break;
952
+ case '#_BOOKINGSUMMARY':
953
+ ob_start();
954
+ em_locate_template('emails/bookingsummary.php', true, array('EM_Booking'=>$this));
955
+ $replace = ob_get_clean();
956
+ break;
957
+ default:
958
+ $replace = $full_result;
959
+ break;
960
+ }
961
+ $replaces[$full_result] = apply_filters('em_booking_output_placeholder', $replace, $this, $full_result, $target);
962
+ }
963
+ //sort out replacements so that during replacements shorter placeholders don't overwrite longer varieties.
964
+ krsort($replaces);
965
+ foreach($replaces as $full_result => $replacement){
966
+ $output_string = str_replace($full_result, $replacement , $output_string );
967
+ }
968
+ //run event output too, since this is never run from within events and will not infinitely loop
969
+ $output_string = $this->get_event()->output($output_string, $target);
970
+ return apply_filters('em_booking_output', $output_string, $this, $format, $target);
971
+ }
972
 
973
  /**
974
  * @param EM_Booking $EM_Booking
975
  * @param EM_Event $event
976
  * @return boolean
977
  */
978
+ function email( $email_admin = true, $force_resend = false, $email_attendee = true ){
979
  global $EM_Mailer;
980
+ $result = true;
981
+ $this->mails_sent = 0;
982
+
983
  //FIXME ticket logic needed
984
  $EM_Event = $this->get_event(); //We NEED event details here.
985
+ $EM_Event->get_bookings(true); //refresh all bookings
986
+
987
  //Make sure event matches booking, and that booking used to be approved.
988
+ if( $this->booking_status !== $this->previous_status || $force_resend ){
989
+ //messages can be overriden just before being sent
990
+ $msg = $this->email_messages();
991
+ $output_type = get_option('dbem_smtp_html') ? 'html':'email';
992
+
993
+ //Send user (booker) emails
994
+ if( !empty($msg['user']['subject']) && $email_attendee ){
995
+ $msg['user']['subject'] = $this->output($msg['user']['subject'], 'raw');
996
+ $msg['user']['body'] = $this->output($msg['user']['body'], $output_type);
997
+ //Send to the person booking
998
+ if( !$this->email_send( $msg['user']['subject'], $msg['user']['body'], $this->get_person()->user_email) ){
999
+ $result = false;
1000
+ }else{
1001
+ $this->mails_sent++;
1002
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1003
  }
1004
 
1005
+ //Send admin/contact emails if this isn't the event owner or an events admin
1006
+ if( $email_admin && !empty($msg['admin']['subject']) ){ //emails won't be sent if admin is logged in unless they book themselves
1007
+ //get admin emails that need to be notified, hook here to add extra admin emails
1008
+ $admin_emails = str_replace(' ','',get_option('dbem_bookings_notify_admin'));
1009
+ $admin_emails = apply_filters('em_booking_admin_emails', explode(',', $admin_emails), $this); //supply emails as array
1010
+ foreach($admin_emails as $key => $email){ if( !is_email($email) ) unset($admin_emails[$key]); } //remove bad emails
1011
+ //proceed to email admins if need be
1012
+ if( get_option('dbem_bookings_contact_email') == 1 || !empty($admin_emails) ){
1013
+ //Only gets sent if this is a pending booking, unless approvals are disabled.
1014
+ $msg['admin']['subject'] = $this->output($msg['admin']['subject'],'raw');
1015
+ $msg['admin']['body'] = $this->output($msg['admin']['body'], $output_type);
1016
+ //email contact
1017
+ if( get_option('dbem_bookings_contact_email') == 1 && !empty($EM_Event->get_contact()->user_email) ){ //if contacts are enabled and user email exists
1018
+ if( !$this->email_send( $msg['admin']['subject'], $msg['admin']['body'], $EM_Event->get_contact()->user_email) && current_user_can('list_users')){
1019
+ $this->errors[] = __('Confirmation email could not be sent to contact person. Registrant should have gotten their email (only admin see this warning).','dbem');
1020
+ $result = false;
1021
+ }else{
1022
+ $this->mails_sent++;
1023
+ }
1024
  }
1025
+ //email admin
1026
+ if( !empty($admin_emails) ){
1027
+ if( !$this->email_send( $msg['admin']['subject'], $msg['admin']['body'], $admin_emails) && current_user_can('list_users') ){
1028
+ $this->errors[] = __('Confirmation email could not be sent to admin. Registrant should have gotten their email (only admin see this warning).','dbem');
1029
+ $result = false;
1030
+ }else{
1031
+ $this->mails_sent++;
1032
+ }
1033
  }
1034
  }
1035
  }
 
1036
  }
1037
+ return $result;
1038
  //TODO need error checking for booking mail send
1039
  }
1040
 
1041
+ function email_messages(){
1042
+ $msg = array( 'user'=> array('subject'=>'', 'body'=>''), 'admin'=> array('subject'=>'', 'body'=>'')); //blank msg template
1043
+ //admin messages won't change whether pending or already approved
1044
+ switch( $this->booking_status ){
1045
+ case 0:
1046
+ case 5: //TODO remove offline status from here and move to pro
1047
+ $msg['user']['subject'] = get_option('dbem_bookings_email_pending_subject');
1048
+ $msg['user']['body'] = get_option('dbem_bookings_email_pending_body');
1049
+ //admins should get something (if set to)
1050
+ $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_pending_subject');
1051
+ $msg['admin']['body'] = get_option('dbem_bookings_contact_email_pending_body');
1052
+ break;
1053
+ case 1:
1054
+ $msg['user']['subject'] = get_option('dbem_bookings_email_confirmed_subject');
1055
+ $msg['user']['body'] = get_option('dbem_bookings_email_confirmed_body');
1056
+ //admins should get something (if set to)
1057
+ $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_confirmed_subject');
1058
+ $msg['admin']['body'] = get_option('dbem_bookings_contact_email_confirmed_body');
1059
+ break;
1060
+ case 2:
1061
+ $msg['user']['subject'] = get_option('dbem_bookings_email_rejected_subject');
1062
+ $msg['user']['body'] = get_option('dbem_bookings_email_rejected_body');
1063
+ //admins should get something (if set to)
1064
+ $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_rejected_subject');
1065
+ $msg['admin']['body'] = get_option('dbem_bookings_contact_email_rejected_body');
1066
+ break;
1067
+ case 3:
1068
+ $msg['user']['subject'] = get_option('dbem_bookings_email_cancelled_subject');
1069
+ $msg['user']['body'] = get_option('dbem_bookings_email_cancelled_body');
1070
+ //admins should get something (if set to)
1071
+ $msg['admin']['subject'] = get_option('dbem_bookings_contact_email_cancelled_subject');
1072
+ $msg['admin']['body'] = get_option('dbem_bookings_contact_email_cancelled_body');
1073
+ break;
1074
+ }
1075
+ return apply_filters('em_booking_email_messages', $msg, $this);
1076
+ }
1077
+
1078
  /**
1079
  * Can the user manage this event?
1080
  */
1081
+ function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
1082
+ return $this->get_event()->can_manage('manage_bookings','manage_others_bookings') || empty($this->booking_id) || !empty($this->manage_override);
1083
  }
1084
 
1085
  /**
classes/em-bookings-table.php ADDED
@@ -0,0 +1,641 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //Builds a table of bookings, still work in progress...
3
+ class EM_Bookings_Table{
4
+ /**
5
+ * associative array of collumns that'll be shown in order from left to right
6
+ *
7
+ * * key - collumn name in the databse, what will be used when searching
8
+ * * value - label for use in collumn headers
9
+ * @var array
10
+ */
11
+ public $cols = array('user_name','event_name','booking_spaces','booking_status','booking_price','actions');
12
+ /**
13
+ * Asoociative array of available collumn keys and corresponding headers, which will be used to display this table of bookings
14
+ * @var unknown_type
15
+ */
16
+ public $cols_template = array();
17
+ public $sortable_cols = array('booking_date');
18
+ /**
19
+ * Object we're viewing bookings in relation to.
20
+ * @var object
21
+ */
22
+ public $cols_view;
23
+ /**
24
+ * Index key used for looking up status information we're filtering in the booking table
25
+ * @var string
26
+ */
27
+ public $string = 'needs-attention';
28
+ /**
29
+ * Associative array of status information.
30
+ *
31
+ * * key - status index value
32
+ * * value - associative array containing keys
33
+ * ** label - the label for use in filter forms
34
+ * ** search - array or integer status numbers to search
35
+ *
36
+ * @var array
37
+ */
38
+ public $statuses = array();
39
+ /**
40
+ * Maximum number of rows to show
41
+ * @var int
42
+ */
43
+ public $limit = 20;
44
+ public $order = 'ASC';
45
+ public $orderby = 'booking_name';
46
+ public $page = 1;
47
+ public $offset = 0;
48
+ public $scope = 'future';
49
+ public $show_tickets = false;
50
+
51
+ function __construct($show_tickets = false){
52
+ $this->statuses = array(
53
+ 'all' => array('label'=>__('All','dbem'), 'search'=>false),
54
+ 'pending' => array('label'=>__('Pending','dbem'), 'search'=>0),
55
+ 'confirmed' => array('label'=>__('Confirmed','dbem'), 'search'=>1),
56
+ 'cancelled' => array('label'=>__('Cancelled','dbem'), 'search'=>3),
57
+ 'rejected' => array('label'=>__('Rejected','dbem'), 'search'=>2),
58
+ 'needs-attention' => array('label'=>__('Needs Attention','dbem'), 'search'=>array(0)),
59
+ 'incomplete' => array('label'=>__('Incomplete Bookings','dbem'), 'search'=>array(0))
60
+ );
61
+ if( !get_option('dbem_bookings_approval') ){
62
+ unset($this->statuses['pending']);
63
+ unset($this->statuses['incomplete']);
64
+ $this->statuses['confirmed']['search'] = array(0,1);
65
+ }
66
+ //Set basic vars
67
+ $this->order = ( !empty($_REQUEST ['order']) && $_REQUEST ['order'] == 'DESC' ) ? 'DESC':'ASC';
68
+ $this->orderby = ( !empty($_REQUEST ['order']) && preg_match('/[a-zA-Z0-9_, ]+/', $_REQUEST ['order']) ) ? $_REQUEST ['order']:'booking_name';
69
+ $this->limit = ( !empty($_REQUEST['limit']) && is_numeric($_REQUEST['pno']) ) ? $_REQUEST['limit'] : 20;//Default limit
70
+ $this->page = ( !empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
71
+ $this->offset = ( $this->page > 1 ) ? ($this->page-1)*$this->limit : 0;
72
+ $this->scope = ( !empty($_REQUEST['scope']) && array_key_exists($_REQUEST ['scope'], em_get_scopes()) ) ? $_REQUEST ['scope']:get_option('dbem_default_bookings_search','future');
73
+ $this->status = ( !empty($_REQUEST['status']) && array_key_exists($_REQUEST['status'], $this->statuses) ) ? $_REQUEST['status']:get_option('dbem_default_bookings_search','needs-attention');
74
+ //build template of possible collumns
75
+ $this->cols_template = apply_filters('em_bookings_table_cols_template', array(
76
+ 'user_name'=>__('Name','dbem'),
77
+ 'first_name'=>__('First Name','dbem'),
78
+ 'last_name'=>__('Last Name','dbem'),
79
+ 'event_name'=>__('Event','dbem'),
80
+ 'event_date'=>__('Event Date(s)','dbem'),
81
+ 'event_time'=>__('Event Time(s)','dbem'),
82
+ 'user_email'=>__('E-mail','dbem'),
83
+ 'dbem_phone'=>__('Phone Number','dbem'),
84
+ 'booking_spaces'=>__('Spaces','dbem'),
85
+ 'booking_status'=>__('Status','dbem'),
86
+ 'booking_date'=>__('Booking Date','dbem'),
87
+ 'booking_price'=>__('Total','dbem'),
88
+ 'booking_id'=>__('Booking ID','dbem'),
89
+ 'booking_comment'=>__('Booking Comment','dbem')
90
+ ), $this);
91
+ $this->cols_tickets_template = apply_filters('em_bookings_table_cols_tickets_template', array(
92
+ 'ticket_name'=>__('Ticket Name','dbem'),
93
+ 'ticket_description'=>__('Ticket Description','dbem'),
94
+ 'ticket_price'=>__('Ticket Price','dbem'),
95
+ 'ticket_id'=>__('Ticket ID','dbem')
96
+ ), $this);
97
+ //add tickets to template if we're showing rows by booking-ticket
98
+ if( $show_tickets ){
99
+ $this->show_tickets = true;
100
+ $this->cols = array('user_name','event_name','ticket_name','ticket_price','booking_spaces','booking_status','actions');
101
+ $this->cols_template = array_merge( $this->cols_template, $this->cols_tickets_template);
102
+ }
103
+ $this->cols_template['actions'] = __('Actions','dbem');
104
+ //calculate collumns if post requests
105
+ if( !empty($_REQUEST ['cols']) && !is_array($_REQUEST ['cols']) ){
106
+ $this->cols = explode(',',$_REQUEST['cols']);
107
+ }elseif( !empty($_REQUEST ['cols']) ){
108
+ $this->cols = $_REQUEST['cols'];
109
+ }
110
+ //load collumn view settings
111
+ if( $this->get_person() !== false ){
112
+ $this->cols_view = $this->get_person();
113
+ }elseif( $this->get_ticket() !== false ){
114
+ $this->cols_view = $this->get_ticket();
115
+ }elseif( $this->get_event() !== false ){
116
+ $this->cols_view = $this->get_event();
117
+ }
118
+ //save collumns depending on context and user preferences
119
+ if( empty($_REQUEST['cols']) ){
120
+ if(!empty($this->cols_view) && is_object($this->cols_view)){
121
+ //check if user has settings for object type
122
+ $settings = get_user_meta(get_current_user_id(), 'em_bookings_view-'.get_class($this->cols_view), true );
123
+ }else{
124
+ $settings = get_user_meta(get_current_user_id(), 'em_bookings_view', true );
125
+ }
126
+ if( !empty($settings) ){
127
+ $this->cols = $settings;
128
+ }
129
+ }elseif( !empty($_REQUEST['cols']) && empty($_REQUEST['no_save']) ){ //save view settings for next time
130
+ if( !empty($this->cols_view) && is_object($this->cols_view) ){
131
+ update_user_meta(get_current_user_id(), 'em_bookings_view-'.get_class($this->cols_view), $this->cols );
132
+ }else{
133
+ update_user_meta(get_current_user_id(), 'em_bookings_view', $this->cols );
134
+ }
135
+ }
136
+ //clean any columns from saved views that no longer exist
137
+ foreach($this->cols as $col_key => $col_name){
138
+ if( !array_key_exists($col_name, $this->cols_template)){
139
+ unset($this->cols[$col_key]);
140
+ }
141
+ }
142
+ do_action('em_bookings_table', $this);
143
+ }
144
+
145
+
146
+ /**
147
+ * @return EM_Person|false
148
+ */
149
+ function get_person(){
150
+ global $EM_Person;
151
+ if( !empty($this->person) && is_object($this->person) ){
152
+ return $this->person;
153
+ }elseif( !empty($_REQUEST['person_id']) && !empty($EM_Person) && is_object($EM_Person) ){
154
+ return $EM_Person;
155
+ }
156
+ return false;
157
+ }
158
+ /**
159
+ * @return EM_Ticket|false
160
+ */
161
+ function get_ticket(){
162
+ global $EM_Ticket;
163
+ if( !empty($this->ticket) && is_object($this->ticket) ){
164
+ return $this->ticket;
165
+ }elseif( !empty($EM_Ticket) && is_object($EM_Ticket) ){
166
+ return $EM_Ticket;
167
+ }
168
+ return false;
169
+ }
170
+ /**
171
+ * @return $EM_Event|false
172
+ */
173
+ function get_event(){
174
+ global $EM_Event;
175
+ if( !empty($this->event) && is_object($this->event) ){
176
+ return $this->event;
177
+ }elseif( !empty($EM_Event) && is_object($EM_Event) ){
178
+ return $EM_Event;
179
+ }
180
+ return false;
181
+ }
182
+
183
+ /**
184
+ * Gets the bookings for this object instance according to its settings
185
+ * @param boolean $force_refresh
186
+ * @return EM_Bookings
187
+ */
188
+ function get_bookings($force_refresh = true){
189
+ if( empty($this->bookings) || $force_refresh ){
190
+ $this->events = array();
191
+ $EM_Ticket = $this->get_ticket();
192
+ $EM_Event = $this->get_event();
193
+ $EM_Person = $this->get_person();
194
+ if( $EM_Person !== false ){
195
+ $args = array('person'=>$EM_Person->ID,'scope'=>$this->scope,'status'=>$this->get_status_search(),'order'=>$this->order,'orderby'=>$this->orderby);
196
+ $this->bookings_count = EM_Bookings::count($args);
197
+ $this->bookings = EM_Bookings::get(array_merge($args, array('limit'=>$this->limit,'offset'=>$this->offset)));
198
+ foreach($this->bookings->bookings as $EM_Booking){
199
+ //create event
200
+ if( !array_key_exists($EM_Booking->event_id,$this->events) ){
201
+ $this->events[$EM_Booking->event_id] = new EM_Event($EM_Booking->event_id);
202
+ }
203
+ }
204
+ }elseif( $EM_Ticket !== false ){
205
+ //searching bookings with a specific ticket
206
+ $args = array('ticket_id'=>$EM_Ticket->ticket_id, 'order'=>$this->order,'orderby'=>$this->orderby);
207
+ $this->bookings_count = EM_Bookings::count($args);
208
+ $this->bookings = EM_Bookings::get(array_merge($args, array('limit'=>$this->limit,'offset'=>$this->offset)));
209
+ $this->events[$EM_Ticket->event_id] = $EM_Ticket->get_event();
210
+ }elseif( $EM_Event !== false ){
211
+ //bookings for an event
212
+ $args = array('event'=>$EM_Event->event_id,'scope'=>false,'status'=>$this->get_status_search(),'order'=>$this->order,'orderby'=>$this->orderby);
213
+ $args['owner'] = !current_user_can('manage_others_bookings') ? get_current_user_id() : false;
214
+ $this->bookings_count = EM_Bookings::count($args);
215
+ $this->bookings = EM_Bookings::get(array_merge($args, array('limit'=>$this->limit,'offset'=>$this->offset)));
216
+ $this->events[$EM_Event->event_id] = $EM_Event;
217
+ }else{
218
+ //all bookings for a status
219
+ $args = array('status'=>$this->get_status_search(),'scope'=>$this->scope,'order'=>$this->order,'orderby'=>$this->orderby);
220
+ $args['owner'] = !current_user_can('manage_others_bookings') ? get_current_user_id() : false;
221
+ $this->bookings_count = EM_Bookings::count($args);
222
+ $this->bookings = EM_Bookings::get(array_merge($args, array('limit'=>$this->limit,'offset'=>$this->offset)));
223
+ //Now let's create events and bookings for this instead of giving each booking an event
224
+ foreach($this->bookings->bookings as $EM_Booking){
225
+ //create event
226
+ if( !array_key_exists($EM_Booking->event_id,$this->events) ){
227
+ $this->events[$EM_Booking->event_id] = new EM_Event($EM_Booking->event_id);
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return $this->bookings;
233
+ }
234
+
235
+ function get_count(){
236
+ return $this->bookings_count;
237
+ }
238
+
239
+ function get_status_search(){
240
+ if(is_array($this->statuses[$this->status]['search'])){
241
+ return implode(',',$this->statuses[$this->status]['search']);
242
+ }
243
+ return $this->statuses[$this->status]['search'];
244
+ }
245
+
246
+ function output(){
247
+ do_action('em_bookings_table_header',$this); //won't be overwritten by JS
248
+ $this->output_overlays();
249
+ $this->output_table();
250
+ do_action('em_bookings_table_footer',$this); //won't be overwritten by JS
251
+ }
252
+
253
+ function output_overlays(){
254
+ $EM_Ticket = $this->get_ticket();
255
+ $EM_Event = $this->get_event();
256
+ $EM_Person = $this->get_person();
257
+ ?>
258
+ <div id="em-bookings-table-settings" class="em-bookings-table-overlay" style="display:none;" title="<?php _e('Bookings Table Settings','dbem'); ?>">
259
+ <form id="em-bookings-table-settings-form" class="em-bookings-table-form" action="" method="post">
260
+ <p><?php _e('Modify what information is displayed in this booking table.','dbem') ?></p>
261
+ <div id="em-bookings-table-settings-form-cols">
262
+ <p>
263
+ <strong><?php _e('Columns to show','dbem')?></strong><br />
264
+ <?php _e('Drag items to or from the left column to add or remove them.','dbem'); ?>
265
+ </p>
266
+ <ul id="em-bookings-cols-active" class="em-bookings-cols-sortable">
267
+ <?php foreach( $this->cols as $col_key ): ?>
268
+ <li class="ui-state-highlight">
269
+ <input id="em-bookings-col-<?php echo esc_attr($col_key); ?>" type="hidden" name="<?php echo esc_attr($col_key); ?>" value="1" class="em-bookings-col-item" />
270
+ <?php echo esc_html($this->cols_template[$col_key]); ?>
271
+ </li>
272
+ <?php endforeach; ?>
273
+ </ul>
274
+ <ul id="em-bookings-cols-inactive" class="em-bookings-cols-sortable">
275
+ <?php foreach( $this->cols_template as $col_key => $col_data ): ?>
276
+ <?php if( !in_array($col_key, $this->cols) ): ?>
277
+ <li class="ui-state-default">
278
+ <input id="em-bookings-col-<?php echo esc_attr($col_key); ?>" type="hidden" name="<?php echo esc_attr($col_key); ?>" value="0" class="em-bookings-col-item" />
279
+ <?php echo esc_html($col_data); ?>
280
+ </li>
281
+ <?php endif; ?>
282
+ <?php endforeach; ?>
283
+ </ul>
284
+ </div>
285
+ </form>
286
+ </div>
287
+ <div id="em-bookings-table-export" class="em-bookings-table-overlay" style="display:none;" title="<?php _e('Export Bookings','dbem'); ?>">
288
+ <form id="em-bookings-table-export-form" class="em-bookings-table-form" action="" method="post">
289
+ <p><?php _e('Select the options below and export all the bookings you have currently filtered (all pages) into a CSV spreadsheet format.','dbem') ?></p>
290
+ <?php if( !get_option('dbem_bookings_tickets_single') ): //single ticket mode means no splitting by ticket type ?>
291
+ <p><?php _e('Split bookings by ticket type','dbem')?> <input type="checkbox" name="show_tickets" value="1" />
292
+ <a href="#" title="<?php _e('If your events have multiple tickets, enabling this will show a seperate row for each ticket within a booking.','dbem'); ?>">?</a>
293
+ <?php endif; ?>
294
+ <?php do_action('em_bookings_table_export_options'); ?>
295
+ <div id="em-bookings-table-settings-form-cols">
296
+ <p><strong><?php _e('Columns to export','dbem')?></strong></p>
297
+ <ul id="em-bookings-export-cols-active" class="em-bookings-cols-sortable">
298
+ <?php foreach( $this->cols as $col_key ): ?>
299
+ <li class="ui-state-highlight">
300
+ <input id="em-bookings-col-<?php echo esc_attr($col_key); ?>" type="hidden" name="cols[<?php echo esc_attr($col_key); ?>]" value="1" class="em-bookings-col-item" />
301
+ <?php echo esc_html($this->cols_template[$col_key]); ?>
302
+ </li>
303
+ <?php endforeach; ?>
304
+ </ul>
305
+ <ul id="em-bookings-export-cols-inactive" class="em-bookings-cols-sortable">
306
+ <?php foreach( $this->cols_template as $col_key => $col_data ): ?>
307
+ <?php if( !in_array($col_key, $this->cols) ): ?>
308
+ <li class="ui-state-default">
309
+ <input id="em-bookings-col-<?php echo esc_attr($col_key); ?>" type="hidden" name="cols[<?php echo esc_attr($col_key); ?>]" value="0" class="em-bookings-col-item" />
310
+ <?php echo esc_html($col_data); ?>
311
+ </li>
312
+ <?php endif; ?>
313
+ <?php endforeach; ?>
314
+ <?php if( !$this->show_tickets ): ?>
315
+ <?php foreach( $this->cols_tickets_template as $col_key => $col_data ): ?>
316
+ <?php if( !in_array($col_key, $this->cols) ): ?>
317
+ <li class="ui-state-default <?php if(array_key_exists($col_key, $this->cols_tickets_template)) echo 'em-bookings-col-item-ticket'; ?>">
318
+ <input id="em-bookings-col-<?php echo esc_attr($col_key); ?>" type="hidden" name="cols[<?php echo esc_attr($col_key); ?>]" value="0" class="em-bookings-col-item" />
319
+ <?php echo esc_html($col_data); ?>
320
+ </li>
321
+ <?php endif; ?>
322
+ <?php endforeach; ?>
323
+ <?php endif; ?>
324
+ </ul>
325
+ </div>
326
+ <?php if( $EM_Event !== false ): ?>
327
+ <input type="hidden" name="event_id" value='<?php echo $EM_Event->event_id; ?>' />
328
+ <?php endif; ?>
329
+ <?php if( $EM_Ticket !== false ): ?>
330
+ <input type="hidden" name="ticket_id" value='<?php echo $EM_Ticket->ticket_id; ?>' />
331
+ <?php endif; ?>
332
+ <?php if( $EM_Person !== false ): ?>
333
+ <input type="hidden" name="person_id" value='<?php echo $EM_Person->ID; ?>' />
334
+ <?php endif; ?>
335
+ <input type="hidden" name="scope" value='<?php echo esc_attr($this->scope); ?>' />
336
+ <input type="hidden" name="status" value='<?php echo esc_attr($this->status); ?>' />
337
+ <input type="hidden" name="no_save" value='1' />
338
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('export_bookings_csv'); ?>" />
339
+ <input type="hidden" name="action" value="export_bookings_csv" />
340
+ </form>
341
+ </div>
342
+ <br class="clear" />
343
+ <?php
344
+ }
345
+
346
+ function output_table(){
347
+ $EM_Ticket = $this->get_ticket();
348
+ $EM_Event = $this->get_event();
349
+ $EM_Person = $this->get_person();
350
+ $this->get_bookings(true); //get bookings and refresh
351
+ ?>
352
+ <div class='em-bookings-table em_obj' id="em-bookings-table">
353
+ <form class='bookings-filter' method='post' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
354
+ <?php if( $EM_Event !== false ): ?>
355
+ <input type="hidden" name="event_id" value='<?php echo $EM_Event->event_id; ?>' />
356
+ <?php endif; ?>
357
+ <?php if( $EM_Ticket !== false ): ?>
358
+ <input type="hidden" name="ticket_id" value='<?php echo $EM_Ticket->ticket_id; ?>' />
359
+ <?php endif; ?>
360
+ <?php if( $EM_Person !== false ): ?>
361
+ <input type="hidden" name="person_id" value='<?php echo $EM_Person->ID; ?>' />
362
+ <?php endif; ?>
363
+ <input type="hidden" name="is_public" value="<?php echo ( !empty($_REQUEST['is_public']) || !is_admin() ) ? 1:0; ?>" />
364
+ <input type="hidden" name="pno" value='<?php echo $this->page ?>' />
365
+ <input type="hidden" name="order" value='<?php echo $this->order ?>' />
366
+ <input type="hidden" name="orderby" value='<?php echo $this->orderby ?>' />
367
+ <input type="hidden" name="_wpnonce" value="<?php echo ( !empty($_REQUEST['_wpnonce']) ) ? esc_attr($_REQUEST['_wpnonce']):wp_create_nonce('em_bookings_table'); ?>" />
368
+ <input type="hidden" name="action" value="em_bookings_table" />
369
+ <input type="hidden" name="cols" value="<?php echo implode(',', $this->cols); ?>" />
370
+
371
+ <div class='tablenav'>
372
+ <div class="alignleft actions">
373
+ <a href="#" class="em-bookings-table-export" id="em-bookings-table-export-trigger" rel="#em-bookings-table-export" title="<?php _e('Export these bookings.','dbem'); ?>"></a>
374
+ <a href="#" class="em-bookings-table-settings" id="em-bookings-table-settings-trigger" rel="#em-bookings-table-settings"></a>
375
+ <?php if( $EM_Event === false ): ?>
376
+ <select name="scope">
377
+ <?php
378
+ foreach ( em_get_scopes() as $key => $value ) {
379
+ $selected = "";
380
+ if ($key == $this->scope)
381
+ $selected = "selected='selected'";
382
+ echo "<option value='".esc_attr($key)."' $selected>".esc_html($value)."</option> ";
383
+ }
384
+ ?>
385
+ </select>
386
+ <?php endif; ?>
387
+ <select name="limit">
388
+ <option value="<?php echo $this->limit ?>"><?php echo sprintf(__('%s Rows','dbem'),$this->limit); ?></option>
389
+ <option value="5">5</option>
390
+ <option value="10">10</option>
391
+ <option value="25">25</option>
392
+ <option value="50">50</option>
393
+ <option value="100">100</option>
394
+ </select>
395
+ <select name="status">
396
+ <?php
397
+ foreach ( $this->statuses as $key => $value ) {
398
+ $selected = "";
399
+ if ($key == $this->status)
400
+ $selected = "selected='selected'";
401
+ echo "<option value='".esc_attr($key)."' $selected>".esc_html($value['label'])."</option> ";
402
+ }
403
+ ?>
404
+ </select>
405
+ <input name="pno" type="hidden" value="1" />
406
+ <input id="post-query-submit" class="button-secondary" type="submit" value="<?php esc_attr_e( 'Filter' )?>" />
407
+ <?php if( $EM_Event !== false ): ?>
408
+ <?php _e('Displaying Event','dbem'); ?> : <?php echo esc_html($EM_Event->event_name); ?>
409
+ <?php elseif( $EM_Person !== false ): ?>
410
+ <?php _e('Displaying User','dbem'); echo ' : '.$EM_Person->get_name(); ?>
411
+ <?php endif; ?>
412
+ </div>
413
+ <?php
414
+ if ( $this->bookings_count >= $this->limit ) {
415
+ $bookings_nav = em_admin_paginate( $this->bookings_count, $this->limit, $this->page, array(),'#%#%','#');
416
+ echo $bookings_nav;
417
+ }
418
+ ?>
419
+ </div>
420
+ <div class="clear"></div>
421
+ <div class='table-wrap'>
422
+ <table id='dbem-bookings-table' class='widefat post '>
423
+ <thead>
424
+ <tr>
425
+ <?php /*
426
+ <th class='manage-column column-cb check-column' scope='col'>
427
+ <input class='select-all' type="checkbox" value='1' />
428
+ </th>
429
+ */ ?>
430
+ <th class='manage-column' scope='col'><?php echo implode("</th><th class='manage-column' scope='col'>", $this->get_headers()); ?></th>
431
+ </tr>
432
+ </thead>
433
+ <?php if( $this->bookings_count > 0 ): ?>
434
+ <tbody>
435
+ <?php
436
+ $rowno = 0;
437
+ $event_count = (!empty($event_count)) ? $event_count:0;
438
+ foreach ($this->bookings->bookings as $EM_Booking) {
439
+ ?>
440
+ <tr>
441
+ <?php /*
442
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
443
+ */
444
+ /* @var $EM_Booking EM_Booking */
445
+ /* @var $EM_Ticket_Booking EM_Ticket_Booking */
446
+ if( $this->show_tickets ){
447
+ foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){
448
+ ?><td><?php echo implode('</td><td>', $this->get_row($EM_Ticket_Booking)); ?></td><?php
449
+ }
450
+ }else{
451
+ ?><td><?php echo implode('</td><td>', $this->get_row($EM_Booking)); ?></td><?php
452
+ }
453
+ ?>
454
+ </tr>
455
+ <?php
456
+ }
457
+ ?>
458
+ </tbody>
459
+ <?php else: ?>
460
+ <tbody>
461
+ <tr><td scope="row" colspan="<?php echo count($this->cols); ?>"><?php _e('No bookings.', 'dbem'); ?></td></tr>
462
+ </tbody>
463
+ <?php endif; ?>
464
+ </table>
465
+ </div>
466
+ <?php if( !empty($bookings_nav) && $this->bookings_count >= $this->limit ) : ?>
467
+ <div class='tablenav'>
468
+ <?php echo $bookings_nav; ?>
469
+ <div class="clear"></div>
470
+ </div>
471
+ <?php endif; ?>
472
+ </form>
473
+ </div>
474
+ <?php
475
+ }
476
+
477
+ function get_headers($csv = false){
478
+ $headers = array();
479
+ foreach($this->cols as $col){
480
+ if( $col == 'actions' ){
481
+ if( !$csv ) $headers[$col] = '&nbsp;';
482
+ }elseif(array_key_exists($col, $this->cols_template)){
483
+ /* for later - col ordering!
484
+ if($this->orderby == $col){
485
+ if($this->order == 'ASC'){
486
+ $headers[] = '<a class="em-bookings-orderby" href="#'.$col.'">'.$this->cols_template[$col].' (^)</a>';
487
+ }else{
488
+ $headers[] = '<a class="em-bookings-orderby" href="#'.$col.'">'.$this->cols_template[$col].' (d)</a>';
489
+ }
490
+ }else{
491
+ $headers[] = '<a class="em-bookings-orderby" href="#'.$col.'">'.$this->cols_template[$col].'</a>';
492
+ }
493
+ */
494
+ $headers[$col] = $this->cols_template[$col];
495
+ }
496
+ }
497
+ return apply_filters('em_bookings_table_get_headers', $headers, $csv, $this);
498
+ }
499
+
500
+ function get_table(){
501
+
502
+ }
503
+
504
+ /**
505
+ * @param Object $object
506
+ * @return array()
507
+ */
508
+ function get_row( $object, $csv = false ){
509
+ /* @var $EM_Ticket EM_Ticket */
510
+ /* @var $EM_Ticket_Booking EM_Ticket_Booking */
511
+ /* @var $EM_Booking EM_Booking */
512
+ if( get_class($object) == 'EM_Ticket_Booking' ){
513
+ $EM_Ticket_Booking = $object;
514
+ $EM_Ticket = $EM_Ticket_Booking->get_ticket();
515
+ $EM_Booking = $EM_Ticket_Booking->get_booking();
516
+ }else{
517
+ $EM_Booking = $object;
518
+ }
519
+ $cols = array();
520
+ foreach($this->cols as $col){
521
+ //is col a user col or else?
522
+ //TODO fix urls so this works in all pages in front as well
523
+ if( $col == 'user_email' ){
524
+ $cols[] = $EM_Booking->get_person()->user_email;
525
+ }elseif($col == 'dbem_phone'){
526
+ $cols[] = esc_html($EM_Booking->get_person()->phone);
527
+ }elseif($col == 'user_name'){
528
+ if( $csv || ( get_option('dbem_bookings_registration_disable') && $EM_Booking->get_person()->ID == get_option('dbem_bookings_registration_user') ) ){
529
+ $cols[] = $EM_Booking->get_person()->get_name();
530
+ }else{
531
+ $cols[] = '<a href="'.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>';
532
+ }
533
+ }elseif($col == 'first_name'){
534
+ $cols[] = esc_html($EM_Booking->get_person()->first_name);
535
+ }elseif($col == 'last_name'){
536
+ $cols[] = esc_html($EM_Booking->get_person()->last_name);
537
+ }elseif($col == 'event_name'){
538
+ if( $csv ){
539
+ $cols[] = $EM_Booking->get_event()->event_name;
540
+ }else{
541
+ $cols[] = '<a href="'.$EM_Booking->get_event()->get_bookings_url().'">'. esc_html($EM_Booking->get_event()->event_name) .'</a>';
542
+ }
543
+ }elseif($col == 'event_date'){
544
+ $cols[] = $EM_Booking->get_event()->output('#_EVENTDATES');
545
+ }elseif($col == 'event_time'){
546
+ $cols[] = $EM_Booking->get_event()->output('#_EVENTTIMES');
547
+ }elseif($col == 'booking_price'){
548
+ if($this->show_tickets && !empty($EM_Ticket)){
549
+ $cols[] = em_get_currency_formatted(apply_filters('em_bookings_table_row_booking_price_ticket', $EM_Ticket_Booking->get_price(false,false, true), $EM_Booking, true));
550
+ }else{
551
+ $cols[] = $EM_Booking->get_price(true);
552
+ }
553
+ }elseif($col == 'booking_status'){
554
+ $cols[] = $EM_Booking->get_status(true);
555
+ }elseif($col == 'booking_date'){
556
+ $cols[] = date_i18n(get_option('dbem_date_format').' '. get_option('dbem_time_format'), $EM_Booking->timestamp);
557
+ }elseif($col == 'actions' ){
558
+ if( !$csv ) $cols[] = implode(' | ', $this->get_booking_actions($EM_Booking));
559
+ }elseif( $col == 'booking_spaces' ){
560
+ $cols[] = ($this->show_tickets && !empty($EM_Ticket)) ? $EM_Ticket_Booking->get_spaces() : $EM_Booking->get_spaces();
561
+ }elseif( $col == 'booking_id' ){
562
+ $cols[] = $EM_Booking->booking_id;
563
+ }elseif( $col == 'ticket_name' && $this->show_tickets && !empty($EM_Ticket) ){
564
+ $cols[] = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col);
565
+ }elseif( $col == 'ticket_description' && $this->show_tickets && !empty($EM_Ticket) ){
566
+ $cols[] = $csv ? $EM_Ticket->$col : esc_html($EM_Ticket->$col);
567
+ }elseif( $col == 'ticket_price' && $this->show_tickets && !empty($EM_Ticket) ){
568
+ $cols[] = $EM_Ticket->get_price(true);
569
+ }elseif( $col == 'ticket_id' && $this->show_tickets && !empty($EM_Ticket) ){
570
+ $cols[] = $EM_Ticket->ticket_id;
571
+ }elseif( $col == 'booking_comment' ){
572
+ $cols[] = $csv ? $EM_Booking->booking_comment : esc_html($EM_Booking->booking_comment);
573
+ }else{
574
+ $val = apply_filters('em_bookings_table_rows_col_'.$col, '', $EM_Booking, $this, $csv);
575
+ $cols[] = apply_filters('em_bookings_table_rows_col', $val, $col, $EM_Booking, $this, $csv);
576
+ }
577
+ }
578
+ //clean up the cols to prevent nasty html or xss
579
+ global $allowedposttags;
580
+ foreach($cols as $key => $col){
581
+ $cols[$key] = wp_kses($col, $allowedposttags);
582
+ }
583
+ return $cols;
584
+ }
585
+
586
+ function get_row_csv($EM_Booking){
587
+ $row = $this->get_row($EM_Booking, true);
588
+ foreach($row as $k=>$v) $row[$k] = html_entity_decode($v); //remove things like &amp; which may have been saved to the DB directly
589
+ return $row;
590
+ }
591
+
592
+ /**
593
+ * @param EM_Booking $EM_Booking
594
+ * @return mixed
595
+ */
596
+ function get_booking_actions($EM_Booking){
597
+ $booking_actions = array();
598
+ $url = $EM_Booking->get_event()->get_bookings_url();
599
+ switch($EM_Booking->booking_status){
600
+ case 0: //pending
601
+ if( get_option('dbem_bookings_approval') ){
602
+ $booking_actions = array(
603
+ 'approve' => '<a class="em-bookings-approve" href="'.em_add_get_params($url, array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Approve','dbem').'</a>',
604
+ 'reject' => '<a class="em-bookings-reject" href="'.em_add_get_params($url, array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Reject','dbem').'</a>',
605
+ 'delete' => '<span class="trash"><a class="em-bookings-delete" href="'.em_add_get_params($url, array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Delete','dbem').'</a></span>',
606
+ 'edit' => '<a class="em-bookings-edit" href="'.em_add_get_params($EM_Booking->get_event()->get_bookings_url(), array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null)).'">'.__('Edit/View','dbem').'</a>',
607
+ );
608
+ break;
609
+ }//if approvals are off, treat as a 1
610
+ case 1: //approved
611
+ $booking_actions = array(
612
+ 'unapprove' => '<a class="em-bookings-unapprove" href="'.em_add_get_params($url, array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Unapprove','dbem').'</a>',
613
+ 'reject' => '<a class="em-bookings-reject" href="'.em_add_get_params($url, array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Reject','dbem').'</a>',
614
+ 'delete' => '<span class="trash"><a class="em-bookings-delete" href="'.em_add_get_params($url, array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Delete','dbem').'</a></span>',
615
+ 'edit' => '<a class="em-bookings-edit" href="'.em_add_get_params($EM_Booking->get_event()->get_bookings_url(), array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null)).'">'.__('Edit/View','dbem').'</a>',
616
+ );
617
+ break;
618
+ case 2: //rejected
619
+ $booking_actions = array(
620
+ 'approve' => '<a class="em-bookings-approve" href="'.em_add_get_params($url, array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Approve','dbem').'</a>',
621
+ 'delete' => '<span class="trash"><a class="em-bookings-delete" href="'.em_add_get_params($url, array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Delete','dbem').'</a></span>',
622
+ 'edit' => '<a class="em-bookings-edit" href="'.em_add_get_params($EM_Booking->get_event()->get_bookings_url(), array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null)).'">'.__('Edit/View','dbem').'</a>',
623
+ );
624
+ break;
625
+ case 3: //cancelled
626
+ case 4: //awaiting online payment - similar to pending but always needs approval in EM Free
627
+ case 5: //awaiting payment - similar to pending but always needs approval in EM Free
628
+ $booking_actions = array(
629
+ 'approve' => '<a class="em-bookings-approve" href="'.em_add_get_params($url, array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Approve','dbem').'</a>',
630
+ 'delete' => '<span class="trash"><a class="em-bookings-delete" href="'.em_add_get_params($url, array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id)).'">'.__('Delete','dbem').'</a></span>',
631
+ 'edit' => '<a class="em-bookings-edit" href="'.em_add_get_params($EM_Booking->get_event()->get_bookings_url(), array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null)).'">'.__('Edit/View','dbem').'</a>',
632
+ );
633
+ break;
634
+
635
+ }
636
+ if( !get_option('dbem_bookings_approval') ) unset($booking_actions['unapprove']);
637
+ $booking_actions = apply_filters('em_bookings_table_booking_actions_'.$EM_Booking->booking_status ,$booking_actions, $EM_Booking);
638
+ return apply_filters('em_bookings_table_cols_col_action', $booking_actions, $EM_Booking);
639
+ }
640
+ }
641
+ ?>
classes/em-bookings.php CHANGED
@@ -16,14 +16,24 @@ class EM_Bookings extends EM_Object implements Iterator{
16
  */
17
  var $tickets;
18
  /**
19
- * @var EM_Event
20
  */
21
- var $event;
22
  /**
23
  * How many spaces this event has
24
  * @var int
25
  */
26
  var $spaces;
 
 
 
 
 
 
 
 
 
 
27
 
28
  /**
29
  * Creates an EM_Bookings instance, currently accepts an EM_Event object (gets all bookings for that event) or array of any EM_Booking objects, which can be manipulated in bulk with helper functions.
@@ -33,11 +43,14 @@ class EM_Bookings extends EM_Object implements Iterator{
33
  function EM_Bookings( $data = false ){
34
  if( is_object($data) && get_class($data) == "EM_Event" ){ //Creates a blank bookings object if needed
35
  global $wpdb;
36
- $this->event = $data;
37
- $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE event_id ='{$this->event->id}'";
38
- $bookings = $wpdb->get_results($sql, ARRAY_A);
 
 
 
39
  foreach ($bookings as $booking){
40
- $this->bookings[] = new EM_Booking($booking);
41
  }
42
  $this->spaces = $this->get_spaces();
43
  }elseif( is_array($data) ){
@@ -46,52 +59,52 @@ class EM_Bookings extends EM_Object implements Iterator{
46
  $this->bookings[] = $EM_Booking;
47
  }
48
  }
49
- $this->get_event();
50
  }
51
  }
52
 
53
  /**
54
- * Add a booking into this event (or add spaces if person already booked this), checking that there's enough space for the event
55
  * @param EM_Booking $EM_Booking
56
  * @return boolean
57
  */
58
  function add( $EM_Booking ){
59
  global $wpdb,$EM_Mailer;
60
- $EM_Booking->get_spaces(true);
61
- if ( $this->get_available_spaces() >= $EM_Booking->get_spaces() ) {
62
- //Save the booking
63
- $email = false;
64
- $result = $EM_Booking->save();
65
- if($result){
66
- //Success
67
- $this->bookings[] = $EM_Booking;
68
- $email = $EM_Booking->email();
69
- if( get_option('dbem_bookings_approval') == 1 ){
70
- $this->feedback_message = __('Booking successful, pending confirmation (you will also receive an email once confirmed).', 'dbem');
71
- }else{
72
- $this->feedback_message = __('Booking successful.', 'dbem');
73
- }
74
- if(!$email){
75
- $this->feedback_message .= ' '.__('However, there were some problems whilst sending confirmation emails to you and/or the event contact person. You may want to contact them directly and letting them know of this error.', 'dbem');
76
- if( current_user_can('activate_plugins') ){
77
- if( count($EM_Booking->get_errors()) > 0 ){
78
- $this->feedback_message .= '<br/><strong>Errors:</strong> (only admins see this message)<br/><ul><li>'. implode('</li><li>', $EM_Booking->get_errors()).'</li></ul>';
79
- }else{
80
- $this->feedback_message .= '<br/><strong>No errors returned by mailer</strong> (only admins see this message)';
81
- }
 
 
 
82
  }
83
  }
84
- return true;
85
- }else{
86
- //Failure
87
- $this->errors[] = "<strong>".__('Booking could not be created','dbem').":</strong><br />". implode('<br />', $EM_Booking->errors);
88
  }
89
- } else {
90
- $this->add_error(__('Booking cannot be made, not enough spaces available!', 'dbem'));
91
- }
92
- return false;
 
 
93
  }
94
-
95
  /**
96
  * Get POST data and create a booking for each ticket requested. If successful, a booking object is returned, false if not.
97
  * @return false|object
@@ -115,17 +128,20 @@ class EM_Bookings extends EM_Object implements Iterator{
115
  * Smart event locator, saves a database read if possible. Note that if an event doesn't exist, a blank object will be created to prevent duplicates.
116
  */
117
  function get_event(){
118
- if( is_object($this->event) && get_class($this->event) == 'EM_Event' ){
119
- return $this->event;
120
- }elseif( count($this->bookings) > 0 ){
121
- foreach($this->bookings as $EM_Booking){
122
- $this->event = $EM_Booking->get_event();
123
- return $this->event;
124
- }
125
  }else{
126
- $this->event = new EM_Event();
127
- return $this->event;
 
 
 
 
 
 
128
  }
 
129
  }
130
 
131
  /**
@@ -135,21 +151,42 @@ class EM_Bookings extends EM_Object implements Iterator{
135
  */
136
  function get_tickets( $force_reload = false ){
137
  if( !is_object($this->tickets) || $force_reload ){
138
- $this->tickets = new EM_Tickets($this->get_event());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  }
140
  return apply_filters('em_bookings_get_tickets', $this->tickets, $this);
141
  }
142
 
143
  /**
144
  * Returns EM_Tickets object with available tickets
 
145
  * @return EM_Tickets
146
  */
147
- function get_available_tickets(){
148
  $tickets = array();
149
- $timesamp = current_time('timestamp');
150
  foreach ($this->get_tickets() as $EM_Ticket){
151
- /* @var EM_Ticket $EM_Ticket */
152
- if( $EM_Ticket->is_available() ){
153
  //within time range
154
  if( $EM_Ticket->get_available_spaces() > 0 ){
155
  $tickets[] = $EM_Ticket;
@@ -157,7 +194,7 @@ class EM_Bookings extends EM_Object implements Iterator{
157
  }
158
  }
159
  $EM_Tickets = new EM_Tickets($tickets);
160
- return apply_filters('em_bookings_get_tickets', $EM_Tickets, $this);
161
  }
162
 
163
  function get_user_list(){
@@ -175,11 +212,32 @@ class EM_Bookings extends EM_Object implements Iterator{
175
  function ticket_exists($ticket_id){
176
  $EM_Tickets = $this->get_tickets();
177
  foreach( $EM_Tickets->tickets as $EM_Ticket){
178
- if($EM_Ticket->id == $ticket_id){
179
  return apply_filters('em_bookings_ticket_exists',true, $EM_Ticket, $this);
180
  }
181
  }
182
- return apply_filters('em_bookings_ticket_exists',false, $EM_Ticket,$this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
 
185
  /**
@@ -189,15 +247,18 @@ class EM_Bookings extends EM_Object implements Iterator{
189
  function delete(){
190
  global $wpdb;
191
  $booking_ids = array();
192
- if( is_object($this->event) ){
193
- $result = $wpdb->query("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id='{$this->event_id}'");
194
- }else{
195
- foreach( $this->bookings as $EM_Booking ){
196
- $booking_ids[] = $EM_Booking->id;
197
- }
 
 
 
198
  $result = $wpdb->query("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id IN (".implode(',',$booking_ids).")");
199
  }
200
- return ($result !== false);
201
  }
202
 
203
 
@@ -236,13 +297,12 @@ class EM_Bookings extends EM_Object implements Iterator{
236
  */
237
  function set_status($status, $booking_ids){
238
  //FIXME status should work with instantiated object
239
- //FIXME there is a vulnerability where any user can approve/reject bookings if they know the ID
240
- if( $this->array_is_numeric($booking_ids) ){
241
  //Get all the bookings
242
  $results = array();
243
  $mails = array();
244
  foreach( $booking_ids as $booking_id ){
245
- $EM_Booking = new EM_Booking($booking_id);
246
  if( !$EM_Booking->can_manage() ){
247
  $this->feedback_message = __('Bookings %s. Mails Sent.', 'dbem');
248
  return false;
@@ -258,7 +318,7 @@ class EM_Bookings extends EM_Object implements Iterator{
258
  return false;
259
  }
260
  }elseif( is_numeric($booking_ids) || is_object($booking_ids) ){
261
- $EM_Booking = ( is_object($booking_ids) && get_class($booking_ids) == 'EM_Booking') ? $booking_ids : new EM_Booking($booking_ids);
262
  $result = $EM_Booking->set_status($status);
263
  $this->feedback_message = $EM_Booking->feedback_message;
264
  return $result;
@@ -276,6 +336,8 @@ class EM_Bookings extends EM_Object implements Iterator{
276
  if($force_refresh || $this->spaces == 0){
277
  $this->spaces = $this->get_tickets()->get_spaces();
278
  }
 
 
279
  return apply_filters('em_booking_get_spaces',$this->spaces,$this);
280
  }
281
 
@@ -284,27 +346,26 @@ class EM_Bookings extends EM_Object implements Iterator{
284
  * @return int
285
  */
286
  function get_available_spaces(){
287
- $available_spaces = 0;
288
- if( get_option('dbem_bookings_approval_reserved') == 1 ){
289
- $available_spaces = $this->get_spaces() - $this->get_booked_spaces() - $this->get_pending_spaces();
290
- }else{
291
- $available_spaces = $this->get_spaces() - $this->get_booked_spaces();
292
  }
293
- return apply_filters('get_available_spaces', $available_spaces, $this);
294
  }
295
 
296
  /**
297
  * Returns number of booked spaces for this event. If approval of bookings is on, will return number of booked confirmed spaces.
298
  * @return int
299
  */
300
- function get_booked_spaces(){
301
  $booked_spaces = 0;
302
- $EM_Bookings = $this->get_bookings(); //get bookings, automatically filtering approvals etc.
303
- foreach ( $EM_Bookings->bookings as $EM_Booking ){
304
- //never show cancelled status, nor pending if approvals required
305
- $booked_spaces += $EM_Booking->get_spaces();
306
  }
307
- return $booked_spaces;
308
  }
309
 
310
  /**
@@ -313,25 +374,25 @@ class EM_Bookings extends EM_Object implements Iterator{
313
  */
314
  function get_pending_spaces(){
315
  if( get_option('dbem_bookings_approval') == 0 ){
316
- return 0;
317
  }
318
  $pending = 0;
319
  foreach ( $this->bookings as $booking ){
320
- if($booking->status == 0){
321
  $pending += $booking->get_spaces();
322
  }
323
  }
324
- return $pending;
325
  }
326
 
327
  /**
328
  * Gets number of bookings (not spaces). If booking approval is enabled, only the number of approved bookings will be shown.
329
  * @return EM_Bookings
330
  */
331
- function get_bookings(){
332
  $confirmed = array();
333
  foreach ( $this->bookings as $booking ){
334
- if( $booking->status == 1 || (get_option('dbem_bookings_approval') == 0 && $booking->status < 2) ){
335
  $confirmed[] = $booking;
336
  }
337
  }
@@ -345,11 +406,11 @@ class EM_Bookings extends EM_Object implements Iterator{
345
  */
346
  function get_pending_bookings(){
347
  if( get_option('dbem_bookings_approval') == 0 ){
348
- return array();
349
  }
350
  $pending = array();
351
  foreach ( $this->bookings as $booking ){
352
- if($booking->status == 0){
353
  $pending[] = $booking;
354
  }
355
  }
@@ -364,7 +425,7 @@ class EM_Bookings extends EM_Object implements Iterator{
364
  function get_rejected_bookings(){
365
  $rejected = array();
366
  foreach ( $this->bookings as $booking ){
367
- if($booking->status == 2){
368
  $rejected[] = $booking;
369
  }
370
  }
@@ -379,7 +440,7 @@ class EM_Bookings extends EM_Object implements Iterator{
379
  function get_cancelled_bookings(){
380
  $cancelled = array();
381
  foreach ( $this->bookings as $booking ){
382
- if($booking->status == 3){
383
  $cancelled[] = $booking;
384
  }
385
  }
@@ -417,8 +478,8 @@ class EM_Bookings extends EM_Object implements Iterator{
417
  }
418
  if( is_numeric($user_id) && $user_id > 0 ){
419
  foreach ($this->bookings as $EM_Booking){
420
- if( $EM_Booking->person->ID == $user_id && $EM_Booking->status != 3 ){
421
- return apply_filters('em_bookings_has_booking', true, $this);
422
  }
423
  }
424
  }
@@ -430,7 +491,7 @@ class EM_Bookings extends EM_Object implements Iterator{
430
  * @return array
431
  * @static
432
  */
433
- function get( $args = array() ){
434
  global $wpdb,$current_user;
435
  $bookings_table = EM_BOOKINGS_TABLE;
436
  $events_table = EM_EVENTS_TABLE;
@@ -446,7 +507,7 @@ class EM_Bookings extends EM_Object implements Iterator{
446
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
447
  $bookings = array();
448
  foreach($results as $result){
449
- $bookings[] = new EM_Booking($result);
450
  }
451
  return $bookings; //We return all the bookings matched as an EM_Booking array.
452
  }
@@ -462,22 +523,27 @@ class EM_Bookings extends EM_Object implements Iterator{
462
  $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):'';
463
 
464
  //Get ordering instructions
465
- $EM_Booking = new EM_Booking();
466
  $accepted_fields = $EM_Booking->get_fields(true);
467
  $orderby = self::build_sql_orderby($args, $accepted_fields);
468
  //Now, build orderby sql
469
- $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
 
 
470
 
471
  //Create the SQL statement and execute
472
  $sql = "
473
- SELECT * FROM $bookings_table
474
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
475
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
476
  $where
477
  $orderby_sql
478
  $limit $offset
479
  ";
480
-
 
 
 
481
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
482
 
483
  //If we want results directly in an array, why not have a shortcut here?
@@ -489,18 +555,22 @@ class EM_Bookings extends EM_Object implements Iterator{
489
  $results = (is_array($results)) ? $results:array();
490
  $bookings = array();
491
  foreach ( $results as $booking ){
492
- $bookings[] = new EM_Booking($booking);
493
  }
494
  $EM_Bookings = new EM_Bookings($bookings);
495
  return apply_filters('em_bookings_get', $EM_Bookings);
496
  }
497
 
 
 
 
 
498
 
499
  //List of patients in the patient database, that a user can choose and go on to edit any previous treatment data, or add a new admission.
500
  function export_csv() {
501
  global $EM_Event;
502
- if($EM_Event->id != $this->event->id ){
503
- $event = new EM_Event($this->event->id);
504
  $event_name = $event->name;
505
  }else{
506
  $event_name = $EM_Event->name;
@@ -510,64 +580,74 @@ class EM_Bookings extends EM_Object implements Iterator{
510
 
511
  header("Content-Type: application/octet-stream");
512
  header("Content-Disposition: Attachment; filename=$file_name");
513
-
514
- //Headers
515
- $labels = array(
516
- 'Booking ID',
517
- 'Name',
518
- 'Email',
519
- 'Phone',
520
- 'Date',
521
- 'Status',
522
- 'Ticket Name',
523
- 'Spaces',
524
- 'Price',
525
- 'Comment'
526
- );
527
- $file = sprintf(__('Booking details for "%s" as of %s','dbem'),$event_name, date_i18n('D d M Y h:i', current_time('timestamp'))) . "\n";
528
- $file = '"'. implode('","', $labels). '"' . "\n";
529
-
530
- //Rows
531
- foreach( $this->bookings as $EM_Booking ) {
532
- /* @var $EM_Booking EM_Booking */
533
- foreach( $EM_Booking->get_tickets_bookings() as $EM_Ticket_Booking){
534
- /* @var $EM_Ticket EM_Ticket */
535
- /* @var $EM_Ticket_Booking EM_Ticket_Booking */
536
- $EM_Ticket = $EM_Ticket_Booking->get_ticket();
537
- $row = array(
538
- $EM_Booking->id,
539
- $EM_Booking->person->display_name,
540
- $EM_Booking->person->user_email,
541
- $EM_Booking->person->phone,
542
- date('Y-m-d h:i', $EM_Booking->timestamp),
543
- $EM_Booking->get_status(),
544
- $EM_Ticket->name,
545
- $EM_Ticket_Booking->get_spaces(),
546
- $EM_Ticket_Booking->get_price(),
547
- $EM_Booking->comment
548
- );
549
- //Display all values
550
- foreach($row as $value){
551
- $value = str_replace('"', '""', $value);
552
- $value = str_replace("=", "", $value);
553
- $file .= '"' . preg_replace("/\n\r|\r\n|\n|\r/", ". ", $value) . '",';
554
- }
555
- $file .= "\n";
556
- }
557
- }
558
-
559
- // $file holds the data
560
- echo $file;
561
- $file = "";
562
  }
563
 
564
  /* Overrides EM_Object method to apply a filter to result
565
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
566
  */
567
- function build_sql_conditions( $args = array() ){
568
  $conditions = apply_filters( 'em_bookings_build_sql_conditions', parent::build_sql_conditions($args), $args );
569
  if( is_numeric($args['status']) ){
570
  $conditions['status'] = 'booking_status='.$args['status'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
  }
572
  return apply_filters('em_bookings_build_sql_conditions', $conditions, $args);
573
  }
@@ -575,27 +655,39 @@ class EM_Bookings extends EM_Object implements Iterator{
575
  /* Overrides EM_Object method to apply a filter to result
576
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
577
  */
578
- function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
579
- return apply_filters( 'em_bookings_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
580
  }
581
 
582
  /*
583
  * Adds custom Events search defaults
 
584
  * @param array $array
585
  * @return array
586
  * @uses EM_Object#get_default_search()
587
  */
588
- function get_default_search( $array = array() ){
589
  $defaults = array(
590
  'status' => false,
591
- 'person' => true //to add later, search by person's bookings...
592
- );
593
- if( true || is_admin() ){
594
- //figure out default owning permissions
595
- if( !current_user_can('edit_others_events') ){
596
- $defaults['owner'] = get_current_user_id();
597
- }else{
598
- $defaults['owner'] = false;
 
 
 
 
 
 
 
 
 
 
 
599
  }
600
  }
601
  return apply_filters('em_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
16
  */
17
  var $tickets;
18
  /**
19
+ * @var int
20
  */
21
+ var $event_id;
22
  /**
23
  * How many spaces this event has
24
  * @var int
25
  */
26
  var $spaces;
27
+ /**
28
+ * If flag is true, a registration will be attempted when booking whether the user is logged in or not. Used in cases such as manual bookings (a Pro feature) and should only be enabled during manipulation by an event admin.
29
+ * @var unknown
30
+ */
31
+ public static $force_registration;
32
+ /**
33
+ * If flag is true, bookings and forms will not impose restrictions for roles. Future iterations will remove restrictions on dates, space capacity, etc. This is mainly for use by event admins such as for a manual booking (a Pro feature).
34
+ * @var bool
35
+ */
36
+ public static $disable_restrictions = false;
37
 
38
  /**
39
  * Creates an EM_Bookings instance, currently accepts an EM_Event object (gets all bookings for that event) or array of any EM_Booking objects, which can be manipulated in bulk with helper functions.
43
  function EM_Bookings( $data = false ){
44
  if( is_object($data) && get_class($data) == "EM_Event" ){ //Creates a blank bookings object if needed
45
  global $wpdb;
46
+ $this->event_id = $data->event_id;
47
+ $bookings = array();
48
+ if( $this->event_id > 0 ){
49
+ $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE event_id ='{$this->event_id}' ORDER BY booking_date";
50
+ $bookings = $wpdb->get_results($sql, ARRAY_A);
51
+ }
52
  foreach ($bookings as $booking){
53
+ $this->bookings[] = em_get_booking($booking);
54
  }
55
  $this->spaces = $this->get_spaces();
56
  }elseif( is_array($data) ){
59
  $this->bookings[] = $EM_Booking;
60
  }
61
  }
 
62
  }
63
  }
64
 
65
  /**
66
+ * Add a booking into this event (or add spaces if person already booked this). We assume at this point that the booking has already been validated usin $EM_Booking->validate()
67
  * @param EM_Booking $EM_Booking
68
  * @return boolean
69
  */
70
  function add( $EM_Booking ){
71
  global $wpdb,$EM_Mailer;
72
+ //Save the booking
73
+ $email = false;
74
+ //set status depending on approval settings
75
+ if( empty($EM_Booking->booking_status) ){ //if status is not set, give 1 or 0 depending on approval settings
76
+ $EM_Booking->booking_status = get_option('dbem_bookings_approval') ? 0:1;
77
+ }
78
+ $result = $EM_Booking->save(false);
79
+ if($result){
80
+ //Success
81
+ do_action('em_bookings_added', $EM_Booking);
82
+ $this->bookings[] = $EM_Booking;
83
+ $email = $EM_Booking->email();
84
+ if( get_option('dbem_bookings_approval') == 1 && $EM_Booking->booking_status == 0){
85
+ $this->feedback_message = get_option('dbem_booking_feedback_pending');
86
+ }else{
87
+ $this->feedback_message = get_option('dbem_booking_feedback');
88
+ }
89
+ if(!$email){
90
+ $EM_Booking->email_not_sent = true;
91
+ $this->feedback_message .= ' '.get_option('dbem_booking_feedback_nomail');
92
+ if( current_user_can('activate_plugins') ){
93
+ if( count($EM_Booking->get_errors()) > 0 ){
94
+ $this->feedback_message .= '<br/><strong>Errors:</strong> (only admins see this message)<br/><ul><li>'. implode('</li><li>', $EM_Booking->get_errors()).'</li></ul>';
95
+ }else{
96
+ $this->feedback_message .= '<br/><strong>No errors returned by mailer</strong> (only admins see this message)';
97
  }
98
  }
 
 
 
 
99
  }
100
+ return apply_filters('em_bookings_add', true, $EM_Booking);
101
+ }else{
102
+ //Failure
103
+ $this->errors[] = "<strong>".get_option('dbem_booking_feedback_error')."</strong><br />". implode('<br />', $EM_Booking->errors);
104
+ }
105
+ return apply_filters('em_bookings_add', false, $EM_Booking);
106
  }
107
+
108
  /**
109
  * Get POST data and create a booking for each ticket requested. If successful, a booking object is returned, false if not.
110
  * @return false|object
128
  * Smart event locator, saves a database read if possible. Note that if an event doesn't exist, a blank object will be created to prevent duplicates.
129
  */
130
  function get_event(){
131
+ global $EM_Event;
132
+ if( is_object($EM_Event) && $EM_Event->event_id == $this->event_id ){
133
+ return $EM_Event;
 
 
 
 
134
  }else{
135
+ if( is_numeric($this->event_id) && $this->event_id > 0 ){
136
+ return em_get_event($this->event_id, 'event_id');
137
+ }elseif( count($this->bookings) > 0 ){
138
+ foreach($this->bookings as $EM_Booking){
139
+ /* @var $EM_Booking EM_Booking */
140
+ return em_get_event($EM_Booking->event_id, 'event_id');
141
+ }
142
+ }
143
  }
144
+ return em_get_event($this->event_id, 'event_id');
145
  }
146
 
147
  /**
151
  */
152
  function get_tickets( $force_reload = false ){
153
  if( !is_object($this->tickets) || $force_reload ){
154
+ $this->tickets = new EM_Tickets($this->event_id);
155
+ if( get_option('dbem_bookings_tickets_single') && count($this->tickets->tickets) == 1 && !empty($this->get_event()->rsvp_end) ){
156
+ //if in single ticket mode, then the event booking cut-off is the ticket end date
157
+ $EM_Ticket = $this->tickets->get_first();
158
+ $EM_Event = $this->get_event();
159
+ //if ticket has cut-off date, that should take precedence as we save the ticket cut-off date/time to the event in single ticket mode
160
+ if( !empty($EM_Ticket->ticket_end) ){
161
+ //if ticket end dates are set, move to event
162
+ $EM_Event->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp);
163
+ $EM_Event->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp);
164
+ $EM_Event->rsvp_end = $EM_Ticket->end_timestamp;
165
+ if( $EM_Event->is_recurring() && !empty($EM_Ticket->ticket_meta['recurrences']) ){
166
+ $EM_Event->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
167
+ }
168
+ }else{
169
+ //if no end date is set, use event end date (which will have defaulted to the event start date
170
+ $EM_Ticket->ticket_end = $EM_Event->event_rsvp_date." ".$EM_Event->event_rsvp_time;
171
+ $EM_Ticket->end_timestamp = $EM_Event->rsvp_end;
172
+ }
173
+ }
174
+ }else{
175
+ $this->tickets->event_id = $this->event_id;
176
  }
177
  return apply_filters('em_bookings_get_tickets', $this->tickets, $this);
178
  }
179
 
180
  /**
181
  * Returns EM_Tickets object with available tickets
182
+ * @param boolean $include_member_tickets - if set to true, member-ony tickets will be considered available even if logged out
183
  * @return EM_Tickets
184
  */
185
+ function get_available_tickets( $include_member_tickets = false ){
186
  $tickets = array();
 
187
  foreach ($this->get_tickets() as $EM_Ticket){
188
+ /* @var $EM_Ticket EM_Ticket */
189
+ if( $EM_Ticket->is_available($include_member_tickets) ){
190
  //within time range
191
  if( $EM_Ticket->get_available_spaces() > 0 ){
192
  $tickets[] = $EM_Ticket;
194
  }
195
  }
196
  $EM_Tickets = new EM_Tickets($tickets);
197
+ return apply_filters('em_bookings_get_available_tickets', $EM_Tickets, $this);
198
  }
199
 
200
  function get_user_list(){
212
  function ticket_exists($ticket_id){
213
  $EM_Tickets = $this->get_tickets();
214
  foreach( $EM_Tickets->tickets as $EM_Ticket){
215
+ if($EM_Ticket->ticket_id == $ticket_id){
216
  return apply_filters('em_bookings_ticket_exists',true, $EM_Ticket, $this);
217
  }
218
  }
219
+ return apply_filters('em_bookings_ticket_exists',false, false,$this);
220
+ }
221
+
222
+ function has_space( $include_member_tickets = false ){
223
+ return count($this->get_available_tickets( $include_member_tickets )->tickets) > 0;
224
+ }
225
+
226
+ function has_open_time(){
227
+ $return = false;
228
+ $EM_Event = $this->get_event();
229
+ if(!empty($EM_Event->event_rsvp_date) && $EM_Event->rsvp_end > current_time('timestamp')){
230
+ $return = true;
231
+ }elseif( empty($EM_Event->event_rsvp_date) && $EM_Event->start > current_time('timestamp') ){
232
+ $return = true;
233
+ }
234
+ return $return;
235
+ }
236
+
237
+ function is_open($include_member_tickets = false){
238
+ //TODO extend booking options
239
+ $return = $this->has_open_time() && $this->has_space($include_member_tickets);
240
+ return apply_filters('em_bookings_is_open', $return, $this, $include_member_tickets);
241
  }
242
 
243
  /**
247
  function delete(){
248
  global $wpdb;
249
  $booking_ids = array();
250
+ //get the booking ids tied to this event
251
+ foreach( $this->bookings as $EM_Booking ){
252
+ $booking_ids[] = $EM_Booking->booking_id;
253
+ }
254
+ $result_tickets = true;
255
+ $result = true;
256
+ if( count($booking_ids) > 0 ){
257
+ //Delete bookings and ticket bookings
258
+ $result_tickets = $wpdb->query("DELETE FROM ". EM_TICKETS_BOOKINGS_TABLE ." WHERE booking_id IN (".implode(',',$booking_ids).");");
259
  $result = $wpdb->query("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id IN (".implode(',',$booking_ids).")");
260
  }
261
+ return ($result !== false && $result_tickets !== false);
262
  }
263
 
264
 
297
  */
298
  function set_status($status, $booking_ids){
299
  //FIXME status should work with instantiated object
300
+ if( self::array_is_numeric($booking_ids) ){
 
301
  //Get all the bookings
302
  $results = array();
303
  $mails = array();
304
  foreach( $booking_ids as $booking_id ){
305
+ $EM_Booking = em_get_booking($booking_id);
306
  if( !$EM_Booking->can_manage() ){
307
  $this->feedback_message = __('Bookings %s. Mails Sent.', 'dbem');
308
  return false;
318
  return false;
319
  }
320
  }elseif( is_numeric($booking_ids) || is_object($booking_ids) ){
321
+ $EM_Booking = ( is_object($booking_ids) && get_class($booking_ids) == 'EM_Booking') ? $booking_ids : em_get_booking($booking_ids);
322
  $result = $EM_Booking->set_status($status);
323
  $this->feedback_message = $EM_Booking->feedback_message;
324
  return $result;
336
  if($force_refresh || $this->spaces == 0){
337
  $this->spaces = $this->get_tickets()->get_spaces();
338
  }
339
+ //check overall events cap
340
+ if(!empty($this->get_event()->event_spaces) && $this->get_event()->event_spaces < $this->spaces) $this->spaces = $this->get_event()->event_spaces;
341
  return apply_filters('em_booking_get_spaces',$this->spaces,$this);
342
  }
343
 
346
  * @return int
347
  */
348
  function get_available_spaces(){
349
+ $spaces = $this->get_spaces();
350
+ $available_spaces = $spaces - $this->get_booked_spaces();
351
+ if( get_option('dbem_bookings_approval_reserved') ){ //deduct reserved/pending spaces from available spaces
352
+ $available_spaces -= $this->get_pending_spaces();
 
353
  }
354
+ return apply_filters('em_booking_get_available_spaces', $available_spaces, $this);
355
  }
356
 
357
  /**
358
  * Returns number of booked spaces for this event. If approval of bookings is on, will return number of booked confirmed spaces.
359
  * @return int
360
  */
361
+ function get_booked_spaces($force_refresh = false){
362
  $booked_spaces = 0;
363
+ foreach ( $this->bookings as $EM_Booking ){
364
+ if( $EM_Booking->booking_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->booking_status == 0 ) ){
365
+ $booked_spaces += $EM_Booking->get_spaces($force_refresh);
366
+ }
367
  }
368
+ return apply_filters('em_bookings_get_booked_spaces', $booked_spaces, $this);
369
  }
370
 
371
  /**
374
  */
375
  function get_pending_spaces(){
376
  if( get_option('dbem_bookings_approval') == 0 ){
377
+ return apply_filters('em_bookings_get_pending_spaces', 0, $this);
378
  }
379
  $pending = 0;
380
  foreach ( $this->bookings as $booking ){
381
+ if($booking->booking_status == 0){
382
  $pending += $booking->get_spaces();
383
  }
384
  }
385
+ return apply_filters('em_bookings_get_pending_spaces', $pending, $this);
386
  }
387
 
388
  /**
389
  * Gets number of bookings (not spaces). If booking approval is enabled, only the number of approved bookings will be shown.
390
  * @return EM_Bookings
391
  */
392
+ function get_bookings( $all_bookings = false ){
393
  $confirmed = array();
394
  foreach ( $this->bookings as $booking ){
395
+ if( $booking->booking_status == 1 || (get_option('dbem_bookings_approval') == 0 && $booking->booking_status == 0) || $all_bookings ){
396
  $confirmed[] = $booking;
397
  }
398
  }
406
  */
407
  function get_pending_bookings(){
408
  if( get_option('dbem_bookings_approval') == 0 ){
409
+ return new EM_Bookings();
410
  }
411
  $pending = array();
412
  foreach ( $this->bookings as $booking ){
413
+ if($booking->booking_status == 0){
414
  $pending[] = $booking;
415
  }
416
  }
425
  function get_rejected_bookings(){
426
  $rejected = array();
427
  foreach ( $this->bookings as $booking ){
428
+ if($booking->booking_status == 2){
429
  $rejected[] = $booking;
430
  }
431
  }
440
  function get_cancelled_bookings(){
441
  $cancelled = array();
442
  foreach ( $this->bookings as $booking ){
443
+ if($booking->booking_status == 3){
444
  $cancelled[] = $booking;
445
  }
446
  }
478
  }
479
  if( is_numeric($user_id) && $user_id > 0 ){
480
  foreach ($this->bookings as $EM_Booking){
481
+ if( $EM_Booking->person->ID == $user_id && !in_array($EM_Booking->booking_status, array(2,3)) ){
482
+ return apply_filters('em_bookings_has_booking', $EM_Booking, $this);
483
  }
484
  }
485
  }
491
  * @return array
492
  * @static
493
  */
494
+ public static function get( $args = array(), $count = false ){
495
  global $wpdb,$current_user;
496
  $bookings_table = EM_BOOKINGS_TABLE;
497
  $events_table = EM_EVENTS_TABLE;
507
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
508
  $bookings = array();
509
  foreach($results as $result){
510
+ $bookings[] = em_get_booking($result);
511
  }
512
  return $bookings; //We return all the bookings matched as an EM_Booking array.
513
  }
523
  $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):'';
524
 
525
  //Get ordering instructions
526
+ $EM_Booking = em_get_booking();
527
  $accepted_fields = $EM_Booking->get_fields(true);
528
  $orderby = self::build_sql_orderby($args, $accepted_fields);
529
  //Now, build orderby sql
530
+ $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : 'ORDER BY booking_date';
531
+ //Selector
532
+ $selectors = ( $count ) ? 'COUNT(*)':'*';
533
 
534
  //Create the SQL statement and execute
535
  $sql = "
536
+ SELECT $selectors FROM $bookings_table
537
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
538
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
539
  $where
540
  $orderby_sql
541
  $limit $offset
542
  ";
543
+ //If we're only counting results, return the number of results
544
+ if( $count ){
545
+ return apply_filters('em_bookings_get_count', $wpdb->get_var($sql), $args);
546
+ }
547
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
548
 
549
  //If we want results directly in an array, why not have a shortcut here?
555
  $results = (is_array($results)) ? $results:array();
556
  $bookings = array();
557
  foreach ( $results as $booking ){
558
+ $bookings[] = em_get_booking($booking);
559
  }
560
  $EM_Bookings = new EM_Bookings($bookings);
561
  return apply_filters('em_bookings_get', $EM_Bookings);
562
  }
563
 
564
+ public static function count( $args = array() ){
565
+ return self::get($args, true);
566
+ }
567
+
568
 
569
  //List of patients in the patient database, that a user can choose and go on to edit any previous treatment data, or add a new admission.
570
  function export_csv() {
571
  global $EM_Event;
572
+ if($EM_Event->event_id != $this->event_id ){
573
+ $event = $this->get_event();
574
  $event_name = $event->name;
575
  }else{
576
  $event_name = $EM_Event->name;
580
 
581
  header("Content-Type: application/octet-stream");
582
  header("Content-Disposition: Attachment; filename=$file_name");
583
+ em_locate_template('templates/csv-event-bookings.php', true);
584
+ exit();
585
+ }
586
+
587
+ static function enqueue_js(){
588
+ if( !defined('EM_BOOKING_JS_LOADED') ){ //request loading of JS file in footer of page load
589
+ add_action('wp_footer','EM_Bookings::em_booking_js_footer', 20);
590
+ add_action('admin_footer','EM_Bookings::em_booking_js_footer', 20);
591
+ define('EM_BOOKING_JS_LOADED',true);
592
+ }
593
+ }
594
+
595
+ static function em_booking_js_footer(){
596
+ ?>
597
+ <script type="text/javascript">
598
+ jQuery(document).ready( function($){
599
+ <?php
600
+ //we call the segmented JS files and include them here
601
+ $include_path = dirname(dirname(__FILE__)); //get path to parent directory
602
+ include($include_path.'/includes/js/bookingsform.js');
603
+ do_action('em_gateway_js');
604
+ ?>
605
+ });
606
+ <?php
607
+ do_action('em_booking_js_footer');
608
+ ?>
609
+ </script>
610
+ <?php
611
+ }
612
+
613
+ /**
614
+ * Checks whether a booking being made should register user information as a booking from another user whilst an admin is logged in
615
+ * @return boolean
616
+ */
617
+ public static function is_registration_forced(){
618
+ return ( defined('EM_FORCE_REGISTRATION') || self::$force_registration );
 
 
 
 
 
 
 
 
 
 
 
 
 
619
  }
620
 
621
  /* Overrides EM_Object method to apply a filter to result
622
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
623
  */
624
+ public static function build_sql_conditions( $args = array() ){
625
  $conditions = apply_filters( 'em_bookings_build_sql_conditions', parent::build_sql_conditions($args), $args );
626
  if( is_numeric($args['status']) ){
627
  $conditions['status'] = 'booking_status='.$args['status'];
628
+ }elseif( is_array($args['status']) && count($args['status']) > 0 ){
629
+ $conditions['status'] = 'booking_status IN ('.implode(',',$args['status']).')';
630
+ }elseif( !is_array($args['status']) && preg_match('/^([0-9],?)+$/', $args['status']) ){
631
+ $conditions['status'] = 'booking_status IN ('.$args['status'].')';
632
+ }
633
+ if( is_numeric($args['person']) && current_user_can('manage_others_bookings') ){
634
+ $conditions['person'] = EM_BOOKINGS_TABLE.'.person_id='.$args['person'];
635
+ }
636
+ if( EM_MS_GLOBAL && !empty($args['blog']) && is_numeric($args['blog']) ){
637
+ if( is_main_site($args['blog']) ){
638
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']} OR ".EM_EVENTS_TABLE.".blog_id IS NULL)";
639
+ }else{
640
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']})";
641
+ }
642
+ }
643
+ if( empty($conditions['event']) && $args['event'] === false ){
644
+ $conditions['event'] = EM_BOOKINGS_TABLE.'.event_id != 0';
645
+ }
646
+ if( is_numeric($args['ticket_id']) ){
647
+ $EM_Ticket = new EM_Ticket($args['ticket_id']);
648
+ if( $EM_Ticket->can_manage() ){
649
+ $conditions['ticket'] = EM_BOOKINGS_TABLE.'.booking_id IN (SELECT booking_id FROM '.EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_id='{$args['ticket_id']}')";
650
+ }
651
  }
652
  return apply_filters('em_bookings_build_sql_conditions', $conditions, $args);
653
  }
655
  /* Overrides EM_Object method to apply a filter to result
656
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
657
  */
658
+ public static function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
659
+ return apply_filters( 'em_bookings_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_bookings_default_order','booking_date')), $args, $accepted_fields, $default_order );
660
  }
661
 
662
  /*
663
  * Adds custom Events search defaults
664
+ * @param array $array_or_defaults may be the array to override defaults
665
  * @param array $array
666
  * @return array
667
  * @uses EM_Object#get_default_search()
668
  */
669
+ public static function get_default_search( $array_or_defaults = array(), $array = array() ){
670
  $defaults = array(
671
  'status' => false,
672
+ 'person' => true, //to add later, search by person's bookings...
673
+ 'blog' => get_current_blog_id(),
674
+ 'ticket_id' => false
675
+ );
676
+ //sort out whether defaults were supplied or just the array of search values
677
+ if( empty($array) ){
678
+ $array = $array_or_defaults;
679
+ }else{
680
+ $defaults = array_merge($defaults, $array_or_defaults);
681
+ }
682
+ //figure out default owning permissions
683
+ if( !current_user_can('edit_others_events') ){
684
+ $defaults['owner'] = get_current_user_id();
685
+ }else{
686
+ $defaults['owner'] = false;
687
+ }
688
+ if( EM_MS_GLOBAL && !is_admin() ){
689
+ if( empty($array['blog']) && is_main_site() && get_site_option('dbem_ms_global_events') ){
690
+ $array['blog'] = false;
691
  }
692
  }
693
  return apply_filters('em_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
classes/em-calendar.php CHANGED
@@ -1,30 +1,34 @@
1
  <?php
2
  class EM_Calendar extends EM_Object {
3
 
4
- function init(){
5
  //nothing to init anymore
6
  }
7
 
8
- function output($args = array()) {
 
9
  global $wpdb;
10
 
11
  $calendar_array = array();
12
  $calendar_array['cells'] = array();
13
-
 
 
14
  $args = self::get_default_search($args);
15
  $full = $args['full']; //For ZDE, don't delete pls
16
  $month = $args['month'];
17
  $year = $args['year'];
18
  $long_events = $args['long_events'];
 
19
 
20
  $week_starts_on_sunday = get_option('dbem_week_starts_sunday');
21
  $start_of_week = get_option('start_of_week');
22
 
23
  if( !(is_numeric($month) && $month <= 12 && $month > 0) ) {
24
- $month = date('m');
25
  }
26
  if( !( is_numeric($year) ) ){
27
- $year = date('Y');
28
  }
29
 
30
  // Get the first day of the month
@@ -62,6 +66,9 @@ class EM_Calendar extends EM_Object {
62
  if($month == 1) {
63
  $month_last = 12;
64
  $year_last = $year -1;
 
 
 
65
  }
66
  $calendar_array['month_last'] = $month_last;
67
  $calendar_array['year_last'] = $year_last;
@@ -102,17 +109,14 @@ class EM_Calendar extends EM_Object {
102
  // so, we will have to figure out
103
  // how many days to appened to the end
104
  // of the final array to make it 35 days.
105
- if($current_num > 35){
106
- $num_weeks = 6;
107
- $outset = (42 - $current_num);
108
- } elseif($current_num < 35){
109
- $num_weeks = 5;
110
- $outset = (35 - $current_num);
111
- }
112
- if($current_num == 35){
113
- $num_weeks = 5;
114
- $outset = 0;
115
- }
116
  // Outset Correction
117
  for($i = 1; $i <= $outset; $i++){
118
  $new_count[] = mktime(0,0,0,$month_next, $i, $year_next);
@@ -125,20 +129,26 @@ class EM_Calendar extends EM_Object {
125
  //Get an array of arguments that don't include default valued args
126
  $link_args = self::get_link_args($args);
127
 
128
- $previous_url = "?ajaxCalendar=1&amp;month={$month_last}&amp;year={$year_last}&amp;{$link_args}";
129
- $next_url = "?ajaxCalendar=1&amp;month={$month_next}&amp;year={$year_next}&amp;{$link_args}";
130
 
131
  $weekdays = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
132
- $n = 0 ;
133
- while( $n < $start_of_week ) {
 
 
 
 
 
 
 
134
  $last_day = array_shift($weekdays);
135
- $weekdays[]= $last_day;
136
- $n++;
137
  }
138
 
139
  $days_initials_array = array();
140
  foreach($weekdays as $weekday) {
141
- $days_initials_array[] = self::translate_and_trim($weekday);
142
  }
143
 
144
  $calendar_array['links'] = array( 'previous_url'=>$previous_url, 'next_url'=>$next_url);
@@ -154,7 +164,7 @@ class EM_Calendar extends EM_Object {
154
  foreach ( $weeks as $week ) {
155
  foreach ( $week as $d ) {
156
  $date = date('Y-m-d', $d);
157
- $calendar_array['cells'][$date] = array('date'=>$d); //set it up so we have the exact array of dates to be filled
158
  if ($i < $offset_count) { //if it is PREVIOUS month
159
  $calendar_array['cells'][$date]['type'] = 'pre';
160
  }
@@ -170,114 +180,206 @@ class EM_Calendar extends EM_Object {
170
  $i ++;
171
  }
172
  $week_count++;
173
- }
174
 
175
- // query the database for events in this time span
176
- if ($month == 1) {
177
- $month_pre=12;
178
- $month_post=2;
179
- $year_pre=$year-1;
180
- $year_post=$year;
181
- } elseif($month == 12) {
182
- $month_pre=11;
183
- $month_post=1;
184
- $year_pre=$year;
185
- $year_post=$year+1;
186
- } else {
187
- $month_pre=$month-1;
188
- $month_post=$month+1;
189
- $year_pre=$year;
190
- $year_post=$year;
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
- $args['year'] = array($year_pre, $year_post);
193
- $args['month'] = array($month_pre, $month_post);
194
- $events = EM_Events::get($args);
 
195
 
196
  $event_format = get_option('dbem_full_calendar_event_format');
197
  $event_title_format = get_option('dbem_small_calendar_event_title_format');
198
  $event_title_separator_format = get_option('dbem_small_calendar_event_title_separator');
199
 
200
  $eventful_days= array();
 
201
  if($events){
202
  //Go through the events and slot them into the right d-m index
203
  foreach($events as $event) {
204
  $event = apply_filters('em_calendar_output_loop_start', $event);
205
  if( $long_events ){
206
  //If $long_events is set then show a date as eventful if there is an multi-day event which runs during that day
207
- $event_start_date = mktime(0,0,0,$month_pre,1,$year_pre);
208
- $event_end_date = mktime(0,0,0,$month_post,date('t', $event_start_date),$year_post );
209
- if( $event_end_date == '' ) $event_end_date = $event_start_date;
210
- while( $event_start_date <= $event->end ){
211
- //Ensure date is within event dates, if so add to eventful days array
212
- if( $event_start_date > $event->start - (86400) ){ //subtract a day since start may be later in day
213
- $event_eventful_date = date('Y-m-d', $event_start_date);
214
- if( array_key_exists($event_eventful_date, $eventful_days) && is_array($eventful_days[$event_eventful_date]) ){
215
- $eventful_days[$event_eventful_date][] = $event;
216
- } else {
217
- $eventful_days[$event_eventful_date] = array($event);
218
- }
219
- }
220
- $event_start_date += (86400); //add a day
 
 
 
 
 
 
221
  }
222
  }else{
223
  //Only show events on the day that they start
224
- if( isset($eventful_days[$event->start_date]) && is_array($eventful_days[$event->start_date]) ){
225
- $eventful_days[$event->start_date][] = $event;
226
- } else {
227
- $eventful_days[$event->start_date] = array($event);
 
 
 
 
 
 
228
  }
 
 
229
  }
230
- $event = apply_filters('em_calendar_output_loop_end', $event);
231
  }
232
  }
 
 
233
  foreach($eventful_days as $day_key => $events) {
234
  if( array_key_exists($day_key, $calendar_array['cells']) ){
235
  //Get link title for this date
236
  $events_titles = array();
237
- foreach($events as $event) {
238
- $events_titles[] = $event->output($event_title_format);
239
- }
 
 
 
 
 
240
  $calendar_array['cells'][$day_key]['link_title'] = implode( $event_title_separator_format, $events_titles);
241
 
242
  //Get the link to this calendar day
243
  global $wp_rewrite;
244
- $event_page_link = get_permalink(get_option('dbem_events_page')); //don't use EM_URI here, since ajax calls this before EM_URI is defined.
245
- if( $wp_rewrite->using_permalinks() ){
246
- $calendar_array['cells'][$day_key]['link'] = $event_page_link.$day_key."/";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  }else{
248
- $joiner = (stristr($event_page_link, "?")) ? "&amp;" : "?";
249
- $calendar_array['cells'][$day_key]['link'] = $event_page_link.$joiner."calendar_day=".$day_key;
 
250
  }
251
  //Add events to array
 
252
  $calendar_array['cells'][$day_key]['events'] = $events;
253
  }
254
  }
255
-
256
- $template = ($args['full']) ? 'templates/calendar-full.php':'templates/calendar-small.php';
 
 
 
 
 
 
 
 
 
 
 
 
257
  ob_start();
258
  em_locate_template($template, true, array('calendar'=>$calendar_array,'args'=>$args));
259
- $calendar = '<div id="em-calendar-'.rand(100,200).'" class="em-calendar-wrapper">'.ob_get_clean().'</div>';
 
 
 
 
260
  return apply_filters('em_calendar_output', $calendar, $args);
261
  }
262
 
263
 
264
- function days_in_month($month, $year) {
265
  return date('t', mktime(0,0,0,$month,1,$year));
266
  }
267
 
268
- function translate_and_trim($string, $length = 1) {
269
- return substr(__($string), 0, $length);
 
 
 
 
 
 
 
270
  }
271
 
272
  /**
273
  * Helper function to create a link querystring from array which contains arguments with only values that aren't defuaults.
274
  */
275
- function get_link_args($args = array(), $html_entities=true){
276
  unset($args['month']); unset($args['year']);
277
  $default_args = self::get_default_search(array());
278
  foreach($default_args as $arg_key => $arg_value){
279
- if( !isset($args[$arg_key]) || $args[$arg_key] == $arg_value ){
280
  unset($args[$arg_key]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
282
  }
283
  $qs_array = array();
@@ -291,14 +393,46 @@ class EM_Calendar extends EM_Object {
291
  }
292
 
293
 
294
- function get_default_search($array=array()){
 
 
 
 
 
 
 
295
  //These defaults aren't for db queries, but flags for what to display in calendar output
296
  $defaults = array(
297
  'full' => 0, //Will display a full calendar with event names
298
  'long_events' => 0, //Events that last longer than a day
299
- 'scope' => 'future',
300
- 'owner' => false
 
 
 
 
 
 
 
 
 
301
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  $atts = parent::get_default_search($defaults, $array);
303
  $atts['full'] = ($atts['full']==true) ? 1:0;
304
  $atts['long_events'] = ($atts['long_events']==true) ? 1:0;
1
  <?php
2
  class EM_Calendar extends EM_Object {
3
 
4
+ public static function init(){
5
  //nothing to init anymore
6
  }
7
 
8
+ public static function get( $args ){
9
+
10
  global $wpdb;
11
 
12
  $calendar_array = array();
13
  $calendar_array['cells'] = array();
14
+
15
+ $args = apply_filters('em_calendar_get_args', $args);
16
+ $original_args = $args;
17
  $args = self::get_default_search($args);
18
  $full = $args['full']; //For ZDE, don't delete pls
19
  $month = $args['month'];
20
  $year = $args['year'];
21
  $long_events = $args['long_events'];
22
+ $limit = $args['limit']; //limit arg will be used per day and not for events search
23
 
24
  $week_starts_on_sunday = get_option('dbem_week_starts_sunday');
25
  $start_of_week = get_option('start_of_week');
26
 
27
  if( !(is_numeric($month) && $month <= 12 && $month > 0) ) {
28
+ $month = date('m', current_time('timestamp'));
29
  }
30
  if( !( is_numeric($year) ) ){
31
+ $year = date('Y', current_time('timestamp'));
32
  }
33
 
34
  // Get the first day of the month
66
  if($month == 1) {
67
  $month_last = 12;
68
  $year_last = $year -1;
69
+ }elseif($month == 12){
70
+ $month_next = 1;
71
+ $year_next = $year + 1;
72
  }
73
  $calendar_array['month_last'] = $month_last;
74
  $calendar_array['year_last'] = $year_last;
109
  // so, we will have to figure out
110
  // how many days to appened to the end
111
  // of the final array to make it 35 days.
112
+ if( !empty($args['number_of_weeks']) && is_numeric($args['number_of_weeks']) ){
113
+ $num_weeks = $args['number_of_weeks'];
114
+ }elseif($current_num > 35){
115
+ $num_weeks = 6;
116
+ }else{
117
+ $num_weeks = 5;
118
+ }
119
+ $outset = ($num_weeks * 7) - $current_num;
 
 
 
120
  // Outset Correction
121
  for($i = 1; $i <= $outset; $i++){
122
  $new_count[] = mktime(0,0,0,$month_next, $i, $year_next);
129
  //Get an array of arguments that don't include default valued args
130
  $link_args = self::get_link_args($args);
131
 
132
+ $previous_url = "?ajaxCalendar=1&amp;mo={$month_last}&amp;yr={$year_last}&amp;{$link_args}";
133
+ $next_url = "?ajaxCalendar=1&amp;mo={$month_next}&amp;yr={$year_next}&amp;{$link_args}";
134
 
135
  $weekdays = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
136
+ if(!empty($args['full'])) {
137
+ if( get_option('dbem_full_calendar_abbreviated_weekdays') ) $weekdays = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
138
+ $day_initials_length = get_option('dbem_full_calendar_initials_length');
139
+ } else {
140
+ if ( get_option('dbem_small_calendar_abbreviated_weekdays') ) $weekdays = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
141
+ $day_initials_length = get_option('dbem_small_calendar_initials_length');
142
+ }
143
+
144
+ for( $n = 0; $n < $start_of_week; $n++ ) {
145
  $last_day = array_shift($weekdays);
146
+ $weekdays[]= $last_day;
 
147
  }
148
 
149
  $days_initials_array = array();
150
  foreach($weekdays as $weekday) {
151
+ $days_initials_array[] = self::translate_and_trim($weekday, $day_initials_length);
152
  }
153
 
154
  $calendar_array['links'] = array( 'previous_url'=>$previous_url, 'next_url'=>$next_url);
164
  foreach ( $weeks as $week ) {
165
  foreach ( $week as $d ) {
166
  $date = date('Y-m-d', $d);
167
+ $calendar_array['cells'][$date] = array('date'=>$d, 'events'=>array(), 'events_count'=>0); //set it up so we have the exact array of dates to be filled
168
  if ($i < $offset_count) { //if it is PREVIOUS month
169
  $calendar_array['cells'][$date]['type'] = 'pre';
170
  }
180
  $i ++;
181
  }
182
  $week_count++;
183
+ }
184
 
185
+ //query the database for events in this time span with $offset days before and $outset days after this month to account for these cells in the calendar
186
+ $scope_datetime_start = new DateTime("{$year}-{$month}-1");
187
+ $scope_datetime_end = new DateTime($scope_datetime_start->format('Y-m-t'));
188
+ $scope_datetime_start->modify("-$offset days");
189
+ $scope_datetime_end->modify("+$outset days");
190
+ //we have two methods here, one for high-volume event sites i.e. many thousands of events per month, and another for thousands or less per month.
191
+ $args['array'] = true; //we're getting an array first to avoid extra queries during object creation
192
+ unset($args['month']);
193
+ unset($args['year']);
194
+ unset($args['limit']); //limits in the events search won't help
195
+ if( defined('EM_CALENDAR_OPT') && EM_CALENDAR_OPT ){
196
+ //here we loop through each day, query that specific date, and then compile a list of event objects
197
+ //in this mode the count will never be accurate, we're grabing at most (31 + 14 days) * (limit + 1) events to reduce memory loads
198
+ $args['limit'] = $limit + 1;
199
+ $scope_datetime_loop = $scope_datetime_start->format('U');
200
+ $events = array();
201
+ while( $scope_datetime_loop <= $scope_datetime_end->format('U') ){
202
+ $args['scope'] = date('Y-m-d', $scope_datetime_loop);
203
+ foreach( EM_Events::get($args) as $event ){
204
+ $events[$event['event_id']] = $event;
205
+ }
206
+ $scope_datetime_loop += (86400); //add a day
207
+ }
208
+ }else{
209
+ //just load all the events for this time-range
210
+ $args['scope'] = array( $scope_datetime_start->format('Y-m-d'), $scope_datetime_end->format('Y-m-d'));
211
+ $events = EM_Events::get($args);
212
  }
213
+ //back to what it was
214
+ $args['month'] = $month;
215
+ $args['year'] = $year;
216
+ $args['limit'] = $limit;
217
 
218
  $event_format = get_option('dbem_full_calendar_event_format');
219
  $event_title_format = get_option('dbem_small_calendar_event_title_format');
220
  $event_title_separator_format = get_option('dbem_small_calendar_event_title_separator');
221
 
222
  $eventful_days= array();
223
+ $eventful_days_count = array();
224
  if($events){
225
  //Go through the events and slot them into the right d-m index
226
  foreach($events as $event) {
227
  $event = apply_filters('em_calendar_output_loop_start', $event);
228
  if( $long_events ){
229
  //If $long_events is set then show a date as eventful if there is an multi-day event which runs during that day
230
+ $event_start_ts = strtotime($event['event_start_date']);
231
+ $event_end_ts = strtotime($event['event_end_date']);
232
+ $event_end_ts = $event_end_ts > $scope_datetime_end->format('U') ? $scope_datetime_end->format('U') : $event_end_ts;
233
+ while( $event_start_ts <= $event_end_ts ){ //we loop until the last day of our time-range, not the end date of the event, which could be in a year
234
+ //Ensure date is within event dates and also within the limits of events to show per day, if so add to eventful days array
235
+ $event_eventful_date = date('Y-m-d', $event_start_ts);
236
+ if( empty($eventful_days_count[$event_eventful_date]) || !$limit || $eventful_days_count[$event_eventful_date] < $limit ){
237
+ //now we know this is an event that'll be used, convert it to an object
238
+ $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : $EM_Event = em_get_event($event['post_id'], 'post_id');
239
+ if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
240
+ //add event to array with a corresponding timestamp for sorting of times including long and all-day events
241
+ $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) strtotime($event_eventful_date.' '.$EM_Event->event_start_time);
242
+ while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
243
+ $event_ts_marker++; //add a second
244
+ }
245
+ $eventful_days[$event_eventful_date][$event_ts_marker] = $EM_Event;
246
+ }
247
+ //count events for that day
248
+ $eventful_days_count[$event_eventful_date] = empty($eventful_days_count[$event_eventful_date]) ? 1 : $eventful_days_count[$event_eventful_date]+1;
249
+ $event_start_ts += (86400); //add a day
250
  }
251
  }else{
252
  //Only show events on the day that they start
253
+ $event_eventful_date = $event['event_start_date'];
254
+ if( empty($eventful_days_count[$event_eventful_date]) || !$limit || $eventful_days_count[$event_eventful_date] < $limit ){
255
+ $EM_Event = EM_MS_GLOBAL ? em_get_event($event['post_id'], $event['blog_id']) : em_get_event($event['post_id'], 'post_id');
256
+ if( empty($eventful_days[$event_eventful_date]) || !is_array($eventful_days[$event_eventful_date]) ) $eventful_days[$event_eventful_date] = array();
257
+ //add event to array with a corresponding timestamp for sorting of times including long and all-day events
258
+ $event_ts_marker = ($EM_Event->event_all_day) ? 0 : (int) $EM_Event->start;
259
+ while( !empty($eventful_days[$event_eventful_date][$event_ts_marker]) ){
260
+ $event_ts_marker++; //add a second
261
+ }
262
+ $eventful_days[$event_eventful_date][$event_ts_marker] = $EM_Event;
263
  }
264
+ //count events for that day
265
+ $eventful_days_count[$event['event_start_date']] = empty($eventful_days_count[$event['event_start_date']]) ? 1 : $eventful_days_count[$event['event_start_date']]+1;
266
  }
 
267
  }
268
  }
269
+ //generate a link argument string containing event search only
270
+ $day_link_args = self::get_link_args( array_intersect_key($original_args, EM_Events::get_post_search($args, true) ));
271
  foreach($eventful_days as $day_key => $events) {
272
  if( array_key_exists($day_key, $calendar_array['cells']) ){
273
  //Get link title for this date
274
  $events_titles = array();
275
+ foreach($events as $event) {
276
+ if( !$limit || count($events_titles) < $limit ){
277
+ $events_titles[] = $event->output($event_title_format);
278
+ }else{
279
+ $events_titles[] = get_option('dbem_display_calendar_events_limit_msg');
280
+ break;
281
+ }
282
+ }
283
  $calendar_array['cells'][$day_key]['link_title'] = implode( $event_title_separator_format, $events_titles);
284
 
285
  //Get the link to this calendar day
286
  global $wp_rewrite;
287
+ if( $eventful_days_count[$day_key] > 1 || !get_option('dbem_calendar_direct_links') ){
288
+ if( get_option("dbem_events_page") > 0 ){
289
+ $event_page_link = get_permalink(get_option("dbem_events_page")); //PAGE URI OF EM
290
+ }else{
291
+ if( $wp_rewrite->using_permalinks() ){
292
+ $event_page_link = trailingslashit(home_url()).EM_POST_TYPE_EVENT_SLUG.'/'; //don't use EM_URI here, since ajax calls this before EM_URI is defined.
293
+ }else{
294
+ $event_page_link = trailingslashit(home_url()).'?post_type='.EM_POST_TYPE_EVENT; //don't use EM_URI here, since ajax calls this before EM_URI is defined.
295
+ }
296
+ }
297
+ if( $wp_rewrite->using_permalinks() && !defined('EM_DISABLE_PERMALINKS') ){
298
+ $calendar_array['cells'][$day_key]['link'] = trailingslashit($event_page_link).$day_key."/";
299
+ if( !empty($day_link_args) ){
300
+ $calendar_array['cells'][$day_key]['link'] .= '?'.$day_link_args;
301
+ }
302
+ }else{
303
+ $joiner = (stristr($event_page_link, "?")) ? "&amp;" : "?";
304
+ $calendar_array['cells'][$day_key]['link'] = $event_page_link.$joiner."calendar_day=".$day_key;
305
+ if( !empty($day_link_args) ){
306
+ $calendar_array['cells'][$day_key]['link'] .= '&amp;'.$day_link_args;
307
+ }
308
+ }
309
  }else{
310
+ foreach($events as $EM_Event){
311
+ $calendar_array['cells'][$day_key]['link'] = $EM_Event->get_permalink();
312
+ }
313
  }
314
  //Add events to array
315
+ $calendar_array['cells'][$day_key]['events_count'] = $eventful_days_count[$day_key];
316
  $calendar_array['cells'][$day_key]['events'] = $events;
317
  }
318
  }
319
+ return apply_filters('em_calendar_get',$calendar_array, $args);
320
+ }
321
+
322
+ public static function output($args = array(), $wrapper = true) {
323
+ //Let month and year REQUEST override for non-JS users
324
+ $args['limit'] = !empty($args['limit']) ? $args['limit'] : get_option('dbem_display_calendar_events_limit'); //limit arg will be used per day and not for events search
325
+ if( !empty($_REQUEST['mo']) || !empty($args['mo']) ){
326
+ $args['month'] = ($_REQUEST['mo']) ? $_REQUEST['mo']:$args['mo'];
327
+ }
328
+ if( !empty($_REQUEST['yr']) || !empty($args['yr']) ){
329
+ $args['year'] = (!empty($_REQUEST['yr'])) ? $_REQUEST['yr']:$args['yr'];
330
+ }
331
+ $calendar_array = self::get($args);
332
+ $template = (!empty($args['full'])) ? 'templates/calendar-full.php':'templates/calendar-small.php';
333
  ob_start();
334
  em_locate_template($template, true, array('calendar'=>$calendar_array,'args'=>$args));
335
+ if($wrapper){
336
+ $calendar = '<div id="em-calendar-'.rand(100,200).'" class="em-calendar-wrapper">'.ob_get_clean().'</div>';
337
+ }else{
338
+ $calendar = ob_get_clean();
339
+ }
340
  return apply_filters('em_calendar_output', $calendar, $args);
341
  }
342
 
343
 
344
+ public static function days_in_month($month, $year) {
345
  return date('t', mktime(0,0,0,$month,1,$year));
346
  }
347
 
348
+ public static function translate_and_trim($string, $length = 1) {
349
+ if( $length > 0 ){
350
+ if(function_exists('mb_substr')){ //fix for diacritic calendar names
351
+ return mb_substr(__($string,'dbem'), 0, $length, 'UTF-8');
352
+ }else{
353
+ return substr(__($string,'dbem'), 0, $length);
354
+ }
355
+ }
356
+ return __($string,'dbem');
357
  }
358
 
359
  /**
360
  * Helper function to create a link querystring from array which contains arguments with only values that aren't defuaults.
361
  */
362
+ public static function get_link_args($args = array(), $html_entities=true){
363
  unset($args['month']); unset($args['year']);
364
  $default_args = self::get_default_search(array());
365
  foreach($default_args as $arg_key => $arg_value){
366
+ if( !isset($args[$arg_key]) ){
367
  unset($args[$arg_key]);
368
+ }else{
369
+ //check that argument doesn't match default
370
+ $arg = array($args[$arg_key], $arg_value);
371
+ foreach($arg as $k => $v){
372
+ if( is_string($v) || is_numeric($v) ){
373
+ //strings must be typecast to avoid false positive for something like 'string' == 0
374
+ $arg[$k] = (string) $v;
375
+ }elseif( is_bool($v) ){
376
+ $arg[$k] = $v ? '1':'0';
377
+ }
378
+ }
379
+ if( $arg[0] == $arg[1] ){
380
+ //argument same as default so it's not needed in link
381
+ unset($args[$arg_key]);
382
+ }
383
  }
384
  }
385
  $qs_array = array();
393
  }
394
 
395
 
396
+ /*
397
+ * Adds custom calendar search defaults
398
+ * @param array $array_or_defaults may be the array to override defaults
399
+ * @param array $array
400
+ * @return array
401
+ * @uses EM_Object#get_default_search()
402
+ */
403
+ public static function get_default_search( $array_or_defaults = array(), $array = array() ){
404
  //These defaults aren't for db queries, but flags for what to display in calendar output
405
  $defaults = array(
406
  'full' => 0, //Will display a full calendar with event names
407
  'long_events' => 0, //Events that last longer than a day
408
+ 'scope' => false,
409
+ 'status' => 1, //approved events only
410
+ 'town' => false,
411
+ 'state' => false,
412
+ 'country' => false,
413
+ 'region' => false,
414
+ 'blog' => get_current_blog_id(),
415
+ 'orderby' => get_option('dbem_display_calendar_orderby'),
416
+ 'order' => get_option('dbem_display_calendar_order'),
417
+ 'number_of_weeks' => false, //number of weeks to be displayed in the calendar
418
+ 'limit' => get_option('dbem_display_calendar_events_limit')
419
  );
420
+ //sort out whether defaults were supplied or just the array of search values
421
+ if( empty($array) ){
422
+ $array = $array_or_defaults;
423
+ }else{
424
+ $defaults = array_merge($defaults, $array_or_defaults);
425
+ }
426
+ //specific functionality
427
+ if(is_multisite()){
428
+ global $bp;
429
+ if( !is_main_site() && !array_key_exists('blog',$array) ){
430
+ //not the main blog, force single blog search
431
+ $array['blog'] = get_current_blog_id();
432
+ }elseif( empty($array['blog']) && get_site_option('dbem_ms_global_events') ) {
433
+ $array['blog'] = false;
434
+ }
435
+ }
436
  $atts = parent::get_default_search($defaults, $array);
437
  $atts['full'] = ($atts['full']==true) ? 1:0;
438
  $atts['long_events'] = ($atts['long_events']==true) ? 1:0;
classes/em-categories-taxonomy.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Categories_Taxonomy{
3
+ public static function init(){
4
+ add_action( EM_TAXONOMY_CATEGORY.'_edit_form_fields', array('EM_Categories_Taxonomy','form'), 10, 1);
5
+ add_action( EM_TAXONOMY_CATEGORY.'_add_form_fields', array('EM_Categories_Taxonomy','form'), 10, 1);
6
+ add_action( 'edited_'.EM_TAXONOMY_CATEGORY, array('EM_Categories_Taxonomy','save'), 10, 2);
7
+ add_action( 'create_'.EM_TAXONOMY_CATEGORY, array('EM_Categories_Taxonomy','save'), 10, 2);
8
+ add_action( 'delete_'.EM_TAXONOMY_CATEGORY, array('EM_Categories_Taxonomy','delete'), 10, 2);
9
+
10
+ add_filter('manage_edit-'.EM_TAXONOMY_CATEGORY.'_columns' , array('EM_Categories_Taxonomy','columns_add'));
11
+ add_filter('manage_'.EM_TAXONOMY_CATEGORY.'_custom_column' , array('EM_Categories_Taxonomy','columns_output'),10,3);
12
+
13
+ self::admin_init();
14
+ }
15
+
16
+
17
+ public static function columns_add($columns) {
18
+ //prepend ID after checkbox
19
+ $columns['cat-id'] = __('ID','dbem');
20
+ return $columns;
21
+ }
22
+
23
+ public static function columns_output( $val, $column, $term_id ) {
24
+ switch ( $column ) {
25
+ case 'cat-id':
26
+ return $term_id;
27
+ break;
28
+ }
29
+ return $val;
30
+ }
31
+
32
+ public static function admin_init(){
33
+ global $pagenow;
34
+ if($pagenow == 'edit-tags.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
+ }
41
+
42
+ public static function form($tag){
43
+ $category_color = '#FFFFFF';
44
+ $category_image = '';
45
+ if( $tag != EM_TAXONOMY_CATEGORY ){ //not an add new tag form
46
+ $EM_Category = new EM_Category($tag);
47
+ $category_color = $EM_Category->get_color();
48
+ $category_image = $EM_Category->get_image_url();
49
+ $category_image_id = $EM_Category->get_image_id();
50
+ }
51
+ ?>
52
+ <tr class="form-field">
53
+ <th scope="row" valign="top"><label for="category-bgcolor">Calendar Color</label></th>
54
+ <td>
55
+ <input type="text" name="category_bgcolor" id="category-bgcolor" class="colorwell" value="<?php echo esc_attr($category_color); ?>" style="width:100px;"/><br />
56
+ <p class="description"><?php echo sprintf(__('Choose a color for your category. You can access this using the %s placeholder.','dbem'),'<code>#_CATEGORYCOLOR</code>'); ?></p>
57
+ <div id="picker" style="position:absolute; display:none; background:#DEDEDE"></div>
58
+ </td>
59
+ </tr>
60
+ <tr class="form-field">
61
+ <th scope="row" valign="top"><label for="category-image">Image</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','dbem'); ?>" 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','dbem'); ?>" 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.','dbem'),'<code>#_CATEGORYIMAGE</code>'); ?></p>
74
+ </td>
75
+ </tr>
76
+ <?php
77
+ }
78
+
79
+ public static function save($term_id, $tt_id){
80
+ global $wpdb;
81
+ if (!$term_id) return;
82
+ if( !empty($_POST['category_bgcolor']) && preg_match('/^#[a-zA-Z0-9]{6}$/', $_POST['category_bgcolor']) ){
83
+ //get results and save/update
84
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-bgcolor'");
85
+ if( count($prev_settings) > 0 ){
86
+ $wpdb->update(EM_META_TABLE, array('object_id'=>$term_id,'meta_value'=>$_POST['category_bgcolor']), array('object_id'=>$term_id,'meta_key'=>'category-bgcolor'));
87
+ }else{
88
+ $wpdb->insert(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-bgcolor','meta_value'=>$_POST['category_bgcolor']));
89
+ }
90
+ }
91
+ if( !empty($_POST['category_image']) ){
92
+ //get results and save/update
93
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-image'");
94
+ if( count($prev_settings) > 0 ){
95
+ $wpdb->update(EM_META_TABLE, array('object_id'=>$term_id,'meta_value'=>$_POST['category_image']), array('object_id'=>$term_id,'meta_key'=>'category-image'));
96
+ }else{
97
+ $wpdb->insert(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-image','meta_value'=>$_POST['category_image']));
98
+ }
99
+ if( !empty($_POST['category_image_id']) && is_numeric($_POST['category_image_id']) ){
100
+ //get results and save/update
101
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-image-id'");
102
+ if( count($prev_settings) > 0 ){
103
+ $wpdb->update(EM_META_TABLE, array('object_id'=>$term_id,'meta_value'=>$_POST['category_image_id']), array('object_id'=>$term_id,'meta_key'=>'category-image-id'));
104
+ }else{
105
+ $wpdb->insert(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-image-id','meta_value'=>$_POST['category_image_id']));
106
+ }
107
+ }
108
+ }else{
109
+ //check if an image exists, if so remove association
110
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-image'");
111
+ if( count($prev_settings) > 0 ){
112
+ $wpdb->delete(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-image'));
113
+ $wpdb->delete(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-image-id'));
114
+ }
115
+ }
116
+ }
117
+
118
+ public static function delete( $term_id ){
119
+ global $wpdb;
120
+ //delete category image and color
121
+ $wpdb->query('DELETE FROM '.EM_META_TABLE." WHERE object_id='$term_id' AND (meta_key='category-image' OR meta_key='category-bgcolor')");
122
+ //delete all events category relations
123
+ $wpdb->query('DELETE FROM '.EM_META_TABLE." WHERE meta_value='{$term_id}' AND meta_key='event-category'");
124
+ }
125
+ }
126
+ add_action('admin_init',array('EM_Categories_Taxonomy','init'));
classes/em-categories.php CHANGED
@@ -7,27 +7,43 @@ class EM_Categories extends EM_Object implements Iterator{
7
  */
8
  var $categories = array();
9
  /**
10
- * @var EM_Event
 
11
  */
12
- var $event;
 
 
 
 
 
13
 
14
  /**
15
  * Creates an EM_Categories instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
16
- * @param EM_Event $event
17
  * @return null
18
  */
19
  function EM_Categories( $data = false ){
20
- if( is_object($data) && get_class($data) == "EM_Event" ){ //Creates a blank categories object if needed
21
- global $wpdb;
22
- $this->event = $data;
23
- $sql = "SELECT meta_value FROM ". EM_META_TABLE ." WHERE meta_key='event-category' AND object_id ='{$this->event->id}'";
24
- $categories = $wpdb->get_results($sql, ARRAY_A);
25
- foreach ($categories as $category_data){
26
- $this->categories[] = new EM_Category($category_data['meta_value']);
 
 
 
 
 
 
 
 
 
 
27
  }
28
- }elseif( is_array($data) && $this->array_is_numeric($data) ){
29
  foreach($data as $category_id){
30
- $this->categories[] = new EM_Category($category_id);
31
  }
32
  }elseif( is_array($data) ){
33
  foreach( $data as $EM_Category ){
@@ -35,99 +51,98 @@ class EM_Categories extends EM_Object implements Iterator{
35
  $this->categories[] = $EM_Category;
36
  }
37
  }
38
- $this->get_event();
39
  }
 
 
40
  }
41
-
42
- function get( $args = array() ) {
43
- global $wpdb;
44
- $categories_table = EM_CATEGORIES_TABLE;
45
- $events_table = EM_EVENTS_TABLE;
46
-
47
- //Quick version, we can accept an array of IDs, which is easy to retrieve
48
- if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
49
- //We can just get all the events here and return them
50
- $sql = "SELECT * FROM $categories_table WHERE category_id=".implode(" OR category_id=", $args);
51
- $results = $wpdb->get_results(apply_filters('em_categories_get_sql',$sql),ARRAY_A);
52
- $categories = array();
53
- foreach($results as $result){
54
- $categories[$result['category_id']] = new EM_Category($result);
55
  }
56
- return $categories; //We return all the categories matched as an EM_Event array.
57
  }
58
-
59
- //We assume it's either an empty array or array of search arguments to merge with defaults
60
- $args = self::get_default_search($args);
61
- $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
62
- $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
63
-
64
- //Get the default conditions
65
- $conditions = self::build_sql_conditions($args);
66
- //Put it all together
67
- $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):'';
68
-
69
- //Get ordering instructions
70
- $EM_Category = new EM_Category();
71
- $accepted_fields = $EM_Category->get_fields(true);
72
- $orderby = self::build_sql_orderby($args, $accepted_fields, get_option('dbem_categories_default_order'));
73
- //Now, build orderby sql
74
- $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
75
-
76
- //Create the SQL statement and execute
77
- $sql = "
78
- SELECT * FROM $categories_table
79
- $where
80
- GROUP BY category_id
81
- $orderby_sql
82
- $limit $offset
83
- ";
84
- $results = $wpdb->get_results( apply_filters('em_categories_get_sql',$sql, $args), ARRAY_A);
85
- //If we want results directly in an array, why not have a shortcut here?
86
- if( $args['array'] == true ){
87
- return $results;
88
  }
89
-
90
- //Make returned results EM_Event objects
91
- $results = (is_array($results)) ? $results:array();
92
- $categories = array();
93
- foreach ( $results as $category_array ){
94
- $categories[$category_array['category_id']] = new EM_Category($category_array);
95
  }
96
-
97
- return apply_filters('em_categories_get', $categories, $args);
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  }
99
 
100
- /**
101
- * Will delete given an array of category_ids or EM_Event objects
102
- * @param unknown_type $id_array
103
- */
104
- function delete( $array ){
105
  global $wpdb;
106
- //Detect array type and generate SQL for event IDs
107
- $category_ids = array();
108
- if( @get_class(current($array)) == 'EM_Category' ){
109
- foreach($array as $EM_Category){
110
- $category_ids[] = $EM_Category->id;
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
  }else{
113
- $category_ids = $array;
114
- }
115
- if(self::array_is_numeric($category_ids)){
116
- apply_filters('em_categories_delete', $category_ids);
117
- $condition = implode(" OR category_id=", $category_ids);
118
- //Delete all the categories
119
- $result_categories = $wpdb->query("DELETE FROM ". EM_CATEGORIES_TABLE ." WHERE category_id=$condition;");
120
- //Now delete the categories
121
- $result = $wpdb->query ( "DELETE FROM ". EM_CATEGORIES_TABLE ." WHERE category_id=$condition;" );
122
- do_action('em_categories_delete', $category_ids);
 
 
 
 
 
123
  }
124
- //TODO add error detection on categories delete fails
125
- return apply_filters('em_categories_delete', true, $category_ids);
126
  }
127
 
128
- function output( $args ){
129
  global $EM_Category;
130
  $EM_Category_old = $EM_Category; //When looping, we can replace EM_Category global with the current event in the loop
 
 
 
 
 
131
  //Can be either an array for the get search or an array of EM_Category objects
132
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Category' ){
133
  $func_args = func_get_args();
@@ -142,10 +157,11 @@ class EM_Categories extends EM_Object implements Iterator{
142
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
143
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
144
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
145
- $args['limit'] = false;
146
- $args['offset'] = false;
147
- $args['page'] = false;
148
  $categories = self::get( $args );
 
 
 
149
  }
150
  //What format shall we output this to, or use default
151
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_categories_list_item_format' ) : $args['format'] ;
@@ -174,9 +190,7 @@ class EM_Categories extends EM_Object implements Iterator{
174
  //Pagination (if needed/requested)
175
  if( !empty($args['pagination']) && !empty($limit) && $categories_count >= $limit ){
176
  //Show the pagination links (unless there's less than 10 events, or the custom limit)
177
- $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
178
- $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'));
179
- $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $categories_count, $limit, $page), $page_link_template, $categories_count, $limit, $page);
180
  }
181
  } else {
182
  $output = get_option ( 'dbem_no_categories_message' );
@@ -186,44 +200,46 @@ class EM_Categories extends EM_Object implements Iterator{
186
  return apply_filters('em_categories_output', $output, $categories, $args);
187
  }
188
 
189
- /**
190
- * If these categories collection are connected with an existing EM_Event object, then we can add categories to this event.
191
- */
192
- function save(){
193
- if( !empty($this->get_event()->id) ){
194
- global $wpdb;
195
- $event_id = $this->event->id;
196
- //remove old cats
197
- $wpdb->query('DELETE FROM '.EM_META_TABLE." WHERE object_id='$event_id' AND meta_key='event-category'");
198
- //Now add new ones
199
- $inserts = array();
200
- foreach($this->get_ids() as $id){
201
- $inserts[] = "($event_id,'event-category',$id)";
202
- }
203
- if( count($inserts) > 0 ){
204
- $result = $wpdb->query("INSERT INTO ".EM_META_TABLE." (`object_id`,`meta_key`,`meta_value`) VALUES ".implode(',',$inserts));
205
- if( $result === false ){
206
- $this->add_error( sprintf(__('Could not save the %s details due to a database error.', 'dbem'),__('category','dbem') ));
207
- }
208
- }
209
  }
210
- return apply_filters('em_categories_save', count($this->errors) == 0, $this);
 
 
 
 
 
 
211
  }
212
 
213
  function has( $search ){
214
  if( is_numeric($search) ){
215
  foreach($this->categories as $EM_Category){
216
- if($EM_Category->id == $search) return apply_filters('em_categories_has', true, $search, $this);
217
  }
 
 
 
 
218
  }
219
  return apply_filters('em_categories_has', false, $search, $this);
220
  }
221
 
 
 
 
 
 
 
 
222
  function get_ids(){
223
  $ids = array();
224
  foreach($this->categories as $EM_Category){
225
- if( !empty($EM_Category->id) ){
226
- $ids[] = $EM_Category->id;
227
  }
228
  }
229
  return $ids;
@@ -234,61 +250,36 @@ class EM_Categories extends EM_Object implements Iterator{
234
  * @return EM_Event
235
  */
236
  function get_event(){
237
- if( !( is_object($this->event) && get_class($this->event) == 'EM_Event' ) ){
238
- $this->event = new EM_Event();
239
- }
240
- return apply_filters('em_categories_get_event', $this->event, $this);
241
- }
242
-
243
- /* Overrides EM_Object method to apply a filter to result. Categories won't accept many arguments as you tend to search with events for much else.
244
- * @see wp-content/plugins/categories-manager/classes/EM_Object#build_sql_conditions()
245
- */
246
- function build_sql_conditions( $args = array() ){
247
- global $wpdb;
248
- $events_table = EM_EVENTS_TABLE;
249
- $locations_table = EM_LOCATIONS_TABLE;
250
-
251
- $temp_conditions = parent::build_sql_conditions($args);
252
- $conditions = array();
253
- if( !empty($temp_conditions['category']) ){
254
- $conditions['category'] = $temp_conditions['category'];
255
  }
256
- return apply_filters( 'em_categories_build_sql_conditions', $conditions, $args );
257
- }
258
-
259
- /* Overrides EM_Object method to apply a filter to result
260
- * @see wp-content/plugins/categories-manager/classes/EM_Object#build_sql_orderby()
261
- */
262
- function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
263
- return apply_filters( 'em_categories_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_categories_default_order')), $args, $accepted_fields, $default_order );
264
  }
265
 
266
  /*
267
- * Adds custom categories search defaults
 
268
  * @param array $array
269
  * @return array
270
  * @uses EM_Object#get_default_search()
271
  */
272
- function get_default_search( $array = array() ){
273
- return apply_filters('em_categories_get_default_search', parent::get_default_search(array(),$array), $array, array());
274
- }
275
-
276
- /**
277
- * will return the default search parameter to use according to permission settings
278
- * @return string
279
- */
280
- function get_default_search_owner(){
281
- //by default, we only get categories the owner can manage
282
- $defaults = array('owner'=>false);
283
- //by default, we only get categories the owner can manage
284
- if( !current_user_can('edit_categories') ){
285
- $defaults['owner'] = get_current_user_id();
286
- break;
287
  }else{
288
- $defaults['owner'] = false;
289
- break;
290
  }
291
- return $defaults['owner'];
292
  }
293
 
294
  //Iterator Implementation
7
  */
8
  var $categories = array();
9
  /**
10
+ * Event ID of this set of categories
11
+ * @var int
12
  */
13
+ var $event_id;
14
+ /**
15
+ * Post ID of this set of categories
16
+ * @var int
17
+ */
18
+ var $post_id;
19
 
20
  /**
21
  * Creates an EM_Categories instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
22
+ * @param mixed $data
23
  * @return null
24
  */
25
  function EM_Categories( $data = false ){
26
+ global $wpdb;
27
+ self::ms_global_switch();
28
+ if( is_object($data) && get_class($data) == "EM_Event" && !empty($data->post_id) ){ //Creates a blank categories object if needed
29
+ $this->event_id = $data->event_id;
30
+ $this->post_id = $data->post_id;
31
+ if( EM_MS_GLOBAL && !is_main_site($data->blog_id) ){
32
+ $cat_ids = $wpdb->get_col('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->event_id}' AND meta_key='event-category'");
33
+ foreach($cat_ids as $cat_id){
34
+ $this->categories[$cat_id] = new EM_Category($cat_id);
35
+ }
36
+ }else{
37
+ $results = get_the_terms( $data->post_id, EM_TAXONOMY_CATEGORY );
38
+ if( is_array($results) ){
39
+ foreach($results as $result){
40
+ $this->categories[$result->term_id] = new EM_Category($result);
41
+ }
42
+ }
43
  }
44
+ }elseif( is_array($data) && self::array_is_numeric($data) ){
45
  foreach($data as $category_id){
46
+ $this->categories[$category_id] = new EM_Category($category_id);
47
  }
48
  }elseif( is_array($data) ){
49
  foreach( $data as $EM_Category ){
51
  $this->categories[] = $EM_Category;
52
  }
53
  }
 
54
  }
55
+ self::ms_global_switch_back();
56
+ do_action('em_categories', $this);
57
  }
58
+
59
+ function get_post(){
60
+ self::ms_global_switch();
61
+ $this->categories = array();
62
+ if(!empty($_POST['event_categories']) && self::array_is_numeric($_POST['event_categories'])){
63
+ foreach( $_POST['event_categories'] as $term ){
64
+ $this->categories[$term] = new EM_Category($term);
 
 
 
 
 
 
 
65
  }
 
66
  }
67
+ self::ms_global_switch_back();
68
+ do_action('em_categories_get_post', $this);
69
+ }
70
+
71
+ function save(){
72
+ $term_slugs = array();
73
+ foreach($this->categories as $EM_Category){
74
+ /* @var $EM_Category EM_Category */
75
+ if( !empty($EM_Category->slug) ) $term_slugs[] = $EM_Category->slug; //save of category will soft-fail if slug is empty
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
+ if( count($term_slugs) == 0 && get_option('dbem_default_category') > 0 ){
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
  }
97
 
98
+ function save_index(){
 
 
 
 
99
  global $wpdb;
100
+ $wpdb->query('DELETE FROM '.EM_META_TABLE." WHERE object_id='{$this->event_id}' AND meta_key='event-category'");
101
+ foreach($this->categories as $EM_Category){
102
+ $wpdb->insert(EM_META_TABLE, array('meta_value'=>$EM_Category->term_id,'object_id'=>$this->event_id,'meta_key'=>'event-category'));
103
+ }
104
+ }
105
+
106
+ public static function get( $args = array() ) {
107
+ //Quick version, we can accept an array of IDs, which is easy to retrieve
108
+ self::ms_global_switch();
109
+ if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
110
+ $results = get_terms( EM_TAXONOMY_CATEGORY );
111
+ $categories = array();
112
+ foreach($results as $result){
113
+ if( in_array($result->term_id, $args) ){
114
+ $categories[$result->term_id] = new EM_Category($result);
115
+ }
116
  }
117
  }else{
118
+ //We assume it's either an empty array or array of search arguments to merge with defaults
119
+ $term_args = self::get_default_search($args);
120
+ $results = get_terms( EM_TAXONOMY_CATEGORY, $term_args);
121
+
122
+ //If we want results directly in an array, why not have a shortcut here? We don't use this in code, so if you're using it and filter the em_categories_get hook, you may want to do this one too.
123
+ if( !empty($args['array']) ){
124
+ return apply_filters('em_categories_get_array', $results, $args);
125
+ }
126
+
127
+ //Make returned results EM_Category objects
128
+ $results = (is_array($results)) ? $results:array();
129
+ $categories = array();
130
+ foreach ( $results as $category ){
131
+ $categories[$category->term_id] = new EM_Category($category);
132
+ }
133
  }
134
+ self::ms_global_switch_back();
135
+ return apply_filters('em_categories_get', $categories, $args);
136
  }
137
 
138
+ public static function output( $args ){
139
  global $EM_Category;
140
  $EM_Category_old = $EM_Category; //When looping, we can replace EM_Category global with the current event in the loop
141
+ //get page number if passed on by request (still needs pagination enabled to have effect)
142
+ $page_queryvar = !empty($args['page_queryvar']) ? $args['page_queryvar'] : 'pno';
143
+ if( !array_key_exists('page',$args) && !empty($args['pagination']) && !empty($_REQUEST[$page_queryvar]) && is_numeric($_REQUEST[$page_queryvar]) ){
144
+ $page = $args['page'] = $_REQUEST[$page_queryvar];
145
+ }
146
  //Can be either an array for the get search or an array of EM_Category objects
147
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Category' ){
148
  $func_args = func_get_args();
157
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
158
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
159
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
160
+ $args['limit'] = $args['offset'] = $args['page'] = false; //we count overall categories here
 
 
161
  $categories = self::get( $args );
162
+ $args['limit'] = $limit;
163
+ $args['offset'] = $offset;
164
+ $args['page'] = $page;
165
  }
166
  //What format shall we output this to, or use default
167
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_categories_list_item_format' ) : $args['format'] ;
190
  //Pagination (if needed/requested)
191
  if( !empty($args['pagination']) && !empty($limit) && $categories_count >= $limit ){
192
  //Show the pagination links (unless there's less than 10 events, or the custom limit)
193
+ $output .= self::get_pagination_links($args, $categories_count);
 
 
194
  }
195
  } else {
196
  $output = get_option ( 'dbem_no_categories_message' );
200
  return apply_filters('em_categories_output', $output, $categories, $args);
201
  }
202
 
203
+ public static function get_pagination_links($args, $count, $search_action = 'search_cats', $default_args = array()){
204
+ //get default args if we're in a search, supply to parent since we can't depend on late static binding until WP requires PHP 5.3 or later
205
+ if( empty($default_args) && (!empty($args['ajax']) || !empty($_REQUEST['action']) && $_REQUEST['action'] == $search_action) ){
206
+ $default_args = self::get_default_search();
207
+ $default_args['limit'] = get_option('dbem_categories_default_limit');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
+ return parent::get_pagination_links($args, $count, $search_action, $default_args);
210
+ }
211
+
212
+ public static function get_post_search($args = array(), $filter = false, $request = array(), $accepted_args = array()){
213
+ //supply $accepted_args to parent argument since we can't depend on late static binding until WP requires PHP 5.3 or later
214
+ $accepted_args = !empty($accepted_args) ? $accepted_args : array_keys(self::get_default_search());
215
+ return apply_filters('em_tags_get_post_search', parent::get_post_search($args, $filter, $request, $accepted_args));
216
  }
217
 
218
  function has( $search ){
219
  if( is_numeric($search) ){
220
  foreach($this->categories as $EM_Category){
221
+ if($EM_Category->term_id == $search) return apply_filters('em_categories_has', true, $search, $this);
222
  }
223
+ }else{
224
+ foreach($this->categories as $EM_Category){
225
+ if($EM_Category->slug == $search || $EM_Category->name == $search ) return apply_filters('em_categories_has', true, $search, $this);
226
+ }
227
  }
228
  return apply_filters('em_categories_has', false, $search, $this);
229
  }
230
 
231
+ function get_first(){
232
+ foreach($this->categories as $EM_Category){
233
+ return $EM_Category;
234
+ }
235
+ return false;
236
+ }
237
+
238
  function get_ids(){
239
  $ids = array();
240
  foreach($this->categories as $EM_Category){
241
+ if( !empty($EM_Category->term_id) ){
242
+ $ids[] = $EM_Category->term_id;
243
  }
244
  }
245
  return $ids;
250
  * @return EM_Event
251
  */
252
  function get_event(){
253
+ if( is_numeric($this->event_id) ){
254
+ return em_get_event($this->event_id);
255
+ }else{
256
+ return new EM_Event();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  }
 
 
 
 
 
 
 
 
258
  }
259
 
260
  /*
261
+ * Adds custom calendar search defaults
262
+ * @param array $array_or_defaults may be the array to override defaults
263
  * @param array $array
264
  * @return array
265
  * @uses EM_Object#get_default_search()
266
  */
267
+ public static function get_default_search( $array_or_defaults = array(), $array = array() ){
268
+ $defaults = array(
269
+ //added from get_terms, so they don't get filtered out
270
+ 'orderby' => get_option('dbem_categories_default_orderby'), 'order' => get_option('dbem_categories_default_order'),
271
+ 'hide_empty' => false, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(),
272
+ 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '',
273
+ 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '',
274
+ 'pad_counts' => false, 'offset' => '', 'search' => '', 'cache_domain' => 'core'
275
+ );
276
+ //sort out whether defaults were supplied or just the array of search values
277
+ if( empty($array) ){
278
+ $array = $array_or_defaults;
 
 
 
279
  }else{
280
+ $defaults = array_merge($defaults, $array_or_defaults);
 
281
  }
282
+ return apply_filters('em_categories_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
283
  }
284
 
285
  //Iterator Implementation
classes/em-category-taxonomy.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Category_Taxonomy{
3
+ public static function init(){
4
+ if( !is_admin() ){
5
+ add_filter('taxonomy_template', array('EM_Category_Taxonomy','template'), 99);
6
+ add_filter('parse_query', array('EM_Category_Taxonomy','parse_query'));
7
+ }
8
+ }
9
+ /**
10
+ * Overrides archive pages e.g. locations, events, event categories, event tags based on user settings
11
+ * @param string $template
12
+ * @return string
13
+ */
14
+ public static function template($template){
15
+ global $wp_query, $EM_Category, $em_category_id, $post;
16
+ if( is_tax(EM_TAXONOMY_CATEGORY) && !locate_template('taxonomy-'.EM_TAXONOMY_CATEGORY.'.php') && get_option('dbem_cp_categories_formats', true) ){
17
+ $EM_Category = em_get_category($wp_query->queried_object->term_id);
18
+ if( get_option('dbem_categories_page') ){
19
+ //less chance for things to go wrong with themes etc. so just reset the WP_Query to think it's a page rather than taxonomy
20
+ $wp_query = new WP_Query(array('page_id'=> get_option('dbem_categories_page')));
21
+ $wp_query->queried_object = $wp_query->post;
22
+ $wp_query->queried_object_id = $wp_query->post->ID;
23
+ $wp_query->post->post_title = $wp_query->posts[0]->post_title = $wp_query->queried_object->post_title = $EM_Category->output(get_option('dbem_category_page_title_format'));
24
+ if( !function_exists('yoast_breadcrumb') ){ //not needed by WP SEO Breadcrumbs
25
+ $wp_query->post->post_parent = $wp_query->posts[0]->post_parent = $wp_query->queried_object->post_parent = $EM_Category->output(get_option('dbem_categories_page'));
26
+ }
27
+ $post = $wp_query->post;
28
+ }else{
29
+ //we don't have a categories page, so we create a fake page
30
+ $wp_query->posts = array();
31
+ $wp_query->posts[0] = new stdClass();
32
+ $wp_query->posts[0]->post_title = $wp_query->queried_object->post_title = $EM_Category->output(get_option('dbem_category_page_title_format'));
33
+ $post_array = array('ID', 'post_author', 'post_date','post_date_gmt','post_content','post_excerpt','post_status','comment_status','ping_status','post_password','post_name','to_ping','pinged','post_modified','post_modified_gmt','post_content_filtered','post_parent','guid','menu_order','post_type','post_mime_type','comment_count','filter');
34
+ foreach($post_array as $post_array_item){
35
+ $wp_query->posts[0]->$post_array_item = '';
36
+ }
37
+ $wp_query->post = $wp_query->posts[0];
38
+ $wp_query->post_count = 1;
39
+ $wp_query->found_posts = 1;
40
+ $wp_query->max_num_pages = 1;
41
+ //tweak flags for determining page type
42
+ $wp_query->is_tax = 0;
43
+ $wp_query->is_page = 1;
44
+ $wp_query->is_single = 0;
45
+ $wp_query->is_singular = 1;
46
+ $wp_query->is_archive = 0;
47
+ }
48
+ remove_filter('the_content', 'em_content'); //one less filter
49
+ add_filter('the_content', array('EM_Category_Taxonomy','the_content')); //come in slightly early and consider other plugins
50
+ add_filter('wpseo_breadcrumb_links',array('EM_Category_Taxonomy','wpseo_breadcrumb_links')); //for Yoast WP SEO
51
+ $wp_query->em_category_id = $em_category_id = $EM_Category->term_id; //we assign $em_category_id just in case other themes/plugins do something out of the ordinary to WP_Query
52
+ $template = locate_template(array('page.php','index.php'),false); //category becomes a page
53
+ }
54
+ return $template;
55
+ }
56
+
57
+ public static function the_content($content){
58
+ global $wp_query, $EM_Category, $post, $em_category_id;
59
+ $is_categories_page = $post->ID == get_option('dbem_categories_page');
60
+ $category_flag = (!empty($wp_query->em_category_id) || !empty($em_category_id));
61
+ if( ($is_categories_page && $category_flag) || (empty($post->ID) && $category_flag) ){
62
+ $EM_Category = empty($wp_query->em_category_id) ? em_get_category($em_category_id):em_get_category($wp_query->em_category_id);
63
+ ob_start();
64
+ em_locate_template('templates/category-single.php',true);
65
+ return ob_get_clean();
66
+ }
67
+ return $content;
68
+ }
69
+
70
+ public static function parse_query( ){
71
+ global $wp_query, $post;
72
+ if( is_tax(EM_TAXONOMY_CATEGORY) ){
73
+ //Scope is future
74
+ $today = strtotime(date('Y-m-d', current_time('timestamp')));
75
+ if( get_option('dbem_events_current_are_past') ){
76
+ $wp_query->query_vars['meta_query'][] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
77
+ }else{
78
+ $wp_query->query_vars['meta_query'][] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
79
+ }
80
+ if( get_option('dbem_categories_default_archive_orderby') == 'title'){
81
+ $wp_query->query_vars['orderby'] = 'title';
82
+ }else{
83
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
84
+ $wp_query->query_vars['meta_key'] = get_option('dbem_categories_default_archive_orderby','_start_ts');
85
+ }
86
+ $wp_query->query_vars['order'] = get_option('dbem_categories_default_archive_order','ASC');
87
+ }elseif( !empty($wp_query->em_category_id) ){
88
+ $post = $wp_query->post;
89
+ }
90
+ }
91
+
92
+ public static function wpseo_breadcrumb_links( $links ){
93
+ global $wp_query;
94
+ array_pop($links);
95
+ if( get_option('dbem_categories_page') ){
96
+ $links[] = array('id'=> get_option('dbem_categories_page'));
97
+ }
98
+ $links[] = array('text'=> $wp_query->posts[0]->post_title);
99
+ return $links;
100
+ }
101
+ }
102
+ EM_Category_Taxonomy::init();
103
+
104
+ /**
105
+ * Create an array of Categories. Copied from Walker_CategoryDropdown, but makes it possible for the selected argument to be an array.
106
+ *
107
+ * @package WordPress
108
+ * @since 2.1.0
109
+ * @uses Walker
110
+ */
111
+ class EM_Walker_Category extends Walker {
112
+ /**
113
+ * @see Walker::$tree_type
114
+ * @since 2.1.0
115
+ * @var string
116
+ */
117
+ var $tree_type = 'event-category';
118
+
119
+ /**
120
+ * @see Walker::$db_fields
121
+ * @since 2.1.0
122
+ * @todo Decouple this
123
+ * @var array
124
+ */
125
+ var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
126
+
127
+ function __construct(){
128
+ $tree_type = EM_TAXONOMY_CATEGORY;
129
+ }
130
+
131
+ /**
132
+ * @see Walker::start_el()
133
+ */
134
+ function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
135
+ $pad = str_repeat('&nbsp;', $depth * 3);
136
+ $cat_name = $object->name;
137
+ $name = !empty($args['name']) ? $args['name']:'event_categories[]';
138
+ $output .= !empty($args['before']) ? $args['after']:'';
139
+ $output .= $pad."<input type=\"checkbox\" name=\"$name\" class=\"level-$depth\" value=\"".$object->term_id."\"";
140
+ if ( (is_array($args['selected']) && in_array($object->term_id, $args['selected'])) || ($object->term_id == $args['selected']) )
141
+ $output .= ' checked="checked"';
142
+ $output .= ' /> ';
143
+ $output .= $cat_name;
144
+ $output .= !empty($args['after']) ? $args['after']:'<br />';
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Create an array of Categories. Copied from Walker_CategoryDropdown, but makes it possible for the selected argument to be an array.
150
+ *
151
+ * @package WordPress
152
+ * @since 2.1.0
153
+ * @uses Walker
154
+ */
155
+ class EM_Walker_CategoryMultiselect extends EM_Walker_Category {
156
+ /**
157
+ * @see Walker::start_el()
158
+ */
159
+ function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
160
+ $pad = str_repeat('&nbsp;', $depth * 3);
161
+ $cat_name = $object->name;
162
+ $output .= "\t<option class=\"level-$depth\" value=\"".$object->term_id."\"";
163
+ if ( (is_array($args['selected']) && in_array($object->term_id, $args['selected'])) || ($object->term_id == $args['selected']) )
164
+ $output .= ' selected="selected"';
165
+ $output .= '>';
166
+ $output .= $pad.$cat_name;
167
+ $output .= "</option>\n";
168
+ }
169
+ }
classes/em-category.php CHANGED
@@ -1,24 +1,40 @@
1
  <?php
2
- //TODO expand em_category to be like other classes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  class EM_Category extends EM_Object {
4
- //DB Fields
5
  var $id = '';
6
- var $slug = '';
7
- var $owner = '';
8
- var $name = '';
 
 
 
9
  var $description = '';
10
- //Other Vars
11
- var $fields = array(
12
- 'category_id' => array('name'=>'id','type'=>'%d'),
13
- 'category_slug' => array('name'=>'slug','type'=>'%s'),
14
- 'category_owner' => array('name'=>'owner','type'=>'%d'),
15
- 'category_name' => array('name'=>'name','type'=>'%s'),
16
- 'category_description' => array('name'=>'description','type'=>'%s')
17
- );
18
- var $required_fields;
19
- var $feedback_message = "";
20
- var $errors = array();
21
  var $image_url = '';
 
22
 
23
  /**
24
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
@@ -27,120 +43,96 @@ class EM_Category extends EM_Object {
27
  */
28
  function EM_Category( $category_data = false ) {
29
  global $wpdb;
 
30
  //Initialize
31
- $this->required_fields = array("name" => __('The category name', 'dbem'));
32
  $category = array();
33
  if( !empty($category_data) ){
34
  //Load category data
35
- if( is_array($category_data) && isset($category_data['category_name']) ){
36
  $category = $category_data;
37
- }elseif( is_numeric($category_data) ){
38
- //Retreiving from the database
39
- $sql = "SELECT * FROM ". EM_CATEGORIES_TABLE ." WHERE category_id ='{$category_data}'";
40
- $category = $wpdb->get_row($sql, ARRAY_A);
41
- }else{
42
- $sql = "SELECT * FROM ". EM_CATEGORIES_TABLE ." WHERE category_slug ='{$category_data}'";
43
- $category = $wpdb->get_row($sql, ARRAY_A);
44
  }
45
- //Save into the object
46
- $this->to_object($category);
47
- }
48
- $this->get_image_url();
49
- add_action('em_category_save',array(&$this, 'image_upload'), 1, 1);
 
 
 
50
  do_action('em_category',$this, $category_data);
51
  }
52
 
53
- function get_post(){
54
- //We are getting the values via POST or GET
55
- do_action('em_category_get_post_pre', $this);
56
- $category = array();
57
- $category['category_id'] = ( !empty($_POST['category_id']) ) ? $_POST['category_id']:'';
58
- $category['category_name'] = ( !empty($_POST['category_name']) ) ? stripslashes($_POST['category_name']):'';
59
- $category['category_description'] = ( !empty($_POST['content']) ) ? stripslashes($_POST['content']) : ''; //WP TinyMCE field
60
- $category['category_owner'] = ( !empty($_POST['category_owner']) && is_numeric($_POST['category_owner']) ) ? $_POST['category_owner']:get_current_user_id();
61
- $this->to_object( apply_filters('em_category_get_post', $category, $this) );
62
- return apply_filters('em_category_get_post',$this->validate(), $this);
63
  }
64
 
65
- function validate(){
66
- //check required fields
67
- foreach ( $this->required_fields as $field => $description) {
68
- if ( $this->$field == "" ) {
69
- $this->add_error($description.__(" is required.", "dbem"));
70
- }
71
  }
72
- $this->image_validate();
73
- return apply_filters('em_location_validate', ( count($this->errors) == 0 ), $this);
74
  }
75
 
76
- function save(){
77
- global $wpdb;
78
- $result = false;
79
- if( $this->can_manage('edit_categories') ){
80
- do_action('em_category_save_pre', $this);
81
- $table = EM_CATEGORIES_TABLE;
82
- $this->slug = $this->sanitize_title();
83
- $data = $this->to_array();
84
- unset($data['category_id']);
85
- if($this->id != ''){
86
- $where = array( 'category_id' => $this->id );
87
- $result = $wpdb->update($table, $data, $where, $this->get_types($data));
88
- if( $result !== false ){
89
- $this->feedback_message = sprintf(__('%s successfully updated.', 'dbem'), __('Category','dbem'));
90
- }
91
- }else{
92
- $wpdb->insert($table, $data, $this->get_types($data));
93
- $result = $this->id = $wpdb->insert_id;
94
- if( $result !== false ){
95
- $this->feedback_message = sprintf(__('%s successfully added.', 'dbem'), __('Category','dbem'));
96
- }
97
- }
98
- }else{
99
- $this->add_error( sprintf(__('You do not have permission to create/edit %s.','dbem'), __('categories','dbem')) );
100
  }
101
- return apply_filters('em_category_save', ($result !== false), $this);
102
  }
103
 
104
- /**
105
- * Takes the title and gives either a unique slug or returns the currently used slug if this record already has it.
106
- * @param unknown_type $title
107
- */
108
- function sanitize_title($iteration = 1){
109
- global $wpdb;
110
- //Generate the slug. If this is a new event, create the slug automatically, if not, verify it is still unique and if not rewrite
111
- if( empty($this->slug) ){
112
- $this->slug = sanitize_title($this->name);
113
  }
114
- $slug = $this->slug;
115
- $slug_matches = $wpdb->get_results('SELECT category_id FROM '.EM_CATEGORIES_TABLE." WHERE category_slug='{$slug}'", ARRAY_A);
116
- if( count($slug_matches) > 0 ){ //we will check that the slug is unique
117
- if( $slug_matches[0]['category_id'] != $this->id || count($slug_matches) > 1 ){
118
- //we have a conflict, so try another alternative
119
- $this->slug = preg_replace('/\-[0-9]+$/', '', $slug).'-'.($iteration+1);
120
- $this->sanitize_title($iteration+1);
121
- }
 
122
  }
123
- return apply_filters('em_location_sanitize_title', $this->slug, $this);
124
  }
125
-
126
- function delete(){
127
- global $wpdb;
128
- $result = false;
129
- if( $this->can_manage('edit_categories') ){
130
- do_action('em_category_delete_pre', $this);
131
- $table_name = EM_CATEGORIES_TABLE;
132
- $sql = "DELETE FROM $table_name WHERE category_id = '{$this->id}';";
133
- $result = $wpdb->query($sql);
134
  }
135
- return apply_filters('em_category_delete', $result, $this);
136
  }
137
 
 
 
 
 
138
  function has_events(){
139
- global $wpdb;
140
- $events_table = EM_EVENTS_TABLE;
141
- $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE category_id = {$this->id}";
142
- $affected_events = $wpdb->get_row($sql);
143
- return apply_filters('em_category_has_events', (count($affected_events) > 0), $this);
144
  }
145
 
146
  function output_single($target = 'html'){
@@ -157,65 +149,144 @@ class EM_Category extends EM_Object {
157
  }
158
  }
159
  $category_string = $format;
160
- preg_match_all("/#_[A-Za-z]+/", $format, $placeholders);
161
- foreach($placeholders[0] as $result) {
162
- $match = true;
163
  $replace = '';
 
164
  switch( $result ){
165
  case '#_CATEGORYNAME':
166
  $replace = $this->name;
167
  break;
168
  case '#_CATEGORYID':
169
- $replace = $this->id;
170
  break;
 
171
  case '#_CATEGORYDESCRIPTION':
172
  $replace = $this->description;
173
  break;
174
  case '#_CATEGORYIMAGE':
175
  case '#_CATEGORYIMAGEURL':
176
- if( $this->image_url != ''){
177
- $replace = ($result == '#_CATEGORYIMAGEURL') ? $this->image_url : "<img src='".$this->image_url."' alt='".$this->name."'/>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
179
  break;
 
 
 
180
  case '#_CATEGORYLINK':
181
  case '#_CATEGORYURL':
182
- $joiner = (stristr(EM_URI, "?")) ? "&amp;" : "?";
183
- $link = EM_URI.$joiner."category_id=".$this->id;
184
- $replace = ($result == '#_CATEGORYURL') ? $link : '<a href="'.$link.'">'.$this->name.'</a>';
185
  break;
186
- case '#_CATEGORYEVENTSPAST':
187
- case '#_CATEGORYEVENTSNEXT':
188
- case '#_CATEGORYEVENTSALL':
189
- if ($result == '#_CATEGORYEVENTSPAST'){ $scope = 'past'; }
190
- elseif ( $result == '#_CATEGORYEVENTSNEXT' ){ $scope = 'future'; }
191
- else{ $scope = 'all'; }
192
- $events = EM_Events::get( array('category'=>$this->id, 'scope'=>$scope) );
193
- if ( count($events) > 0 ){
194
- foreach($events as $EM_Event){
195
- $replace .= $EM_Event->output(get_option('dbem_location_event_list_item_format'));
196
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  } else {
198
- $replace = get_option('dbem_location_no_events_message');
 
 
 
 
 
 
 
199
  }
200
  break;
201
  default:
202
- $replace = $result;
203
  break;
204
  }
205
- $replace = apply_filters('em_category_output_placeholder', $replace, $this, $result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
206
- $category_string = str_replace($result, $replace , $category_string );
 
 
 
207
  }
208
- $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
209
- $category_string = str_replace('#_CATEGORY', apply_filters($name_filter, $this->name) , $category_string ); //Depreciated
210
  return apply_filters('em_category_output', $category_string, $this, $format, $target);
211
  }
212
 
213
- function can_manage( $capability_owner = 'edit_categories', $capability_admin = false ){
214
  global $em_capabilities_array;
215
  //Figure out if this is multisite and require an extra bit of validation
216
  $multisite_check = true;
217
  $can_manage = current_user_can($capability_owner);
218
- if( is_multisite() && get_site_option('dbem_ms_global_table') && !is_main_site() ){
 
 
219
  //User can't admin this bit, as they're on a sub-blog
220
  $can_manage = false;
221
  if(array_key_exists($capability_owner, $em_capabilities_array) ){
1
  <?php
2
+ /**
3
+ * Get an category in a db friendly way, by checking globals and passed variables to avoid extra class instantiations
4
+ * @param mixed $id
5
+ * @return EM_Category
6
+ */
7
+ function em_get_category($id = false) {
8
+ global $EM_Category;
9
+ //check if it's not already global so we don't instantiate again
10
+ if( is_object($EM_Category) && get_class($EM_Category) == 'EM_Category' ){
11
+ if( $EM_Category->term_id == $id ){
12
+ return $EM_Category;
13
+ }elseif( is_object($id) && $EM_Category->term_id == $id->term_id ){
14
+ return $EM_Category;
15
+ }
16
+ }
17
+ if( is_object($id) && get_class($id) == 'EM_Category' ){
18
+ return $id;
19
+ }else{
20
+ return new EM_Category($id);
21
+ }
22
+ }
23
  class EM_Category extends EM_Object {
24
+ //Taxonomy Fields
25
  var $id = '';
26
+ var $term_id;
27
+ var $name;
28
+ var $slug;
29
+ var $term_group;
30
+ var $term_taxonomy_id;
31
+ var $taxonomy;
32
  var $description = '';
33
+ var $parent = 0;
34
+ var $count;
35
+ //extra attributes imposed by EM_Category
 
 
 
 
 
 
 
 
36
  var $image_url = '';
37
+ var $color;
38
 
39
  /**
40
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
43
  */
44
  function EM_Category( $category_data = false ) {
45
  global $wpdb;
46
+ self::ms_global_switch();
47
  //Initialize
 
48
  $category = array();
49
  if( !empty($category_data) ){
50
  //Load category data
51
+ if( is_object($category_data) && !empty($category_data->taxonomy) && $category_data->taxonomy == EM_TAXONOMY_CATEGORY ){
52
  $category = $category_data;
53
+ }elseif( !is_numeric($category_data) ){
54
+ $category = get_term_by('slug', $category_data, EM_TAXONOMY_CATEGORY);
55
+ if( !$category ){
56
+ $category = get_term_by('name', $category_data, EM_TAXONOMY_CATEGORY);
57
+ }
58
+ }else{
59
+ $category = get_term_by('id', $category_data, EM_TAXONOMY_CATEGORY);
60
  }
61
+ }
62
+ if( is_object($category) || is_array($category) ){
63
+ foreach($category as $key => $value){
64
+ $this->$key = $value;
65
+ }
66
+ }
67
+ $this->id = $this->term_id; //backward compatability
68
+ self::ms_global_switch_back();
69
  do_action('em_category',$this, $category_data);
70
  }
71
 
72
+ function get_color(){
73
+ if( empty($this->color) ){
74
+ global $wpdb;
75
+ $color = $wpdb->get_var('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->term_id}' AND meta_key='category-bgcolor' LIMIT 1");
76
+ $this->color = ($color != '') ? $color:get_option('dbem_category_default_color', '#FFFFFF');
77
+ }
78
+ return $this->color;
 
 
 
79
  }
80
 
81
+ function get_image_url( $size = 'full' ){
82
+ if( empty($this->image_url) ){
83
+ global $wpdb;
84
+ $image_url = $wpdb->get_var('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->term_id}' AND meta_key='category-image' LIMIT 1");
85
+ $this->image_url = ($image_url != '') ? $image_url:'';
 
86
  }
87
+ return $this->image_url;
 
88
  }
89
 
90
+ function get_image_id(){
91
+ if( empty($this->image_id) ){
92
+ global $wpdb;
93
+ $image_id = $wpdb->get_var('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->term_id}' AND meta_key='category-image-id' LIMIT 1");
94
+ $this->image_id = ($image_id != '') ? $image_id:'';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
+ return $this->image_id;
97
  }
98
 
99
+ function get_url(){
100
+ if( empty($this->link) ){
101
+ self::ms_global_switch();
102
+ $this->link = get_term_link($this->slug, EM_TAXONOMY_CATEGORY);
103
+ self::ms_global_switch_back();
104
+ if ( is_wp_error($this->link) ) $this->link = '';
 
 
 
105
  }
106
+ return apply_filters('em_category_get_url', $this->link);
107
+ }
108
+
109
+ function get_ical_url(){
110
+ global $wp_rewrite;
111
+ if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){
112
+ $return = trailingslashit($this->get_url()).'ical/';
113
+ }else{
114
+ $return = em_add_get_params($this->get_url(), array('ical'=>1));
115
  }
116
+ return apply_filters('em_category_get_ical_url', $return);
117
  }
118
+
119
+ function get_rss_url(){
120
+ global $wp_rewrite;
121
+ if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){
122
+ $return = trailingslashit($this->get_url()).'feed/';
123
+ }else{
124
+ $return = em_add_get_params($this->get_url(), array('feed'=>1));
 
 
125
  }
126
+ return apply_filters('em_category_get_rss_url', $return);
127
  }
128
 
129
+ /**
130
+ * Depreciated, don't use.
131
+ * @return mixed
132
+ */
133
  function has_events(){
134
+ global $wpdb;
135
+ return false;
 
 
 
136
  }
137
 
138
  function output_single($target = 'html'){
149
  }
150
  }
151
  $category_string = $format;
152
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([a-zA-Z0-9,]+)})?/", $format, $placeholders);
153
+ $replaces = array();
154
+ foreach($placeholders[1] as $key => $result) {
155
  $replace = '';
156
+ $full_result = $placeholders[0][$key];
157
  switch( $result ){
158
  case '#_CATEGORYNAME':
159
  $replace = $this->name;
160
  break;
161
  case '#_CATEGORYID':
162
+ $replace = $this->term_id;
163
  break;
164
+ case '#_CATEGORYNOTES':
165
  case '#_CATEGORYDESCRIPTION':
166
  $replace = $this->description;
167
  break;
168
  case '#_CATEGORYIMAGE':
169
  case '#_CATEGORYIMAGEURL':
170
+ if( $this->get_image_url() != ''){
171
+ $image_url = esc_url($this->get_image_url());
172
+ if($result == '#_CATEGORYIMAGEURL'){
173
+ $replace = $image_url;
174
+ }else{
175
+ if( empty($placeholders[3][$key]) ){
176
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->name)."'/>";
177
+ }else{
178
+ $image_size = explode(',', $placeholders[3][$key]);
179
+ if( self::array_is_numeric($image_size) && count($image_size) > 1 ){
180
+ if( $this->get_image_id() ){
181
+ //get a thumbnail
182
+ if( get_option('dbem_disable_thumbnails') ){
183
+ $image_attr = '';
184
+ $image_args = array();
185
+ if( empty($image_size[1]) && !empty($image_size[0]) ){
186
+ $image_attr = 'width="'.$image_size[0].'"';
187
+ $image_args['w'] = $image_size[0];
188
+ }elseif( empty($image_size[0]) && !empty($image_size[1]) ){
189
+ $image_attr = 'height="'.$image_size[1].'"';
190
+ $image_args['h'] = $image_size[1];
191
+ }elseif( !empty($image_size[0]) && !empty($image_size[1]) ){
192
+ $image_attr = 'width="'.$image_size[0].'" height="'.$image_size[1].'"';
193
+ $image_args = array('w'=>$image_size[0], 'h'=>$image_size[1]);
194
+ }
195
+ $replace = "<img src='".esc_url(em_add_get_params($image_url, $image_args))."' alt='".esc_attr($this->name)."' $image_attr />";
196
+ }else{
197
+ //since we previously didn't store image ids along with the url to the image (since taxonomies don't allow normal featured images), sometimes we won't be able to do this, which is why we check there's a valid image id first
198
+ self::ms_global_switch();
199
+ $replace = wp_get_attachment_image($this->get_image_id(), $image_size);
200
+ self::ms_global_switch_back();
201
+ }
202
+ }
203
+ }else{
204
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->name)."'/>";
205
+ }
206
+ }
207
+ }
208
  }
209
  break;
210
+ case '#_CATEGORYCOLOR':
211
+ $replace = $this->get_color();
212
+ break;
213
  case '#_CATEGORYLINK':
214
  case '#_CATEGORYURL':
215
+ $link = $this->get_url();
216
+ $replace = ($result == '#_CATEGORYURL') ? $link : '<a href="'.$link.'">'.esc_html($this->name).'</a>';
 
217
  break;
218
+ case '#_CATEGORYICALURL':
219
+ case '#_CATEGORYICALLINK':
220
+ $replace = $this->get_ical_url();
221
+ if( $result == '#_CATEGORYICALLINK' ){
222
+ $replace = '<a href="'.esc_url($replace).'">iCal</a>';
223
+ }
224
+ break;
225
+ case '#_CATEGORYRSSURL':
226
+ case '#_CATEGORYRSSLINK':
227
+ $replace = $this->get_rss_url();
228
+ if( $result == '#_CATEGORYRSSLINK' ){
229
+ $replace = '<a href="'.esc_url($replace).'">RSS</a>';
230
+ }
231
+ break;
232
+ case '#_CATEGORYSLUG':
233
+ $replace = $this->slug;
234
+ break;
235
+ case '#_CATEGORYEVENTSPAST': //depreciated, erroneous documentation, left for compatability
236
+ case '#_CATEGORYEVENTSNEXT': //depreciated, erroneous documentation, left for compatability
237
+ case '#_CATEGORYEVENTSALL': //depreciated, erroneous documentation, left for compatability
238
+ case '#_CATEGORYPASTEVENTS':
239
+ case '#_CATEGORYNEXTEVENTS':
240
+ case '#_CATEGORYALLEVENTS':
241
+ //convert depreciated placeholders for compatability
242
+ $result = ($result == '#_CATEGORYEVENTSPAST') ? '#_CATEGORYPASTEVENTS':$result;
243
+ $result = ($result == '#_CATEGORYEVENTSNEXT') ? '#_CATEGORYNEXTEVENTS':$result;
244
+ $result = ($result == '#_CATEGORYEVENTSALL') ? '#_CATEGORYALLEVENTS':$result;
245
+ //forget it ever happened? :/
246
+ if ($result == '#_CATEGORYPASTEVENTS'){ $scope = 'past'; }
247
+ elseif ( $result == '#_CATEGORYNEXTEVENTS' ){ $scope = 'future'; }
248
+ else{ $scope = 'all'; }
249
+ $events_count = EM_Events::count( array('category'=>$this->term_id, 'scope'=>$scope) );
250
+ if ( $events_count > 0 ){
251
+ $args = array('category'=>$this->term_id, 'scope'=>$scope, 'pagination'=>1, 'ajax'=>0);
252
+ $args['format_header'] = get_option('dbem_category_event_list_item_header_format');
253
+ $args['format_footer'] = get_option('dbem_category_event_list_item_footer_format');
254
+ $args['format'] = get_option('dbem_category_event_list_item_format');
255
+ $args['limit'] = get_option('dbem_category_event_list_limit');
256
+ $args['page'] = (!empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) )? $_REQUEST['pno'] : 1;
257
+ $replace = EM_Events::output($args);
258
  } else {
259
+ $replace = get_option('dbem_category_no_events_message','</ul>');
260
+ }
261
+ break;
262
+ case '#_CATEGORYNEXTEVENT':
263
+ $events = EM_Events::get( array('category'=>$this->term_id, 'scope'=>'future', 'limit'=>1, 'orderby'=>'event_start_date,event_start_time') );
264
+ $replace = get_option('dbem_category_no_event_message');
265
+ foreach($events as $EM_Event){
266
+ $replace = $EM_Event->output(get_option('dbem_category_event_single_format'));
267
  }
268
  break;
269
  default:
270
+ $replace = $full_result;
271
  break;
272
  }
273
+ $replaces[$full_result] = apply_filters('em_category_output_placeholder', $replace, $this, $full_result, $target);
274
+ }
275
+ krsort($replaces);
276
+ foreach($replaces as $full_result => $replacement){
277
+ $category_string = str_replace($full_result, $replacement , $category_string );
278
  }
 
 
279
  return apply_filters('em_category_output', $category_string, $this, $format, $target);
280
  }
281
 
282
+ function can_manage( $capability_owner = 'edit_categories', $capability_admin = false, $user_to_check = false ){
283
  global $em_capabilities_array;
284
  //Figure out if this is multisite and require an extra bit of validation
285
  $multisite_check = true;
286
  $can_manage = current_user_can($capability_owner);
287
+ //if multisite and supoer admin, just return true
288
+ if( is_multisite() && is_super_admin() ){ return true; }
289
+ if( EM_MS_GLOBAL && !is_main_site() ){
290
  //User can't admin this bit, as they're on a sub-blog
291
  $can_manage = false;
292
  if(array_key_exists($capability_owner, $em_capabilities_array) ){
classes/em-event-post-admin.php ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Events Edit Page
4
+ */
5
+ class EM_Event_Post_Admin{
6
+ public static function init(){
7
+ global $pagenow;
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'));
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
+ }
15
+ //Save/Edit actions
16
+ add_filter('wp_insert_post_data',array('EM_Event_Post_Admin','wp_insert_post_data'),100,2); //validate post meta before saving is done
17
+ add_action('save_post',array('EM_Event_Post_Admin','save_post'),1,1); //set to 1 so metadata gets saved ASAP
18
+ add_action('before_delete_post',array('EM_Event_Post_Admin','before_delete_post'),10,1);
19
+ add_action('trashed_post',array('EM_Event_Post_Admin','trashed_post'),10,1);
20
+ add_action('untrash_post',array('EM_Event_Post_Admin','untrash_post'),10,1);
21
+ add_action('untrashed_post',array('EM_Event_Post_Admin','untrashed_post'),10,1);
22
+ //Notices
23
+ add_action('post_updated_messages',array('EM_Event_Post_Admin','admin_notices_filter'),1,1);
24
+ }
25
+
26
+ public static function admin_head(){
27
+ global $post, $EM_Event;
28
+ if( !empty($post) && $post->post_type == EM_POST_TYPE_EVENT ){
29
+ $EM_Event = em_get_event($post->ID, 'post_id');
30
+ }
31
+ }
32
+
33
+ public static function admin_notices(){
34
+ //When editing
35
+ global $post, $EM_Event, $pagenow;
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.', 'dbem' )."</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.', 'dbem' );
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.', 'dbem')."</strong></p>";
43
+ $warning .= "<p>". sprintf(__('If you update this event data and save, it could get overwritten if you edit the recurring event template. To make it an independent, <a href="%s">detach it</a>.', 'dbem' ), $EM_Event->get_detach_url())."</p>";
44
+ $warning .= "<p>".sprintf(__('To manage the whole set, <a href="%s">edit the recurring event template</a>.', 'dbem'),admin_url('post.php?action=edit&amp;post='.$EM_Event->get_event_recurrence()->post_id))."</p>";
45
+ ?><div class="updated"><?php echo $warning; ?></div><?php
46
+ }
47
+ if( !empty($EM_Event->group_id) && function_exists('groups_get_group') ){
48
+ $group = groups_get_group(array('group_id'=>$EM_Event->group_id));
49
+ $warning = sprintf(__('WARNING: This is a event belonging to the group "%s". Other group admins can also modify this event.', 'dbem'), $group->name);
50
+ ?><div class="updated"><p><?php echo $warning; ?></p></div><?php
51
+ }
52
+ }
53
+ }
54
+
55
+ public static function admin_notices_filter($messages){
56
+ //When editing
57
+ global $post, $EM_Notices;
58
+ if( $post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring' ){
59
+ if ( $EM_Notices->count_errors() > 0 ) {
60
+ unset($_GET['message']);
61
+ }
62
+ }
63
+ return $messages;
64
+ }
65
+
66
+ public static function wp_insert_post_data( $data, $postarr ){
67
+ global $wpdb, $EM_Event, $EM_Location, $EM_Notices, $EM_SAVING_EVENT;
68
+ if( !empty($EM_SAVING_EVENT) ) return $data; //never proceed with this if using EM_Event::save();
69
+ $post_type = $data['post_type'];
70
+ $post_ID = !empty($postarr['ID']) ? $postarr['ID'] : false;
71
+ $is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
72
+ $saving_status = !in_array($data['post_status'], array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
73
+ $untrashing = $post_ID && defined('UNTRASHING_'.$post_ID);
74
+ if( !$untrashing && $is_post_type && $saving_status ){
75
+ if( !empty($_REQUEST['_emnonce']) && wp_verify_nonce($_REQUEST['_emnonce'], 'edit_event') ){
76
+ //this is only run if we know form data was submitted, hence the nonce
77
+ $EM_Event = em_get_event();
78
+ $EM_Event->post_type = $post_type;
79
+ //Handle Errors by making post draft
80
+ $get_meta = $EM_Event->get_post_meta();
81
+ $validate_meta = $EM_Event->validate_meta();
82
+ if( !$get_meta || !$validate_meta ) $data['post_status'] = 'draft';
83
+ }
84
+ }
85
+ return $data;
86
+ }
87
+
88
+ public static function save_post($post_id){
89
+ global $wpdb, $EM_Event, $EM_Location, $EM_Notices, $EM_SAVING_EVENT, $EM_EVENT_SAVE_POST;
90
+ if( !empty($EM_SAVING_EVENT) ) return; //never proceed with this if using EM_Event::save();
91
+ if ( isset($_GET['preview_id']) && isset($_GET['preview_nonce']) && wp_verify_nonce( $_GET['preview_nonce'], 'post_preview_' . $post_id ) ) return; //don't proceed with saving when previewing, may cause issues
92
+ $post_type = get_post_type($post_id);
93
+ $is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
94
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
95
+ $EM_EVENT_SAVE_POST = true; //first filter for save_post in EM for events
96
+ if(!defined('UNTRASHING_'.$post_id) && $is_post_type && $saving_status ){
97
+ $EM_Event = em_get_event($post_id, 'post_id'); //grab event, via post info
98
+ $EM_Event->post_type = $post_type;
99
+ if( !empty($_REQUEST['_emnonce']) && wp_verify_nonce($_REQUEST['_emnonce'], 'edit_event') ){
100
+ //this is only run if we know form data was submitted, hence the nonce
101
+ do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
102
+ //Handle Errors by making post draft
103
+ $get_meta = $EM_Event->get_post_meta();
104
+ $validate_meta = $EM_Event->validate_meta();
105
+ $save_meta = $EM_Event->save_meta();
106
+ $EM_Event->get_categories()->save(); //save categories in case of default category
107
+ if( !$get_meta || !$validate_meta || !$save_meta ){
108
+ //failed somewhere, set to draft, don't publish
109
+ $EM_Event->set_status(null, true);
110
+ if( $EM_Event->is_recurring() ){
111
+ $EM_Notices->add_error( '<strong>'.__('Your event details are incorrect and recurrences cannot be created, please correct these errors first:','dbem').'</strong>', true); //Always seems to redirect, so we make it static
112
+ }else{
113
+ $EM_Notices->add_error( '<strong>'.sprintf(__('Your %s details are incorrect and cannot be published, please correct these errors first:','dbem'),__('event','dbem')).'</strong>', true); //Always seems to redirect, so we make it static
114
+ }
115
+ $EM_Notices->add_error($EM_Event->get_errors(), true); //Always seems to redirect, so we make it static
116
+ apply_filters('em_event_save', false, $EM_Event);
117
+ }else{
118
+ //if this is just published, we need to email the user about the publication, or send to pending mode again for review
119
+ if( (!$EM_Event->is_recurring() && !current_user_can('publish_events')) || ($EM_Event->is_recurring() && !current_user_can('publish_recurring_events')) ){
120
+ if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
121
+ }
122
+ apply_filters('em_event_save', true, $EM_Event);
123
+ }
124
+ }else{
125
+ //we're updating only the quick-edit style information, which is only post info saved into the index
126
+ if( $EM_Event->validate() ){
127
+ do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
128
+ //first things first, we must make sure we have an index, if not, reset it to a new one:
129
+ $event_truly_exists = $wpdb->get_var('SELECT event_id FROM '.EM_EVENTS_TABLE." WHERE event_id={$EM_Event->event_id}") == $EM_Event->event_id;
130
+ if(empty($EM_Event->event_id) || !$event_truly_exists){ $EM_Event->save_meta(); }
131
+ //we can save the status now
132
+ $EM_Event->get_previous_status(); //before we save anything
133
+ $event_status = $EM_Event->get_status(true);
134
+ //if this is just published, we need to email the user about the publication, or send to pending mode again for review
135
+ if( (!$EM_Event->is_recurring() && !current_user_can('publish_events')) || ($EM_Event->is_recurring() && !current_user_can('publish_recurring_events')) ){
136
+ if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
137
+ }
138
+ //now update the db
139
+ $where_array = array($EM_Event->event_name, $EM_Event->event_owner, $EM_Event->event_slug, $EM_Event->event_private, $EM_Event->event_id);
140
+ $sql = $wpdb->prepare("UPDATE ".EM_EVENTS_TABLE." SET event_name=%s, event_owner=%d, event_slug=%s, event_status={$event_status}, event_private=%d WHERE event_id=%d", $where_array);
141
+ $wpdb->query($sql);
142
+ if( $EM_Event->is_recurring() && $EM_Event->is_published()){
143
+ //recurrences are (re)saved only if event is published
144
+ $EM_Event->save_events();
145
+ }
146
+ apply_filters('em_event_save', true, $EM_Event);
147
+ }else{
148
+ do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
149
+ //Event doesn't validate, so set status to null
150
+ $EM_Event->set_status(null, true);
151
+ apply_filters('em_event_save', false, $EM_Event);
152
+ }
153
+ }
154
+ self::maybe_publish_location($EM_Event);
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Publish the location if the event has just been approved and the location is pending. We assume an editor published the event and approves the location too.
160
+ * @param EM_Event $EM_Event
161
+ */
162
+ public static function maybe_publish_location($EM_Event){
163
+ //do a dirty update for location too if it's not published
164
+ if( $EM_Event->is_published() && !empty($EM_Event->location_id) ){
165
+ $EM_Location = $EM_Event->get_location();
166
+ if( $EM_Location->location_status !== 1 ){
167
+ //let's also publish the location
168
+ $EM_Location->set_status(1, true);
169
+ }
170
+ }
171
+ }
172
+
173
+ public static function before_delete_post($post_id){
174
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
175
+ $EM_Event = em_get_event($post_id,'post_id');
176
+ do_action('em_event_delete_pre ',$EM_Event);
177
+ $EM_Event->delete_meta();
178
+ }
179
+ }
180
+
181
+ public static function trashed_post($post_id){
182
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
183
+ global $EM_Notices;
184
+ $EM_Event = em_get_event($post_id,'post_id');
185
+ $EM_Event->set_status(-1);
186
+ $EM_Notices->remove_all(); //no validation/notices needed
187
+ }
188
+ }
189
+
190
+ public static function untrash_post($post_id){
191
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
192
+ //set a constant so we know this event doesn't need 'saving'
193
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
194
+ }
195
+ }
196
+
197
+ public static function untrashed_post($post_id){
198
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
199
+ global $EM_Notices, $EM_Event;
200
+ $EM_Event = new EM_Event($post_id, 'post_id'); //get a refreshed $EM_Event because otherwise statuses don't get updated by WP
201
+ $EM_Event->set_status( $EM_Event->get_status() );
202
+ $EM_Notices->remove_all(); //no validation/notices needed
203
+ }
204
+ }
205
+
206
+ public static function meta_boxes(){
207
+ global $EM_Event;
208
+ if( !empty($EM_Event->event_owner_anonymous) ){
209
+ add_meta_box('em-event-anonymous', __('Anonymous Submitter Info','dbem'), array('EM_Event_Post_Admin','meta_box_anonymous'),EM_POST_TYPE_EVENT, 'side','high');
210
+ }
211
+ add_meta_box('em-event-when', __('When','dbem'), array('EM_Event_Post_Admin','meta_box_date'),EM_POST_TYPE_EVENT, 'side','high');
212
+ if(get_option('dbem_locations_enabled', true)){
213
+ add_meta_box('em-event-where', __('Where','dbem'), array('EM_Event_Post_Admin','meta_box_location'),EM_POST_TYPE_EVENT, 'normal','high');
214
+ }
215
+ if( defined('WP_DEBUG') && WP_DEBUG ){
216
+ add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),EM_POST_TYPE_EVENT, 'normal','high');
217
+ }
218
+ if(get_option('dbem_rsvp_enabled', true)){
219
+ add_meta_box('em-event-bookings', __('Bookings/Registration','dbem'), array('EM_Event_Post_Admin','meta_box_bookings'),EM_POST_TYPE_EVENT, 'normal','high');
220
+ if( !empty($EM_Event->event_id) && $EM_Event->event_rsvp ){
221
+ add_meta_box('em-event-bookings-stats', __('Bookings Stats','dbem'), array('EM_Event_Post_Admin','meta_box_bookings_stats'),EM_POST_TYPE_EVENT, 'side','core');
222
+ }
223
+ }
224
+ if( get_option('dbem_attributes_enabled', true) ){
225
+ add_meta_box('em-event-attributes', __('Attributes','dbem'), array('EM_Event_Post_Admin','meta_box_attributes'),EM_POST_TYPE_EVENT, 'normal','default');
226
+ }
227
+ if( EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
228
+ add_meta_box('em-event-categories', __('Site Categories','dbem'), array('EM_Event_Post_Admin','meta_box_ms_categories'),EM_POST_TYPE_EVENT, 'side','low');
229
+ }
230
+ }
231
+
232
+ public static function meta_box_metadump(){
233
+ global $post,$EM_Event;
234
+ echo "<pre>"; print_r($EM_Event); echo "</pre>";
235
+ }
236
+
237
+ public static function meta_box_anonymous(){
238
+ global $EM_Event;
239
+ ?>
240
+ <div class='updated'><p><?php _e('This event was submitted by a guest. You will find their details in the <em>Anonymous Submitter Info</em> box','dbem')?></p></div>
241
+ <p><strong><?php _e('Name','dbem'); ?> :</strong> <?php echo $EM_Event->event_owner_name; ?></p>
242
+ <p><strong><?php _e('Name','dbem'); ?> :</strong> <?php echo $EM_Event->event_owner_email; ?></p>
243
+ <?php
244
+ }
245
+
246
+ public static function meta_box_date(){
247
+ //create meta box check of date nonce
248
+ ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_event'); ?>" /><?php
249
+ em_locate_template('forms/event/when.php', true);
250
+ }
251
+
252
+ public static function meta_box_bookings_stats(){
253
+ em_locate_template('forms/event/booking-stats.php',true);
254
+ }
255
+
256
+ public static function meta_box_bookings(){
257
+ em_locate_template('forms/event/bookings.php', true);
258
+ add_action('admin_footer',array('EM_Event_Post_Admin','meta_box_bookings_overlay'));
259
+ }
260
+
261
+ public static function meta_box_bookings_overlay(){
262
+ em_locate_template('forms/tickets-form.php', true); //put here as it can't be in the add event form
263
+ }
264
+
265
+ public static function meta_box_attributes(){
266
+ em_locate_template('forms/event/attributes.php',true);
267
+ }
268
+
269
+ public static function meta_box_location(){
270
+ em_locate_template('forms/event/location.php',true);
271
+ }
272
+
273
+ public static function meta_box_ms_categories(){
274
+ global $EM_Event;
275
+ EM_Object::ms_global_switch();
276
+ $categories = EM_Categories::get(array('hide_empty'=>false));
277
+ ?>
278
+ <?php if( count($categories) > 0 ): ?>
279
+ <p class="ms-global-categories">
280
+ <?php $selected = $EM_Event->get_categories()->get_ids(); ?>
281
+ <?php $walker = new EM_Walker_Category(); ?>
282
+ <?php $args_em = array( 'hide_empty' => 0, 'name' => 'event_categories[]', 'hierarchical' => true, 'id' => EM_TAXONOMY_CATEGORY, 'taxonomy' => EM_TAXONOMY_CATEGORY, 'selected' => $selected, 'walker'=> $walker); ?>
283
+ <?php echo walk_category_dropdown_tree($categories, 0, $args_em); ?>
284
+ </p>
285
+ <?php else: ?>
286
+ <p><?php sprintf(__('No categories available, <a href="%s">create one here first</a>','dbem'), get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-categories'); ?></p>
287
+ <?php endif; ?>
288
+ <!-- END Categories -->
289
+ <?php
290
+ EM_Object::ms_global_switch_back();
291
+ }
292
+ }
293
+ add_action('admin_init',array('EM_Event_Post_Admin','init'));
294
+
295
+ /*
296
+ * Recurring Events
297
+ */
298
+ class EM_Event_Recurring_Post_Admin{
299
+ public static function init(){
300
+ global $pagenow;
301
+ if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
302
+ add_action('admin_head', array('EM_Event_Recurring_Post_Admin','admin_head'));
303
+ //Meta Boxes
304
+ add_action('add_meta_boxes', array('EM_Event_Recurring_Post_Admin','meta_boxes'));
305
+ //Notices
306
+ add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices')); //shared with posts
307
+ }
308
+ //Save/Edit actions
309
+ add_action('save_post',array('EM_Event_Recurring_Post_Admin','save_post'),10000,1); //late priority for checking non-EM meta data added later
310
+ add_action('before_delete_post',array('EM_Event_Recurring_Post_Admin','before_delete_post'),10,1);
311
+ add_action('trashed_post',array('EM_Event_Recurring_Post_Admin','trashed_post'),10,1);
312
+ add_action('untrash_post',array('EM_Event_Recurring_Post_Admin','untrash_post'),10,1);
313
+ add_action('untrashed_post',array('EM_Event_Recurring_Post_Admin','untrashed_post'),10,1);
314
+ //Notices
315
+ add_action('post_updated_messages',array('EM_Event_Post_Admin','admin_notices_filter'),1,1); //shared with posts
316
+ }
317
+
318
+ public static function admin_head(){
319
+ global $post, $EM_Event;
320
+ if( !empty($post) && $post->post_type == 'event-recurring' ){
321
+ $EM_Event = em_get_event($post->ID, 'post_id');
322
+ //quick hacks to make event admin table make more sense for events
323
+ ?>
324
+ <script type="text/javascript">
325
+ jQuery(document).ready( function($){
326
+ if(!EM.recurrences_menu){
327
+ $('#menu-posts-'+EM.event_post_type+', #menu-posts-'+EM.event_post_type+' > a').addClass('wp-has-current-submenu');
328
+ }
329
+ });
330
+ </script>
331
+ <?php
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Beacuse in wp admin recurrences get saved early on during save_post, meta added by other plugins to the recurring event template don't get copied over to recurrences
337
+ * This re-saves meta late in save_post to correct this issue, in the future when recurrences refer to one post, this shouldn't be an issue
338
+ * @param int $post_id
339
+ */
340
+ public static function save_post($post_id){
341
+ global $wpdb, $EM_Notices, $EM_SAVING_EVENT, $EM_EVENT_SAVE_POST;
342
+ if( !empty($EM_SAVING_EVENT) ) return; //never proceed with this if using EM_Event::save(); which only gets executed outside wp admin
343
+ $post_type = get_post_type($post_id);
344
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
345
+ if(!defined('UNTRASHING_'.$post_id) && $post_type == 'event-recurring' && $saving_status && !empty($EM_EVENT_SAVE_POST) ){
346
+ $EM_Event = em_get_event($post_id, 'post_id');
347
+ $EM_Event->post_type = $post_type;
348
+ //get the list post IDs for recurrences this recurrence
349
+ if( !$EM_Event->save_events() && $EM_Event->is_published() ){
350
+ $EM_Event->set_status(null, true);
351
+ $EM_Notices->add_error(__ ( 'Something went wrong with the recurrence update...', 'dbem' ). __ ( 'There was a problem saving the recurring events.', 'dbem' ));
352
+ }
353
+ }
354
+ $EM_EVENT_SAVE_POST = false; //last filter of save_post in EM for events
355
+ }
356
+
357
+ public static function before_delete_post($post_id){
358
+ if(get_post_type($post_id) == 'event-recurring'){
359
+ $EM_Event = em_get_event($post_id,'post_id');
360
+ do_action('em_event_delete_pre ',$EM_Event);
361
+ //now delete recurrences
362
+ //only delete other events if this isn't a draft-never-published event
363
+ if( !empty($EM_Event->event_id) ){
364
+ $events_array = EM_Events::get( array('recurrence'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>'everything' ) );
365
+ foreach($events_array as $event){
366
+ /* @var $event EM_Event */
367
+ if($EM_Event->event_id == $event->recurrence_id && !empty($event->recurrence_id) ){ //double check the event is a recurrence of this event
368
+ wp_delete_post($event->post_id, true);
369
+ }
370
+ }
371
+ }
372
+ $EM_Event->post_type = EM_POST_TYPE_EVENT; //trick it into thinking it's one event.
373
+ $EM_Event->delete_meta();
374
+ }
375
+ }
376
+
377
+ public static function trashed_post($post_id){
378
+ if(get_post_type($post_id) == 'event-recurring'){
379
+ global $EM_Notices, $wpdb;
380
+ $EM_Event = em_get_event($post_id,'post_id');
381
+ $EM_Event->set_status(null);
382
+ //only trash other events if this isn't a draft-never-published event
383
+ if( !empty($EM_Event->event_id) ){
384
+ //now trash recurrences
385
+ $events_array = EM_Events::get( array('recurrence_id'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>'everything' ) );
386
+ foreach($events_array as $event){
387
+ /* @var $event EM_Event */
388
+ if($EM_Event->event_id == $event->recurrence_id ){ //double check the event is a recurrence of this event
389
+ wp_trash_post($event->post_id);
390
+ }
391
+ }
392
+ }
393
+ $EM_Notices->remove_all(); //no validation/notices needed
394
+ }
395
+ }
396
+
397
+ public static function untrash_post($post_id){
398
+ if(get_post_type($post_id) == 'event-recurring'){
399
+ global $wpdb;
400
+ //set a constant so we know this event doesn't need 'saving'
401
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
402
+ $EM_Event = em_get_event($post_id,'post_id');
403
+ //only untrash other events if this isn't a draft-never-published event, because if so it never had other events to untrash
404
+ if( !empty($EM_Event->event_id) ){
405
+ $events_array = EM_Events::get( array('recurrence_id'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>'everything' ) );
406
+ foreach($events_array as $event){
407
+ /* @var $event EM_Event */
408
+ if($EM_Event->event_id == $event->recurrence_id){
409
+ wp_untrash_post($event->post_id);
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ public static function untrashed_post($post_id){
417
+ if(get_post_type($post_id) == 'event-recurring'){
418
+ global $EM_Notices,$EM_Event;
419
+ $EM_Event->set_status(1);
420
+ $EM_Notices->remove_all(); //no validation/notices needed
421
+ }
422
+ }
423
+
424
+ public static function meta_boxes(){
425
+ add_meta_box('em-event-recurring', __('Recurrences','dbem'), array('EM_Event_Recurring_Post_Admin','meta_box_recurrence'),'event-recurring', 'normal','high');
426
+ //add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),'event-recurring', 'normal','high');
427
+ add_meta_box('em-event-where', __('Where','dbem'), array('EM_Event_Post_Admin','meta_box_location'),'event-recurring', 'normal','high');
428
+ if(get_option('dbem_rsvp_enabled')){
429
+ add_meta_box('em-event-bookings', __('Bookings/Registration','dbem'), array('EM_Event_Post_Admin','meta_box_bookings'),'event-recurring', 'normal','high');
430
+ }
431
+ if( get_option('dbem_attributes_enabled') ){
432
+ add_meta_box('em-event-attributes', __('Attributes','dbem'), array('EM_Event_Post_Admin','meta_box_attributes'),'event-recurring', 'normal','default');
433
+ }
434
+ if( EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
435
+ add_meta_box('em-event-categories', __('Site Categories','dbem'), array('EM_Event_Post_Admin','meta_box_ms_categories'),'event-recurring', 'side','low');
436
+ }
437
+ }
438
+
439
+ public static function meta_box_recurrence(){
440
+ em_locate_template('forms/event/recurring-when.php', true);
441
+ }
442
+ }
443
+ add_action('admin_init',array('EM_Event_Recurring_Post_Admin','init'));
classes/em-event-post.php ADDED
@@ -0,0 +1,354 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controls how events are queried and displayed via the WordPress Custom Post APIs
4
+ * @author marcus
5
+ *
6
+ */
7
+ class EM_Event_Post {
8
+
9
+ public static function init(){
10
+ global $wp_query;
11
+ //Front Side Modifiers
12
+ if( !is_admin() ){
13
+ //override single page with formats?
14
+ add_filter('the_content', array('EM_Event_Post','the_content'));
15
+ add_filter('the_excerpt_rss', array('EM_Event_Post','the_excerpt_rss'));
16
+ if( get_option('dbem_cp_events_excerpt_formats') ){
17
+ add_filter('the_excerpt', array('EM_Event_Post','the_excerpt'));
18
+ }
19
+ //display as page template?
20
+ if( get_option('dbem_cp_events_template') ){
21
+ add_filter('single_template',array('EM_Event_Post','single_template'));
22
+ }
23
+ //add classes to body and post_class()
24
+ if( get_option('dbem_cp_events_post_class') != '' ){
25
+ add_filter('post_class', array('EM_Event_Post','post_class'), 10, 3);
26
+ }
27
+ if( get_option('dbem_cp_events_body_class') != '' ){
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'));
38
+ add_action('publish_future_post',array('EM_Event_Post','publish_future_post'),10,1);
39
+ }
40
+
41
+ public static function publish_future_post($post_id){
42
+ global $wpdb, $EM_Event, $EM_Location, $EM_Notices;
43
+ $post_type = get_post_type($post_id);
44
+ $is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
45
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
46
+ if(!defined('UNTRASHING_'.$post_id) && $is_post_type && $saving_status ){
47
+ $EM_Event = em_get_event($post_id, 'post_id');
48
+ $EM_Event->set_status(1);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Overrides the default post format of an event and can display an event as a page, which uses the page.php template.
54
+ * @param string $template
55
+ * @return string
56
+ */
57
+ public static function single_template($template){
58
+ global $post;
59
+ if( !locate_template('single-'.EM_POST_TYPE_EVENT.'.php') && $post->post_type == EM_POST_TYPE_EVENT ){
60
+ //do we have a default template to choose for events?
61
+ if( get_option('dbem_cp_events_template') == 'page' ){
62
+ $post_templates = array('page.php','index.php');
63
+ }else{
64
+ $post_templates = array(get_option('dbem_cp_events_template'));
65
+ }
66
+ if( !empty($post_templates) ){
67
+ $post_template = locate_template($post_templates,false);
68
+ if( !empty($post_template) ) $template = $post_template;
69
+ }
70
+ }
71
+ return $template;
72
+ }
73
+
74
+ public static function post_class( $classes, $class, $post_id ){
75
+ $post = get_post($post_id);
76
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
77
+ foreach( explode(' ', get_option('dbem_cp_events_post_class')) as $class ){
78
+ $classes[] = esc_attr($class);
79
+ }
80
+ }
81
+ return $classes;
82
+ }
83
+
84
+ public static function body_class( $classes ){
85
+ if( em_is_event_page() ){
86
+ foreach( explode(' ', get_option('dbem_cp_events_body_class')) as $class ){
87
+ $classes[] = esc_attr($class);
88
+ }
89
+ }
90
+ return $classes;
91
+ }
92
+
93
+ /**
94
+ * Overrides the_excerpt if this is an event post type
95
+ */
96
+ public static function the_excerpt($content){
97
+ global $post;
98
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
99
+ $EM_Event = em_get_event($post);
100
+ $output = !empty($EM_Event->post_excerpt) ? get_option('dbem_event_excerpt_format'):get_option('dbem_event_excerpt_alt_format');
101
+ $content = $EM_Event->output($output);
102
+ }
103
+ return $content;
104
+ }
105
+
106
+ public static function the_excerpt_rss( $content ){
107
+ global $post;
108
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
109
+ if( get_option('dbem_cp_events_formats') ){
110
+ $EM_Event = em_get_event($post);
111
+ $content = $EM_Event->output( get_option ( 'dbem_rss_description_format' ), "rss");
112
+ $content = ent2ncr(convert_chars($content)); //Some RSS filtering
113
+ }
114
+ }
115
+ return $content;
116
+ }
117
+
118
+ public static function the_content( $content ){
119
+ global $post, $EM_Event;
120
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
121
+ if( is_archive() || is_search() ){
122
+ if(get_option('dbem_cp_events_archive_formats')){
123
+ $EM_Event = em_get_event($post);
124
+ $content = $EM_Event->output(get_option('dbem_event_list_item_format'));
125
+ }
126
+ }else{
127
+ if( get_option('dbem_cp_events_formats') && !post_password_required() ){
128
+ $EM_Event = em_get_event($post);
129
+ ob_start();
130
+ em_locate_template('templates/event-single.php',true);
131
+ $content = ob_get_clean();
132
+ }elseif( !post_password_required() ){
133
+ $EM_Event = em_get_event($post);
134
+ if( $EM_Event->event_rsvp ){
135
+ $content .= $EM_Event->output('<h2>Bookings</h2>#_BOOKINGFORM');
136
+ }
137
+ }
138
+ }
139
+ }
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 ){
148
+ $the_date = date_i18n(get_option('date_format'), $EM_Event->start);
149
+ }else{
150
+ $the_date = date_i18n($d, $EM_Event->start);
151
+ }
152
+ }
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 ){
161
+ $the_time = date_i18n(get_option('time_format'), $EM_Event->start);
162
+ }else{
163
+ $the_time = date_i18n($f, $EM_Event->start);
164
+ }
165
+ }
166
+ return $the_time;
167
+ }
168
+
169
+ public static function the_category( $thelist, $separator = '', $parents='' ){
170
+ global $post, $wp_rewrite;
171
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
172
+ $EM_Event = em_get_event($post);
173
+ $categories = $EM_Event->get_categories();
174
+ if( empty($categories) ) return '';
175
+
176
+ /* Copied from get_the_category_list function, with a few minor edits to make urls work, and removing parent stuff (for now) */
177
+ $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
178
+
179
+ $thelist = '';
180
+ if ( '' == $separator ) {
181
+ $thelist .= '<ul class="post-categories">';
182
+ foreach ( $categories as $category ) {
183
+ $thelist .= "\n\t<li>";
184
+ switch ( strtolower( $parents ) ) {
185
+ case 'multiple':
186
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
187
+ break;
188
+ case 'single':
189
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>';
190
+ $thelist .= $category->name.'</a></li>';
191
+ break;
192
+ case '':
193
+ default:
194
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
195
+ }
196
+ }
197
+ $thelist .= '</ul>';
198
+ } else {
199
+ $i = 0;
200
+ foreach ( $categories as $category ) {
201
+ if ( 0 < $i )
202
+ $thelist .= $separator;
203
+ switch ( strtolower( $parents ) ) {
204
+ case 'multiple':
205
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>';
206
+ break;
207
+ case 'single':
208
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>';
209
+ $thelist .= "$category->name</a>";
210
+ break;
211
+ case '':
212
+ default:
213
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s", 'dbem' ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>';
214
+ }
215
+ ++$i;
216
+ }
217
+ }
218
+ /* End copying */
219
+ }
220
+ return $thelist;
221
+ }
222
+
223
+ public static function parse_query(){
224
+ global $wp_query;
225
+ //Search Query Filtering
226
+ if( is_admin() ){
227
+ if( !empty($wp_query->query_vars[EM_TAXONOMY_CATEGORY]) && is_numeric($wp_query->query_vars[EM_TAXONOMY_CATEGORY]) ){
228
+ //sorts out filtering admin-side as it searches by id
229
+ $term = get_term_by('id', $wp_query->query_vars[EM_TAXONOMY_CATEGORY], EM_TAXONOMY_CATEGORY);
230
+ $wp_query->query_vars[EM_TAXONOMY_CATEGORY] = ( $term !== false && !is_wp_error($term) )? $term->slug:0;
231
+ }
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']) ){
242
+ if( is_archive() ){
243
+ $scope = $wp_query->query_vars['scope'] = get_option('dbem_events_archive_scope');
244
+ }else{
245
+ $scope = $wp_query->query_vars['scope'] = 'all'; //otherwise we'll get 404s for past events
246
+ }
247
+ }else{
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);
255
+ $tomorrow = $today + 60*60*24-1;
256
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
257
+ $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' );
258
+ }else{
259
+ $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
260
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
261
+ }
262
+ }elseif ($scope == "future"){
263
+ $today = strtotime(date('Y-m-d', $time));
264
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
265
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
266
+ }else{
267
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
268
+ }
269
+ }elseif ($scope == "past"){
270
+ $today = strtotime(date('Y-m-d', $time));
271
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
272
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' );
273
+ }else{
274
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' );
275
+ }
276
+ }elseif ($scope == "today"){
277
+ $today = strtotime(date('Y-m-d', $time));
278
+ $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
279
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
280
+ //date must be only today
281
+ $query[] = array( 'key' => '_start_ts', 'value' => array($today, $tomorrow), 'compare' => 'BETWEEN');
282
+ }else{
283
+ $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<' );
284
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
285
+ }
286
+ }elseif ($scope == "tomorrow"){
287
+ $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
288
+ $after_tomorrow = $tomorrow + 60*60*24;
289
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
290
+ //date must be only tomorrow
291
+ $query[] = array( 'key' => '_start_ts', 'value' => array($tomorrow, $after_tomorrow), 'compare' => 'BETWEEN');
292
+ }else{
293
+ $query[] = array( 'key' => '_start_ts', 'value' => $after_tomorrow, 'compare' => '<' );
294
+ $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' );
295
+ }
296
+ }elseif ($scope == "month"){
297
+ $start_month = strtotime(date('Y-m-d',$time));
298
+ $end_month = strtotime(date('Y-m-t',$time)) + 86399;
299
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
300
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
301
+ }else{
302
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
303
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
304
+ }
305
+ }elseif ($scope == "next-month"){
306
+ $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day
307
+ $start_month = strtotime(date('Y-m-1',$start_month_timestamp));
308
+ $end_month = strtotime(date('Y-m-t',$start_month_timestamp)) + 86399;
309
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
310
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
311
+ }else{
312
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
313
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
314
+ }
315
+ }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
316
+ $months_to_add = $matches[1];
317
+ $start_month = strtotime(date('Y-m-d',$time));
318
+ $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time))) + 86399;
319
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
320
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
321
+ }else{
322
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
323
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
324
+ }
325
+ }
326
+ if( !empty($query) && is_array($query) ){
327
+ $wp_query->query_vars['meta_query'] = $query;
328
+ }
329
+ if( is_admin() ){
330
+ //admin areas don't need special ordering, so make it simple
331
+ $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby']:'meta_value_num';
332
+ $wp_query->query_vars['meta_key'] = '_start_ts';
333
+ $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
334
+ }else{
335
+ if( get_option('dbem_events_default_archive_orderby') == 'title'){
336
+ $wp_query->query_vars['orderby'] = 'title';
337
+ $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
338
+ }else{
339
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
340
+ $wp_query->query_vars['meta_key'] = '_start_ts';
341
+ }
342
+ $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_order','ASC');
343
+ }
344
+ }elseif( !empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT ){
345
+ $wp_query->query_vars['scope'] = 'all';
346
+ if( $wp_query->query_vars['post_status'] == 'pending' ){
347
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
348
+ $wp_query->query_vars['order'] = 'ASC';
349
+ $wp_query->query_vars['meta_key'] = '_start_ts';
350
+ }
351
+ }
352
+ }
353
+ }
354
+ EM_Event_Post::init();
classes/em-event-posts-admin.php ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Event_Posts_Admin{
3
+ public static function init(){
4
+ global $pagenow;
5
+ if( $pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == EM_POST_TYPE_EVENT ){ //only needed for events list
6
+ if( !empty($_REQUEST['category_id']) && is_numeric($_REQUEST['category_id']) ){
7
+ $term = get_term_by('id', $_REQUEST['category_id'], EM_TAXONOMY_CATEGORY);
8
+ if( !empty($term->slug) ){
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' );
15
+ if( !$hidden ){
16
+ $hidden = array('event-id');
17
+ update_user_option(get_current_user_id(), "manage{$screen}columnshidden", $hidden, true);
18
+ }
19
+ //deal with actions
20
+ $row_action_type = is_post_type_hierarchical( EM_POST_TYPE_EVENT ) ? 'page_row_actions' : 'post_row_actions';
21
+ add_filter($row_action_type, array('EM_Event_Posts_Admin','row_actions'),10,2);
22
+ add_action('admin_head', array('EM_Event_Posts_Admin','admin_head'));
23
+ //collumns
24
+ add_filter('manage_edit-'.EM_POST_TYPE_EVENT.'_columns' , array('EM_Event_Posts_Admin','columns_add'));
25
+ add_filter('manage_'.EM_POST_TYPE_EVENT.'_posts_custom_column' , array('EM_Event_Posts_Admin','columns_output'),10,2 );
26
+ }
27
+ //clean up the views in the admin selection area - WIP
28
+ //add_filter('views_edit-'.EM_POST_TYPE_EVENT, array('EM_Event_Posts_Admin','restrict_views'),10,2);
29
+ //add_filter('views_edit-event-recurring', array('EM_Event_Posts_Admin','restrict_views'),10,2);
30
+ //add filters to event post list tables
31
+ add_action('restrict_manage_posts', array('EM_Event_Posts_Admin','restrict_manage_posts'));
32
+ }
33
+
34
+ public static function admin_head(){
35
+ //quick hacks to make event admin table make more sense for events
36
+ ?>
37
+ <script type="text/javascript">
38
+ jQuery(document).ready( function($){
39
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
40
+ $('.em-detach-link').click(function( event ){
41
+ if( !confirm(EM.event_detach_warning) ){
42
+ event.preventDefault();
43
+ return false;
44
+ }
45
+ });
46
+ $('.em-delete-recurrence-link').click(function( event ){
47
+ if( !confirm(EM.delete_recurrence_warning) ){
48
+ event.preventDefault();
49
+ return false;
50
+ }
51
+ });
52
+ });
53
+ </script>
54
+ <style>
55
+ table.fixed{ table-layout:auto !important; }
56
+ .tablenav select[name="m"] { display:none; }
57
+ </style>
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
64
+ */
65
+ public static function parse_query(){
66
+ global $wp_query;
67
+ //Search Query Filtering
68
+ if( !empty($wp_query->query_vars[EM_TAXONOMY_CATEGORY]) && is_numeric($wp_query->query_vars[EM_TAXONOMY_CATEGORY]) ){
69
+ //sorts out filtering admin-side as it searches by id
70
+ $term = get_term_by('id', $wp_query->query_vars[EM_TAXONOMY_CATEGORY], EM_TAXONOMY_CATEGORY);
71
+ $wp_query->query_vars[EM_TAXONOMY_CATEGORY] = ( $term !== false && !is_wp_error($term) )? $term->slug:0;
72
+ }
73
+ 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'))) ) {
74
+ //Set up Scope for EM_Event_Post
75
+ $scope = $wp_query->query_vars['scope'] = (!empty($_REQUEST['scope'])) ? $_REQUEST['scope']:'future';
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Adds Future view to make things simpler, and also changes counts if user doesn't have edit_others_events permission
81
+ * @param array $views
82
+ * @return array
83
+ */
84
+ public static function restrict_views( $views ){
85
+ global $wp_query;
86
+ //TODO alter views of locations, events and recurrences, specifically find a good way to alter the wp_count_posts method to force user owned posts only
87
+ $post_type = get_current_screen()->post_type;
88
+ if( in_array($post_type, array(EM_POST_TYPE_EVENT, 'event-recurring')) ){
89
+ //get counts for future events
90
+ $num_posts = wp_count_posts( $post_type, 'readable' );
91
+ //prepare to alter cache if neccessary
92
+ if( !isset($num_posts->em_future) ){
93
+ $cache_key = $post_type;
94
+ $user = wp_get_current_user();
95
+ if ( is_user_logged_in() && !current_user_can('read_private_events') ) {
96
+ $cache_key .= '_readable_' . $user->ID; //as seen on wp_count_posts
97
+ }
98
+ $args = array('scope'=>'future', 'status'=>'all');
99
+ if( $post_type == 'event-recurring' ) $args['recurring'] = 1;
100
+ $num_posts->em_future = EM_Events::count($args);
101
+ wp_cache_set($cache_key, $num_posts, 'counts');
102
+ }
103
+ $class = '';
104
+ //highlight the 'Future' status if necessary
105
+ if( empty($_REQUEST['post_status']) && !empty($wp_query->query_vars['scope']) && $wp_query->query_vars['scope'] == 'future'){
106
+ $class = ' class="current"';
107
+ foreach($views as $key => $view){
108
+ $views[$key] = str_replace(' class="current"','', $view);
109
+ }
110
+ }
111
+ //change the 'All' status to have scope=all
112
+ $views['all'] = str_replace('edit.php?', 'edit.php?scope=all&', $views['all'] );
113
+ //merge new custom status into views
114
+ $old_views = $views;
115
+ $views = array('em_future' => "<a href='edit.php?post_type=$post_type'$class>" . sprintf( _nx( 'Future <span class="count">(%s)</span>', 'Future <span class="count">(%s)</span>', $num_posts->em_future, 'events', 'dbem' ), number_format_i18n( $num_posts->em_future ) ) . '</a>');
116
+ $views = array_merge($views, $old_views);
117
+ }
118
+
119
+ return $views;
120
+ }
121
+
122
+ public static function restrict_manage_posts(){
123
+ global $wp_query;
124
+ if( $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT || $wp_query->query_vars['post_type'] == 'event-recurring' ){
125
+ ?>
126
+ <select name="scope">
127
+ <?php
128
+ $scope = (!empty($wp_query->query_vars['scope'])) ? $wp_query->query_vars['scope']:'future';
129
+ foreach ( em_get_scopes() as $key => $value ) {
130
+ $selected = "";
131
+ if ($key == $scope)
132
+ $selected = "selected='selected'";
133
+ echo "<option value='$key' $selected>$value</option> ";
134
+ }
135
+ ?>
136
+ </select>
137
+ <?php
138
+ if( get_option('dbem_categories_enabled') ){
139
+ //Categories
140
+ $selected = !empty($_GET['event-categories']) ? $_GET['event-categories'] : 0;
141
+ wp_dropdown_categories(array( 'hide_empty' => 1, 'name' => EM_TAXONOMY_CATEGORY,
142
+ 'hierarchical' => true, 'orderby'=>'name', 'id' => EM_TAXONOMY_CATEGORY,
143
+ 'taxonomy' => EM_TAXONOMY_CATEGORY, 'selected' => $selected,
144
+ 'show_option_all' => __('View all categories')));
145
+ }
146
+ if( !empty($_REQUEST['author']) ){
147
+ ?>
148
+ <input type="hidden" name="author" value="<?php echo esc_attr($_REQUEST['author']); ?>" />
149
+ <?php
150
+ }
151
+ }
152
+ }
153
+
154
+ public static function views($views){
155
+ if( !current_user_can('edit_others_events') ){
156
+ //alter the views to reflect correct numbering
157
+
158
+ }
159
+ return $views;
160
+ }
161
+
162
+ public static function columns_add($columns) {
163
+ if( array_key_exists('cb', $columns) ){
164
+ $cb = $columns['cb'];
165
+ unset($columns['cb']);
166
+ $id_array = array('cb'=>$cb, 'event-id' => sprintf(__('%s ID','dbem'),__('Event','dbem')));
167
+ }else{
168
+ $id_array = array('event-id' => sprintf(__('%s ID','dbem'),__('Event','dbem')));
169
+ }
170
+ unset($columns['comments']);
171
+ unset($columns['date']);
172
+ unset($columns['author']);
173
+ $columns = array_merge($id_array, $columns, array(
174
+ 'location' => __('Location','dbem'),
175
+ 'date-time' => __('Date and Time','dbem'),
176
+ 'author' => __('Owner','dbem'),
177
+ 'extra' => ''
178
+ ));
179
+ if( !get_option('dbem_locations_enabled') ){
180
+ unset($columns['location']);
181
+ }
182
+ return $columns;
183
+ }
184
+
185
+ public static function columns_output( $column ) {
186
+ global $post, $EM_Event;
187
+ $EM_Event = em_get_event($post, 'post_id');
188
+ /* @var $post EM_Event */
189
+ switch ( $column ) {
190
+ case 'event-id':
191
+ echo $EM_Event->event_id;
192
+ break;
193
+ case 'location':
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','dbem');
200
+ }
201
+ break;
202
+ case 'date-time':
203
+ //get meta value to see if post has location, otherwise
204
+ $localised_start_date = date_i18n(get_option('date_format'), $EM_Event->start);
205
+ $localised_end_date = date_i18n(get_option('date_format'), $EM_Event->end);
206
+ echo $localised_start_date;
207
+ echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'';
208
+ echo "<br />";
209
+ if(!$EM_Event->event_all_day){
210
+ echo date_i18n(get_option('time_format'), $EM_Event->start) . " - " . date_i18n(get_option('time_format'), $EM_Event->end);
211
+ }else{
212
+ echo get_option('dbem_event_all_day_message');
213
+ }
214
+ break;
215
+ case 'extra':
216
+ if( get_option('dbem_rsvp_enabled') == 1 && !empty($EM_Event->event_rsvp) && $EM_Event->can_manage('manage_bookings','manage_others_bookings')){
217
+ ?>
218
+ <a href="<?php echo $EM_Event->get_bookings_url(); ?>"><?php echo __("Bookings",'dbem'); ?></a> &ndash;
219
+ <?php _e("Booked",'dbem'); ?>: <?php echo $EM_Event->get_bookings()->get_booked_spaces()."/".$EM_Event->get_spaces(); ?>
220
+ <?php if( get_option('dbem_bookings_approval') == 1 ): ?>
221
+ | <?php _e("Pending",'dbem') ?>: <?php echo $EM_Event->get_bookings()->get_pending_spaces(); ?>
222
+ <?php endif;
223
+ echo ($EM_Event->is_recurrence()) ? '<br />':'';
224
+ }
225
+ if ( $EM_Event->is_recurrence() && $EM_Event->can_manage('edit_recurring_events','edit_others_recurring_events') ) {
226
+ $recurrence_delete_confirm = __('WARNING! You will delete ALL recurrences of this event, including booking history associated with any event in this recurrence. To keep booking information, go to the relevant single event and save it to detach it from this recurrence series.','dbem');
227
+ ?>
228
+ <strong>
229
+ <?php echo $EM_Event->get_recurrence_description(); ?> <br />
230
+ </strong>
231
+ <div class="row-actions">
232
+ <a href="<?php echo admin_url(); ?>post.php?action=edit&amp;post=<?php echo $EM_Event->get_event_recurrence()->post_id ?>"><?php _e ( 'Edit Recurring Events', 'dbem' ); ?></a> | <span class="trash"><a class="em-delete-recurrence-link" href="<?php echo get_delete_post_link($EM_Event->get_event_recurrence()->post_id); ?>"><?php _e('Delete','dbem'); ?></a></span> | <a class="em-detach-link" href="<?php echo $EM_Event->get_detach_url(); ?>"><?php _e('Detach', 'dbem'); ?></a>
233
+ </div>
234
+ <?php
235
+ }
236
+
237
+ break;
238
+ }
239
+ }
240
+
241
+ public static function row_actions($actions, $post){
242
+ if($post->post_type == EM_POST_TYPE_EVENT){
243
+ global $post, $EM_Event;
244
+ $EM_Event = em_get_event($post, 'post_id');
245
+ $actions['duplicate'] = '<a href="'.admin_url().'edit.php?action=event_duplicate&amp;event_id='.$EM_Event->event_id.'&amp;_wpnonce='.wp_create_nonce('event_duplicate_'.$EM_Event->event_id).'" title="'.sprintf(__('Duplicate %s','dbem'), __('Event','dbem')).'">'.__('Duplicate','dbem').'</a>';
246
+ }
247
+ return $actions;
248
+ }
249
+ }
250
+ add_action('admin_init', array('EM_Event_Posts_Admin','init'));
251
+
252
+ /*
253
+ * Recurring Events
254
+ */
255
+ class EM_Event_Recurring_Posts_Admin{
256
+ public static function init(){
257
+ global $pagenow;
258
+ if( $pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == 'event-recurring' ){
259
+ //hide some cols by default:
260
+ $screen = 'edit-'.EM_POST_TYPE_EVENT;
261
+ $hidden = get_user_option( 'manage' . $screen . 'columnshidden' );
262
+ if( !$hidden ){
263
+ $hidden = array('event-id');
264
+ update_user_option(get_current_user_id(), "manage{$screen}columnshidden", $hidden, true);
265
+ }
266
+ //notices
267
+ add_action('admin_notices',array('EM_Event_Recurring_Posts_Admin','admin_notices'));
268
+ add_action('admin_head', array('EM_Event_Recurring_Posts_Admin','admin_head'));
269
+ //collumns
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>.', 'dbem' ), 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(){
282
+ //quick hacks to make event admin table make more sense for events
283
+ ?>
284
+ <script type="text/javascript">
285
+ jQuery(document).ready( function($){
286
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
287
+ if(!EM.recurrences_menu){
288
+ $('#menu-posts-'+EM.event_post_type+', #menu-posts-'+EM.event_post_type+' > a').addClass('wp-has-current-submenu');
289
+ }
290
+ });
291
+ </script>
292
+ <style>
293
+ table.fixed{ table-layout:auto !important; }
294
+ .tablenav select[name="m"] { display:none; }
295
+ </style>
296
+ <?php
297
+ }
298
+
299
+ public static function columns_add($columns) {
300
+ if( array_key_exists('cb', $columns) ){
301
+ $cb = $columns['cb'];
302
+ unset($columns['cb']);
303
+ $id_array = array('cb'=>$cb, 'event-id' => sprintf(__('%s ID','dbem'),__('Event','dbem')));
304
+ }else{
305
+ $id_array = array('event-id' => sprintf(__('%s ID','dbem'),__('Event','dbem')));
306
+ }
307
+ unset($columns['comments']);
308
+ unset($columns['date']);
309
+ unset($columns['author']);
310
+ return array_merge($id_array, $columns, array(
311
+ 'location' => __('Location'),
312
+ 'date-time' => __('Date and Time'),
313
+ 'author' => __('Owner','dbem'),
314
+ ));
315
+ }
316
+
317
+
318
+ public static function columns_output( $column ) {
319
+ global $post, $EM_Event;
320
+ if( $post->post_type == 'event-recurring' ){
321
+ $post = $EM_Event = em_get_event($post);
322
+ /* @var $post EM_Event */
323
+ switch ( $column ) {
324
+ case 'event-id':
325
+ echo $EM_Event->event_id;
326
+ break;
327
+ case 'location':
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','dbem');
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'));
classes/em-event.php CHANGED
@@ -1,4 +1,30 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Event Object. This holds all the info pertaining to an event, including location and recurrence info.
4
  * An event object can be one of three "types" a recurring event, recurrence of a recurring event, or a single event.
@@ -11,61 +37,88 @@
11
  //TODO Integrate recurrences into events table
12
  //FIXME If you create a super long recurrence timespan, there could be thousands of events... need an upper limit here.
13
  class EM_Event extends EM_Object{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
- * Assoc array where keys are names of database fields and values are array corresponding object property name, regex, data types, etc.
16
- * for use when importing/exporting event data between database and object
17
  * @var array
18
  */
19
  var $fields = array(
20
  'event_id' => array( 'name'=>'id', 'type'=>'%d' ),
21
- 'event_slug' => array( 'name'=>'slug', 'type'=>'%s' ),
22
- 'event_owner' => array( 'name'=>'owner', 'type'=>'%d' ),
23
- 'event_name' => array( 'name'=>'name', 'type'=>'%s' ),
24
- 'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s' ),
25
- 'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s' ),
26
- 'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s' ),
27
- 'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s' ),
28
- 'event_notes' => array( 'name'=>'notes', 'type'=>'%s' ),
29
- 'event_rsvp' => array( 'name'=>'rsvp', 'type'=>'%d' ),
30
- //'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d' ),
31
- 'location_id' => array( 'name'=>'location_id', 'type'=>'%d' ),
32
- 'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d' ),
33
- 'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s' ),
34
- 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d' ),
35
- 'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d' ), //every x day(s)/week(s)/month(s)
36
- 'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s' ), //daily,weekly,monthly?
37
- 'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s' ), //if weekly or monthly, what days of the week?
38
- 'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d' ), //if monthly which week (-1 is last)
39
- 'event_status' => array( 'name'=>'status', 'type'=>'%d' ), //if monthly which week (-1 is last)
40
- 'event_date_modified' => array( 'name'=>'date_modified', 'type'=>'%s' ),
41
- 'group_id' => array( 'name'=>'group_id', 'type'=>'%d' )
 
 
 
 
 
 
 
 
 
 
42
  );
43
- /* Field Names - see above for matching DB field names and other field meta data */
44
- var $id;
45
- var $slug;
46
- var $owner;
47
- var $name;
48
- var $start_time;
49
- var $end_time;
50
- var $start_date;
51
- var $end_date;
52
- var $notes;
53
- var $rsvp;
54
- //var $spaces;
55
- var $location_id;
56
- var $recurrence_id;
57
- var $category_id;
58
- var $attributes = array();
59
- var $recurrence;
60
- var $interval;
61
- var $freq;
62
- var $byday;
63
- var $byweekno;
64
- var $status;
65
- var $date_created;
66
- var $date_modified;
67
- var $blog_id;
68
- var $group_id;
69
 
70
  var $image_url = '';
71
  /**
@@ -78,6 +131,11 @@ class EM_Event extends EM_Object{
78
  * @var int
79
  */
80
  var $end;
 
 
 
 
 
81
  /**
82
  * Created on timestamp, taken from DB, converted to TS
83
  * @var int
@@ -118,7 +176,7 @@ class EM_Event extends EM_Object{
118
  */
119
  var $feedback_message;
120
  /**
121
- * Any warnings about an event (e.g. bad data, recurring/recurrence, etc.)
122
  * @var string
123
  */
124
  var $warnings;
@@ -128,450 +186,877 @@ class EM_Event extends EM_Object{
128
  */
129
  var $required_fields = array('event_name', 'event_start_date');
130
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  /**
133
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
134
  * @param mixed $event_data
 
135
  * @return null
136
  */
137
- function EM_Event($event_data = false) {
138
- global $wpdb, $EM_Recurrences;
139
- //TODO Change the way we deal with time, maybe revert to timestamps for manipulation, and worry about output in html and db writes?
140
- if( $event_data !== false ){
141
- $event = array();
142
- if( is_array($event_data) ){
143
- //Accepts a raw array that'll just be imported directly into the object with no DB lookups (same for event and recurrence)
144
- $event = $event_data;
145
- if($event['location_name']){
146
- $this->location = new EM_Location( $event );
147
- }
148
- }elseif( !empty($event_data) ) {
149
- if( is_numeric($event_data) && $event_data > 0 ){
150
- $cond = "event_id = $event_data";
 
 
 
151
  }else{
152
- $cond = "event_slug = '".$wpdb->escape($event_data)."'";
153
  }
154
- //Retreiving from the database
155
- $events_table = EM_EVENTS_TABLE;
156
- $locations_table = EM_LOCATIONS_TABLE;
157
- $categories_table = EM_CATEGORIES_TABLE;
158
- $sql = "
159
- SELECT * FROM $events_table
160
- LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
161
- WHERE $cond
162
- "; //We get event and location data here to avoid extra queries
163
- $event = $wpdb->get_row ( $sql, ARRAY_A );
164
- //Sort Location
165
- $this->location = new EM_Location ( $event );
166
- }
167
- //Sort out attributes
168
- if( !empty($event['event_attributes']) ){
169
- if( is_serialized($event['event_attributes']) ){
170
- $event['event_attributes'] = @unserialize($event['event_attributes']);
171
  }
172
- $event['event_attributes'] = (!is_array($event['event_attributes'])) ? array() : $event['event_attributes'] ;
173
  }
174
- $event['recurrence_byday'] = ( empty($event['recurrence_byday']) || $event['recurrence_byday'] == 7 ) ? 0:$event['recurrence_byday']; //Backward compatibility (since 3.0.3), using 0 makes more sense due to date() function
175
- $this->to_object($event, true);
176
- $this->blog_id = $event['blog_id'];
177
-
178
- //Start/End times should be available as timestamp
179
- $this->start = strtotime($this->start_date." ".$this->start_time);
180
- $this->end = strtotime($this->end_date." ".$this->end_time);
181
- $this->modified = ( !empty($event['event_date_modified']) ) ? strtotime($event['event_date_modified']):time();
182
- $this->created = ( !empty($event['event_date_created']) ) ? strtotime($event['event_date_created']):time();
183
-
184
- //Add Owner as Contact Person
185
- if($this->owner && $this->owner > 0){
186
- $this->contact = get_userdata($this->owner);
187
- }
188
- if( !is_object($this->contact) ){
189
- $this->owner = get_option('dbem_default_contact_person');
190
- $this->contact = get_userdata($this->owner);
191
- }
192
- if( is_object($this->contact) ){
193
- $this->contact->phone = get_metadata('user', $this->contact->ID, 'dbem_phone', true);
194
- }
195
- //Now, if this is a recurrence, get the recurring for caching to the $EM_Recurrences
196
- if( $this->is_recurrence() && is_array($EM_Recurrences) && !array_key_exists($this->recurrence_id, $EM_Recurrences) ){
197
- $EM_Recurrences[$this->recurrence_id] = new EM_Event($this->recurrence_id);
198
- }
199
- }else{
200
- $this->location = new EM_Location(); //blank location
201
  }
202
- $this->get_location();
 
203
  //Do it here so things appear in the po file.
204
  $this->status_array = array(
205
  0 => __('Pending','dbem'),
206
  1 => __('Approved','dbem')
207
  );
208
-
209
- //Set up some warning meta
210
- if ( $this->is_recurring() ) {
211
- $this->warnings['recurring'] = __( 'WARNING: This is a recurring event.', 'dbem' )."<br />". __( '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.', 'dbem' );
212
- } elseif ( $this->is_recurrence() ) {
213
- $this->warnings['recurrence'] = __('WARNING: This is a recurrence in a set of recurring events.', 'dbem')."<br />". __('If you update this event data and save, it will become an independent event, and will not be deleted or modified automatically if you reschedule the original recurring event details.', 'dbem' );
214
- }elseif( !empty($this->group_id) && function_exists('groups_get_group') ){
215
- $group = groups_get_group(array('group_id'=>$this->group_id));
216
- $this->warnings['group'] = sprintf(__('WARNING: This is a event belonging to the group "%s". Other group admins can also modify this event.', 'dbem'), $group->name);
217
- }
218
- $this->get_image_url();
219
- add_action('em_event_save',array(&$this, 'image_upload'), 1, 1);
220
- do_action('em_event', $this, $event_data);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
 
223
  /**
224
- * Retrieve event, location and recurring information via POST
225
  * @return boolean
226
  */
227
- function get_post(){
228
- //Build Event Array
229
- do_action('em_event_get_post_pre', $this);
230
- $this->name = ( !empty($_POST['event_name']) ) ? stripslashes($_POST['event_name']) : '' ;
231
- $this->slug = ( !empty($_POST['event_slug']) ) ? $_POST['event_slug'] : '' ;
232
- $this->start_date = ( !empty($_POST['event_start_date']) ) ? $_POST['event_start_date'] : '';
233
- $this->end_date = ( !empty($_POST['event_end_date']) ) ? $_POST['event_end_date'] : $this->start_date;
234
- $this->rsvp = ( !empty($_POST['event_rsvp']) ) ? 1:0;
235
- //$this->spaces = ( !empty($_POST['event_spaces']) && is_numeric($_POST['event_spaces']) ) ? $_POST['event_spaces']:0;
236
- $this->notes = ( !empty($_POST['content']) ) ? stripslashes($_POST['content']) : ''; //WP TinyMCE field
237
- //Sort out time
238
- //TODO make time handling less painful
239
- $match = array();
240
- if( !empty($_POST['event_start_time']) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d)(AM|PM)?$/', $_POST['event_start_time'], $match ) ){
241
- if( $match[3] == 'PM' && $match[1] != 12 ){
242
- $match[1] = 12+$match[1];
243
- }elseif( $match[3] == 'AM' && $match[1] == 12 ){
244
- $match[1] = '00';
245
- }
246
- $this->start_time = $match[1].":".$match[2].":00";
247
- }else{
248
- $this->start_time = "00:00:00";
249
- }
250
- if( !empty($_POST['event_end_time']) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d)(AM|PM)?$/', $_POST['event_end_time'], $match ) ){
251
- if( $match[3] == 'PM' && $match[1] != 12 ){
252
- $match[1] = 12+$match[1];
253
- }elseif( $match[3] == 'AM' && $match[1] == 12 ){
254
- $match[1] = '00';
255
- }
256
- $this->end_time = $match[1].":".$match[2].":00";
 
 
 
 
 
 
 
 
 
257
  }else{
258
- $this->end_time = $this->start_time;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  }
260
  //Start/End times should be available as timestamp
261
- $this->start = strtotime($this->start_date." ".$this->start_time);
262
- $this->end = strtotime($this->end_date." ".$this->end_time);
263
-
264
- //owner
265
- if( !empty($_REQUEST['event_owner']) && is_numeric($_REQUEST['event_owner']) ){
266
- $this->owner = current_user_can('edit_others_events') ? $_REQUEST['event_owner']:get_current_user_id();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  }
268
-
269
- //categories
270
- if( !empty($_POST['event_categories']) && is_array($_POST['event_categories']) ){
271
- $this->categories = new EM_Categories($_POST['event_categories']);
272
- }
273
- //Attributes
274
- $event_attributes = array();
275
- $post = $_POST;
276
- $event_available_attributes = em_get_attributes();
277
- if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
278
- foreach($_POST['em_attributes'] as $att_key => $att_value ){
279
- if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->attributes) ) && trim($att_value) != '' ){
280
- $att_vals = count($event_available_attributes['values'][$att_key]);
281
- if( $att_vals == 0 || ($att_vals > 0 && in_array($event_available_attributes['values'][$att_key])) ){
282
- $event_attributes[$att_key] = $att_value;
 
 
 
283
  }
284
  }
285
  }
286
  }
287
- $this->attributes = $event_attributes;
 
 
 
 
 
288
  //Recurrence data
289
- $this->recurrence_id = ( !empty($_POST['recurrence_id']) && is_numeric($_POST['recurrence_id']) ) ? $_POST['recurrence_id'] : 0 ;
290
- if( !empty($_POST['repeated_event']) ){
291
- $this->recurrence = 1;
292
- $this->freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly')) ) ? $_POST['recurrence_freq']:'daily';
293
- if( !empty($_POST['recurrence_bydays']) && $this->freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){
294
- $this->byday = implode ( ",", $_POST['recurrence_bydays'] );
295
- }elseif( !empty($_POST['recurrence_byday']) && $this->freq == 'monthly' ){
296
- $this->byday = $_POST['recurrence_byday'];
297
  }
298
- $this->interval = ( !empty($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1;
299
- $this->byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? $_POST['recurrence_byweekno']:'';
 
300
  }
301
-
302
- //Add location information, or just link to previous location, this is a requirement...
303
- if( !empty($_POST['location_id']) && is_numeric($_POST['location_id'])) {
304
- $this->location_id = $_POST['location_id'];
305
- $this->location = new EM_Location($_POST['location_id']);
306
- } else {
307
- $this->location = new EM_Location();
308
- $this->location->get_post();
309
- }
310
- if( !$this->get_bookings()->get_tickets()->get_post() ){
311
- $EM_Tickets = $this->get_bookings()->get_tickets();
312
- array_merge($this->errors, $this->get_bookings()->get_tickets()->errors);
313
- }
314
- return apply_filters('em_event_get_post', $this->validate(), $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  }
316
 
317
  /**
318
  * Will save the current instance into the database, along with location information if a new one was created and return true if successful, false if not.
319
- * Will automatically detect what type of event it is (recurrent, recurrence or normal) and whether it's a new or existing event.
320
  * @return boolean
321
  */
322
  function save(){
323
- //FIXME Event doesn't save title when inserting first time
324
- global $wpdb, $current_user;
325
- if( !$this->can_manage('edit_events', 'edit_others_events')){
 
326
  return apply_filters('em_event_save', false, $this);
327
  }
 
328
  do_action('em_event_save_pre', $this);
329
- get_currentuserinfo();
330
- $events_table = EM_EVENTS_TABLE;
331
- $request = $_REQUEST;
332
- //First let's save the location, no location no event!
333
- if ( !$this->get_location()->id && !$this->location->save() ){ //shouldn't try to save if location exists
334
- $this->errors[] = __ ( 'There was a problem saving the location so event was not saved.', 'dbem' );
335
- return apply_filters('em_event_save', false, $this);
336
- }
337
- $this->location_id = $this->location->id;
338
- //owner person can be anyone the admin wants, but the creator if not.
339
- if( current_user_can('edit_others_events') ){
340
- $this->owner = ( $this->owner > 0 ) ? $this->owner:0;
341
- }else{
342
- //force
343
- $this->owner = get_current_user_id();
344
  }
345
- //Set status of this event, depending on user type
346
- if( current_user_can('publish_events') ){
347
- //top level can edit and publish any events
348
- $this->status = 1;
 
 
 
 
 
 
 
 
349
  }else{
350
- //any updates or additions put the event into pending status
351
- $this->status = 0;
352
  }
353
- $this->slug = $this->sanitize_title();
354
-
355
- //Now save the event
356
- if ( !$this->id ) {
357
- // Insert New Event
358
- $this->owner = $current_user->ID; //Record creator of event
359
- $event = $this->to_array(true);
360
- $event['event_attributes'] = serialize($this->attributes);
361
- $event['recurrence_id'] = ( is_numeric($this->recurrence_id) ) ? $this->recurrence_id : 0;
362
- $event = apply_filters('em_event_save_pre',$event,$this);
363
- if( is_multisite() ){
364
- $event['blog_id'] = get_current_blog_id();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  }
366
- $result = $wpdb->insert ( $events_table, $event, $this->get_types($event) );
367
- if($result !== false){
368
- $this->id = $wpdb->insert_id;
369
- $this->is_new = true;
370
- //Add Tickets
371
- if( !$this->get_bookings()->get_tickets()->save() ){
372
- $this->errors[] = __( 'Something went wrong with creating tickets.', 'dbem' );
373
- return apply_filters('em_event_save', false, $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  }
375
- //Save Categories
376
- if( !$this->get_categories()->save() ){
377
- $this->add_error( $this->get_categories()->get_errors() );
378
- return apply_filters('em_event_save', false, $this);
379
  }
380
- //Deal with recurrences
381
- if ( $this->is_recurring() ) {
382
- //Recurrence master event saved, now Save Events & check errors
383
- if( !$this->save_events() ){
384
- $this->errors[] = __ ( 'Something went wrong with the recurrence update...', 'dbem' ).
385
- __ ( 'There was a problem saving the recurring events.', 'dbem' );
386
- $this->delete();
387
- return apply_filters('em_event_save', false, $this);
388
- }
389
- //All good! Event Saved
390
- $this->feedback_message = __ ( 'New recurrent event inserted!', 'dbem' );
391
- return apply_filters('em_event_save', true, $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  }
393
- //Successful individual save
394
- $this->feedback_message = __ ( 'New event successfully inserted!', 'dbem' );
395
- return apply_filters('em_event_save', true, $this);
396
  }else{
397
- $this->errors[] = __ ( 'Could not save the event details due to a database error.', 'dbem' );
398
  }
399
- } else {
400
- // Update Event
401
- //TODO event privacy protection, only authors and authorized users can edit events
402
- //$this->owner = $current_user->ID; //Record creator of event
403
- //FIXME Saving recurrence and disabling recurrence doesn't work
404
- $this->recurrence_id = 0; // If it's saved here, it becomes individual
405
- $event = $this->to_array();
406
- $event['event_attributes'] = serialize($event['event_attributes']);
407
- $event['event_date_modified'] = current_time('mysql');
408
- $event = apply_filters('em_event_save_pre',$event,$this);
409
- $result = $wpdb->update ( $events_table, $event, array('event_id' => $this->id), $this->get_types($event) );
410
- if($result !== false){ //Can't just do $result since if you don't make an actual record details change, it'll return 0 for no changes made
411
- //Add Tickets
412
- $this->feedback_message = "{$this->name} " . __ ( 'updated', 'dbem' ) . "!";
413
- if( !$this->get_bookings()->get_tickets()->save() ){
414
- $this->errors[] = __( 'Something went wrong with creating tickets.', 'dbem' );
415
- return apply_filters('em_event_save', false, $this);
416
  }
417
- //Save Categories
418
- if( !$this->get_categories()->save() ){
419
- $this->add_error( $this->get_categories()->get_errors() );
420
- return apply_filters('em_event_save', false, $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
  }
422
- //Deal with recurrences
423
- if ( $this->is_recurring() ) {
424
- if( !$this->save_events() ){
425
- $this->errors[] = __ ( 'Something went wrong with the recurrence update...', 'dbem' ).
426
- __ ( 'There was a problem saving the recurring events.', 'dbem' );
427
- return apply_filters('em_event_save', false, $this);
428
- }
429
- $this->feedback_message = __ ( 'Recurrence updated!', 'dbem' );
430
- return apply_filters('em_event_save', true, $this);
 
 
 
 
 
 
 
431
  }
432
- }else{
433
- $this->errors[] = __('Could not save the event details due to a database error.', 'dbem');
434
- return apply_filters('em_event_save', false, $this);
435
  }
436
- //Successful individual or recurrence save
437
- $this->feedback_message = "{$this->name} " . __ ( 'updated', 'dbem' ) . "!";
438
- if($this->rsvp == 0){
439
- $this->delete_bookings();
440
  }
441
- return apply_filters('em_event_save', true, $this);
442
  }
 
 
443
  }
444
 
445
  /**
446
- * Takes the title and gives either a unique slug or returns the currently used slug if this record already has it.
447
- * @param unknown_type $title
448
  */
449
- function sanitize_title($iteration = 1){
450
- global $wpdb;
451
- //Generate the slug. If this is a new event, create the slug automatically, if not, verify it is still unique and if not rewrite
452
- if( empty($this->slug) ){
453
- $this->slug = sanitize_title($this->name);
454
- }
455
- $slug = $this->slug;
456
- $slug_matches = $wpdb->get_results('SELECT event_id FROM '.EM_EVENTS_TABLE." WHERE event_slug='{$slug}'", ARRAY_A);
457
- if( count($slug_matches) > 0 ){ //we will check that the slug is unique
458
- if( $slug_matches[0]['event_id'] != $this->id || count($slug_matches) > 1 ){
459
- //we have a conflict, so try another alternative
460
- $this->slug = preg_replace('/\-[0-9]+$/', '', $slug).'-'.($iteration+1);
461
- $this->sanitize_title($iteration+1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
  }
464
- return apply_filters('em_event_sanitize_title', $this->slug, $this);
 
465
  }
466
 
467
  /**
468
- * Delete whole event, including recurrence and recurring data
469
- * @param $recurrence_id
470
  * @return boolean
471
  */
472
- function delete(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  global $wpdb;
474
- do_action('em_event_delete_pre', $this);
475
  $result = false;
476
- if( $this->can_manage( 'delete_events','delete_others_events' ) ){
477
- if( $this->is_recurring() ){
 
 
 
 
478
  //Delete the recurrences then this recurrence event
479
- $this->delete_events();
480
- }
481
- $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->id) );
482
- if($result !== false){
483
- $result = $this->get_bookings()->delete();
 
 
484
  }
485
  }
486
- return apply_filters('em_event_delete', $result !== false, $this);
487
  }
488
 
489
  /**
490
- * approve a booking.
491
- * @return bool
492
  */
493
- function approve(){
494
- return $this->set_status(1);
 
 
 
 
 
 
 
495
  }
496
 
497
  /**
498
- * Change the status of the event. This will save to the Database too.
499
- * @param unknown_type $status
500
- * @return string
501
  */
502
- function set_status($status){
503
- $action_string = strtolower($this->status_array[$status]);
504
- $this->previous_status = $this->status;
505
- $this->status = $status;
506
- $result = $this->save();
507
- if($result){
508
- $this->feedback_message = sprintf(__('Event %s.','dbem'), $action_string);
509
- return true;
510
- }else{
511
- //errors should be logged by save()
512
- $this->feedback_message = sprintf(__('Booking could not be %s.','dbem'), $action_string);
513
- return false;
514
  }
 
515
  }
516
 
517
  /**
518
- * Duplicates this event and returns the duplicated event. Will return false if there is a problem with duplication.
519
- * @return EM_Event
 
 
520
  */
521
- function duplicate(){
522
- global $wpdb, $EZSQL_ERROR;
523
- //First, duplicate.
524
- if( $this->can_manage('edit_events','edit_others_events') ){
525
- $event_table_name = EM_EVENTS_TABLE;
526
- $eventArray = $this->to_array();
527
- unset($eventArray['event_id']);
528
- $EM_Event = new EM_Event( $eventArray );
529
- if( $EM_Event->save() ){
530
- $EM_Event->feedback_message = sprintf(__("%s successfully duplicated.", 'dbem'), __('Event','dbem'));
531
- return apply_filters('em_event_duplicate', $EM_Event, $this);
532
  }
 
 
 
 
 
 
 
533
  }else{
534
- $EM_Event->add_error( sprintf(__('You are not allowed to manage this %s.'), __('event','dbem')) );
 
 
 
 
 
 
 
 
535
  }
536
- //TODO add error notifications for duplication failures.
537
- return apply_filters('em_event_duplicate', false, $this);;
 
 
538
  }
539
 
 
 
 
540
 
541
- /**
542
- * Validates the event. Should be run during any form submission or saving operation.
543
- * @return boolean
544
- */
545
- function validate() {
546
- $missing_fields = Array ();
547
- foreach ( $this->required_fields as $field ) {
548
- $true_field = $this->fields[$field]['name'];
549
- if ( $this->$true_field == "") {
550
- $missing_fields[] = $field;
551
- }
552
- }
553
- if ( count($missing_fields) > 0){
554
- // TODO Create friendly equivelant names for missing fields notice in validation
555
- $this->add_error( __( 'Missing fields: ' ) . implode ( ", ", $missing_fields ) . ". " );
556
- }
557
- if ( !empty($_POST['repeated_event']) && $_POST['repeated_event'] == "1" && $this->end_date == "" ){
558
- $this->add_error( __( 'Since the event is repeated, you must specify an event date.', 'dbem' ));
 
 
 
 
 
559
  }
560
- if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->end_date) ){
561
- if( strtotime($this->start_date . $this->start_time) > strtotime($this->end_date . $this->end_time) ){
562
- $this->add_error(__('Events cannot start after they end.','dbem'));
563
- }
564
- }else{
565
- $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem'));
566
- }
567
- if( $this->get_location()->id == '' && !$this->location->validate() ){
568
- $this->errors = array_merge($this->errors, $this->location->errors);
569
  }
570
- $this->image_validate();
571
-
572
- //TODO validate recurrence during event validate
573
- $count = count($this->errors);
574
- return apply_filters('em_event_validate', count($this->errors) == 0, $this );
575
  }
576
 
577
  /**
@@ -579,15 +1064,12 @@ class EM_Event extends EM_Object{
579
  * @return EM_Categories
580
  */
581
  function get_categories() {
582
- global $EM_Categories;
583
- if( !empty($this->categories) && is_object($this->categories) && get_class($this->categories)=='EM_Categories' && ( empty($this->categories->event->id) || $this->categories->event->id == $this->id ) ){
584
- $this->categories = $this->categories;
585
- }elseif( is_object($EM_Categories) && $EM_Categories->get_event()->id == $this->id ){
586
- $this->categories = $EM_Categories;
587
- }else{
588
  $this->categories = new EM_Categories($this);
 
 
 
589
  }
590
- $this->categories->event = $this;
591
  return apply_filters('em_event_get_categories', $this->categories, $this);
592
  }
593
 
@@ -596,28 +1078,35 @@ class EM_Event extends EM_Object{
596
  * @return EM_Location
597
  */
598
  function get_location() {
599
- global $EM_location;
600
- if( is_object($this->location) && get_class($this->location)=='EM_Location' && ($this->location_id == $this->location->id || empty($this->id)) ){
601
- return $this->location;
602
- }elseif( is_object($EM_location) && $EM_location->id == $this->location_id ){
603
- $this->location = $EM_location;
604
  }else{
605
- $this->location = new EM_location($this->location_id);
 
 
606
  }
607
- return apply_filters('em_event_get_location', $this->location, $this);
608
  }
609
 
610
  /**
611
- * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
612
- */
613
- function delete_bookings(){
614
- global $wpdb;
615
- do_action('em_event_delete_bookings_pre', $this);
616
- $result = false;
617
- if( $this->can_manage('manage_bookings','manage_others_bookings') ){
618
- $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d", $this->id) );
 
 
 
 
 
 
 
619
  }
620
- return apply_filters('em_event_delete_bookings', $result, $this);
621
  }
622
 
623
  /**
@@ -630,21 +1119,31 @@ class EM_Event extends EM_Object{
630
  if( (!$this->bookings || $force_reload) ){
631
  $this->bookings = new EM_Bookings($this);
632
  }
 
633
  }else{
634
  return new EM_Bookings();
635
  }
 
636
  return apply_filters('em_event_get_bookings', $this->bookings, $this);
637
  }
638
 
639
- function is_free(){
640
- $free = true;
641
- if( isset($this->free) ) return $this->free;
642
- foreach($this->get_bookings()->get_tickets() as $EM_Ticket){
643
- if( $EM_Ticket->price > 0 ){
644
- $free = false;
645
- }
646
- }
647
- return apply_filters('em_event_is_free',$free,$this);
 
 
 
 
 
 
 
 
648
  }
649
 
650
  /**
@@ -656,6 +1155,106 @@ class EM_Event extends EM_Object{
656
  return $this->get_bookings()->get_spaces($force_refresh);
657
  }
658
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
659
  /**
660
  * Will output a single event format of this event.
661
  * Equivalent of calling EM_Event::output( get_option ( 'dbem_single_event_format' ) )
@@ -673,87 +1272,292 @@ class EM_Event extends EM_Object{
673
  * @param string $target
674
  * @return string
675
  */
676
- function output($format, $target="html") {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  //First let's do some conditional placeholder removals
678
- preg_match_all('/\{([a-zA-Z0-9_]+)\}([^{]+)\{\/[a-zA-Z0-9_]+\}/', $format, $conditionals);
679
- if( count($conditionals[0]) > 0 ){
680
- //Check if the language we want exists, if not we take the first language there
681
- foreach($conditionals[1] as $key => $condition){
682
- $replacement = $conditionals[0][$key];
683
- if ($condition == 'has_bookings') {
684
- //check if there's a booking, if not, remove this section of code.
685
- if($this->rsvp){
686
- $replacement = substr($conditionals[0][$key], 14, strlen($conditionals[0][$key])-29); //29 = (15+14)
687
- }else{
688
- $replacement = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
  }
690
- }
691
- if ($condition == 'no_bookings') {
692
- //check if there's a booking, if not, remove this section of code.
693
- if(!$this->rsvp){
694
- $replacement = substr($conditionals[0][$key], 13, strlen($conditionals[0][$key])-28); //28 = (13+14)
 
695
  }else{
696
  $replacement = '';
697
  }
698
- str_replace($conditionals[0][$key], $replacement, $format);
699
  }
700
- $format = str_replace($conditionals[0][$key], apply_filters('em_event_output_condition', $replacement, $condition, $conditionals[0][$key], $this), $format);
701
  }
702
- }
703
- $event_string = $format;
704
  //Now let's check out the placeholders.
705
- preg_match_all("/#@?_?[A-Za-z0-9]+/", $format, $placeholders);
706
- foreach($placeholders[0] as $result) {
 
707
  $match = true;
708
  $replace = '';
 
709
  switch( $result ){
710
  //Event Details
711
  case '#_EVENTID':
712
- $replace = $this->id;
 
 
 
713
  break;
714
- case '#_NAME':
715
- $replace = $this->name;
 
716
  break;
717
- case '#_NOTES':
718
- case '#_EXCERPT':
719
- //SEE AT BOTTOM OF FILE FOR OLD TARGET FILTERS FROM 2.x
720
- $replace = $this->notes;
721
- if($result == "#_EXCERPT"){
722
- $matches = explode('<!--more', $this->notes);
723
- $replace = $matches[0];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
  }
725
  break;
726
  case '#_EVENTIMAGEURL':
727
  case '#_EVENTIMAGE':
728
- if($this->image_url != ''){
729
- $replace = ($result == '#_EVENTIMAGEURL') ? $this->image_url : "<img src='".$this->image_url."' alt='".$this->name."'/>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
730
  }
731
  break;
732
- //Times
733
  case '#_24HSTARTTIME':
734
  case '#_24HENDTIME':
735
- $time = ($result == '#_24HSTARTTIME') ? $this->start_time:$this->end_time;
736
  $replace = substr($time, 0,5);
737
  break;
738
  case '#_12HSTARTTIME':
739
  case '#_12HENDTIME':
740
- $time = ($result == '#_12HSTARTTIME') ? $this->start_time:$this->end_time;
741
  $replace = date('g:i A', strtotime($time));
742
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
743
  //Links
744
  case '#_EVENTPAGEURL': //Depreciated
745
  case '#_LINKEDNAME': //Depreciated
746
  case '#_EVENTURL': //Just the URL
747
  case '#_EVENTLINK': //HTML Link
748
- //If this event is not of this blog, we need a new URL
749
- $EM_URI = EM_URI;
750
- if( is_multisite() && get_site_option('dbem_ms_global_events') && get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
751
- $EM_URI = get_blog_permalink($this->blog_id, get_blog_option($this->blog_id, 'dbem_events_page'));
752
- }
753
- $joiner = (stristr($EM_URI, "?")) ? "&amp;" : "?";
754
- $event_link = $EM_URI.$joiner."event_id=".$this->id;
755
  if($result == '#_LINKEDNAME' || $result == '#_EVENTLINK'){
756
- $replace = "<a href='{$event_link}' title='{$this->name}'>{$this->name}</a>";
757
  }else{
758
  $replace = $event_link;
759
  }
@@ -761,13 +1565,11 @@ class EM_Event extends EM_Object{
761
  case '#_EDITEVENTURL':
762
  case '#_EDITEVENTLINK':
763
  if( $this->can_manage('edit_events','edit_others_events') ){
764
- if( is_multisite() && get_site_option('dbem_ms_global_events') && get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
765
- $replace = get_site_url($this->blog_id, "/wp-admin/admin.php?page=events-manager-event&amp;event_id={$this->id}");
766
- }else{
767
- $replace = get_bloginfo('wpurl')."/wp-admin/admin.php?page=events-manager-event&amp;event_id={$this->id}";
768
- }
769
  if( $result == '#_EDITEVENTLINK'){
770
- $replace = "<a href='{$replace}'>".__('Edit').' '.__('Event', 'dbem')."</a>";
 
 
771
  }
772
  }
773
  break;
@@ -775,18 +1577,81 @@ class EM_Event extends EM_Object{
775
  case '#_ADDBOOKINGFORM': //Depreciated
776
  case '#_REMOVEBOOKINGFORM': //Depreciated
777
  case '#_BOOKINGFORM':
778
- ob_start();
779
- $template = em_locate_template('placeholders/bookingform.php', true, array('EM_Event'=>$this));
780
- $replace = ob_get_clean();
 
 
 
 
 
 
 
 
781
  break;
782
  case '#_BOOKINGBUTTON':
783
- ob_start();
784
- $template = em_locate_template('placeholders/bookingbutton.php', true, array('EM_Event'=>$this));
785
- $replace = ob_get_clean();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
786
  break;
787
  case '#_AVAILABLESEATS': //Depreciated
788
  case '#_AVAILABLESPACES':
789
- if ($this->rsvp && get_option('dbem_rsvp_enabled')) {
790
  $replace = $this->get_bookings()->get_available_spaces();
791
  } else {
792
  $replace = "0";
@@ -794,14 +1659,18 @@ class EM_Event extends EM_Object{
794
  break;
795
  case '#_BOOKEDSEATS': //Depreciated
796
  case '#_BOOKEDSPACES':
797
- if ($this->rsvp && get_option('dbem_rsvp_enabled')) {
798
- $replace = $this->get_bookings()->get_booked_spaces();
 
 
 
 
799
  } else {
800
  $replace = "0";
801
  }
802
  break;
803
  case '#_PENDINGSPACES':
804
- if ($this->rsvp && get_option('dbem_rsvp_enabled')) {
805
  $replace = $this->get_bookings()->get_pending_spaces();
806
  } else {
807
  $replace = "0";
@@ -813,50 +1682,62 @@ class EM_Event extends EM_Object{
813
  break;
814
  case '#_BOOKINGSURL':
815
  case '#_BOOKINGSLINK':
816
- $bookings_link = get_bloginfo ( 'wpurl' )."/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=".$this->id;
817
- if($result == '#_BOOKINGSLINK'){
818
- $replace = "<a href='{$bookings_link}' title='{$this->name}'>{$this->name}</a>";
819
- }else{
820
- $replace = $bookings_link;
 
 
 
 
 
 
 
 
 
 
 
 
 
821
  }
822
  break;
823
  //Contact Person
824
  case '#_CONTACTNAME':
825
  case '#_CONTACTPERSON': //Depreciated (your call, I think name is better)
826
- $replace = $this->contact->display_name;
827
  break;
828
  case '#_CONTACTUSERNAME':
829
- $replace = $this->contact->user_login;
830
  break;
831
  case '#_CONTACTEMAIL':
832
  case '#_CONTACTMAIL': //Depreciated
833
- $replace = $this->contact->user_email;
 
 
 
834
  break;
835
  case '#_CONTACTID':
836
- $replace = $this->contact->ID;
837
  break;
838
  case '#_CONTACTPHONE':
839
- $replace = ( $this->contact->phone != '') ? $this->contact->phone : __('N/A', 'dbem');
840
  break;
841
  case '#_CONTACTAVATAR':
842
- $replace = get_avatar( $this->contact->ID, $size = '50' );
843
  break;
844
  case '#_CONTACTPROFILELINK':
845
  case '#_CONTACTPROFILEURL':
846
  if( function_exists('bp_core_get_user_domain') ){
847
- $replace = bp_core_get_user_domain($this->contact->ID);
848
  if( $result == '#_CONTACTPROFILELINK' ){
849
- $replace = '<a href="'.$replace.'">'.__('Profile').'</a>';
850
  }
851
  }
852
  break;
853
- case '#_CONTACTPROFILELINK':
854
- case '#_CONTACTPROFILEURL':
855
- if( function_exists('bp_core_get_user_domain') ){
856
- $replace = bp_core_get_user_domain($this->contact->ID);
857
- if( $result == '#_CONTACTPROFILELINK' ){
858
- $replace = '<a href="'.$replace.'">'.__('Profile').'</a>';
859
- }
860
  }
861
  break;
862
  case '#_ATTENDEES':
@@ -864,20 +1745,98 @@ class EM_Event extends EM_Object{
864
  $template = em_locate_template('placeholders/attendees.php', true, array('EM_Event'=>$this));
865
  $replace = ob_get_clean();
866
  break;
867
- case '#_CATEGORIES':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
  ob_start();
869
  $template = em_locate_template('placeholders/categories.php', true, array('EM_Event'=>$this));
870
  $replace = ob_get_clean();
871
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
872
  default:
873
- $replace = $result;
874
  break;
875
  }
876
- $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
877
- $event_string = str_replace($result, $replace , $event_string );
 
 
 
 
 
 
 
 
 
 
878
  }
879
  //Time placeholders
880
- foreach($placeholders[0] as $result) {
881
  // matches all PHP START date and time placeholders
882
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
883
  $replace = date_i18n(ltrim($result, "#"), $this->start);
@@ -891,86 +1850,318 @@ class EM_Event extends EM_Object{
891
  $event_string = str_replace($result, $replace, $event_string );
892
  }
893
  }
894
- //Time place holder that doesn't show if empty.
895
- //TODO add filter here too
896
- preg_match_all('/#@?_\{[A-Za-z0-9 -\/,\.\\\]+\}/', $format, $results);
897
- foreach($results[0] as $result) {
898
- if(substr($result, 0, 3 ) == "#@_"){
899
- $date = 'end_date';
900
- $offset = 4;
901
- }else{
902
- $date = 'start_date';
903
- $offset = 3;
904
- }
905
- if( $date == 'end_date' && $this->end_date == $this->start_date ){
906
- $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
907
- }else{
908
- $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) );
909
- }
910
- $event_string = str_replace($result,$replace,$event_string );
911
- }
912
- //This is for the custom attributes
913
- preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+)\})?/', $format, $results);
914
- foreach($results[0] as $resultKey => $result) {
915
- //Strip string of placeholder and just leave the reference
916
- $attRef = substr( substr($result, 0, strpos($result, '}')), 6 );
917
- $attString = '';
918
- if( is_array($this->attributes) && array_key_exists($attRef, $this->attributes) ){
919
- $attString = $this->attributes[$attRef];
920
- }elseif( !empty($results[3][$resultKey]) ){
921
- //Check to see if we have a second set of braces;
922
- $attString = $results[3][$resultKey];
923
- }
924
- $attString = apply_filters('em_event_output_placeholder', $attString, $this, $result, $target);
925
- $event_string = str_replace($result, $attString ,$event_string );
926
- }
927
-
928
  //Now do dependent objects
929
- $event_string = $this->location->output($event_string, $target);
 
 
 
 
 
930
 
931
  //for backwards compat and easy use, take over the individual category placeholders with the frirst cat in th elist.
932
- $EM_Category = $this->get_categories()->categories[0];
 
 
 
 
933
  if( empty($EM_Category) ) $EM_Category = new EM_Category();
934
  $event_string = $EM_Category->output($event_string, $target);
935
 
936
- return apply_filters('em_event_output', $event_string, $this, $target);
937
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
938
 
939
  /**********************************************************
940
  * RECURRENCE METHODS
941
  ***********************************************************/
942
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
943
  /**
944
  * Saves events and replaces old ones. Returns true if sucecssful or false if not.
945
  * @return boolean
946
  */
947
  function save_events() {
948
- if( $this->is_recurring() && $this->can_manage('edit_events','edit_others_events') ){
 
 
949
  do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
950
- global $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
951
  $event_saves = array();
952
  $matching_days = $this->get_recurrence_days(); //Get days where events recur
953
- $this->delete_events(); //Delete old events beforehand
954
- //Make template event (and we just change dates)
955
- $event = $this->to_array();
956
- unset($event['event_id']); //remove id and we have a event template to feed to wpdb insert
957
- $event['event_attributes'] = serialize($event['event_attributes']);
958
- foreach($event as $key => $value ){ //remove recurrence information
959
- if( substr($key, 0, 10) == 'recurrence' ){
960
- unset($event[$key]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
961
  }
962
- }
963
- $event['recurrence_id'] = $this->id;
964
- //Save event template with different dates
965
- foreach( $matching_days as $day ) {
966
- $event['event_start_date'] = date("Y-m-d", $day);
967
- $event['event_end_date'] = $event['event_start_date'];
968
- $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event, $this->get_types($event));
969
- if( EM_DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
  }
971
- return apply_filters('em_event_save_events', !in_array(false, $event_saves), $this);
972
  }
973
- return apply_filters('em_event_save_events', false, $this);;
974
  }
975
 
976
  /**
@@ -984,48 +2175,16 @@ class EM_Event extends EM_Object{
984
  //So we don't do something we'll regret later, we could just supply the get directly into the delete, but this is safer
985
  $result = false;
986
  if( $this->can_manage('delete_events', 'delete_others_events') ){
987
- $EM_Events = EM_Events::get( array('recurrence_id'=>$this->id) );
988
- $event_ids = array();
989
- foreach($EM_Events as $EM_Event){
990
- if($EM_Event->recurrence_id == $this->id){
991
- $event_ids[] = $EM_Event->id; //ONLY ADD if id's match - hard coded
 
992
  }
993
- }
994
- $result = EM_Events::delete( $event_ids );
995
  }
996
- return apply_filters('delete_events', $result, $this);
997
- }
998
-
999
- /**
1000
- * Returns true if this event is a recurring event, meaning that it's not an individual event,
1001
- * but an event that defines many events that recur over a span of time.
1002
- * For checking if a specific event is part of a greater set of recurring events, use is_recurrence()
1003
- * @return boolean
1004
- */
1005
- function is_recurring(){
1006
- return ( $this->recurrence );
1007
- }
1008
- /**
1009
- * Will return true if this individual event is part of a set of events that recur
1010
- * For checking if this is the "master recurring event", see is_recurring()
1011
- * @return boolean
1012
- */
1013
- function is_recurrence(){
1014
- return ( $this->id > 0 && $this->recurrence_id > 0 );
1015
- }
1016
- /**
1017
- * Returns if this is an individual event and is not recurring or a recurrence
1018
- * @return boolean
1019
- */
1020
- function is_individual(){
1021
- return ( !$this->is_recurring() && !$this->is_recurrence() );
1022
- }
1023
-
1024
- /**
1025
- * Can the user manage this?
1026
- */
1027
- function can_manage( $owner_capability = false, $admin_capability = false ){
1028
- return apply_filters('em_event_can_manage', parent::can_manage($owner_capability, $admin_capability), $this);
1029
  }
1030
 
1031
  /**
@@ -1033,182 +2192,181 @@ class EM_Event extends EM_Object{
1033
  * @param array $recurrence
1034
  * @return array
1035
  */
1036
- function get_recurrence_days(){
1037
- if( $this->is_recurring() ){
1038
-
1039
- $start_date = strtotime($this->start_date);
1040
- $end_date = strtotime($this->end_date);
1041
-
1042
- $weekdays = explode(",", $this->byday); //what days of the week (or if monthly, one value at index 0)
1043
-
1044
- $matching_days = array();
1045
- $aDay = 86400; // a day in seconds
1046
- $aWeek = $aDay * 7;
1047
 
1048
- //TODO can this be optimized?
1049
- switch ( $this->freq ){
1050
- case 'daily':
1051
- //If daily, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
1052
- $current_date = $start_date;
1053
- while( $current_date <= $end_date ){
1054
- $matching_days[] = $current_date;
1055
- $current_date = $current_date + ($aDay * $this->interval);
1056
- }
1057
- break;
1058
- case 'weekly':
1059
- //sort out week one, get starting days and then days that match time span of event (i.e. remove past events in week 1)
1060
- $start_of_week = get_option('start_of_week'); //Start of week depends on wordpress
1061
- //first, get the start of this week as timestamp
1062
- $event_start_day = date('w', $start_date);
1063
- $offset = 0;
1064
- if( $event_start_day > $start_of_week ){
1065
- $offset = $event_start_day - $start_of_week; //x days backwards
1066
- }elseif( $event_start_day < $start_of_week ){
1067
- $offset = $start_of_week;
 
 
 
 
 
 
 
 
 
1068
  }
1069
- $start_week_date = $start_date - ( ($event_start_day - $start_of_week) * $aDay );
1070
- //then get the timestamps of weekdays during this first week, regardless if within event range
1071
- $start_weekday_dates = array(); //Days in week 1 where there would events, regardless of event date range
1072
- for($i = 0; $i < 7; $i++){
1073
- $weekday_date = $start_week_date+($aDay*$i); //the date of the weekday we're currently checking
1074
- $weekday_day = date('w',$weekday_date); //the day of the week we're checking, taking into account wp start of week setting
1075
- if( in_array( $weekday_day, $weekdays) ){
1076
- $start_weekday_dates[] = $weekday_date; //it's in our starting week day, so add it
1077
- }
1078
- }
1079
- //for each day of eventful days in week 1, add 7 days * weekly intervals
1080
- foreach ($start_weekday_dates as $weekday_date){
1081
- //Loop weeks by interval until we reach or surpass end date
1082
- while($weekday_date <= $end_date){
1083
- if( $weekday_date >= $start_date && $weekday_date <= $end_date ){
1084
- $matching_days[] = $weekday_date;
1085
- }
1086
- $weekday_date = $weekday_date + ($aWeek * $this->interval);
1087
- }
1088
- }//done!
1089
- break;
1090
- case 'monthly':
1091
- //loop months starting this month by intervals
1092
- $current_arr = getdate($start_date);
1093
- $end_arr = getdate($end_date);
1094
- $end_month_date = strtotime( date('Y-m-t', $end_date) ); //End date on last day of month
1095
- $current_date = strtotime( date('Y-m-1', $start_date) ); //Start date on first day of month
1096
- while( $current_date <= $end_month_date ){
1097
- $last_day_of_month = date('t', $current_date);
1098
- //Now find which day we're talking about
1099
- $current_week_day = date('w',$current_date);
1100
- $matching_month_days = array();
1101
- //Loop through days of this years month and save matching days to temp array
1102
- for($day = 1; $day <= $last_day_of_month; $day++){
1103
- if($current_week_day == $this->byday){
1104
- $matching_month_days[] = $day;
1105
- }
1106
- $current_week_day = ($current_week_day < 6) ? $current_week_day+1 : 0;
1107
- }
1108
- //Now grab from the array the x day of the month
1109
- $matching_day = ($this->byweekno > 0) ? $matching_month_days[$this->byweekno-1] : array_pop($matching_month_days);
1110
- $matching_date = strtotime(date('Y-m',$current_date).'-'.$matching_day);
1111
- if($matching_date >= $start_date && $matching_date <= $end_date){
1112
- $matching_days[] = $matching_date;
1113
  }
1114
- //add the number of days in this month to make start of next month
1115
- $current_arr['mon'] += $this->interval;
1116
- if($current_arr['mon'] > 12){
1117
- //FIXME this won't work if interval is more than 12
1118
- $current_arr['mon'] = $current_arr['mon'] - 12;
1119
- $current_arr['year']++;
 
 
 
 
 
 
 
 
 
 
 
 
 
1120
  }
1121
- $current_date = strtotime("{$current_arr['year']}-{$current_arr['mon']}-1");
1122
  }
1123
- break;
1124
- }
1125
- sort($matching_days);
1126
- //TODO delete this after testing
1127
- /*Delete*/
1128
- $test_dates = array();
1129
- foreach($matching_days as $matching_day){
1130
- $test_dates[] = date('d/m/Y', $matching_day);
1131
- }
1132
- /*end delete*/
1133
- return $matching_days;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1134
  }
 
 
1135
  }
1136
 
1137
- function get_recurrence(){
1138
- global $EM_Recurrences;
1139
- if( is_array($EM_Recurrences) && array_key_exists($this->recurrence_id, $EM_Recurrences) && is_object($EM_Recurrences[$this->recurrence_id]) && get_class($EM_Recurrences[$this->recurrence_id]) == 'EM_Event' ){
1140
- $recurrence = $EM_Recurrences[$this->recurrence_id];
1141
- }else{
1142
- //get this recurrence
1143
- $recurrence = new EM_Event($this->recurrence_id);
1144
- $EM_Recurrences[$this->recurrence_id] = $recurrence;
 
 
 
 
1145
  }
1146
- return $recurrence;
1147
  }
1148
 
1149
  /**
1150
  * Returns a string representation of this recurrence. Will return false if not a recurrence
1151
  * @return string
1152
  */
1153
- function get_recurrence_description() {
1154
- if( $this->is_individual() ) return false;
1155
- $recurrence = $this->get_recurrence()->to_array();
1156
- $weekdays_name = array(__('Sunday'),__('Monday'),__('Tuesday'),__('Wednesday'),__('Thursday'),__('Friday'),__('Saturday'));
1157
  $monthweek_name = array('1' => __('the first %s of the month', 'dbem'),'2' => __('the second %s of the month', 'dbem'), '3' => __('the third %s of the month', 'dbem'), '4' => __('the fourth %s of the month', 'dbem'), '-1' => __('the last %s of the month', 'dbem'));
1158
- $output = sprintf (__('From %1$s to %2$s', 'dbem'), $recurrence['event_start_date'], $recurrence['event_end_date']).", ";
1159
- if ($recurrence['recurrence_freq'] == 'daily') {
1160
  $freq_desc =__('everyday', 'dbem');
1161
- if ($recurrence['recurrence_interval'] > 1 ) {
1162
- $freq_desc = sprintf (__("every %s days", 'dbem'), $recurrence['recurrence_interval']);
1163
  }
1164
- }elseif ($recurrence['recurrence_freq'] == 'weekly') {
1165
- $weekday_array = explode(",", $recurrence['recurrence_byday']);
1166
  $natural_days = array();
1167
  foreach($weekday_array as $day){
1168
  array_push($natural_days, $weekdays_name[$day]);
1169
  }
1170
- $output .= implode(" and ", $natural_days);
1171
- $freq_desc = ", " . __("every week", 'dbem');
1172
- if ($recurrence['recurrence_interval'] > 1 ) {
1173
- $freq_desc = ", ".sprintf (__("every %s weeks", 'dbem'), $recurrence['recurrence_interval']);
1174
  }
1175
 
1176
- }elseif ($recurrence['recurrence_freq'] == 'monthly') {
1177
- $weekday_array = explode(",", $recurrence['recurrence_byday']);
1178
  $natural_days = array();
1179
  foreach($weekday_array as $day){
1180
- array_push($natural_days, $weekdays_name[$day]);
 
 
 
 
 
 
1181
  }
1182
- $freq_desc = sprintf (($monthweek_name[$recurrence['recurrence_byweekno']]), implode(" and ", $natural_days));
1183
- if ($recurrence['recurrence_interval'] > 1 ) {
1184
- $freq_desc .= ", ".sprintf (__("every %s months",'dbem'), $recurrence['recurrence_interval']);
 
1185
  }
1186
  }else{
1187
  $freq_desc = "[ERROR: corrupted database record]";
1188
  }
1189
  $output .= $freq_desc;
1190
  return $output;
1191
- }
1192
 
1193
  /**********************************************************
1194
  * UTILITIES
1195
  ***********************************************************/
1196
-
1197
  /**
1198
- * Returns this object in the form of an array, useful for saving directly into the wp_dbem_events table.
1199
- * @param boolean $for_database
1200
- * @return array
1201
  */
1202
- function to_array($for_database = false){
1203
- $event = array();
1204
- //Core Event Data
1205
- foreach ( $this->fields as $key => $val ) {
1206
- //TODO does it matter if it's for db or not... shouldn't it just not include blanks?
1207
- if( !$for_database || $for_database && $this->$val['name'] != '' ){
1208
- $event[$key] = $this->$val['name'];
1209
- }
1210
  }
1211
- return $event;
1212
  }
1213
  }
1214
 
@@ -1221,28 +2379,90 @@ class EM_Event extends EM_Object{
1221
  * @param string $target
1222
  * @return mixed
1223
  */
1224
- function em_event_output_placeholder($result,$event,$placeholder,$target='html'){
1225
- if( ($placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT") && $target == 'html' ){
 
1226
  $result = apply_filters('dbem_notes_excerpt', $result);
1227
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
1228
- $result = em_ascii_encode($event->contact->user_email);
1229
- }elseif( $placeholder == "#_NOTES" || $placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT" ){
1230
- if($target == 'html'){
1231
- $result = apply_filters('dbem_notes', $result);
1232
- }elseif($target == 'map'){
1233
- $result = apply_filters('dbem_notes_map', $result);
1234
- }else{
1235
  $result = apply_filters('dbem_notes_rss', $result);
1236
  $result = apply_filters('the_content_rss', $result);
 
 
 
 
 
 
 
 
1237
  }
1238
- }elseif( in_array($placeholder, array("#_NAME",'#_ADDRESS','#_LOCATION','#_TOWN')) ){
1239
- if ($target == "html"){
1240
- $result = apply_filters('dbem_general', $result);
1241
- }else{
1242
  $result = apply_filters('dbem_general_rss', $result);
 
 
 
 
 
 
1243
  }
1244
  }
1245
  return $result;
1246
  }
 
1247
  add_filter('em_event_output_placeholder','em_event_output_placeholder',1,4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1248
  ?>
1
  <?php
2
+ /**
3
+ * Get an event in a db friendly way, by checking globals and passed variables to avoid extra class instantiations
4
+ * @param mixed $id
5
+ * @param mixed $search_by
6
+ * @return EM_Event
7
+ */
8
+ function em_get_event($id = false, $search_by = 'event_id') {
9
+ global $EM_Event;
10
+ //check if it's not already global so we don't instantiate again
11
+ if( is_object($EM_Event) && get_class($EM_Event) == 'EM_Event' ){
12
+ if( is_object($id) && $EM_Event->post_id == $id->ID ){
13
+ return apply_filters('em_get_event', $EM_Event);
14
+ }elseif( !is_object($id) ){
15
+ if( $search_by == 'event_id' && $EM_Event->event_id == $id ){
16
+ return apply_filters('em_get_event', $EM_Event);
17
+ }elseif( $search_by == 'post_id' && $EM_Event->post_id == $id ){
18
+ return apply_filters('em_get_event', $EM_Event);
19
+ }
20
+ }
21
+ }
22
+ if( is_object($id) && get_class($id) == 'EM_Event' ){
23
+ return apply_filters('em_get_event', $id);
24
+ }else{
25
+ return apply_filters('em_get_event', new EM_Event($id,$search_by));
26
+ }
27
+ }
28
  /**
29
  * Event Object. This holds all the info pertaining to an event, including location and recurrence info.
30
  * An event object can be one of three "types" a recurring event, recurrence of a recurring event, or a single event.
37
  //TODO Integrate recurrences into events table
38
  //FIXME If you create a super long recurrence timespan, there could be thousands of events... need an upper limit here.
39
  class EM_Event extends EM_Object{
40
+ /* Field Names */
41
+ var $event_id;
42
+ var $post_id;
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;
51
+ var $post_content;
52
+ var $event_rsvp;
53
+ var $event_rsvp_date;
54
+ var $event_rsvp_time = "00:00:00";
55
+ var $event_rsvp_spaces;
56
+ var $event_spaces;
57
+ var $event_private;
58
+ var $location_id;
59
+ var $recurrence_id;
60
+ var $event_status;
61
+ var $event_date_created;
62
+ var $event_date_modified;
63
+ var $blog_id;
64
+ var $group_id;
65
+ /**
66
+ * Populated with the non-hidden event post custom fields (i.e. not starting with _)
67
+ * @var array
68
+ */
69
+ var $event_attributes = array();
70
+ /* Recurring Specific Values */
71
+ var $recurrence;
72
+ var $recurrence_interval;
73
+ var $recurrence_freq;
74
+ var $recurrence_byday;
75
+ var $recurrence_days = 0;
76
+ var $recurrence_byweekno;
77
+ var $recurrence_rsvp_days;
78
+ /* anonymous submission information */
79
+ var $event_owner_anonymous;
80
+ var $event_owner_name;
81
+ var $event_owner_email;
82
  /**
83
+ * Previously used to give this object shorter property names for db values (each key has a name) but this is now depreciated, use the db field names as properties. This propertey provides extra info about the db fields.
 
84
  * @var array
85
  */
86
  var $fields = array(
87
  'event_id' => array( 'name'=>'id', 'type'=>'%d' ),
88
+ 'post_id' => array( 'name'=>'post_id', 'type'=>'%d' ),
89
+ 'event_slug' => array( 'name'=>'slug', 'type'=>'%s', 'null'=>true ),
90
+ 'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ),
91
+ 'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ),
92
+ 'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ),
93
+ 'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ),
94
+ 'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ),
95
+ 'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ),
96
+ 'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s', 'null'=>true ),
97
+ 'post_content' => array( 'name'=>'notes', 'type'=>'%s', 'null'=>true ),
98
+ 'event_rsvp' => array( 'name'=>'rsvp', 'type'=>'%d', 'null'=>true ), //has a default, so can be null/excluded
99
+ 'event_rsvp_date' => array( 'name'=>'rsvp_date', 'type'=>'%s', 'null'=>true ),
100
+ 'event_rsvp_time' => array( 'name'=>'rsvp_time', 'type'=>'%s', 'null'=>true ),
101
+ 'event_rsvp_spaces' => array( 'name'=>'rsvp_spaces', 'type'=>'%d', 'null'=>true ),
102
+ 'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d', 'null'=>true),
103
+ 'location_id' => array( 'name'=>'location_id', 'type'=>'%d', 'null'=>true ),
104
+ 'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d', 'null'=>true ),
105
+ 'event_status' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
106
+ 'event_private' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
107
+ 'event_date_created' => array( 'name'=>'date_created', 'type'=>'%s', 'null'=>true ),
108
+ 'event_date_modified' => array( 'name'=>'date_modified', 'type'=>'%s', 'null'=>true ),
109
+ 'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s', 'null'=>true ),
110
+ 'blog_id' => array( 'name'=>'blog_id', 'type'=>'%d', 'null'=>true ),
111
+ 'group_id' => array( 'name'=>'group_id', 'type'=>'%d', 'null'=>true ),
112
+ 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
113
+ 'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
114
+ 'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s', 'null'=>true ), //daily,weekly,monthly?
115
+ 'recurrence_days' => array( 'name'=>'days', 'type'=>'%d', 'null'=>true ), //daily,weekly,monthly?
116
+ 'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s', 'null'=>true ), //if weekly or monthly, what days of the week?
117
+ 'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d', 'null'=>true ), //if monthly which week (-1 is last)
118
+ 'recurrence_rsvp_days' => array( 'name'=>'recurrence_rsvp_days', 'type'=>'%d', 'null'=>true ), //days before or after start date to generat bookings cut-off date
119
  );
120
+ var $post_fields = array('event_slug','event_owner','event_name','event_attributes','post_id','post_content'); //fields that won't be taken from the em_events table anymore
121
+ var $recurrence_fields = array('recurrence_interval', 'recurrence_freq', 'recurrence_days', 'recurrence_byday', 'recurrence_byweekno');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
  var $image_url = '';
124
  /**
131
  * @var int
132
  */
133
  var $end;
134
+ /**
135
+ * Timestamp for booking cut-off date/time
136
+ * @var int
137
+ */
138
+ var $rsvp_end;
139
  /**
140
  * Created on timestamp, taken from DB, converted to TS
141
  * @var int
176
  */
177
  var $feedback_message;
178
  /**
179
+ * Any warnings about an event (e.g. bad data, recurrence, etc.)
180
  * @var string
181
  */
182
  var $warnings;
186
  */
187
  var $required_fields = array('event_name', 'event_start_date');
188
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
189
+ /**
190
+ * previous status of event when instantiated
191
+ * @access protected
192
+ * @var mixed
193
+ */
194
+ var $previous_status = false;
195
+
196
+ /* Post Variables - copied out of post object for easy IDE reference */
197
+ var $ID;
198
+ var $post_author;
199
+ var $post_date;
200
+ var $post_date_gmt;
201
+ var $post_title;
202
+ var $post_excerpt;
203
+ var $post_status;
204
+ var $comment_status;
205
+ var $ping_status;
206
+ var $post_password;
207
+ var $post_name;
208
+ var $to_ping;
209
+ var $pinged;
210
+ var $post_modified;
211
+ var $post_modified_gmt;
212
+ var $post_content_filtered;
213
+ var $post_parent;
214
+ var $guid;
215
+ var $menu_order;
216
+ var $post_type;
217
+ var $post_mime_type;
218
+ var $comment_count;
219
+ var $ancestors;
220
+ var $filter;
221
 
222
  /**
223
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
224
  * @param mixed $event_data
225
+ * @param mixed $search_by default is post_id, otherwise it can be by event_id as well.
226
  * @return null
227
  */
228
+ function __construct($id = false, $search_by = 'event_id') {
229
+ global $wpdb;
230
+ if( is_array($id) ){
231
+ //deal with the old array style, but we can't supply arrays anymore
232
+ $id = (!empty($id['event_id'])) ? $id['event_id'] : $id['post_id'];
233
+ $search_by = (!empty($id['event_id'])) ? 'event_id':'post_id';
234
+ }
235
+ $is_post = !empty($id->ID) && ($id->post_type == EM_POST_TYPE_EVENT || $id->post_type == 'event-recurring');
236
+ if( is_numeric($id) || $is_post ){ //only load info if $id is a number
237
+ if($search_by == 'event_id' && !$is_post ){
238
+ //search by event_id, get post_id and blog_id (if in ms mode) and load the post
239
+ $results = $wpdb->get_row($wpdb->prepare("SELECT post_id, blog_id FROM ".EM_EVENTS_TABLE." WHERE event_id=%d",$id), ARRAY_A);
240
+ if( !empty($results['post_id']) ){ $this->post_id = $results['post_id']; }
241
+ if( is_multisite() && (is_numeric($results['blog_id']) || $results['blog_id']=='' ) ){
242
+ if( $results['blog_id']=='' ) $results['blog_id'] = get_current_site()->blog_id;
243
+ $event_post = get_blog_post($results['blog_id'], $results['post_id']);
244
+ $search_by = $this->blog_id = $results['blog_id'];
245
  }else{
246
+ $event_post = get_post($results['post_id']);
247
  }
248
+ }else{
249
+ if(!$is_post){
250
+ if( is_multisite() && (is_numeric($search_by) || $search_by == '') ){
251
+ if( $search_by == '' ) $search_by = get_current_site()->blog_id;
252
+ //we've been given a blog_id, so we're searching for a post id
253
+ $event_post = get_blog_post($search_by, $id);
254
+ $this->blog_id = $search_by;
255
+ }else{
256
+ //search for the post id only
257
+ $event_post = get_post($id);
258
+ }
259
+ }else{
260
+ $event_post = $id;
 
 
 
 
261
  }
262
+ $this->post_id = !empty($id->ID) ? $id->ID : $id;
263
  }
264
+ $this->load_postdata($event_post, $search_by);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  }
266
+ $this->recurrence = $this->is_recurring() ? 1:0;
267
+ //if(defined('trashtest')){ print_r($this); die("got here");}
268
  //Do it here so things appear in the po file.
269
  $this->status_array = array(
270
  0 => __('Pending','dbem'),
271
  1 => __('Approved','dbem')
272
  );
273
+ do_action('em_event', $this, $id, $search_by);
274
+ }
275
+
276
+ function load_postdata($event_post, $search_by = false){
277
+ if( is_object($event_post) ){
278
+ //load post data - regardless
279
+ $this->post_id = $event_post->ID;
280
+ $this->event_name = $event_post->post_title;
281
+ $this->event_owner = $event_post->post_author;
282
+ $this->post_content = $event_post->post_content;
283
+ $this->post_excerpt = $event_post->post_excerpt;
284
+ $this->event_slug = $event_post->post_name;
285
+ $this->event_modified = $event_post->post_modified;
286
+ foreach( $event_post as $key => $value ){ //merge post object into this object
287
+ $this->$key = $value;
288
+ }
289
+ $this->recurrence = $this->is_recurring() ? 1:0;
290
+ //load meta data and other related information
291
+ if( $event_post->post_status != 'auto-draft' ){
292
+ $event_meta = $this->get_event_meta($search_by);
293
+ //Get custom fields and post meta
294
+ foreach($event_meta as $event_meta_key => $event_meta_val){
295
+ $field_name = substr($event_meta_key, 1);
296
+ if($event_meta_key[0] != '_'){
297
+ $this->event_attributes[$event_meta_key] = ( count($event_meta_val) > 1 ) ? $event_meta_val:$event_meta_val[0];
298
+ }elseif( is_string($field_name) && !in_array($field_name, $this->post_fields) ){
299
+ if( array_key_exists($field_name, $this->fields) ){
300
+ $this->$field_name = $event_meta_val[0];
301
+ }elseif( in_array($field_name, array('event_owner_name','event_owner_anonymous','event_owner_email')) ){
302
+ $this->$field_name = $event_meta_val[0];
303
+ }
304
+ }
305
+ }
306
+ //Start/End times should be available as timestamp
307
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp'));
308
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp'));
309
+ if( !empty($this->event_rsvp_date ) ){
310
+ $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
311
+ }
312
+ //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
313
+ if( empty($this->event_id) && !$this->is_recurring() ){
314
+ global $wpdb;
315
+ if( EM_MS_GLOBAL ){
316
+ $event_array = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".EM_EVENTS_TABLE." WHERE post_id=%d && blog_id=%d",$this->post_id, $this->blog_id), ARRAY_A);
317
+ }else{
318
+ $event_array = $wpdb->get_row('SELECT * FROM '.EM_EVENTS_TABLE. ' WHERE post_id='.$this->post_id, ARRAY_A);
319
+ }
320
+ if( !empty($event_array['event_id']) ){
321
+ foreach($event_array as $key => $value){
322
+ if( !empty($value) && empty($this->$key) ){
323
+ update_post_meta($event_post->ID, '_'.$key, $value);
324
+ $this->$key = $value;
325
+ }
326
+ }
327
+ }
328
+ }
329
+ }
330
+ $this->get_status();
331
+ $this->compat_keys();
332
+ }elseif( !empty($this->post_id) ){
333
+ //we have an orphan... show it, so that we can at least remove it on the front-end
334
+ global $wpdb;
335
+ if( EM_MS_GLOBAL ){ //if MS Global mode enabled, make sure we search by blog too so there's no cross-post confusion
336
+ $event_array = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".EM_EVENTS_TABLE." WHERE post_id=%d && blog_id=%d",$this->post_id, $this->blog_id), ARRAY_A);
337
+ }else{
338
+ $event_array = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".EM_EVENTS_TABLE." WHERE post_id=%d",$this->post_id), ARRAY_A);
339
+ }
340
+ if( is_array($event_array) ){
341
+ $this->orphaned_event = true;
342
+ $this->post_id = $this->ID = $event_array['post_id'] = null; //reset post_id because it doesn't really exist
343
+ $this->to_object($event_array);
344
+ }
345
+ //Start/End times should be available as timestamp
346
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time, current_time('timestamp'));
347
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time, current_time('timestamp'));
348
+ }
349
+ }
350
+
351
+ function get_event_meta($blog_id = false){
352
+ if( is_numeric($blog_id) && $blog_id > 0 && is_multisite() ){
353
+ // if in multisite mode, switch blogs quickly to get the right post meta.
354
+ switch_to_blog($blog_id);
355
+ $event_meta = get_post_meta($this->post_id);
356
+ restore_current_blog();
357
+ $this->blog_id = $blog_id;
358
+ }else{
359
+ $event_meta = get_post_meta($this->post_id);
360
+ }
361
+ return $event_meta;
362
  }
363
 
364
  /**
365
+ * Retrieve event information via POST (only used in situations where posts aren't submitted via WP)
366
  * @return boolean
367
  */
368
+ function get_post($validate = true){
369
+ global $allowedposttags;
370
+ //we need to get the post/event name and content.... that's it.
371
+ $this->post_content = isset($_POST['content']) ? wp_kses( stripslashes($_POST['content']), $allowedposttags):'';
372
+ $this->event_name = !empty($_POST['event_name']) ? htmlspecialchars_decode(wp_kses_data(htmlspecialchars_decode(stripslashes($_POST['event_name'])))):'';
373
+ $this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
374
+ //don't forget categories!
375
+ $this->get_categories()->get_post();
376
+ //anonymous submissions and guest basic info
377
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){
378
+ $this->event_owner_anonymous = 1;
379
+ $this->event_owner_name = !empty($_POST['event_owner_name']) ? wp_kses_data(stripslashes($_POST['event_owner_name'])):'';
380
+ $this->event_owner_email = !empty($_POST['event_owner_email']) ? wp_kses_data($_POST['event_owner_email']):'';
381
+ }
382
+ //get the rest and validate (optional)
383
+ $this->get_post_meta(false);
384
+ $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
385
+ return apply_filters('em_event_get_post', $result, $this);
386
+ }
387
+
388
+ /**
389
+ * Retrieve event post meta information via POST, which should be always be called when saving the event custom post via WP.
390
+ * @param boolean $validate whether or not to run validation, default is true
391
+ * @return boolean
392
+ */
393
+ function get_post_meta($validate = true){
394
+ //Grab POST data
395
+ $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? wp_kses_data($_POST['event_start_date']) : '';
396
+ $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? wp_kses_data($_POST['event_end_date']) : $this->event_start_date;
397
+ //check if this is recurring or not
398
+ if( !empty($_POST['recurring']) ){
399
+ $this->recurrence = 1;
400
+ $this->post_type = 'event-recurring';
401
+ }
402
+ //Get Location info
403
+ 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')) ){
404
+ $this->location_id = 0;
405
+ }elseif( !empty($_POST['location_id']) && is_numeric($_POST['location_id']) ){
406
+ $this->location_id = $_POST['location_id'];
407
  }else{
408
+ //we're adding a new location, so create an empty location and populate
409
+ $this->location_id = null;
410
+ $this->get_location()->get_post(false);
411
+ $this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise
412
+ }
413
+ //Sort out time
414
+ $this->event_all_day = ( !empty($_POST['event_all_day']) ) ? 1 : 0;
415
+ if( !$this->event_all_day ){
416
+ $this->event_start_time = $this->event_end_time = '00:00:00';
417
+ }
418
+ foreach( array('event_start_time','event_end_time', 'event_rsvp_time') as $timeName ){
419
+ $match = array();
420
+ if( !empty($_POST[$timeName]) && preg_match ( '/^([01]\d|[0-9]|2[0-3])(:([0-5]\d))? ?(AM|PM)?$/', $_POST[$timeName], $match ) ){
421
+ if( empty($match[3]) ) $match[3] = '00';
422
+ if( strlen($match[1]) == 1 ) $match[1] = '0'.$match[1];
423
+ if( !empty($match[4]) && $match[4] == 'PM' && $match[1] != 12 ){
424
+ $match[1] = 12+$match[1];
425
+ }elseif( !empty($match[4]) && $match[4] == 'AM' && $match[1] == 12 ){
426
+ $match[1] = '00';
427
+ }
428
+ $this->$timeName = $match[1].":".$match[3].":00";
429
+ }else{
430
+ $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
431
+ }
432
  }
433
  //Start/End times should be available as timestamp
434
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
435
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
436
+ //Bookings
437
+ if( !empty($_POST['event_rsvp']) && $_POST['event_rsvp'] ){
438
+ $this->get_bookings()->get_tickets()->get_post();
439
+ $this->event_rsvp = 1;
440
+ //RSVP cuttoff TIME is set up above where start/end times are as well
441
+ if( !$this->is_recurring() ){
442
+ if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
443
+ //single ticket mode will use the ticket end date/time as cut-off date/time
444
+ $EM_Ticket = $this->get_tickets()->get_first();
445
+ $this->event_rsvp_date = '';
446
+ if( !empty($EM_Ticket->end_timestamp) ){
447
+ $this->event_rsvp_date = date('Y-m-d', $EM_Ticket->end_timestamp);
448
+ $this->event_rsvp_time = date('H:i:00', $EM_Ticket->end_timestamp);
449
+ }else{
450
+ //no default ticket end time, so make it default to event start date/time
451
+ $this->event_rsvp_date = $this->event_start_date;
452
+ $this->event_rsvp_time = $this->event_start_time;
453
+ if( $this->event_all_day && empty($_POST['event_rsvp_date']) ){ $this->event_rsvp_time = '00:00:00'; } //all-day events start at 0 hour
454
+ }
455
+ }else{
456
+ //if no rsvp cut-off date supplied, make it the event start date
457
+ $this->event_rsvp_date = ( !empty($_POST['event_rsvp_date']) ) ? wp_kses_data($_POST['event_rsvp_date']) : $this->event_start_date;
458
+ if ( empty($_POST['event_rsvp_date']) ) $this->event_rsvp_time = $this->event_start_time;
459
+ if( $this->event_all_day && empty($_POST['event_rsvp_date']) ){ $this->event_rsvp_time = '00:00:00'; } //all-day events start at 0 hour
460
+ }
461
+ //create timestamp
462
+ if( empty($this->event_rsvp_date) ){
463
+ //falback in case nothing gets set for rsvp cut-off
464
+ $this->event_rsvp_time = '00:00:00';
465
+ $this->rsvp_end = 0; //empty value but timestamp compatible
466
+ }else{
467
+ $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
468
+ }
469
+ }else{
470
+ //recurring events may have a cut-off date x days before or after the recurrence start dates
471
+ $this->recurrence_rsvp_days = null;
472
+ if( get_option('dbem_bookings_tickets_single') && count($this->get_tickets()->tickets) == 1 ){
473
+ //if in single ticket mode then ticket cut-off date determines event cut-off date
474
+ $EM_Ticket = $this->get_tickets()->get_first();
475
+ if( !empty($EM_Ticket->ticket_meta['recurrences']) ){
476
+ $this->recurrence_rsvp_days = $EM_Ticket->ticket_meta['recurrences']['end_days'];
477
+ $this->event_rsvp_time = $EM_Ticket->ticket_meta['recurrences']['end_time'];
478
+ }
479
+ }else{
480
+ if( array_key_exists('recurrence_rsvp_days', $_POST) && is_numeric($_POST['recurrence_rsvp_days']) ){
481
+ if( !empty($_POST['recurrence_rsvp_days_when']) && $_POST['recurrence_rsvp_days_when'] == 'after' ){
482
+ $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']);
483
+ }else{ //by default the start date is the point of reference
484
+ $this->recurrence_rsvp_days = absint($_POST['recurrence_rsvp_days']) * -1;
485
+ }
486
+ }
487
+ }
488
+ //create timestamps and set rsvp date/time for a normal event
489
+ if( !is_numeric($this->recurrence_rsvp_days) ){
490
+ //falback in case nothing gets set for rsvp cut-off
491
+ $this->event_rsvp_date = '';
492
+ $this->event_rsvp_time = '00:00:00';
493
+ $this->rsvp_end = 0; //empty value but timestamp compatible
494
+ }else{
495
+ $this->event_rsvp_date = date('Y-m-d', strtotime($this->recurrence_rsvp_days.' days', $this->start));
496
+ $this->rsvp_end = strtotime($this->event_rsvp_date." ".$this->event_rsvp_time, current_time('timestamp'));
497
+ }
498
+ }
499
+ $this->event_spaces = ( isset($_POST['event_spaces']) ) ? absint($_POST['event_spaces']):0;
500
+ $this->event_rsvp_spaces = ( isset($_POST['event_rsvp_spaces']) ) ? absint($_POST['event_rsvp_spaces']):0;
501
+ }else{
502
+ $this->event_rsvp = 0;
503
+ $this->event_rsvp_time = '00:00:00';
504
  }
505
+ //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
506
+ if(get_option('dbem_attributes_enabled')){
507
+ global $allowedtags;
508
+ if( !is_array($this->event_attributes) ){ $this->event_attributes = array(); }
509
+ $event_available_attributes = em_get_attributes();
510
+ if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
511
+ foreach($_POST['em_attributes'] as $att_key => $att_value ){
512
+ if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->event_attributes) ) ){
513
+ $this->event_attributes[$att_key] = '';
514
+ $att_vals = count($event_available_attributes['values'][$att_key]);
515
+ if( !empty($att_value) ){
516
+ if( $att_vals <= 1 || ($att_vals > 1 && in_array($att_value, $event_available_attributes['values'][$att_key])) ){
517
+ $this->event_attributes[$att_key] = stripslashes($att_value);
518
+ }
519
+ }
520
+ if( empty($att_value) && $att_vals > 1){
521
+ $this->event_attributes[$att_key] = stripslashes(wp_kses($event_available_attributes['values'][$att_key][0], $allowedtags));
522
+ }
523
  }
524
  }
525
  }
526
  }
527
+ //Set Blog ID
528
+ if( is_multisite() ){
529
+ $this->blog_id = get_current_blog_id();
530
+ }
531
+ //group id
532
+ $this->group_id = (!empty($_POST['group_id']) && is_numeric($_POST['group_id'])) ? $_POST['group_id']:0;
533
  //Recurrence data
534
+ if( $this->is_recurring() ){
535
+ $this->recurrence = 1; //just in case
536
+ $this->recurrence_freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly','yearly')) ) ? $_POST['recurrence_freq']:'daily';
537
+ if( !empty($_POST['recurrence_bydays']) && $this->recurrence_freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){
538
+ $this->recurrence_byday = str_replace(' ', '', implode( ",", $_POST['recurrence_bydays'] ));
539
+ }elseif( !empty($_POST['recurrence_byday']) && $this->recurrence_freq == 'monthly' ){
540
+ $this->recurrence_byday = wp_kses_data($_POST['recurrence_byday']);
 
541
  }
542
+ $this->recurrence_interval = ( !empty($_POST['recurrence_interval']) && is_numeric($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1;
543
+ $this->recurrence_byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? wp_kses_data($_POST['recurrence_byweekno']):'';
544
+ $this->recurrence_days = ( !empty($_POST['recurrence_days']) && is_numeric($_POST['recurrence_days']) ) ? (int) $_POST['recurrence_days']:0;
545
  }
546
+ //categories in MS GLobal
547
+ if(EM_MS_GLOBAL && !is_main_site()){
548
+ $this->get_categories()->get_post(); //it'll know what to do
549
+ }
550
+ //validate (optional) and return result
551
+ $this->compat_keys(); //compatability
552
+ return apply_filters('em_event_get_post', count($this->errors) == 0, $this);
553
+ }
554
+
555
+ function validate(){
556
+ $validate_post = true;
557
+ if( empty($this->event_name) ){
558
+ $validate_post = false;
559
+ $this->add_error( sprintf(__("%s is required.", "dbem"), __('Event name','dbem')) );
560
+ }
561
+ //anonymous submissions and guest basic info
562
+ if( !empty($this->event_owner_anonymous) ){
563
+ if( !is_email($this->event_owner_email) ){
564
+ $this->add_error( sprintf(__("%s is required.", "dbem"), __('A valid email','dbem')) );
565
+ }
566
+ if( empty($this->event_owner_name) ){
567
+ $this->add_error( sprintf(__("%s is required.", "dbem"), __('Your name','dbem')) );
568
+ }
569
+ }
570
+ $validate_tickets = $this->get_bookings()->get_tickets()->validate();
571
+ $validate_image = $this->image_validate();
572
+ $validate_meta = $this->validate_meta();
573
+ return apply_filters('em_event_validate', $validate_post && $validate_image && $validate_meta && $validate_tickets, $this );
574
+ }
575
+
576
+ function validate_meta(){
577
+ $missing_fields = Array ();
578
+ foreach ( array('event_start_date') as $field ) {
579
+ if ( $this->$field == "") {
580
+ $missing_fields[$field] = $field;
581
+ }
582
+ }
583
+ if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_end_date) ){
584
+ if( strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_end_date . $this->event_end_time) ){
585
+ $this->add_error(__('Events cannot start after they end.','dbem'));
586
+ }elseif( $this->is_recurring() && $this->recurrence_days == 0 && strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_start_date . $this->event_end_time) ){
587
+ $this->add_error(__('Events cannot start after they end.','dbem').' '.__('For recurring events that end the following day, ensure you make your event last 1 or more days.'));
588
+ }
589
+ }else{
590
+ if( !empty($missing_fields['event_start_date']) ) { unset($missing_fields['event_start_date']); }
591
+ if( !empty($missing_fields['event_end_date']) ) { unset($missing_fields['event_end_date']); }
592
+ $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem'));
593
+ }
594
+ if( $this->event_rsvp ){
595
+ if( !$this->get_bookings()->get_tickets()->validate() ){
596
+ $this->add_error($this->get_bookings()->get_tickets()->get_errors());
597
+ }
598
+ if( !empty($this->event_rsvp_date) && !preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_rsvp_date) ){
599
+ $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem'));
600
+ }
601
+ }
602
+ if( get_option('dbem_locations_enabled') && empty($this->location_id) ){ //location ids don't need validating as we're not saving a location
603
+ if( get_option('dbem_require_location',true) || $this->location_id !== 0 ){
604
+ if( !$this->get_location()->validate() ){
605
+ $this->add_error($this->get_location()->get_errors());
606
+ }
607
+ }
608
+ }
609
+ if ( count($missing_fields) > 0){
610
+ // TODO Create friendly equivelant names for missing fields notice in validation
611
+ $this->add_error( __( 'Missing fields: ', 'dbem') . implode ( ", ", $missing_fields ) . ". " );
612
+ }
613
+ if ( $this->is_recurring() ){
614
+ if( $this->event_end_date == "" || $this->event_end_date == $this->event_start_date){
615
+ $this->add_error( __( 'Since the event is repeated, you must specify an event end date greater than the start date.', 'dbem' ));
616
+ }
617
+ if( $this->recurrence_freq == 'weekly' && !preg_match('/^[0-9](,[0-9])*$/',$this->recurrence_byday) ){
618
+ $this->add_error( __( 'Please speficy what days of the week this event should occur on.', 'dbem' ));
619
+ }
620
+ }
621
+ return apply_filters('em_event_validate_meta', count($this->errors) == 0, $this );
622
  }
623
 
624
  /**
625
  * Will save the current instance into the database, along with location information if a new one was created and return true if successful, false if not.
626
+ * Will automatically detect whether it's a new or existing event.
627
  * @return boolean
628
  */
629
  function save(){
630
+ global $wpdb, $current_user, $blog_id, $EM_SAVING_EVENT;
631
+ $EM_SAVING_EVENT = true;
632
+ if( !$this->can_manage('edit_events', 'edit_others_events') && !( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) ){
633
+ //unless events can be submitted by an anonymous user (and this is a new event), user must have permissions.
634
  return apply_filters('em_event_save', false, $this);
635
  }
636
+ remove_action('save_post',array('EM_Event_Post_Admin','save_post'),10,1); //disable the default save post action, we'll do it manually this way
637
  do_action('em_event_save_pre', $this);
638
+ $post_array = array();
639
+ //Deal with updates to an event
640
+ if( !empty($this->post_id) ){
641
+ //get the full array of post data so we don't overwrite anything.
642
+ if( !empty($this->blog_id) && is_multisite() ){
643
+ $post_array = (array) get_blog_post($this->blog_id, $this->post_id);
644
+ }else{
645
+ $post_array = (array) get_post($this->post_id);
646
+ }
 
 
 
 
 
 
647
  }
648
+ //Overwrite new post info
649
+ $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT;
650
+ $post_array['post_title'] = $this->event_name;
651
+ $post_array['post_content'] = $this->post_content;
652
+ $post_array['post_excerpt'] = $this->post_excerpt;
653
+ //decide on post status
654
+ if( empty($this->force_status) ){
655
+ if( count($this->errors) == 0 ){
656
+ $post_array['post_status'] = ( $this->can_manage('publish_events','publish_events') ) ? 'publish':'pending';
657
+ }else{
658
+ $post_array['post_status'] = 'draft';
659
+ }
660
  }else{
661
+ $post_array['post_status'] = $this->force_status;
 
662
  }
663
+ //anonymous submission only
664
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){
665
+ $post_array['post_author'] = get_option('dbem_events_anonymous_user');
666
+ if( !is_numeric($post_array['post_author']) ) $post_array['post_author'] = 0;
667
+ }
668
+ //Save post and continue with meta
669
+ $post_id = wp_insert_post($post_array);
670
+ $post_save = false;
671
+ $meta_save = false;
672
+ if( !is_wp_error($post_id) && !empty($post_id) ){
673
+ $post_save = true;
674
+ //refresh this event with wp post info we'll put into the db
675
+ $post_data = get_post($post_id);
676
+ $this->post_id = $post_id;
677
+ $this->event_slug = $post_data->post_name;
678
+ $this->event_owner = $post_data->post_author;
679
+ $this->post_status = $post_data->post_status;
680
+ $this->get_status();
681
+ //Categories? note that categories will soft-fail, so no errors
682
+ $this->get_categories()->event_id = $this->event_id;
683
+ $this->categories->post_id = $this->post_id;
684
+ $this->categories->save();
685
+ //anonymous submissions should save this information
686
+ if( !empty($this->event_owner_anonymous) ){
687
+ update_post_meta($this->post_id, '_event_owner_anonymous', 1);
688
+ update_post_meta($this->post_id, '_event_owner_name', $this->event_owner_name);
689
+ update_post_meta($this->post_id, '_event_owner_email', $this->event_owner_email);
690
  }
691
+ //save the image
692
+ $this->image_upload();
693
+ //now save the meta
694
+ $meta_save = $this->save_meta();
695
+ $image_save = (count($this->errors) == 0); //whilst it might not be an image save that fails, we can know something went wrong
696
+ }
697
+ $result = $meta_save && $post_save && $image_save;
698
+ if($result) $this->load_postdata($post_data, $blog_id); //reload post info
699
+ //do a dirty update for location too if it's not published
700
+ if( $this->is_published() && !empty($this->location_id) ){
701
+ $EM_Location = $this->get_location();
702
+ if( $EM_Location->location_status !== 1 ){
703
+ //let's also publish the location
704
+ $EM_Location->set_status(1, true);
705
+ }
706
+ }
707
+ $return = apply_filters('em_event_save', $result, $this);
708
+ $EM_SAVING_EVENT = false;
709
+ return $return;
710
+ }
711
+
712
+ function save_meta(){
713
+ global $wpdb;
714
+ if( ( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) || $this->can_manage('edit_events', 'edit_others_events') ){
715
+ do_action('em_event_save_meta_pre', $this);
716
+ //first save location
717
+ if( empty($this->location_id) && !($this->location_id === 0 && !get_option('dbem_require_location',true)) ){
718
+ if( !$this->get_location()->save() ){ //soft fail
719
+ global $EM_Notices;
720
+ if( !empty($this->get_location()->location_id) ){
721
+ $EM_Notices->add_error( __('There were some errors saving your location.','dbem').' '.sprintf(__('It will not be displayed on the website listings, to correct this you must <a href="%s">edit your location</a> directly.'),$this->get_location()->output('#_LOCATIONEDITURL')), true);
722
+ }
723
  }
724
+ if( !empty($this->location->location_id) ){ //only case we don't use get_location(), since it will fail as location has an id, whereas location_id isn't set in this object
725
+ $this->location_id = $this->location->location_id;
 
 
726
  }
727
+ }
728
+ //Update Post Meta
729
+ foreach($this->fields as $key => $field_info){
730
+ if( !in_array($key, $this->post_fields) && $key != 'event_attributes' ){
731
+ update_post_meta($this->post_id, '_'.$key, $this->$key);
732
+ }elseif($key == 'event_attributes'){
733
+ //attributes get saved as individual keys
734
+ foreach($this->event_attributes as $event_attribute_key => $event_attribute){
735
+ if( !empty($event_attribute) ){
736
+ update_post_meta($this->post_id, $event_attribute_key, $event_attribute);
737
+ }else{
738
+ delete_post_meta($this->post_id, $event_attribute_key);
739
+ }
740
+ }
741
+ }
742
+ }
743
+ //update timestampes
744
+ update_post_meta($this->post_id, '_start_ts', str_pad($this->start, 10, 0, STR_PAD_LEFT));
745
+ update_post_meta($this->post_id, '_end_ts', str_pad($this->end, 10, 0, STR_PAD_LEFT));
746
+ //sort out event status
747
+ $result = count($this->errors) == 0;
748
+ $this->get_status();
749
+ $this->event_status = ($result) ? $this->event_status:null; //set status at this point, it's either the current status, or if validation fails, null
750
+ //Save to em_event table
751
+ $event_array = $this->to_array(true);
752
+ unset($event_array['event_id']);
753
+ //decide whether or not event is private at this point
754
+ $event_array['event_private'] = ( $this->post_status == 'private' ) ? 1:0;
755
+ //save event_attributes just in case
756
+ $event_array['event_attributes'] = serialize($this->event_attributes);
757
+ //check if event truly exists, meaning the event_id is actually a valid event id
758
+ if( !empty($this->event_id) ){
759
+ $blog_condition = '';
760
+ if( !empty($this->orphaned_event ) && !empty($this->post_id) ){
761
+ //we're dealing with an orphaned event in wp_em_events table, so we want to update the post_id and give it a post parent
762
+ $event_truly_exists = true;
763
+ }else{
764
+ if( EM_MS_GLOBAL ){
765
+ if( is_main_site() ){
766
+ $blog_condition = " AND (blog_id='".get_current_blog_id()."' OR blog_id IS NULL)";
767
+ }else{
768
+ $blog_condition = " AND blog_id='".get_current_blog_id()."' ";
769
+ }
770
+ }
771
+ $event_truly_exists = $wpdb->get_var('SELECT post_id FROM '.EM_EVENTS_TABLE." WHERE event_id={$this->event_id}".$blog_condition) == $this->post_id;
772
  }
 
 
 
773
  }else{
774
+ $event_truly_exists = false;
775
  }
776
+ //save all the meta
777
+ if( empty($this->event_id) || !$event_truly_exists ){
778
+ $this->previous_status = 0; //for sure this was previously status 0
779
+ $this->event_date_created = $event_array['event_date_created'] = current_time('mysql');
780
+ if ( !$wpdb->insert(EM_EVENTS_TABLE, $event_array) ){
781
+ $this->add_error( sprintf(__('Something went wrong saving your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem')));
782
+ }else{
783
+ //success, so link the event with the post via an event id meta value for easy retrieval
784
+ $this->event_id = $wpdb->insert_id;
785
+ update_post_meta($this->post_id, '_event_id', $this->event_id);
786
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem'));
787
+ $just_added_event = true; //make an easy hook
788
+ do_action('em_event_save_new', $this);
 
 
 
 
789
  }
790
+ }else{
791
+ $event_array['post_content'] = $this->post_content; //in case the content was removed, which is acceptable
792
+ $this->get_previous_status();
793
+ $this->event_date_modified = $event_array['event_date_modified'] = current_time('mysql');
794
+ if ( $wpdb->update(EM_EVENTS_TABLE, $event_array, array('event_id'=>$this->event_id) ) === false ){
795
+ $this->add_error( sprintf(__('Something went wrong updating your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem')));
796
+ }else{
797
+ //Also set the status here if status != previous status
798
+ if( $this->previous_status != $this->get_status() ) $this->set_status($this->get_status());
799
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem'));
800
+ }
801
+ }
802
+ //Add/Delete Tickets
803
+ if($this->event_rsvp == 0){
804
+ $this->get_bookings()->delete();
805
+ }else{
806
+ if( !$this->get_bookings()->get_tickets()->save() ){
807
+ $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
808
  }
809
+ }
810
+ $result = count($this->errors) == 0;
811
+ //If we're saving event categories in MS Global mode, we'll add them here, saving by term id (cat ids are gone now)
812
+ if( EM_MS_GLOBAL && !is_main_site() ){
813
+ $this->get_categories()->save(); //it'll know what to do
814
+ }elseif( EM_MS_GLOBAL ){
815
+ $this->get_categories()->save_index(); //just save to index, we assume cats are saved in $this->save();
816
+ }
817
+ //build recurrences if needed
818
+ if( $this->is_recurring() && $result && $this->is_published() ){ //only save events if recurring event validates and is published
819
+ global $EM_EVENT_SAVE_POST;
820
+ //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
821
+ if( empty($EM_EVENT_SAVE_POST) ){
822
+ if( !$this->save_events() ){
823
+ $this->add_error(__ ( 'Something went wrong with the recurrence update...', 'dbem' ). __ ( 'There was a problem saving the recurring events.', 'dbem' ));
824
+ }
825
  }
 
 
 
826
  }
827
+ if( !empty($just_added_event) ){
828
+ do_action('em_event_added', $this);
 
 
829
  }
 
830
  }
831
+ $this->compat_keys();
832
+ return apply_filters('em_event_save_meta', count($this->errors) == 0, $this);
833
  }
834
 
835
  /**
836
+ * Duplicates this event and returns the duplicated event. Will return false if there is a problem with duplication.
837
+ * @return EM_Event
838
  */
839
+ function duplicate(){
840
+ global $wpdb, $EZSQL_ERROR;
841
+ //First, duplicate.
842
+ if( $this->can_manage('edit_events','edit_others_events') ){
843
+ $EM_Event = clone $this;
844
+ $EM_Event->get_categories(); //before we remove event/post ids
845
+ $EM_Event->get_bookings()->get_tickets(); //in case this wasn't loaded and before we reset ids
846
+ $EM_Event->event_id = null;
847
+ $EM_Event->post_id = null;
848
+ $EM_Event->ID = null;
849
+ $EM_Event->post_name = '';
850
+ $EM_Event->location_id = (empty($EM_Event->location_id) && !get_option('dbem_require_location')) ? 0:$EM_Event->location_id;
851
+ $EM_Event->get_bookings()->event_id = null;
852
+ $EM_Event->get_bookings()->get_tickets()->event_id = null;
853
+ //if bookings reset ticket ids and duplicate tickets
854
+ foreach($EM_Event->get_bookings()->get_tickets()->tickets as $EM_Ticket){
855
+ $EM_Ticket->ticket_id = null;
856
+ $EM_Ticket->event_id = null;
857
+ }
858
+ do_action('em_event_duplicate_pre', $EM_Event);
859
+ $EM_Event->duplicated = true;
860
+ $EM_Event->force_status = 'draft';
861
+ if( $EM_Event->save() ){
862
+ $EM_Event->feedback_message = sprintf(__("%s successfully duplicated.", 'dbem'), __('Event','dbem'));
863
+ //save tags here - eventually will be moved into part of $this->save();
864
+ if( get_option('dbem_tags_enabled') ){
865
+ $EM_Tags = new EM_Tags($this);
866
+ $EM_Tags->event_id = $EM_Event->event_id;
867
+ $EM_Tags->post_id = $EM_Event->post_id;
868
+ $EM_Tags->save();
869
+ }
870
+ //other non-EM post meta inc. featured image
871
+ $event_meta = $this->get_event_meta($this->blog_id);
872
+ $new_event_meta = $EM_Event->get_event_meta($EM_Event->blog_id);
873
+ $event_meta_inserts = array();
874
+ //Get custom fields and post meta - adapted from $this->load_post_meta()
875
+ foreach($event_meta as $event_meta_key => $event_meta_vals){
876
+ if($event_meta_key[0] == '_' && is_array($event_meta_vals)){
877
+ $field_name = substr($event_meta_key, 1);
878
+ if($field_name != 'event_attributes' && !array_key_exists($event_meta_key, $new_event_meta) && !in_array($field_name, array('edit_last', 'edit_lock', 'event_owner_name','event_owner_anonymous','event_owner_email')) ){
879
+ foreach($event_meta_vals as $event_meta_val){
880
+ $event_meta_inserts[] = "({$EM_Event->post_id}, '{$event_meta_key}', '{$event_meta_val}')";
881
+ }
882
+ }
883
+ }
884
+ }
885
+ //save in one SQL statement
886
+ if( !empty($event_meta_inserts) ){
887
+ $wpdb->query('INSERT INTO '.$wpdb->postmeta." (post_id, meta_key, meta_value) VALUES ".implode(', ', $event_meta_inserts));
888
+ }
889
+ if( array_key_exists('_event_approvals_count', $event_meta) ) update_post_meta($EM_Event->post_id, '_event_approvals_count', 0);
890
+ //copy anything from the em_meta table too
891
+ $wpdb->query('INSERT INTO '.EM_META_TABLE." (object_id, meta_key, meta_value) SELECT '{$EM_Event->event_id}', meta_key, meta_value FROM ".EM_META_TABLE." WHERE object_id='{$this->event_id}'");
892
+ //set event to draft status
893
+ return apply_filters('em_event_duplicate', $EM_Event, $this);
894
  }
895
  }
896
+ //TODO add error notifications for duplication failures.
897
+ return apply_filters('em_event_duplicate', false, $this);;
898
  }
899
 
900
  /**
901
+ * Delete whole event, including bookings, tickets, etc.
 
902
  * @return boolean
903
  */
904
+ function delete($force_delete = false){ //atm wp seems to force cp deletions anyway
905
+ if( $this->can_manage('delete_events', 'delete_others_events') ){
906
+ if( !is_admin() ){
907
+ include_once('em-event-post-admin.php');
908
+ if( !defined('EM_EVENT_DELETE_INCLUDE') ){
909
+ EM_Event_Post_Admin::init();
910
+ EM_Event_Recurring_Post_Admin::init();
911
+ define('EM_EVENT_DELETE_INCLUDE',true);
912
+ }
913
+ }
914
+ do_action('em_event_delete_pre', $this);
915
+ if( $force_delete ){
916
+ $result = wp_delete_post($this->post_id,$force_delete);
917
+ }else{
918
+ $result = wp_trash_post($this->post_id);
919
+ if( !$result && $this->post_status == 'trash' ){
920
+ //we're probably dealing with a trashed post already, but the event_status is null from < v5.4.1
921
+ $this->set_status(-1);
922
+ $result = true;
923
+ }
924
+ }
925
+ if( !$result && !empty($this->orphaned_event) ){
926
+ //this is an orphaned event, so the wp delete posts would have never worked, so we just delete the row in our events table
927
+ $this->delete_meta();
928
+ }
929
+ }else{
930
+ $result = false;
931
+ }
932
+ return apply_filters('em_event_delete', $result != false, $this);
933
+ }
934
+
935
+ function delete_meta(){
936
  global $wpdb;
 
937
  $result = false;
938
+ if( $this->can_manage('delete_events', 'delete_others_events') ){
939
+ do_action('em_event_delete_meta_event_pre', $this);
940
+ $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->event_id) );
941
+ if( $result !== false ){
942
+ $this->delete_bookings();
943
+ $this->delete_tickets();
944
  //Delete the recurrences then this recurrence event
945
+ if( $this->is_recurring() ){
946
+ $result = $this->delete_events(); //was true at this point, so false if fails
947
+ }
948
+ //Delete categories from meta if in MS global mode
949
+ if( EM_MS_GLOBAL ){
950
+ $wpdb->query('DELETE FROM '.EM_META_TABLE.' WHERE object_id='.$this->event_id." AND meta_key='event-category'");
951
+ }
952
  }
953
  }
954
+ return apply_filters('em_event_delete_meta', $result !== false, $this);
955
  }
956
 
957
  /**
958
+ * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
 
959
  */
960
+ function delete_bookings(){
961
+ global $wpdb;
962
+ do_action('em_event_delete_bookings_pre', $this);
963
+ $result = false;
964
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
965
+ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE booking_id IN (SELECT booking_id FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d)", $this->event_id) );
966
+ $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d", $this->event_id) );
967
+ }
968
+ return apply_filters('em_event_delete_bookings', $result !== false && $result_bt !== false, $this);
969
  }
970
 
971
  /**
972
+ * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
 
 
973
  */
974
+ function delete_tickets(){
975
+ global $wpdb;
976
+ do_action('em_event_delete_tickets_pre', $this);
977
+ $result = false;
978
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
979
+ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_id IN (SELECT ticket_id FROM ".EM_TICKETS_TABLE." WHERE event_id=%d)", $this->event_id) );
980
+ $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_TABLE." WHERE event_id=%d", $this->event_id) );
 
 
 
 
 
981
  }
982
+ return apply_filters('em_event_delete_tickets', $result, $this);
983
  }
984
 
985
  /**
986
+ * Change the status of the event. This will save to the Database too.
987
+ * @param int $status
988
+ * @param boolean $set_post_status
989
+ * @return string
990
  */
991
+ function set_status($status, $set_post_status = false){
992
+ global $wpdb;
993
+ if($status === null){
994
+ $set_status='NULL';
995
+ if($set_post_status){
996
+ //if the post is trash, don't untrash it!
997
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
 
 
 
 
998
  }
999
+ $this->post_status = 'draft'; //set post status in this instance
1000
+ }elseif( $status == -1 ){ //trashed post
1001
+ $set_status = -1;
1002
+ if($set_post_status){
1003
+ $wpdb->update( $wpdb->posts, array( 'post_status' => $this->post_status ), array( 'ID' => $this->post_id ) );
1004
+ }
1005
+ $this->post_status = 'trash'; //set post status in this instance
1006
  }else{
1007
+ $set_status = $status ? 1:0;
1008
+ $post_status = $set_status ? 'publish':'pending';
1009
+ if($set_post_status){
1010
+ if($this->post_status == 'pending' && empty($this->post_name)){
1011
+ $this->post_name = sanitize_title($this->post_title);
1012
+ }
1013
+ $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
1014
+ }
1015
+ $this->post_status = $post_status;
1016
  }
1017
+ $this->get_previous_status();
1018
+ $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)) );
1019
+ $this->get_status(); //reload status
1020
+ return apply_filters('em_event_set_status', $result !== false, $status, $this);
1021
  }
1022
 
1023
+ function is_published(){
1024
+ return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
1025
+ }
1026
 
1027
+ function get_status($db = false){
1028
+ switch( $this->post_status ){
1029
+ case 'private':
1030
+ $this->event_private = 1;
1031
+ $this->event_status = $status = 1;
1032
+ break;
1033
+ case 'publish':
1034
+ $this->event_private = 0;
1035
+ $this->event_status = $status = 1;
1036
+ break;
1037
+ case 'pending':
1038
+ $this->event_private = 0;
1039
+ $this->event_status = $status = 0;
1040
+ break;
1041
+ case 'trash':
1042
+ $this->event_private = 0;
1043
+ $this->event_status = $status = -1;
1044
+ break;
1045
+ default: //draft or unknown
1046
+ $this->event_private = 0;
1047
+ $status = $db ? 'NULL':null;
1048
+ $this->event_status = null;
1049
+ break;
1050
  }
1051
+ return $status;
1052
+ }
1053
+
1054
+ function get_previous_status( $force = false ){
1055
+ global $wpdb;
1056
+ if( $this->event_id > 0 && ($this->previous_status === false || $force) ){
1057
+ $this->previous_status = $wpdb->get_var('SELECT event_status FROM '.EM_EVENTS_TABLE.' WHERE event_id='.$this->event_id); //get status from db, not post_status, as posts get saved quickly
 
 
1058
  }
1059
+ return $this->previous_status;
 
 
 
 
1060
  }
1061
 
1062
  /**
1064
  * @return EM_Categories
1065
  */
1066
  function get_categories() {
1067
+ if( empty($this->categories) ){
 
 
 
 
 
1068
  $this->categories = new EM_Categories($this);
1069
+ }elseif(empty($this->categories->event_id)){
1070
+ $this->categories->event_id = $this->event_id;
1071
+ $this->categories->post_id = $this->post_id;
1072
  }
 
1073
  return apply_filters('em_event_get_categories', $this->categories, $this);
1074
  }
1075
 
1078
  * @return EM_Location
1079
  */
1080
  function get_location() {
1081
+ global $EM_Location;
1082
+ if( is_object($EM_Location) && $EM_Location->location_id == $this->location_id ){
1083
+ $this->location = $EM_Location;
 
 
1084
  }else{
1085
+ if( !is_object($this->location) || $this->location->location_id != $this->location_id ){
1086
+ $this->location = em_get_location($this->location_id);
1087
+ }
1088
  }
1089
+ return $this->location;
1090
  }
1091
 
1092
  /**
1093
+ * Returns the location object this event belongs to.
1094
+ * @return EM_Person
1095
+ */
1096
+ function get_contact(){
1097
+ if( !is_object($this->contact) ){
1098
+ $this->contact = new EM_Person($this->event_owner);
1099
+ //if this is anonymous submission, change contact email and name
1100
+ if( $this->event_owner_anonymous ){
1101
+ $this->contact->user_email = $this->event_owner_email;
1102
+ $name = explode(' ',$this->event_owner_name);
1103
+ $first_name = array_shift($name);
1104
+ $last_name = (count($name) > 0) ? implode(' ',$name):'';
1105
+ $this->contact->user_firstname = $this->contact->first_name = $first_name;
1106
+ $this->contact->user_lastname = $this->contact->last_name = $last_name;
1107
+ }
1108
  }
1109
+ return $this->contact;
1110
  }
1111
 
1112
  /**
1119
  if( (!$this->bookings || $force_reload) ){
1120
  $this->bookings = new EM_Bookings($this);
1121
  }
1122
+ $this->bookings->event_id = $this->event_id; //always refresh event_id
1123
  }else{
1124
  return new EM_Bookings();
1125
  }
1126
+ //TODO for some reason this returned instance doesn't modify the original, e.g. try $this->get_bookings()->add($EM_Booking) and see how $this->bookings->feedback_message doesn't change
1127
  return apply_filters('em_event_get_bookings', $this->bookings, $this);
1128
  }
1129
 
1130
+ /**
1131
+ * Get the tickets related to this event.
1132
+ * @param boolean $force_reload
1133
+ * @return EM_Tickets
1134
+ */
1135
+ function get_tickets( $force_reload = false ){
1136
+ return $this->get_bookings($force_reload)->get_tickets();
1137
+ }
1138
+
1139
+ /*
1140
+ * Provides the tax rate for this event.
1141
+ * Currently a site-wide default, but this hook allows easy overriding of tax rates for specific events.
1142
+ * @uses apply_filters() on 'em_event_get_tax_rate' before returning value
1143
+ * @uses EM_Object::get_tax_rate()
1144
+ */
1145
+ function get_tax_rate(){
1146
+ return apply_filters('em_event_get_tax_rate', parent::get_tax_rate(), $this);
1147
  }
1148
 
1149
  /**
1155
  return $this->get_bookings()->get_spaces($force_refresh);
1156
  }
1157
 
1158
+ /*
1159
+ * Extends the default EM_Object function by switching blogs as needed if in MS Global mode
1160
+ * @param string $size
1161
+ * @return string
1162
+ * @see EM_Object::get_image_url()
1163
+ */
1164
+ function get_image_url($size = 'full'){
1165
+ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){
1166
+ switch_to_blog($this->blog_id);
1167
+ $switch_back = true;
1168
+ }
1169
+ $return = parent::get_image_url($size);
1170
+ if( !empty($switch_back) ){ restore_current_blog(); }
1171
+ return $return;
1172
+ }
1173
+
1174
+ function get_edit_reschedule_url(){
1175
+ if( $this->is_recurrence() ){
1176
+ $EM_Event = em_get_event($this->recurrence_id);
1177
+ return $EM_Event->get_edit_url();
1178
+ }
1179
+ }
1180
+
1181
+ function get_edit_url(){
1182
+ if( $this->can_manage('edit_events','edit_others_events') ){
1183
+ if( EM_MS_GLOBAL && get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
1184
+ if( get_blog_option($this->blog_id, 'dbem_edit_events_page') ){
1185
+ $link = em_add_get_params(get_permalink(get_blog_option($this->blog_id, 'dbem_edit_events_page')), array('action'=>'edit','event_id'=>$this->event_id), false);
1186
+ }
1187
+ if( empty($link))
1188
+ $link = get_admin_url($this->blog_id, "post.php?post={$this->post_id}&action=edit");
1189
+ }else{
1190
+ if( get_option('dbem_edit_events_page') && !is_admin() ){
1191
+ $link = em_add_get_params(get_permalink(get_option('dbem_edit_events_page')), array('action'=>'edit','event_id'=>$this->event_id), false);
1192
+ }
1193
+ if( empty($link))
1194
+ $link = admin_url()."post.php?post={$this->post_id}&action=edit";
1195
+ }
1196
+ return apply_filters('em_event_get_edit_url', $link, $this);
1197
+ }
1198
+ }
1199
+
1200
+ function get_bookings_url(){
1201
+ if( get_option('dbem_edit_bookings_page') && (!is_admin() || !empty($_REQUEST['is_public'])) ){
1202
+ $my_bookings_page = get_permalink(get_option('dbem_edit_bookings_page'));
1203
+ $bookings_link = em_add_get_params($my_bookings_page, array('event_id'=>$this->event_id), false);
1204
+ }else{
1205
+ if( is_multisite() && $this->blog_id != get_current_blog_id() ){
1206
+ $bookings_link = get_admin_url($this->blog_id, 'edit.php?post_type='.EM_POST_TYPE_EVENT."&page=events-manager-bookings&event_id=".$this->event_id);
1207
+ }else{
1208
+ $bookings_link = EM_ADMIN_URL. "&page=events-manager-bookings&event_id=".$this->event_id;
1209
+ }
1210
+ }
1211
+ return apply_filters('em_event_get_bookings_url', $bookings_link, $this);
1212
+ }
1213
+
1214
+ function get_permalink(){
1215
+ if( EM_MS_GLOBAL ){
1216
+ //if no blog id defined, assume it's the main blog
1217
+ $blog_id = empty($this->blog_id) ? get_current_site()->blog_id:$this->blog_id;
1218
+ //if we're not on the same blog as this event then decide whether to link to main blog or to source blog
1219
+ if( $blog_id != get_current_blog_id() ){
1220
+ if( !get_site_option('dbem_ms_global_events_links') && is_main_site() && get_option('dbem_events_page') ){
1221
+ //if on main site, and events page exists and direct links are disabled then show link to main site
1222
+ $event_link = trailingslashit(get_permalink(get_option('dbem_events_page')).get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/'.$this->event_slug.'-'.$this->event_id);
1223
+ }else{
1224
+ //linking directly to the source blog by default
1225
+ $event_link = get_blog_permalink( $blog_id, $this->post_id);
1226
+ }
1227
+ }
1228
+ }
1229
+ if( empty($event_link) ){
1230
+ $event_link = get_post_permalink($this->post_id);
1231
+ }
1232
+ return apply_filters('em_event_get_permalink', $event_link, $this);
1233
+ }
1234
+
1235
+ function get_ical_url(){
1236
+ global $wp_rewrite;
1237
+ if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){
1238
+ $return = trailingslashit($this->get_permalink()).'ical/';
1239
+ }else{
1240
+ $return = em_add_get_params($this->get_permalink(), array('ical'=>1));
1241
+ }
1242
+ return apply_filters('em_event_get_ical_url', $return);
1243
+ }
1244
+
1245
+ function is_free( $now = false ){
1246
+ $free = true;
1247
+ foreach($this->get_tickets() as $EM_Ticket){
1248
+ /* @var $EM_Ticket EM_Ticket */
1249
+ if( $EM_Ticket->get_price() > 0 ){
1250
+ if( !$now || $EM_Ticket->is_available() ){
1251
+ $free = false;
1252
+ }
1253
+ }
1254
+ }
1255
+ return apply_filters('em_event_is_free',$free,$this);
1256
+ }
1257
+
1258
  /**
1259
  * Will output a single event format of this event.
1260
  * Equivalent of calling EM_Event::output( get_option ( 'dbem_single_event_format' ) )
1272
  * @param string $target
1273
  * @return string
1274
  */
1275
+ function output($format, $target="html") {
1276
+ $event_string = $format;
1277
+ //Time place holder that doesn't show if empty.
1278
+ //TODO add filter here too
1279
+ preg_match_all('/#@?_\{[^}]+\}/', $format, $results);
1280
+ foreach($results[0] as $result) {
1281
+ if(substr($result, 0, 3 ) == "#@_"){
1282
+ $date = 'end_date';
1283
+ $offset = 4;
1284
+ }else{
1285
+ $date = 'start_date';
1286
+ $offset = 3;
1287
+ }
1288
+ if( $date == 'end_date' && $this->event_end_date == $this->event_start_date ){
1289
+ $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
1290
+ }else{
1291
+ $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) );
1292
+ }
1293
+ $event_string = str_replace($result,$replace,$event_string );
1294
+ }
1295
+ //This is for the custom attributes
1296
+ preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+)\})?/', $event_string, $results);
1297
+ $attributes = em_get_attributes();
1298
+ foreach($results[0] as $resultKey => $result) {
1299
+ //Strip string of placeholder and just leave the reference
1300
+ $attRef = substr( substr($result, 0, strpos($result, '}')), 6 );
1301
+ $attString = '';
1302
+ if( is_array($this->event_attributes) && array_key_exists($attRef, $this->event_attributes) ){
1303
+ $attString = $this->event_attributes[$attRef];
1304
+ }elseif( !empty($results[3][$resultKey]) ){
1305
+ //Check to see if we have a second set of braces;
1306
+ $attString = $results[3][$resultKey];
1307
+ }elseif( !empty($attributes['values'][$attRef][0]) ){
1308
+ $attString = $attributes['values'][$attRef][0];
1309
+ }
1310
+ $attString = apply_filters('em_event_output_placeholder', $attString, $this, $result, $target);
1311
+ $event_string = str_replace($result, $attString ,$event_string );
1312
+ }
1313
  //First let's do some conditional placeholder removals
1314
+ for ($i = 0 ; $i < EM_CONDITIONAL_RECURSIONS; $i++){ //you can add nested recursions by modifying this setting in your wp_options table
1315
+ preg_match_all('/\{([a-zA-Z0-9_\-]+)\}(.+?)\{\/\1\}/s', $event_string, $conditionals);
1316
+ if( count($conditionals[0]) > 0 ){
1317
+ //Check if the language we want exists, if not we take the first language there
1318
+ foreach($conditionals[1] as $key => $condition){
1319
+ $show_condition = false;
1320
+ if ($condition == 'has_bookings') {
1321
+ //check if there's a booking, if not, remove this section of code.
1322
+ $show_condition = ($this->event_rsvp && get_option('dbem_rsvp_enabled'));
1323
+ }elseif ($condition == 'no_bookings') {
1324
+ //check if there's a booking, if not, remove this section of code.
1325
+ $show_condition = (!$this->event_rsvp && get_option('dbem_rsvp_enabled'));
1326
+ }elseif ($condition == 'no_location'){
1327
+ //does this event have a valid location?
1328
+ $show_condition = ( empty($this->location_id) || !$this->get_location()->location_status );
1329
+ }elseif ($condition == 'has_location'){
1330
+ //does this event have a valid location?
1331
+ $show_condition = ( !empty($this->location_id) && $this->get_location()->location_status );
1332
+ }elseif ($condition == 'has_image'){
1333
+ //does this event have an image?
1334
+ $show_condition = ( $this->get_image_url() != '' );
1335
+ }elseif ($condition == 'no_image'){
1336
+ //does this event have an image?
1337
+ $show_condition = ( $this->get_image_url() == '' );
1338
+ }elseif ($condition == 'has_time'){
1339
+ //are the booking times different and not an all-day event
1340
+ $show_condition = ( $this->event_start_time != $this->event_end_time && !$this->event_all_day );
1341
+ }elseif ($condition == 'no_time'){
1342
+ //are the booking times exactly the same and it's not an all-day event.
1343
+ $show_condition = ( $this->event_start_time == $this->event_end_time && !$this->event_all_day );
1344
+ }elseif ($condition == 'all_day'){
1345
+ //is it an all day event
1346
+ $show_condition = !empty($this->event_all_day);
1347
+ }elseif ($condition == 'logged_in'){
1348
+ //user is logged in
1349
+ $show_condition = is_user_logged_in();
1350
+ }elseif ($condition == 'not_logged_in'){
1351
+ //not logged in
1352
+ $show_condition = !is_user_logged_in();
1353
+ }elseif ($condition == 'has_spaces'){
1354
+ //there are still empty spaces
1355
+ $show_condition = $this->event_rsvp && $this->get_bookings()->get_available_spaces() > 0;
1356
+ }elseif ($condition == 'fully_booked'){
1357
+ //event is fully booked
1358
+ $show_condition = $this->event_rsvp && $this->get_bookings()->get_available_spaces() <= 0;
1359
+ }elseif ($condition == 'bookings_open'){
1360
+ //bookings are still open
1361
+ $show_condition = $this->event_rsvp && $this->get_bookings()->is_open();
1362
+ }elseif ($condition == 'bookings_closed'){
1363
+ //bookings are still closed
1364
+ $show_condition = $this->event_rsvp && !$this->get_bookings()->is_open();
1365
+ }elseif ($condition == 'is_free' || $condition == 'is_free_now'){
1366
+ //is it a free day event, if _now then free right now
1367
+ $show_condition = !$this->event_rsvp || $this->is_free( $condition == 'is_free_now' );
1368
+ }elseif ($condition == 'not_free' || $condition == 'not_free_now'){
1369
+ //is it a paid event, if _now then paid right now
1370
+ $show_condition = $this->event_rsvp && !$this->is_free( $condition == 'not_free_now' );
1371
+ }elseif ($condition == 'is_long'){
1372
+ //is it an all day event
1373
+ $show_condition = $this->event_start_date != $this->event_end_date;
1374
+ }elseif ($condition == 'not_long'){
1375
+ //is it an all day event
1376
+ $show_condition = $this->event_start_date == $this->event_end_date;
1377
+ }elseif ($condition == 'is_past'){
1378
+ //if event is past
1379
+ if( get_option('dbem_events_current_are_past') ){
1380
+ $show_condition = $this->start <= current_time('timestamp');
1381
+ }else{
1382
+ $show_condition = $this->end <= current_time('timestamp');
1383
+ }
1384
+ }elseif ($condition == 'is_future'){
1385
+ //if event is upcoming
1386
+ $show_condition = $this->start > current_time('timestamp');
1387
+ }elseif ($condition == 'is_current'){
1388
+ //if event is upcoming
1389
+ $ts = current_time('timestamp');
1390
+ $show_condition = $this->start <= $ts && $this->end >= $ts;
1391
+ }elseif ($condition == 'is_recurrence'){
1392
+ //if event is a recurrence
1393
+ $show_condition = $this->is_recurrence();
1394
+ }elseif ($condition == 'not_recurrence'){
1395
+ //if event is not a recurrence
1396
+ $show_condition = !$this->is_recurrence();
1397
+ }elseif ($condition == 'is_private'){
1398
+ //if event is a recurrence
1399
+ $show_condition = $this->event_private == 1;
1400
+ }elseif ($condition == 'not_private'){
1401
+ //if event is not a recurrence
1402
+ $show_condition = $this->event_private == 0;
1403
+ }elseif ( preg_match('/^has_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){
1404
+ //event is in this category
1405
+ $show_condition = has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id);
1406
+ }elseif ( preg_match('/^no_category_([a-zA-Z0-9_\-]+)$/', $condition, $category_match)){
1407
+ //event is NOT in this category
1408
+ $show_condition = !has_term($category_match[1], EM_TAXONOMY_CATEGORY, $this->post_id);
1409
+ }elseif ( preg_match('/^has_tag_([a-zA-Z0-9_\-]+)$/', $condition, $tag_match)){
1410
+ //event has this tag
1411
+ $show_condition = has_term($tag_match[1], EM_TAXONOMY_TAG, $this->post_id);
1412
+ }elseif ( preg_match('/^no_tag_([a-zA-Z0-9_\-]+)$/', $condition, $tag_match)){
1413
+ //event doesn't have this tag
1414
+ $show_condition = !has_term($tag_match[1], EM_TAXONOMY_TAG, $this->post_id);
1415
  }
1416
+ //other potential ones - has_attribute_... no_attribute_... has_categories_...
1417
+ $show_condition = apply_filters('em_event_output_show_condition', $show_condition, $condition, $conditionals[0][$key], $this);
1418
+ if($show_condition){
1419
+ //calculate lengths to delete placeholders
1420
+ $placeholder_length = strlen($condition)+2;
1421
+ $replacement = substr($conditionals[0][$key], $placeholder_length, strlen($conditionals[0][$key])-($placeholder_length *2 +1));
1422
  }else{
1423
  $replacement = '';
1424
  }
1425
+ $event_string = str_replace($conditionals[0][$key], apply_filters('em_event_output_condition', $replacement, $condition, $conditionals[0][$key], $this), $event_string);
1426
  }
 
1427
  }
1428
+ }
 
1429
  //Now let's check out the placeholders.
1430
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([^}]+)})?/", $event_string, $placeholders);
1431
+ $replaces = array();
1432
+ foreach($placeholders[1] as $key => $result) {
1433
  $match = true;
1434
  $replace = '';
1435
+ $full_result = $placeholders[0][$key];
1436
  switch( $result ){
1437
  //Event Details
1438
  case '#_EVENTID':
1439
+ $replace = $this->event_id;
1440
+ break;
1441
+ case '#_EVENTPOSTID':
1442
+ $replace = $this->post_id;
1443
  break;
1444
+ case '#_NAME': //depreciated
1445
+ case '#_EVENTNAME':
1446
+ $replace = $this->event_name;
1447
  break;
1448
+ case '#_NOTES': //depreciated
1449
+ case '#_EXCERPT': //depreciated
1450
+ case '#_EVENTNOTES':
1451
+ case '#_EVENTEXCERPT':
1452
+ $replace = $this->post_content;
1453
+ if($result == "#_EXCERPT" || $result == "#_EVENTEXCERPT"){
1454
+ if( !empty($this->post_excerpt) ){
1455
+ $replace = $this->post_excerpt;
1456
+ }else{
1457
+ $excerpt_length = 55;
1458
+ $excerpt_more = apply_filters('em_excerpt_more', ' ' . '[...]');
1459
+ if( !empty($placeholders[3][$key]) ){
1460
+ $trim = true;
1461
+ $ph_args = explode(',', $placeholders[3][$key]);
1462
+ if( is_numeric($ph_args[0]) ) $excerpt_length = $ph_args[0];
1463
+ if( !empty($ph_args[1]) ) $excerpt_more = $ph_args[1];
1464
+ }
1465
+ if ( preg_match('/<!--more(.*?)?-->/', $replace, $matches) ) {
1466
+ $content = explode($matches[0], $replace, 2);
1467
+ $replace = force_balance_tags($content[0]);
1468
+ }
1469
+ if( !empty($trim) ){
1470
+ //shorten content by supplied number - copied from wp_trim_excerpt
1471
+ $replace = strip_shortcodes( $replace );
1472
+ $replace = str_replace(']]>', ']]&gt;', $replace);
1473
+ $replace = wp_trim_words( $replace, $excerpt_length, $excerpt_more );
1474
+ }
1475
+ }
1476
  }
1477
  break;
1478
  case '#_EVENTIMAGEURL':
1479
  case '#_EVENTIMAGE':
1480
+ if($this->get_image_url() != ''){
1481
+ if($result == '#_EVENTIMAGEURL'){
1482
+ $replace = esc_url($this->image_url);
1483
+ }else{
1484
+ if( empty($placeholders[3][$key]) ){
1485
+ $replace = "<img src='".esc_url($this->image_url)."' alt='".esc_attr($this->event_name)."'/>";
1486
+ }else{
1487
+ $image_size = explode(',', $placeholders[3][$key]);
1488
+ $image_url = $this->image_url;
1489
+ if( self::array_is_numeric($image_size) && count($image_size) > 1 ){
1490
+ //get a thumbnail
1491
+ if( get_option('dbem_disable_thumbnails') ){
1492
+ $image_attr = '';
1493
+ $image_args = array();
1494
+ if( empty($image_size[1]) && !empty($image_size[0]) ){
1495
+ $image_attr = 'width="'.$image_size[0].'"';
1496
+ $image_args['w'] = $image_size[0];
1497
+ }elseif( empty($image_size[0]) && !empty($image_size[1]) ){
1498
+ $image_attr = 'height="'.$image_size[1].'"';
1499
+ $image_args['h'] = $image_size[1];
1500
+ }elseif( !empty($image_size[0]) && !empty($image_size[1]) ){
1501
+ $image_attr = 'width="'.$image_size[0].'" height="'.$image_size[1].'"';
1502
+ $image_args = array('w'=>$image_size[0], 'h'=>$image_size[1]);
1503
+ }
1504
+ $replace = "<img src='".esc_url(em_add_get_params($image_url, $image_args))."' alt='".esc_attr($this->event_name)."' $image_attr />";
1505
+ }else{
1506
+ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){
1507
+ switch_to_blog($this->blog_id);
1508
+ $switch_back = true;
1509
+ }
1510
+ $replace = get_the_post_thumbnail($this->ID, $image_size);
1511
+ if( !empty($switch_back) ){ restore_current_blog(); }
1512
+ }
1513
+ }else{
1514
+ $replace = "<img src='".esc_url($image_url)."' alt='".esc_attr($this->event_name)."'/>";
1515
+ }
1516
+ }
1517
+ }
1518
  }
1519
  break;
1520
+ //Times & Dates
1521
  case '#_24HSTARTTIME':
1522
  case '#_24HENDTIME':
1523
+ $time = ($result == '#_24HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1524
  $replace = substr($time, 0,5);
1525
  break;
1526
  case '#_12HSTARTTIME':
1527
  case '#_12HENDTIME':
1528
+ $time = ($result == '#_12HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1529
  $replace = date('g:i A', strtotime($time));
1530
  break;
1531
+ case '#_EVENTTIMES':
1532
+ //get format of time to show
1533
+ if( !$this->event_all_day ){
1534
+ $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
1535
+ if($this->event_start_time != $this->event_end_time ){
1536
+ $replace = date_i18n($time_format, $this->start). get_option('dbem_times_separator') . date_i18n($time_format, $this->end);
1537
+ }else{
1538
+ $replace = date_i18n($time_format, $this->start);
1539
+ }
1540
+ }else{
1541
+ $replace = get_option('dbem_event_all_day_message');
1542
+ }
1543
+ break;
1544
+ case '#_EVENTDATES':
1545
+ //get format of time to show
1546
+ $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
1547
+ if( $this->event_start_date != $this->event_end_date){
1548
+ $replace = date_i18n($date_format, $this->start). get_option('dbem_dates_separator') . date_i18n($date_format, $this->end);
1549
+ }else{
1550
+ $replace = date_i18n($date_format, $this->start);
1551
+ }
1552
+ break;
1553
  //Links
1554
  case '#_EVENTPAGEURL': //Depreciated
1555
  case '#_LINKEDNAME': //Depreciated
1556
  case '#_EVENTURL': //Just the URL
1557
  case '#_EVENTLINK': //HTML Link
1558
+ $event_link = esc_url($this->get_permalink());
 
 
 
 
 
 
1559
  if($result == '#_LINKEDNAME' || $result == '#_EVENTLINK'){
1560
+ $replace = '<a href="'.$event_link.'" title="'.esc_attr($this->event_name).'">'.esc_attr($this->event_name).'</a>';
1561
  }else{
1562
  $replace = $event_link;
1563
  }
1565
  case '#_EDITEVENTURL':
1566
  case '#_EDITEVENTLINK':
1567
  if( $this->can_manage('edit_events','edit_others_events') ){
1568
+ $link = esc_url($this->get_edit_url());
 
 
 
 
1569
  if( $result == '#_EDITEVENTLINK'){
1570
+ $replace = '<a href="'.$link.'">'.esc_html(sprintf(__('Edit Event','dbem'))).'</a>';
1571
+ }else{
1572
+ $replace = $link;
1573
  }
1574
  }
1575
  break;
1577
  case '#_ADDBOOKINGFORM': //Depreciated
1578
  case '#_REMOVEBOOKINGFORM': //Depreciated
1579
  case '#_BOOKINGFORM':
1580
+ if( get_option('dbem_rsvp_enabled')){
1581
+ if( !defined('EM_XSS_BOOKINGFORM_FILTER') && locate_template('plugins/events-manager/placeholders/bookingform.php') ){
1582
+ //xss fix for old overriden booking forms
1583
+ add_filter('em_booking_form_action_url','esc_url');
1584
+ define('EM_XSS_BOOKINGFORM_FILTER',true);
1585
+ }
1586
+ ob_start();
1587
+ $template = em_locate_template('placeholders/bookingform.php', true, array('EM_Event'=>$this));
1588
+ EM_Bookings::enqueue_js();
1589
+ $replace = ob_get_clean();
1590
+ }
1591
  break;
1592
  case '#_BOOKINGBUTTON':
1593
+ if( get_option('dbem_rsvp_enabled') && $this->event_rsvp ){
1594
+ ob_start();
1595
+ $template = em_locate_template('placeholders/bookingbutton.php', true, array('EM_Event'=>$this));
1596
+ $replace = ob_get_clean();
1597
+ }
1598
+ break;
1599
+ case '#_EVENTPRICERANGEALL':
1600
+ $show_all_ticket_prices = true; //continues below
1601
+ case '#_EVENTPRICERANGE':
1602
+ //get the range of prices
1603
+ $min = false;
1604
+ $max = 0;
1605
+ if( $this->get_bookings()->is_open() || !empty($show_all_ticket_prices) ){
1606
+ foreach( $this->get_tickets()->tickets as $EM_Ticket ){
1607
+ /* @var $EM_Ticket EM_Ticket */
1608
+ if( $EM_Ticket->is_available() || get_option('dbem_bookings_tickets_show_unavailable') || !empty($show_all_ticket_prices) ){
1609
+ if($EM_Ticket->get_price() > $max ){
1610
+ $max = $EM_Ticket->get_price();
1611
+ }
1612
+ if($EM_Ticket->get_price() < $min || $min === false){
1613
+ $min = $EM_Ticket->get_price();
1614
+ }
1615
+ }
1616
+ }
1617
+ }
1618
+ if( $min === false ) $min = 0;
1619
+ if( $min != $max ){
1620
+ $replace = em_get_currency_formatted($min).' - '.em_get_currency_formatted($max);
1621
+ }else{
1622
+ $replace = em_get_currency_formatted($min);
1623
+ }
1624
+ break;
1625
+ case '#_EVENTPRICEMIN':
1626
+ //get the range of prices
1627
+ $min = false;
1628
+ foreach( $this->get_tickets()->tickets as $EM_Ticket ){
1629
+ /* @var $EM_Ticket EM_Ticket */
1630
+ if( $EM_Ticket->is_available()|| get_option('dbem_bookings_tickets_show_unavailable') ){
1631
+ if( $EM_Ticket->get_price() < $min || $min === false){
1632
+ $min = $EM_Ticket->get_price();
1633
+ }
1634
+ }
1635
+ }
1636
+ if( $min === false ) $min = 0;
1637
+ $replace = em_get_currency_formatted($min);
1638
+ break;
1639
+ case '#_EVENTPRICEMAX':
1640
+ //get the range of prices
1641
+ $max = 0;
1642
+ foreach( $this->get_tickets()->tickets as $EM_Ticket ){
1643
+ /* @var $EM_Ticket EM_Ticket */
1644
+ if( $EM_Ticket->is_available()|| get_option('dbem_bookings_tickets_show_unavailable') ){
1645
+ if( $EM_Ticket->get_price() > $max ){
1646
+ $max = $EM_Ticket->get_price();
1647
+ }
1648
+ }
1649
+ }
1650
+ $replace = em_get_currency_formatted($max);
1651
  break;
1652
  case '#_AVAILABLESEATS': //Depreciated
1653
  case '#_AVAILABLESPACES':
1654
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1655
  $replace = $this->get_bookings()->get_available_spaces();
1656
  } else {
1657
  $replace = "0";
1659
  break;
1660
  case '#_BOOKEDSEATS': //Depreciated
1661
  case '#_BOOKEDSPACES':
1662
+ //This placeholder is actually a little misleading, as it'll consider reserved (i.e. pending) bookings as 'booked'
1663
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1664
+ $replace = $this->get_bookings()->get_booked_spaces();
1665
+ if( get_option('dbem_bookings_approval_reserved') ){
1666
+ $replace += $this->get_bookings()->get_pending_spaces();
1667
+ }
1668
  } else {
1669
  $replace = "0";
1670
  }
1671
  break;
1672
  case '#_PENDINGSPACES':
1673
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1674
  $replace = $this->get_bookings()->get_pending_spaces();
1675
  } else {
1676
  $replace = "0";
1682
  break;
1683
  case '#_BOOKINGSURL':
1684
  case '#_BOOKINGSLINK':
1685
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
1686
+ $bookings_link = esc_url($this->get_bookings_url());
1687
+ if($result == '#_BOOKINGSLINK'){
1688
+ $replace = '<a href="'.$bookings_link.'" title="'.esc_attr($this->event_name).'">'.esc_html($this->event_name).'</a>';
1689
+ }else{
1690
+ $replace = $bookings_link;
1691
+ }
1692
+ }
1693
+ break;
1694
+ case '#_BOOKINGSCUTOFF':
1695
+ case '#_BOOKINGSCUTOFFDATE':
1696
+ case '#_BOOKINGSCUTOFFTIME':
1697
+ $replace = '';
1698
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled') && !empty($this->rsvp_end)) {
1699
+ $replace_format = get_option('dbem_date_format').' '. get_option('dbem_time_format');
1700
+ if( $result == '#_BOOKINGSCUTOFFDATE' ) $replace_format = get_option('dbem_date_format');
1701
+ if( $result == '#_BOOKINGSCUTOFFTIME' ) $replace_format = get_option('dbem_time_format');
1702
+ $replace = date($replace_format, $this->rsvp_end);
1703
  }
1704
  break;
1705
  //Contact Person
1706
  case '#_CONTACTNAME':
1707
  case '#_CONTACTPERSON': //Depreciated (your call, I think name is better)
1708
+ $replace = $this->get_contact()->display_name;
1709
  break;
1710
  case '#_CONTACTUSERNAME':
1711
+ $replace = $this->get_contact()->user_login;
1712
  break;
1713
  case '#_CONTACTEMAIL':
1714
  case '#_CONTACTMAIL': //Depreciated
1715
+ $replace = $this->get_contact()->user_email;
1716
+ break;
1717
+ case '#_CONTACTURL':
1718
+ $replace = $this->get_contact()->user_url;
1719
  break;
1720
  case '#_CONTACTID':
1721
+ $replace = $this->get_contact()->ID;
1722
  break;
1723
  case '#_CONTACTPHONE':
1724
+ $replace = ( $this->get_contact()->phone != '') ? $this->get_contact()->phone : __('N/A', 'dbem');
1725
  break;
1726
  case '#_CONTACTAVATAR':
1727
+ $replace = get_avatar( $this->get_contact()->ID, $size = '50' );
1728
  break;
1729
  case '#_CONTACTPROFILELINK':
1730
  case '#_CONTACTPROFILEURL':
1731
  if( function_exists('bp_core_get_user_domain') ){
1732
+ $replace = bp_core_get_user_domain($this->get_contact()->ID);
1733
  if( $result == '#_CONTACTPROFILELINK' ){
1734
+ $replace = '<a href="'.esc_url($replace).'">'.__('Profile', 'dbem').'</a>';
1735
  }
1736
  }
1737
  break;
1738
+ case '#_CONTACTMETA':
1739
+ if( !empty($placeholders[3][$key]) ){
1740
+ $replace = get_user_meta($this->event_owner, $placeholders[3][$key], true);
 
 
 
 
1741
  }
1742
  break;
1743
  case '#_ATTENDEES':
1745
  $template = em_locate_template('placeholders/attendees.php', true, array('EM_Event'=>$this));
1746
  $replace = ob_get_clean();
1747
  break;
1748
+ case '#_ATTENDEESLIST':
1749
+ ob_start();
1750
+ $template = em_locate_template('placeholders/attendeeslist.php', true, array('EM_Event'=>$this));
1751
+ $replace = ob_get_clean();
1752
+ break;
1753
+ case '#_ATTENDEESPENDINGLIST':
1754
+ ob_start();
1755
+ $template = em_locate_template('placeholders/attendeespendinglist.php', true, array('EM_Event'=>$this));
1756
+ $replace = ob_get_clean();
1757
+ break;
1758
+ //Categories and Tags
1759
+ case '#_EVENTCATEGORIESIMAGES':
1760
+ ob_start();
1761
+ $template = em_locate_template('placeholders/eventcategoriesimages.php', true, array('EM_Event'=>$this));
1762
+ $replace = ob_get_clean();
1763
+ break;
1764
+ case '#_EVENTTAGS':
1765
+ ob_start();
1766
+ $template = em_locate_template('placeholders/eventtags.php', true, array('EM_Event'=>$this));
1767
+ $replace = ob_get_clean();
1768
+ break;
1769
+ case '#_CATEGORIES': //depreciated
1770
+ case '#_EVENTCATEGORIES':
1771
  ob_start();
1772
  $template = em_locate_template('placeholders/categories.php', true, array('EM_Event'=>$this));
1773
  $replace = ob_get_clean();
1774
  break;
1775
+ //Ical Stuff
1776
+ case '#_EVENTICALURL':
1777
+ case '#_EVENTICALLINK':
1778
+ $replace = $this->get_ical_url();
1779
+ if( $result == '#_EVENTICALLINK' ){
1780
+ $replace = '<a href="'.esc_url($replace).'">iCal</a>';
1781
+ }
1782
+ break;
1783
+ case '#_EVENTGCALURL':
1784
+ case '#_EVENTGCALLINK':
1785
+ //get dates in UTC/GMT time
1786
+ if($this->event_all_day && $this->event_start_date == $this->event_end_date){
1787
+ $dateStart = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd');
1788
+ $dateEnd = get_gmt_from_date(date('Y-m-d H:i:s', $this->start + 60*60*24), 'Ymd');
1789
+ }else{
1790
+ $dateStart = get_gmt_from_date(date('Y-m-d H:i:s', $this->start), 'Ymd\THis\Z');
1791
+ $dateEnd = get_gmt_from_date(date('Y-m-d H:i:s', $this->end), 'Ymd\THis\Z');
1792
+ }
1793
+ //build url
1794
+ $gcal_url = 'http://www.google.com/calendar/event?action=TEMPLATE&text=event_name&dates=start_date/end_date&details=post_content&location=location_name&trp=false&sprop=event_url&sprop=name:blog_name';
1795
+ $gcal_url = str_replace('event_name', urlencode($this->event_name), $gcal_url);
1796
+ $gcal_url = str_replace('start_date', urlencode($dateStart), $gcal_url);
1797
+ $gcal_url = str_replace('end_date', urlencode($dateEnd), $gcal_url);
1798
+ $gcal_url = str_replace('location_name', urlencode($this->output('#_LOCATION')), $gcal_url);
1799
+ $gcal_url = str_replace('blog_name', urlencode(get_bloginfo()), $gcal_url);
1800
+ $gcal_url = str_replace('event_url', urlencode($this->get_permalink()), $gcal_url);
1801
+ //calculate URL length so we know how much we can work with to make a description.
1802
+ if( !empty($this->post_excerpt) ){
1803
+ $gcal_url_description = $this->post_excerpt;
1804
+ }else{
1805
+ $matches = explode('<!--more', $this->post_content);
1806
+ $gcal_url_description = wp_kses_data($matches[0]);
1807
+ }
1808
+ $gcal_url_length = strlen($gcal_url) - 9;
1809
+ if( strlen($gcal_url_description) + $gcal_url_length > 1350 ){
1810
+ $gcal_url_description = substr($gcal_url_description, 0, 1380 - $gcal_url_length - 3 ).'...';
1811
+ }
1812
+ $gcal_url = str_replace('post_content', urlencode($gcal_url_description), $gcal_url);
1813
+ //get the final url
1814
+ $replace = $gcal_url;
1815
+ if( $result == '#_EVENTGCALLINK' ){
1816
+ $img_url = 'www.google.com/calendar/images/ext/gc_button2.gif';
1817
+ $img_url = is_ssl() ? 'https://'.$img_url:'http://'.$img_url;
1818
+ $replace = '<a href="'.esc_url($replace).'" target="_blank"><img src="'.esc_url($img_url).'" alt="0" border="0"></a>';
1819
+ }
1820
+ break;
1821
  default:
1822
+ $replace = $full_result;
1823
  break;
1824
  }
1825
+ $replaces[$full_result] = apply_filters('em_event_output_placeholder', $replace, $this, $full_result, $target);
1826
+ }
1827
+ //sort out replacements so that during replacements shorter placeholders don't overwrite longer varieties.
1828
+ krsort($replaces);
1829
+ foreach($replaces as $full_result => $replacement){
1830
+ if( !in_array($full_result, array('#_NOTES','#_EVENTNOTES')) ){
1831
+ $event_string = str_replace($full_result, $replacement , $event_string );
1832
+ }else{
1833
+ $new_placeholder = str_replace('#_', '__#', $full_result); //this will avoid repeated filters when locations/categories are parsed
1834
+ $event_string = str_replace($full_result, $new_placeholder , $event_string );
1835
+ $desc_replace[$new_placeholder] = $replacement;
1836
+ }
1837
  }
1838
  //Time placeholders
1839
+ foreach($placeholders[1] as $result) {
1840
  // matches all PHP START date and time placeholders
1841
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
1842
  $replace = date_i18n(ltrim($result, "#"), $this->start);
1850
  $event_string = str_replace($result, $replace, $event_string );
1851
  }
1852
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1853
  //Now do dependent objects
1854
+ if( !empty($this->location_id) && $this->get_location()->location_status ){
1855
+ $event_string = $this->get_location()->output($event_string, $target);
1856
+ }else{
1857
+ $EM_Location = new EM_Location();
1858
+ $event_string = $EM_Location->output($event_string, $target);
1859
+ }
1860
 
1861
  //for backwards compat and easy use, take over the individual category placeholders with the frirst cat in th elist.
1862
+ $EM_Categories = $this->get_categories();
1863
+ if( count($EM_Categories->categories) > 0 ){
1864
+ $EM_Category = $EM_Categories->get_first();
1865
+ }
1866
+
1867
  if( empty($EM_Category) ) $EM_Category = new EM_Category();
1868
  $event_string = $EM_Category->output($event_string, $target);
1869
 
1870
+ //Finally, do the event notes, so that previous placeholders don't get replaced within the content, which may use shortcodes
1871
+ if( !empty($desc_replace) ){
1872
+ foreach($desc_replace as $full_result => $replacement){
1873
+ $event_string = str_replace($full_result, $replacement , $event_string );
1874
+ }
1875
+ }
1876
+
1877
+ //do some specific formatting
1878
+ //TODO apply this sort of formatting to any output() function
1879
+ if( $target == 'ical' ){
1880
+ //strip html and escape characters
1881
+ $event_string = str_replace('\\','\\\\',strip_tags($event_string));
1882
+ $event_string = str_replace(';','\;',$event_string);
1883
+ $event_string = str_replace(',','\,',$event_string);
1884
+ //remove and define line breaks in ical format
1885
+ $event_string = str_replace('\\\\n','\n',$event_string);
1886
+ $event_string = str_replace("\r\n",'\n',$event_string);
1887
+ $event_string = str_replace("\n",'\n',$event_string);
1888
+ }
1889
+ return apply_filters('em_event_output', $event_string, $this, $format, $target);
1890
+ }
1891
 
1892
  /**********************************************************
1893
  * RECURRENCE METHODS
1894
  ***********************************************************/
1895
 
1896
+ /**
1897
+ * Returns true if this is a recurring event.
1898
+ * @return boolean
1899
+ */
1900
+ function is_recurring(){
1901
+ return $this->post_type == 'event-recurring' && get_option('dbem_recurrence_enabled');
1902
+ }
1903
+ /**
1904
+ * Will return true if this individual event is part of a set of events that recur
1905
+ * @return boolean
1906
+ */
1907
+ function is_recurrence(){
1908
+ return ( $this->event_id > 0 && $this->recurrence_id > 0 && get_option('dbem_recurrence_enabled') );
1909
+ }
1910
+ /**
1911
+ * Returns if this is an individual event and is not a recurrence
1912
+ * @return boolean
1913
+ */
1914
+ function is_individual(){
1915
+ return ( !$this->is_recurring() && !$this->is_recurrence() );
1916
+ }
1917
+
1918
+ /**
1919
+ * Gets the event recurrence template, which is an EM_Event_Recurrence object (based off an event-recurring post)
1920
+ * @return EM_Event_Recurrence
1921
+ */
1922
+ function get_event_recurrence(){
1923
+ if(!$this->is_recurring()){
1924
+ return new EM_Event($this->recurrence_id); //remember, recurrence_id is a post!
1925
+ }else{
1926
+ return $this;
1927
+ }
1928
+ }
1929
+
1930
+ function get_detach_url(){
1931
+ return admin_url().'admin.php?event_id='.$this->event_id.'&amp;action=event_detach&amp;_wpnonce='.wp_create_nonce('event_detach_'.get_current_user_id().'_'.$this->event_id);
1932
+ }
1933
+
1934
+ function get_attach_url($recurrence_id){
1935
+ return admin_url().'admin.php?undo_id='.$recurrence_id.'&amp;event_id='.$this->event_id.'&amp;action=event_attach&amp;_wpnonce='.wp_create_nonce('event_attach_'.get_current_user_id().'_'.$this->event_id);
1936
+ }
1937
+
1938
+ /**
1939
+ * Returns if this is an individual event and is not recurring or a recurrence
1940
+ * @return boolean
1941
+ */
1942
+ function detach(){
1943
+ global $wpdb;
1944
+ if( $this->is_recurrence() && !$this->is_recurring() && $this->can_manage('edit_recurring_events','edit_others_recurring_events') ){
1945
+ //remove recurrence id from post meta and index table
1946
+ $url = $this->get_attach_url($this->recurrence_id);
1947
+ $wpdb->update(EM_EVENTS_TABLE, array('recurrence_id'=>0), array('event_id' => $this->event_id));
1948
+ update_post_meta($this->post_id, '_recurrence_id', 0);
1949
+ $this->feedback_message = __('Event detached.','dbem') . ' <a href="'.$url.'">'.__('Undo','dbem').'</a>';
1950
+ $this->recurrence_id = 0;
1951
+ return true;
1952
+ }
1953
+ $this->add_error(__('Event could not be detached.','dbem'));
1954
+ return false;
1955
+ }
1956
+
1957
+ /**
1958
+ * Returns if this is an individual event and is not recurring or a recurrence
1959
+ * @return boolean
1960
+ */
1961
+ function attach($recurrence_id){
1962
+ global $wpdb;
1963
+ if( !$this->is_recurrence() && !$this->is_recurring() && is_numeric($recurrence_id) && $this->can_manage('edit_recurring_events','edit_others_recurring_events') ){
1964
+ //add recurrence id to post meta and index table
1965
+ $wpdb->update(EM_EVENTS_TABLE, array('recurrence_id'=>$recurrence_id), array('event_id' => $this->event_id));
1966
+ update_post_meta($this->post_id, '_recurrence_id', $recurrence_id);
1967
+ $this->feedback_message = __('Event re-attached to recurrence.','dbem');
1968
+ return true;
1969
+ }
1970
+ $this->add_error(__('Event could not be attached.','dbem'));
1971
+ return false;
1972
+ }
1973
+
1974
  /**
1975
  * Saves events and replaces old ones. Returns true if sucecssful or false if not.
1976
  * @return boolean
1977
  */
1978
  function save_events() {
1979
+ global $wpdb;
1980
+ $event_ids = $post_ids = array();
1981
+ if( $this->can_manage('edit_events','edit_others_events') && $this->is_published() ){
1982
  do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
1983
+ //Make template event index, post, and meta (and we just change event dates)
1984
+ $event = $this->to_array(true); //event template - for index
1985
+ $event['event_attributes'] = serialize($event['event_attributes']);
1986
+ $post_fields = $wpdb->get_row('SELECT * FROM '.$wpdb->posts.' WHERE ID='.$this->post_id, ARRAY_A); //post to copy
1987
+ $post_name = $post_fields['post_name']; //save post slug since we'll be using this
1988
+ $post_fields['post_type'] = 'event'; //make sure we'll save events, not recurrence templates
1989
+ $meta_fields_map = $wpdb->get_results('SELECT meta_key,meta_value FROM '.$wpdb->postmeta.' WHERE post_id='.$this->post_id, ARRAY_A);
1990
+ $meta_fields = array();
1991
+ //convert meta_fields into a cleaner array
1992
+ foreach($meta_fields_map as $meta_data){
1993
+ $meta_fields[$meta_data['meta_key']] = $meta_data['meta_value'];
1994
+ }
1995
+ //remove id and we have a event template to feed to wpdb insert
1996
+ unset($event['event_id']);
1997
+ unset($post_fields['ID']);
1998
+ //remove recurrence meta info we won't need in events
1999
+ foreach( array_keys($this->recurrence_fields) as $recurrence_field){
2000
+ unset($event[$recurrence_field]);
2001
+ unset($meta_fields['_'.$recurrence_field]);
2002
+ }
2003
+ $event['event_date_created'] = current_time('mysql'); //since the recurrences are recreated
2004
+ unset($event['event_date_modified']);
2005
+ //Set the recurrence ID
2006
+ $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
2007
+ $event['recurrence'] = $meta_fields['_recurrence'] = 0;
2008
+ //Let's start saving!
2009
+ $this->delete_events(); //Delete old events beforehand, this will change soon
2010
  $event_saves = array();
2011
  $matching_days = $this->get_recurrence_days(); //Get days where events recur
2012
+ if( count($matching_days) > 0 ){
2013
+ //first save event post data
2014
+ $recurring_date_format = apply_filters('em_event_save_events_format', 'Y-m-d');
2015
+ foreach( $matching_days as $day ) {
2016
+ //rewrite post fields if needed
2017
+ $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);
2018
+ //adjust certain meta information
2019
+ $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day);
2020
+ $meta_fields['_start_ts'] = strtotime($event['event_start_date'].' '.$event['event_start_time']);
2021
+ if( is_numeric($event['recurrence_rsvp_days']) ){
2022
+ $event_rsvp_days = $event['recurrence_rsvp_days'] >= 0 ? '+'. $event['recurrence_rsvp_days']: $event['recurrence_rsvp_days'];
2023
+ $event_rsvp_date = date('Y-m-d', strtotime($event_rsvp_days.' days', $meta_fields['_start_ts']));
2024
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event_rsvp_date;
2025
+ $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_rsvp_time'];
2026
+ }else{
2027
+ $event['event_rsvp_date'] = $meta_fields['_event_rsvp_date'] = $event['event_start_date'];
2028
+ $event['event_rsvp_time'] = $meta_fields['_event_rsvp_time'] = $event['event_start_time'];
2029
+ }
2030
+ if($this->recurrence_days > 0){
2031
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_start_ts'] + ($this->recurrence_days * 60*60*24));
2032
+ }else{
2033
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
2034
+ }
2035
+ $meta_fields['_end_ts'] = strtotime($event['event_end_date'].' '.$event['event_end_time']);
2036
+ //create the event
2037
+ if( $wpdb->insert($wpdb->posts, $post_fields ) ){
2038
+ $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
2039
+ // Set GUID and event slug as per wp_insert_post
2040
+ $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_id ) ), array('ID'=>$post_id) );
2041
+ //insert into events index table
2042
+ $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
2043
+ $event_ids[$post_id] = $event_id = $wpdb->insert_id;
2044
+ $event_dates[$event_id] = $meta_fields['_start_ts'];
2045
+ //create the meta inserts for each event
2046
+ $meta_fields['_event_id'] = $event_id;
2047
+ foreach($meta_fields as $meta_key => $meta_val){
2048
+ $meta_inserts[] = $wpdb->prepare("(%d, %s, %s)", array($post_id, $meta_key, $meta_val));
2049
+ }
2050
+ }else{
2051
+ $event_saves[] = false;
2052
+ }
2053
+ //if( EM_DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
2054
+ }
2055
+ //insert the metas in one go, faster than one by one
2056
+ if( count($meta_inserts) > 0 ){
2057
+ $result = $wpdb->query("INSERT INTO ".$wpdb->postmeta." (post_id,meta_key,meta_value) VALUES ".implode(',',$meta_inserts));
2058
+ if($result === false){
2059
+ $this->add_error('There was a problem adding custom fields to your recurring events.','dbem');
2060
+ }
2061
+ }
2062
+ //copy the event tags and categories
2063
+ $taxonomies = self::get_taxonomies();
2064
+ foreach($taxonomies as $tax_name => $tax_data){
2065
+ //In MS Global mode, we also save category meta information for global lookups so we use our objects
2066
+ if( EM_MS_GLOBAL && $tax_name == 'category' ){
2067
+ //use EM_Categories as this is a special taxonomy in global mode
2068
+ $EM_Categories = new EM_Categories($this);
2069
+ //we save index data for each category in in MS Global mode
2070
+ foreach($event_ids as $post_id => $event_id){
2071
+ foreach( $EM_Categories->categories as $EM_Category ){
2072
+ $EM_Categories->event_id = $event_id;
2073
+ $EM_Categories->post_id = $post_id;
2074
+ $EM_Categories->save();
2075
+ }
2076
+ }
2077
+ }else{
2078
+ //general taxonomies including event tags
2079
+ $terms = get_the_terms( $this->post_id, $tax_data['name']);
2080
+ $term_slugs = array();
2081
+ if( is_array($terms) ){
2082
+ foreach($terms as $term){
2083
+ if( !empty($term->slug) ) $term_slugs[] = $term->slug; //save of category will soft-fail if slug is empty
2084
+ }
2085
+ }
2086
+ foreach($post_ids as $post_id){
2087
+ wp_set_object_terms($post_id, $term_slugs, $tax_data['name']);
2088
+ }
2089
+ }
2090
+ }
2091
+ //featured images
2092
+ if( !empty($this->attributes['thumbnail_id']) ){
2093
+ $image_inserts = array();
2094
+ foreach($post_ids as $post_ids){
2095
+ $image_inserts[] = "({$this->post_id}, '_thumbnail_id', {$this->attributes['thumbnail_id']})";
2096
+ }
2097
+ if( count($image_inserts) > 0 ){
2098
+ $wpdb->query('INSERT INTO '.$wpdb->postmeta.' (post_id, meta_key, meta_value) VALUES '.implode(', ', $image_inserts));
2099
+ }
2100
+ }
2101
+ //MS Global Categories
2102
+ if( $cat_slugs_count > 0 && EM_MS_GLOBAL ){
2103
+ foreach($categories as $EM_Category){
2104
+ foreach($event_ids as $event_id){
2105
+ $wpdb->insert(EM_META_TABLE, array('meta_value'=>$EM_Category->term_id,'object_id'=>$event_id,'meta_key'=>'event-category'));
2106
+ }
2107
+ }
2108
  }
2109
+ //now, save booking info for each event
2110
+ if( $this->event_rsvp ){
2111
+ $meta_inserts = array();
2112
+ foreach($this->get_tickets() as $EM_Ticket){
2113
+ /* @var $EM_Ticket EM_Ticket */
2114
+ //get array, modify event id and insert
2115
+ $ticket = $EM_Ticket->to_array();
2116
+ //empty cut-off dates of ticket, add them at per-event level
2117
+ unset($ticket['ticket_start']); unset($ticket['ticket_end']);
2118
+ if( !empty($ticket['ticket_meta']['recurrences']) ){
2119
+ $ticket_meta_recurrences = $ticket['ticket_meta']['recurrences'];
2120
+ unset($ticket['ticket_meta']['recurrences']);
2121
+ }
2122
+ //unset id
2123
+ unset($ticket['ticket_id']);
2124
+ //clean up ticket values
2125
+ foreach($ticket as $k => $v){
2126
+ if( empty($v) && $k != 'ticket_name' ){
2127
+ $ticket[$k] = 'NULL';
2128
+ }else{
2129
+ $data_type = !empty($EM_Ticket->fields[$k]['type']) ? $EM_Ticket->fields[$k]['type']:'%s';
2130
+ if(is_array($ticket[$k])) $v = serialize($ticket[$k]);
2131
+ $ticket[$k] = $wpdb->prepare($data_type,$v);
2132
+ }
2133
+ }
2134
+ foreach($event_ids as $event_id){
2135
+ $ticket['event_id'] = $event_id;
2136
+ //sort out cut-of dates
2137
+ if( !empty($ticket_meta_recurrences) ){
2138
+ if( array_key_exists('start_days', $ticket_meta_recurrences) ){
2139
+ $ticket_start_days = $ticket_meta_recurrences['start_days'] >= 0 ? '+'. $ticket_meta_recurrences['start_days']: $ticket_meta_recurrences['start_days'];
2140
+ $ticket_start_date = date('Y-m-d', strtotime($ticket_start_days.' days', $event_dates[$event_id]));
2141
+ $ticket['ticket_start'] = "'". $ticket_start_date . ' '. $ticket_meta_recurrences['start_time'] ."'";
2142
+ }
2143
+ if( array_key_exists('end_days', $ticket_meta_recurrences) ){
2144
+ $ticket_end_days = $ticket_meta_recurrences['end_days'] >= 0 ? '+'. $ticket_meta_recurrences['end_days']: $ticket_meta_recurrences['end_days'];
2145
+ $ticket_end_date = date('Y-m-d', strtotime($ticket_end_days.' days', $event_dates[$event_id]));
2146
+ $ticket['ticket_end'] = "'". $ticket_end_date . ' '. $ticket_meta_recurrences['end_time'] . "'";
2147
+ }
2148
+ }
2149
+ //add insert data
2150
+ $meta_inserts[] = "(".implode(",",$ticket).")";
2151
+ }
2152
+ }
2153
+ $keys = "(".implode(",",array_keys($ticket)).")";
2154
+ $values = implode(',',$meta_inserts);
2155
+ $sql = "INSERT INTO ".EM_TICKETS_TABLE." $keys VALUES $values";
2156
+ $result = $wpdb->query($sql);
2157
+ }
2158
+ }else{
2159
+ $this->add_error('You have not defined a date range long enough to create a recurrence.','dbem');
2160
+ $result = false;
2161
  }
2162
+ return apply_filters('em_event_save_events', !in_array(false, $event_saves) && $result !== false, $this, $event_ids, $post_ids);
2163
  }
2164
+ return apply_filters('em_event_save_events', false, $this, $event_ids, $post_ids);
2165
  }
2166
 
2167
  /**
2175
  //So we don't do something we'll regret later, we could just supply the get directly into the delete, but this is safer
2176
  $result = false;
2177
  if( $this->can_manage('delete_events', 'delete_others_events') ){
2178
+ //delete events from em_events table
2179
+ $events_array = EM_Events::get( array('recurrence_id'=>$this->event_id, 'scope'=>'all', 'status'=>false ) );
2180
+ foreach($events_array as $EM_Event){
2181
+ /* @var $EM_Event EM_Event */
2182
+ if($EM_Event->recurrence_id == $this->event_id){
2183
+ $EM_Event->delete(true);
2184
  }
2185
+ }
 
2186
  }
2187
+ return apply_filters('delete_events', $result, $this, $events_array);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2188
  }
2189
 
2190
  /**
2192
  * @param array $recurrence
2193
  * @return array
2194
  */
2195
+ function get_recurrence_days(){
2196
+ $start_date = strtotime($this->event_start_date);
2197
+ $end_date = strtotime($this->event_end_date);
 
 
 
 
 
 
 
 
2198
 
2199
+ $weekdays = explode(",", $this->recurrence_byday); //what days of the week (or if monthly, one value at index 0)
2200
+
2201
+ $matching_days = array();
2202
+ $aDay = 86400; // a day in seconds
2203
+ $aWeek = $aDay * 7;
2204
+
2205
+ //TODO can this be optimized?
2206
+ switch ( $this->recurrence_freq ){
2207
+ case 'daily':
2208
+ //If daily, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
2209
+ $current_date = $start_date;
2210
+ while( $current_date <= $end_date ){
2211
+ $matching_days[] = $current_date;
2212
+ $current_date = $current_date + ($aDay * $this->recurrence_interval);
2213
+ }
2214
+ break;
2215
+ case 'weekly':
2216
+ //sort out week one, get starting days and then days that match time span of event (i.e. remove past events in week 1)
2217
+ $start_of_week = get_option('start_of_week'); //Start of week depends on WordPress
2218
+ //first, get the start of this week as timestamp
2219
+ $event_start_day = date('w', $start_date);
2220
+ //then get the timestamps of weekdays during this first week, regardless if within event range
2221
+ $start_weekday_dates = array(); //Days in week 1 where there would events, regardless of event date range
2222
+ for($i = 0; $i < 7; $i++){
2223
+ $weekday_date = $start_date+($aDay*$i); //the date of the weekday we're currently checking
2224
+ $weekday_day = date('w',$weekday_date); //the day of the week we're checking, taking into account wp start of week setting
2225
+
2226
+ if( in_array( $weekday_day, $weekdays) ){
2227
+ $start_weekday_dates[] = $weekday_date; //it's in our starting week day, so add it
2228
  }
2229
+ }
2230
+ //for each day of eventful days in week 1, add 7 days * weekly intervals
2231
+ foreach ($start_weekday_dates as $weekday_date){
2232
+ //Loop weeks by interval until we reach or surpass end date
2233
+ while($weekday_date <= $end_date){
2234
+ if( $weekday_date >= $start_date && $weekday_date <= $end_date ){
2235
+ $matching_days[] = $weekday_date;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2236
  }
2237
+ $weekday_date = $weekday_date + ($aWeek * $this->recurrence_interval);
2238
+ }
2239
+ }//done!
2240
+ break;
2241
+ case 'monthly':
2242
+ //loop months starting this month by intervals
2243
+ $current_arr = getdate($start_date);
2244
+ $end_arr = getdate($end_date);
2245
+ $end_month_date = strtotime( date('Y-m-t', $end_date) ); //End date on last day of month
2246
+ $current_date = strtotime( date('Y-m-1', $start_date) ); //Start date on first day of month
2247
+ while( $current_date <= $end_month_date ){
2248
+ $last_day_of_month = date('t', $current_date);
2249
+ //Now find which day we're talking about
2250
+ $current_week_day = date('w',$current_date);
2251
+ $matching_month_days = array();
2252
+ //Loop through days of this years month and save matching days to temp array
2253
+ for($day = 1; $day <= $last_day_of_month; $day++){
2254
+ if((int) $current_week_day == $this->recurrence_byday){
2255
+ $matching_month_days[] = $day;
2256
  }
2257
+ $current_week_day = ($current_week_day < 6) ? $current_week_day+1 : 0;
2258
  }
2259
+ //Now grab from the array the x day of the month
2260
+ $matching_day = ($this->recurrence_byweekno > 0) ? $matching_month_days[$this->recurrence_byweekno-1] : array_pop($matching_month_days);
2261
+ $matching_date = strtotime(date('Y-m',$current_date).'-'.$matching_day);
2262
+ if($matching_date >= $start_date && $matching_date <= $end_date){
2263
+ $matching_days[] = $matching_date;
2264
+ }
2265
+ //add the number of days in this month to make start of next month
2266
+ $current_arr['mon'] += $this->recurrence_interval;
2267
+ if($current_arr['mon'] > 12){
2268
+ //FIXME this won't work if interval is more than 12
2269
+ $current_arr['mon'] = $current_arr['mon'] - 12;
2270
+ $current_arr['year']++;
2271
+ }
2272
+ $current_date = strtotime("{$current_arr['year']}-{$current_arr['mon']}-1");
2273
+ }
2274
+ break;
2275
+ case 'yearly':
2276
+ //If yearly, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
2277
+ $month = date('m', $this->start);
2278
+ $day = date('d',$this->start);
2279
+ $year = date('Y',$this->start);
2280
+ $end_year = date('Y',$this->end);
2281
+ if( @mktime(0,0,0,$day,$month,$end_year) < $this->end ) $end_year--;
2282
+ while( $year <= $end_year ){
2283
+ $matching_days[] = mktime(0,0,0,$month,$day,$year);
2284
+ $year++;
2285
+ }
2286
+ break;
2287
  }
2288
+ sort($matching_days);
2289
+ return apply_filters('em_events_get_recurrence_days', $matching_days, $this);
2290
  }
2291
 
2292
+ /**
2293
+ * If event is recurring, set recurrences to same status as template
2294
+ * @param $status
2295
+ */
2296
+ function set_status_events($status){
2297
+ //give sub events same status
2298
+ $events_array = EM_Events::get( array('recurrence_id'=>$this->post_id, 'scope'=>'all', 'status'=>false ) );
2299
+ foreach($events_array as $EM_Event){
2300
+ /* @var $EM_Event EM_Event */
2301
+ if($EM_Event->recurrence_id == $this->event_id){
2302
+ $EM_Event->set_status($status);
2303
+ }
2304
  }
 
2305
  }
2306
 
2307
  /**
2308
  * Returns a string representation of this recurrence. Will return false if not a recurrence
2309
  * @return string
2310
  */
2311
+ function get_recurrence_description() {
2312
+ $EM_Event_Recurring = $this->get_event_recurrence();
2313
+ $recurrence = $this->to_array();
2314
+ $weekdays_name = array(__('Sunday', 'dbem'),__('Monday', 'dbem'),__('Tuesday', 'dbem'),__('Wednesday', 'dbem'),__('Thursday', 'dbem'),__('Friday', 'dbem'),__('Saturday', 'dbem'));
2315
  $monthweek_name = array('1' => __('the first %s of the month', 'dbem'),'2' => __('the second %s of the month', 'dbem'), '3' => __('the third %s of the month', 'dbem'), '4' => __('the fourth %s of the month', 'dbem'), '-1' => __('the last %s of the month', 'dbem'));
2316
+ $output = sprintf (__('From %1$s to %2$s', 'dbem'), $EM_Event_Recurring->event_start_date, $EM_Event_Recurring->event_end_date).", ";
2317
+ if ($EM_Event_Recurring->recurrence_freq == 'daily') {
2318
  $freq_desc =__('everyday', 'dbem');
2319
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2320
+ $freq_desc = sprintf (__("every %s days", 'dbem'), $EM_Event_Recurring->recurrence_interval);
2321
  }
2322
+ }elseif ($EM_Event_Recurring->recurrence_freq == 'weekly') {
2323
+ $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
2324
  $natural_days = array();
2325
  foreach($weekday_array as $day){
2326
  array_push($natural_days, $weekdays_name[$day]);
2327
  }
2328
+ $output .= implode(", ", $natural_days);
2329
+ $freq_desc = " " . __("every week", 'dbem');
2330
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2331
+ $freq_desc = " ".sprintf (__("every %s weeks", 'dbem'), $EM_Event_Recurring->recurrence_interval);
2332
  }
2333
 
2334
+ }elseif ($EM_Event_Recurring->recurrence_freq == 'monthly') {
2335
+ $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
2336
  $natural_days = array();
2337
  foreach($weekday_array as $day){
2338
+ if( !empty($day) ){
2339
+ array_push($natural_days, $weekdays_name[$day]);
2340
+ }
2341
+ }
2342
+ $freq_desc = sprintf (($monthweek_name[$EM_Event_Recurring->recurrence_byweekno]), implode(" and ", $natural_days));
2343
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2344
+ $freq_desc .= ", ".sprintf (__("every %s months",'dbem'), $EM_Event_Recurring->recurrence_interval);
2345
  }
2346
+ }elseif ($EM_Event_Recurring->recurrence_freq == 'yearly') {
2347
+ $freq_desc .= __("every year", 'dbem');
2348
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
2349
+ $freq_desc .= sprintf (__("every %s years",'dbem'), $EM_Event_Recurring->recurrence_interval);
2350
  }
2351
  }else{
2352
  $freq_desc = "[ERROR: corrupted database record]";
2353
  }
2354
  $output .= $freq_desc;
2355
  return $output;
2356
+ }
2357
 
2358
  /**********************************************************
2359
  * UTILITIES
2360
  ***********************************************************/
2361
+
2362
  /**
2363
+ * Can the user manage this?
 
 
2364
  */
2365
+ function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
2366
+ if( $this->event_id == '' && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
2367
+ $user_to_check = get_option('dbem_events_anonymous_user');
 
 
 
 
 
2368
  }
2369
+ 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);
2370
  }
2371
  }
2372
 
2379
  * @param string $target
2380
  * @return mixed
2381
  */
2382
+ function em_event_output_placeholder($result,$event,$placeholder,$target='html'){
2383
+ if( $target == 'raw' ) return $result;
2384
+ if( in_array($placeholder, array("#_EXCERPT",'#_EVENTEXCERPT', "#_LOCATIONEXCERPT")) && $target == 'html' ){
2385
  $result = apply_filters('dbem_notes_excerpt', $result);
2386
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
2387
+ $result = em_ascii_encode($event->get_contact()->user_email);
2388
+ }elseif( in_array($placeholder, array('#_EVENTNOTES','#_NOTES','#_DESCRIPTION','#_LOCATIONNOTES','#_CATEGORYNOTES','#_CATEGORYDESCRIPTION')) ){
2389
+ if($target == 'rss'){
 
 
 
 
2390
  $result = apply_filters('dbem_notes_rss', $result);
2391
  $result = apply_filters('the_content_rss', $result);
2392
+ }elseif($target == 'map'){
2393
+ $result = apply_filters('dbem_notes_map', $result);
2394
+ }elseif($target == 'ical'){
2395
+ $result = apply_filters('dbem_notes_ical', $result);
2396
+ }elseif ($target == "email"){
2397
+ $result = apply_filters('dbem_notes_email', $result);
2398
+ }else{ //html
2399
+ $result = apply_filters('dbem_notes', $result);
2400
  }
2401
+ }elseif( in_array($placeholder, array("#_NAME",'#_LOCATION','#_TOWN','#_ADDRESS','#_LOCATIONNAME',"#_EVENTNAME","#_LOCATIONNAME",'#_CATEGORY')) ){
2402
+ if ($target == "rss"){
 
 
2403
  $result = apply_filters('dbem_general_rss', $result);
2404
+ }elseif ($target == "ical"){
2405
+ $result = apply_filters('dbem_general_ical', $result);
2406
+ }elseif ($target == "email"){
2407
+ $result = apply_filters('dbem_general_email', $result);
2408
+ }else{ //html
2409
+ $result = apply_filters('dbem_general', $result);
2410
  }
2411
  }
2412
  return $result;
2413
  }
2414
+ add_filter('em_category_output_placeholder','em_event_output_placeholder',1,4);
2415
  add_filter('em_event_output_placeholder','em_event_output_placeholder',1,4);
2416
+ add_filter('em_location_output_placeholder','em_event_output_placeholder',1,4);
2417
+ // FILTERS
2418
+ // filters for general events field (corresponding to those of "the _title")
2419
+ add_filter('dbem_general', 'wptexturize');
2420
+ add_filter('dbem_general', 'convert_chars');
2421
+ add_filter('dbem_general', 'trim');
2422
+ // filters for the notes field in html (corresponding to those of "the _content")
2423
+ add_filter('dbem_notes', 'wptexturize');
2424
+ add_filter('dbem_notes', 'convert_smilies');
2425
+ add_filter('dbem_notes', 'convert_chars');
2426
+ add_filter('dbem_notes', 'wpautop');
2427
+ add_filter('dbem_notes', 'prepend_attachment');
2428
+ add_filter('dbem_notes', 'do_shortcode');
2429
+ // filters for the notes field in html (corresponding to those of "the _content")
2430
+ add_filter('dbem_notes_excerpt', 'wptexturize');
2431
+ add_filter('dbem_notes_excerpt', 'convert_smilies');
2432
+ add_filter('dbem_notes_excerpt', 'convert_chars');
2433
+ add_filter('dbem_notes_excerpt', 'wpautop');
2434
+ add_filter('dbem_notes_excerpt', 'prepend_attachment');
2435
+ add_filter('dbem_notes_excerpt', 'do_shortcode');
2436
+ // RSS content filter
2437
+ add_filter('dbem_notes_rss', 'convert_chars', 8);
2438
+ add_filter('dbem_general_rss', 'esc_html', 8);
2439
+ // Notes map filters
2440
+ add_filter('dbem_notes_map', 'convert_chars', 8);
2441
+ add_filter('dbem_notes_map', 'js_escape');
2442
+ //embeds support if using placeholders
2443
+ if ( is_object($GLOBALS['wp_embed']) ){
2444
+ add_filter( 'dbem_notes', array( $GLOBALS['wp_embed'], 'run_shortcode' ), 8 );
2445
+ add_filter( 'dbem_notes', array( $GLOBALS['wp_embed'], 'autoembed' ), 8 );
2446
+ }
2447
+
2448
+ /**
2449
+ * This function replaces the default gallery shortcode, so it can check if this is a recurring event recurrence and pass on the parent post id as the default post.
2450
+ * @param array $attr
2451
+ */
2452
+ function em_event_gallery_override( $attr = array() ){
2453
+ global $post;
2454
+ if( $post->post_type == EM_POST_TYPE_EVENT && empty($attr['id']) && empty($attr['ids']) ){
2455
+ //no id specified, so check if it's recurring and override id with recurrence template post id
2456
+ $EM_Event = em_get_event($post->ID, 'post_id');
2457
+ if( $EM_Event->is_recurrence() ){
2458
+ $attr['id'] = $EM_Event->get_event_recurrence()->post_id;
2459
+ }
2460
+ }
2461
+ return gallery_shortcode($attr);
2462
+ }
2463
+ function em_event_gallery_override_init(){
2464
+ remove_shortcode('gallery');
2465
+ add_shortcode('gallery', 'em_event_gallery_override');
2466
+ }
2467
+ add_action('init','em_event_gallery_override_init', 1000); //so that plugins like JetPack don't think we're overriding gallery, we're not i swear!
2468
  ?>
classes/em-events.php CHANGED
@@ -4,25 +4,7 @@
4
  * Use this class to query and manipulate sets of events. If dealing with more than one event, you probably want to use this class in some way.
5
  *
6
  */
7
- class EM_Events extends EM_Object implements Iterator {
8
- /**
9
- * Array of EM_Event objects
10
- * @var array EM_Event
11
- */
12
- var $events = array();
13
-
14
- function EM_Events( $args = array() ){
15
- if( is_array($args) ){
16
- if( is_object(current($args)) && get_class(current($args)) == 'EM_Event' ){
17
- $this->events = $args;
18
- }else{
19
- $this->events = EM_Events::get($args);
20
- }
21
- }else{
22
- $this->events = EM_Events::get();
23
- }
24
- do_action('em_events',$this);
25
- }
26
 
27
  /**
28
  * Returns an array of EM_Events that match the given specs in the argument, or returns a list of future evetnts in future
@@ -32,8 +14,8 @@ class EM_Events extends EM_Object implements Iterator {
32
  * @param array $args
33
  * @return EM_Event array()
34
  */
35
- function get( $args = array(), $count=false ) {
36
- global $wpdb;
37
  $events_table = EM_EVENTS_TABLE;
38
  $locations_table = EM_LOCATIONS_TABLE;
39
 
@@ -57,6 +39,7 @@ class EM_Events extends EM_Object implements Iterator {
57
  $args = self::get_default_search($args);
58
  $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
59
  $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
 
60
 
61
  //Get the default conditions
62
  $conditions = self::build_sql_conditions($args);
@@ -65,37 +48,67 @@ class EM_Events extends EM_Object implements Iterator {
65
 
66
  //Get ordering instructions
67
  $EM_Event = new EM_Event();
68
- $accepted_fields = $EM_Event->get_fields(true);
69
- $orderby = self::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order'));
70
  //Now, build orderby sql
71
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
72
 
73
  //Create the SQL statement and execute
74
- $selectors = ( $count ) ? 'COUNT(*)':'*';
75
- $sql = "
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  SELECT $selectors FROM $events_table
77
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
78
  $where
79
- $orderby_sql
80
  $limit $offset
81
- ";
82
-
83
  //If we're only counting results, return the number of results
84
  if( $count ){
85
- return $wpdb->get_var($sql);
 
86
  }
87
- $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
88
 
89
  //If we want results directly in an array, why not have a shortcut here?
90
  if( $args['array'] == true ){
91
- return $results;
92
  }
93
 
94
  //Make returned results EM_Event objects
95
  $results = (is_array($results)) ? $results:array();
96
  $events = array();
97
- foreach ( $results as $event ){
98
- $events[] = new EM_Event($event);
 
 
 
 
 
 
 
99
  }
100
 
101
  return apply_filters('em_events_get', $events, $args);
@@ -106,14 +119,14 @@ class EM_Events extends EM_Object implements Iterator {
106
  * @param $date
107
  * @return int
108
  */
109
- function count_date($date){
110
  global $wpdb;
111
  $table_name = EM_EVENTS_TABLE;
112
  $sql = "SELECT COUNT(*) FROM $table_name WHERE (event_start_date like '$date') OR (event_start_date <= '$date' AND event_end_date >= '$date');";
113
  return apply_filters('em_events_count_date', $wpdb->get_var($sql));
114
  }
115
 
116
- function count( $args = array() ){
117
  return apply_filters('em_events_count', self::get($args, true), $args);
118
  }
119
 
@@ -121,34 +134,22 @@ class EM_Events extends EM_Object implements Iterator {
121
  * Will delete given an array of event_ids or EM_Event objects
122
  * @param unknown_type $id_array
123
  */
124
- function delete( $array ){
125
- //TODO add better cap checks in bulk actions
126
  global $wpdb;
127
  //Detect array type and generate SQL for event IDs
128
- $event_ids = array();
129
- if( @get_class(current($array)) == 'EM_Event' ){
130
- foreach($array as $EM_Event){
131
- $event_ids[] = $EM_Event->id;
132
- }
133
  }else{
134
- $event_ids = $array;
135
  }
136
- if(self::array_is_numeric($event_ids)){
137
- //First we have to check that they're all deletable by this user.
138
- if ( self::can_manage($event_ids) ) {
139
- apply_filters('em_events_delete_pre', $event_ids);
140
- $condition = implode(" OR event_id=", $event_ids);
141
- //Delete all the bookings
142
- $result_bookings = $wpdb->query("DELETE FROM ". EM_BOOKINGS_TABLE ." WHERE event_id=$condition;");
143
- //Now delete the events
144
- $result = $wpdb->query ( "DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=$condition;" );
145
- return apply_filters('em_events_delete', true, $event_ids);
146
- }else{
147
- return apply_filters('em_events_delete', true, $event_ids);
148
- }
149
  }
150
  //TODO add better error feedback on events delete fails
151
- return apply_filters('em_events_delete', true, $event_ids);
152
  }
153
 
154
 
@@ -159,11 +160,15 @@ class EM_Events extends EM_Object implements Iterator {
159
  * @param array $secondary_args
160
  * @return string
161
  */
162
- function output( $args ){
163
  global $EM_Event;
164
  $EM_Event_old = $EM_Event; //When looping, we can replace EM_Event global with the current event in the loop
 
 
 
 
 
165
  //Can be either an array for the get search or an array of EM_Event objects
166
- $func_args = func_get_args();
167
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Event' ){
168
  $func_args = func_get_args();
169
  $events = $func_args[0];
@@ -172,15 +177,18 @@ class EM_Events extends EM_Object implements Iterator {
172
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
173
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
174
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
 
175
  }else{
176
  //Firstly, let's check for a limit/offset here, because if there is we need to remove it and manually do this
177
- $args = apply_filters('em_events_output_args', self::get_default_search($args) );
178
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
179
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
180
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
181
- $args['limit'] = false;
182
- $args['offset'] = false;
183
- $args['page'] = false;
 
 
184
  $events = self::get( $args );
185
  }
186
  //What format shall we output this to, or use default
@@ -188,16 +196,9 @@ class EM_Events extends EM_Object implements Iterator {
188
 
189
  $output = "";
190
  $events = apply_filters('em_events_output_events', $events);
191
- $events_count = count($events);
192
  if ( $events_count > 0 ) {
193
- $event_count = 0;
194
- $events_shown = 0;
195
  foreach ( $events as $EM_Event ) {
196
- if( ($events_shown < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ){
197
- $output .= $EM_Event->output($format);
198
- $events_shown++;
199
- }
200
- $event_count++;
201
  }
202
  //Add headers and footers to output
203
  if( $format == get_option ( 'dbem_event_list_item_format' ) ){
@@ -210,10 +211,7 @@ class EM_Events extends EM_Object implements Iterator {
210
  $output = $format_header . $output . $format_footer;
211
  //Pagination (if needed/requested)
212
  if( !empty($args['pagination']) && !empty($limit) && $events_count > $limit ){
213
- //Show the pagination links (unless there's less than $limit events)
214
- $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
215
- $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'));
216
- $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $events_count, $limit, $page), $page_link_template, $events_count, $limit, $page);
217
  }
218
  } else {
219
  $output = get_option ( 'dbem_no_events_message' );
@@ -225,7 +223,114 @@ class EM_Events extends EM_Object implements Iterator {
225
  return $output;
226
  }
227
 
228
- function can_manage($event_ids){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  global $wpdb;
230
  if( current_user_can('edit_others_events') ){
231
  return apply_filters('em_events_can_manage', true, $event_ids);
@@ -233,44 +338,83 @@ class EM_Events extends EM_Object implements Iterator {
233
  if( EM_Object::array_is_numeric($event_ids) ){
234
  $condition = implode(" OR event_id=", $event_ids);
235
  //we try to find any of these events that don't belong to this user
236
- $results = $wpdb->get_var("SELECT COUNT(*) FROM ". EM_BOOKINGS_TABLE ." WHERE event_owner != '". get_current_user_id() ."' event_id=$condition;");
237
  return apply_filters('em_events_can_manage', ($results == 0), $event_ids);
238
  }
239
  return apply_filters('em_events_can_manage', false, $event_ids);
240
  }
241
 
242
- function get_post_search($args = array()){
243
- $accepted_searches = apply_filters('em_accepted_searches', array('scope','search','category','country','state'), $args);
244
- foreach($_REQUEST as $post_key => $post_value){
245
- if( in_array($post_key, $accepted_searches) && !empty($post_value) ){
246
- if(is_array($post_value)){
247
- $post_value = implode(',',$post_value);
248
- }
249
- if($post_value != ',' ){
250
- $args[$post_key] = $post_value;
251
- }
252
- }
253
- }
254
- return $args;
255
  }
256
 
257
  /* Overrides EM_Object method to apply a filter to result
258
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
259
  */
260
- function build_sql_conditions( $args = array() ){
 
261
  $conditions = parent::build_sql_conditions($args);
262
  if( !empty($args['search']) ){
263
- $like_search = array('event_name','event_notes','location_name','location_address','location_town','location_postcode','location_state','location_country');
264
  $conditions['search'] = "(".implode(" LIKE '%{$args['search']}%' OR ", $like_search). " LIKE '%{$args['search']}%')";
265
  }
266
- if( array_key_exists('status',$args) && is_numeric($args['status']) ){
267
- $conditions['status'] = "(`event_status`={$args['status']})";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
- if( is_multisite() && array_key_exists('blog',$args) && is_numeric($args['blog']) ){
270
- if( is_main_site($args['blog']) ){
271
- $conditions['blog'] = "(`blog_id`={$args['blog']} OR blog_id IS NULL)";
 
272
  }else{
273
- $conditions['blog'] = "(`blog_id`={$args['blog']})";
274
  }
275
  }
276
  return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
@@ -279,37 +423,49 @@ class EM_Events extends EM_Object implements Iterator {
279
  /* Overrides EM_Object method to apply a filter to result
280
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
281
  */
282
- function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
 
283
  return apply_filters( 'em_events_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
284
  }
285
 
286
  /*
287
  * Adds custom Events search defaults
 
288
  * @param array $array
289
  * @return array
290
  * @uses EM_Object#get_default_search()
291
  */
292
- function get_default_search( $array = array() ){
 
293
  $defaults = array(
294
  'orderby' => get_option('dbem_events_default_orderby'),
295
  'order' => get_option('dbem_events_default_order'),
296
- 'rsvp' => false, //if set to true, only events with bookings enabled are returned
297
  'status' => 1, //approved events only
298
  'format_header' => '', //events can have custom html above the list
299
  'format_footer' => '', //events can have custom html below the list
300
- 'state' => '',
301
- 'country' => '',
 
 
302
  'blog' => get_current_blog_id(),
 
 
 
303
  );
304
- if(is_multisite()){
305
- if( !is_main_site() ){
306
- //not the main blog, force single blog search
307
- $array['blog'] = get_current_blog_id();
308
- }elseif( empty($array['blog']) && get_site_option('dbem_ms_global_events') ) {
309
- $array['blog'] = false;
 
 
 
 
310
  }
311
  }
312
- if( is_admin() ){
313
  //figure out default owning permissions
314
  $defaults['owner'] = !current_user_can('edit_others_events') ? get_current_user_id() : false;
315
  if( !array_key_exists('status', $array) && current_user_can('edit_others_events') ){
@@ -318,31 +474,5 @@ class EM_Events extends EM_Object implements Iterator {
318
  }
319
  return apply_filters('em_events_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
320
  }
321
-
322
- //TODO Implement object and interators for handling groups of events.
323
- public function rewind(){
324
- reset($this->events);
325
- }
326
-
327
- public function current(){
328
- $var = current($this->events);
329
- return $var;
330
- }
331
-
332
- public function key(){
333
- $var = key($this->events);
334
- return $var;
335
- }
336
-
337
- public function next(){
338
- $var = next($this->events);
339
- return $var;
340
- }
341
-
342
- public function valid(){
343
- $key = key($this->events);
344
- $var = ($key !== NULL && $key !== FALSE);
345
- return $var;
346
- }
347
  }
348
  ?>
4
  * Use this class to query and manipulate sets of events. If dealing with more than one event, you probably want to use this class in some way.
5
  *
6
  */
7
+ class EM_Events extends EM_Object {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  /**
10
  * Returns an array of EM_Events that match the given specs in the argument, or returns a list of future evetnts in future
14
  * @param array $args
15
  * @return EM_Event array()
16
  */
17
+ public static function get( $args = array(), $count=false ) {
18
+ global $wpdb;
19
  $events_table = EM_EVENTS_TABLE;
20
  $locations_table = EM_LOCATIONS_TABLE;
21
 
39
  $args = self::get_default_search($args);
40
  $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
41
  $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
42
+ $groupby_sql = '';
43
 
44
  //Get the default conditions
45
  $conditions = self::build_sql_conditions($args);
48
 
49
  //Get ordering instructions
50
  $EM_Event = new EM_Event();
51
+ $EM_Location = new EM_Location();
52
+ $orderby = self::build_sql_orderby($args, array_keys(array_merge($EM_Event->fields, $EM_Location->fields)), get_option('dbem_events_default_order'));
53
  //Now, build orderby sql
54
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
55
 
56
  //Create the SQL statement and execute
57
+
58
+ if( !$count && $args['array'] ){
59
+ $selectors_array = array();
60
+ foreach( array_keys($EM_Event->fields) as $field_selector){
61
+ $selectors_array[] = $events_table.'.'.$field_selector;
62
+ }
63
+ $selectors = implode(',', $selectors_array);
64
+ }elseif( EM_MS_GLOBAL ){
65
+ $selectors = $events_table.'.post_id, '.$events_table.'.blog_id';
66
+ $groupby_sql[] = $events_table.'.post_id, '. $events_table.'.blog_id';
67
+ }else{
68
+ $selectors = $events_table.'.post_id';
69
+ $groupby_sql[] = $events_table.'.post_id'; //prevent duplicates showing in lists
70
+ }
71
+ if( $count ){
72
+ $selectors = 'SQL_CALC_FOUND_ROWS *';
73
+ $limit = 'LIMIT 1';
74
+ $offset = 'OFFSET 0';
75
+ }
76
+
77
+ //add group_by if needed
78
+ $groupby_sql = !empty($groupby_sql) && is_array($groupby_sql) ? 'GROUP BY '.implode(',', $groupby_sql):'';
79
+
80
+ $sql = apply_filters('em_events_get_sql',"
81
  SELECT $selectors FROM $events_table
82
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
83
  $where
84
+ $groupby_sql $orderby_sql
85
  $limit $offset
86
+ ", $args);
87
+
88
  //If we're only counting results, return the number of results
89
  if( $count ){
90
+ $wpdb->query($sql);
91
+ return apply_filters('em_events_get_count', $wpdb->get_var('SELECT FOUND_ROWS()'), $args);
92
  }
93
+ $results = $wpdb->get_results( $sql, ARRAY_A);
94
 
95
  //If we want results directly in an array, why not have a shortcut here?
96
  if( $args['array'] == true ){
97
+ return apply_filters('em_events_get_array',$results, $args);
98
  }
99
 
100
  //Make returned results EM_Event objects
101
  $results = (is_array($results)) ? $results:array();
102
  $events = array();
103
+
104
+ if( EM_MS_GLOBAL ){
105
+ foreach ( $results as $event ){
106
+ $events[] = em_get_event($event['post_id'], $event['blog_id']);
107
+ }
108
+ }else{
109
+ foreach ( $results as $event ){
110
+ $events[] = em_get_event($event['post_id'], 'post_id');
111
+ }
112
  }
113
 
114
  return apply_filters('em_events_get', $events, $args);
119
  * @param $date
120
  * @return int
121
  */
122
+ public static function count_date($date){
123
  global $wpdb;
124
  $table_name = EM_EVENTS_TABLE;
125
  $sql = "SELECT COUNT(*) FROM $table_name WHERE (event_start_date like '$date') OR (event_start_date <= '$date' AND event_end_date >= '$date');";
126
  return apply_filters('em_events_count_date', $wpdb->get_var($sql));
127
  }
128
 
129
+ public static function count( $args = array() ){
130
  return apply_filters('em_events_count', self::get($args, true), $args);
131
  }
132
 
134
  * Will delete given an array of event_ids or EM_Event objects
135
  * @param unknown_type $id_array
136
  */
137
+ public static function delete( $array ){
 
138
  global $wpdb;
139
  //Detect array type and generate SQL for event IDs
140
+ $results = array();
141
+ if( !empty($array) && @get_class(current($array)) != 'EM_Event' ){
142
+ $events = self::get($array);
 
 
143
  }else{
144
+ $events = $array;
145
  }
146
+ $event_ids = array();
147
+ foreach ($events as $EM_Event){
148
+ $event_ids[] = $EM_Event->event_id;
149
+ $results[] = $EM_Event->delete();
 
 
 
 
 
 
 
 
 
150
  }
151
  //TODO add better error feedback on events delete fails
152
+ return apply_filters('em_events_delete', in_array(false, $results), $event_ids);
153
  }
154
 
155
 
160
  * @param array $secondary_args
161
  * @return string
162
  */
163
+ public static function output( $args ){
164
  global $EM_Event;
165
  $EM_Event_old = $EM_Event; //When looping, we can replace EM_Event global with the current event in the loop
166
+ //get page number if passed on by request (still needs pagination enabled to have effect)
167
+ $page_queryvar = !empty($args['page_queryvar']) ? $args['page_queryvar'] : 'pno';
168
+ if( !empty($args['pagination']) && !array_key_exists('page',$args) && !empty($_REQUEST[$page_queryvar]) && is_numeric($_REQUEST[$page_queryvar]) ){
169
+ $page = $args['page'] = $_REQUEST[$page_queryvar];
170
+ }
171
  //Can be either an array for the get search or an array of EM_Event objects
 
172
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Event' ){
173
  $func_args = func_get_args();
174
  $events = $func_args[0];
177
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
178
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
179
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
180
+ $events_count = count($events);
181
  }else{
182
  //Firstly, let's check for a limit/offset here, because if there is we need to remove it and manually do this
183
+ $args = apply_filters('em_events_output_args', self::get_default_search($args));
184
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
185
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
186
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
187
+ $args_count = $args;
188
+ $args_count['limit'] = false;
189
+ $args_count['offset'] = false;
190
+ $args_count['page'] = false;
191
+ $events_count = self::count($args_count);
192
  $events = self::get( $args );
193
  }
194
  //What format shall we output this to, or use default
196
 
197
  $output = "";
198
  $events = apply_filters('em_events_output_events', $events);
 
199
  if ( $events_count > 0 ) {
 
 
200
  foreach ( $events as $EM_Event ) {
201
+ $output .= $EM_Event->output($format);
 
 
 
 
202
  }
203
  //Add headers and footers to output
204
  if( $format == get_option ( 'dbem_event_list_item_format' ) ){
211
  $output = $format_header . $output . $format_footer;
212
  //Pagination (if needed/requested)
213
  if( !empty($args['pagination']) && !empty($limit) && $events_count > $limit ){
214
+ $output .= self::get_pagination_links($args, $events_count);
 
 
 
215
  }
216
  } else {
217
  $output = get_option ( 'dbem_no_events_message' );
223
  return $output;
224
  }
225
 
226
+ /**
227
+ * Generate a grouped list of events by year, month, week or day.
228
+ * @since 5.4.4.2
229
+ * @param array $args
230
+ * @return string
231
+ */
232
+ public static function output_grouped( $args = array() ){
233
+ //Reset some args to include pagination for if pagination is requested.
234
+ $args['limit'] = isset($args['limit']) ? $args['limit'] : get_option('dbem_events_default_limit');
235
+ $args['page'] = (!empty($args['page']) && is_numeric($args['page']) )? $args['page'] : 1;
236
+ $args['page'] = (!empty($args['pagination']) && !empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) )? $_REQUEST['pno'] : $args['page'];
237
+ $args['offset'] = ($args['page']-1) * $args['limit'];
238
+ $args['orderby'] = 'event_start_date,event_start_time,event_name'; // must override this to display events in right cronology.
239
+
240
+ $args['mode'] = !empty($args['mode']) ? $args['mode'] : get_option('dbem_event_list_groupby');
241
+ $args['header_format'] = !empty($args['header_format']) ? $args['header_format'] : get_option('dbem_event_list_groupby_header_format', '<h2>#s</h2>');
242
+ $args['date_format'] = !empty($args['date_format']) ? $args['date_format'] : get_option('dbem_event_list_groupby_format');
243
+ //Reset some vars for counting events and displaying set arrays of events
244
+ $atts = (array) $args;
245
+ $atts['pagination'] = false;
246
+ $atts['limit'] = false;
247
+ $atts['page'] = false;
248
+ $atts['offset'] = false;
249
+ //decide what form of dates to show
250
+ $events_count = self::count($atts);
251
+ ob_start();
252
+ if( $events_count > 0 ){
253
+ $EM_Events = self::get($args);
254
+ switch ( $args['mode'] ){
255
+ case 'yearly':
256
+ //go through the events and put them into a monthly array
257
+ $format = (!empty($args['date_format'])) ? $args['date_format']:'Y';
258
+ $events_dates = array();
259
+ foreach($EM_Events as $EM_Event){
260
+ $events_dates[date_i18n($format,$EM_Event->start)][] = $EM_Event;
261
+ }
262
+ foreach ($events_dates as $year => $events){
263
+ echo str_replace('#s', $year, $args['header_format']);
264
+ echo self::output($events, $atts);
265
+ }
266
+ break;
267
+ case 'monthly':
268
+ //go through the events and put them into a monthly array
269
+ $format = (!empty($args['date_format'])) ? $args['date_format']:'M Y';
270
+ $events_dates = array();
271
+ foreach($EM_Events as $EM_Event){
272
+ $events_dates[date_i18n($format, $EM_Event->start)][] = $EM_Event;
273
+ }
274
+ foreach ($events_dates as $month => $events){
275
+ echo str_replace('#s', $month, $args['header_format']);
276
+ echo self::output($events, $atts);
277
+ }
278
+ break;
279
+ case 'weekly':
280
+ $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
281
+ $events_dates = array();
282
+ foreach($EM_Events as $EM_Event){
283
+ $start_of_week = get_option('start_of_week');
284
+ $day_of_week = date('w',$EM_Event->start);
285
+ $day_of_week = date('w',$EM_Event->start);
286
+ $offset = $day_of_week - $start_of_week;
287
+ if($offset<0){ $offset += 7; }
288
+ $offset = $offset * 60*60*24; //days in seconds
289
+ $start_day = strtotime($EM_Event->start_date);
290
+ $events_dates[$start_day - $offset][] = $EM_Event;
291
+ }
292
+ foreach ($events_dates as $event_day_ts => $events){
293
+ echo str_replace('#s', date_i18n($format,$event_day_ts). get_option('dbem_dates_separator') .date_i18n($format,$event_day_ts+(60*60*24*6)), $args['header_format']);
294
+ echo self::output($events, $atts);
295
+ }
296
+ break;
297
+ default: //daily
298
+ //go through the events and put them into a daily array
299
+ $format = (!empty($args['date_format'])) ? $args['date_format']:get_option('date_format');
300
+ $events_dates = array();
301
+ foreach($EM_Events as $EM_Event){
302
+ $events_dates[strtotime($EM_Event->start_date)][] = $EM_Event;
303
+ }
304
+ foreach ($events_dates as $event_day_ts => $events){
305
+ echo str_replace('#s', date_i18n($format,$event_day_ts), $args['header_format']);
306
+ echo self::output($events, $atts);
307
+ }
308
+ break;
309
+ }
310
+ //Show the pagination links (unless there's less than $limit events)
311
+ if( !empty($args['pagination']) && !empty($args['limit']) && $events_count > $args['limit'] ){
312
+ echo self::get_pagination_links($args, $events_count, 'search_events_grouped');
313
+ }
314
+ }else{
315
+ echo get_option ( 'dbem_no_events_message' );
316
+ }
317
+ return ob_get_clean();
318
+ }
319
+
320
+ public static function get_pagination_links($args, $count, $search_action = 'search_events', $default_args = array()){
321
+ //get default args if we're in a search, supply to parent since we can't depend on late static binding until WP requires PHP 5.3 or later
322
+ if( empty($default_args) && (!empty($args['ajax']) || !empty($_REQUEST['action']) && $_REQUEST['action'] == $search_action) ){
323
+ $default_args = self::get_default_search();
324
+ $default_args['limit'] = get_option('dbem_events_default_limit');
325
+ }
326
+ return parent::get_pagination_links($args, $count, $search_action, $default_args);
327
+ }
328
+
329
+ /* (non-PHPdoc)
330
+ * DEPRECATED - this class should just contain static classes,
331
+ * @see EM_Object::can_manage()
332
+ */
333
+ function can_manage($event_ids = false , $admin_capability = false, $user_to_check = false ){
334
  global $wpdb;
335
  if( current_user_can('edit_others_events') ){
336
  return apply_filters('em_events_can_manage', true, $event_ids);
338
  if( EM_Object::array_is_numeric($event_ids) ){
339
  $condition = implode(" OR event_id=", $event_ids);
340
  //we try to find any of these events that don't belong to this user
341
+ $results = $wpdb->get_var("SELECT COUNT(*) FROM ". EM_EVENTS_TABLE ." WHERE event_owner != '". get_current_user_id() ."' event_id=$condition;");
342
  return apply_filters('em_events_can_manage', ($results == 0), $event_ids);
343
  }
344
  return apply_filters('em_events_can_manage', false, $event_ids);
345
  }
346
 
347
+ public static function get_post_search($args = array(), $filter = false, $request = array(), $accepted_args = array()){
348
+ //supply $accepted_args to parent argument since we can't depend on late static binding until WP requires PHP 5.3 or later
349
+ $accepted_args = !empty($accepted_args) ? $accepted_args : array_keys(self::get_default_search());
350
+ return apply_filters('em_events_get_post_search', parent::get_post_search($args, $filter, $request, $accepted_args));
 
 
 
 
 
 
 
 
 
351
  }
352
 
353
  /* Overrides EM_Object method to apply a filter to result
354
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
355
  */
356
+ public static function build_sql_conditions( $args = array() ){
357
+ self::$context = EM_POST_TYPE_EVENT;
358
  $conditions = parent::build_sql_conditions($args);
359
  if( !empty($args['search']) ){
360
+ $like_search = array('event_name',EM_EVENTS_TABLE.'.post_content','location_name','location_address','location_town','location_postcode','location_state','location_country','location_region');
361
  $conditions['search'] = "(".implode(" LIKE '%{$args['search']}%' OR ", $like_search). " LIKE '%{$args['search']}%')";
362
  }
363
+ $conditions['status'] = "(`event_status` >= 0 )"; //shows pending & published if not defined
364
+ if( array_key_exists('status',$args) ){
365
+ if( is_numeric($args['status']) ){
366
+ $conditions['status'] = "(`event_status`={$args['status']})"; //pending or published
367
+ }elseif( $args['status'] == 'pending' ){
368
+ $conditions['status'] = "(`event_status`=0)"; //pending
369
+ }elseif( $args['status'] == 'publish' ){
370
+ $conditions['status'] = "(`event_status`=1)"; //published
371
+ }elseif( $args['status'] === null || $args['status'] == 'draft' ){
372
+ $conditions['status'] = "(`event_status` IS NULL )"; //show draft items
373
+ }elseif( $args['status'] == 'trash' ){
374
+ $conditions['status'] = "(`event_status` = -1 )"; //show trashed items
375
+ }elseif( $args['status'] == 'all'){
376
+ $conditions['status'] = "(`event_status` >= 0 OR `event_status` IS NULL)"; //search all statuses that aren't trashed
377
+ }elseif( $args['status'] == 'everything'){
378
+ unset($conditions['status']); //search all statuses
379
+ }
380
+ }
381
+ //private events
382
+ if( empty($args['private']) ){
383
+ $conditions['private'] = "(`event_private`=0)";
384
+ }elseif( !empty($args['private_only']) ){
385
+ $conditions['private_only'] = "(`event_private`=1)";
386
+ }
387
+ if( EM_MS_GLOBAL && !empty($args['blog']) ){
388
+ if( is_numeric($args['blog']) ){
389
+ if( is_main_site($args['blog']) ){
390
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']} OR ".EM_EVENTS_TABLE.".blog_id IS NULL)";
391
+ }else{
392
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']})";
393
+ }
394
+ }else{
395
+ if( !is_array($args['blog']) && preg_match('/^([\-0-9],?)+$/', $args['blog']) ){
396
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id IN ({$args['blog']}) )";
397
+ }elseif( is_array($args['blog']) && self::array_is_numeric($args['blog']) ){
398
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id IN (".implode(',',$args['blog']).") )";
399
+ }
400
+ }
401
+ }
402
+ if( $args['bookings'] === 'user' && is_user_logged_in()){
403
+ //get bookings of user
404
+ $EM_Person = new EM_Person(get_current_user_id());
405
+ $booking_ids = $EM_Person->get_bookings(true);
406
+ if( count($booking_ids) > 0 ){
407
+ $conditions['bookings'] = "(event_id IN (SELECT event_id FROM ".EM_BOOKINGS_TABLE." WHERE booking_id IN (".implode(',',$booking_ids).")))";
408
+ }else{
409
+ $conditions['bookings'] = "(event_id = 0)";
410
+ }
411
  }
412
+ //post search
413
+ if( !empty($args['post_id'])){
414
+ if( is_array($args['post_id']) ){
415
+ $conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id IN (".implode(',',$args['post_id'])."))";
416
  }else{
417
+ $conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id={$args['post_id']})";
418
  }
419
  }
420
  return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
423
  /* Overrides EM_Object method to apply a filter to result
424
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
425
  */
426
+ public static function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
427
+ self::$context = EM_POST_TYPE_EVENT;
428
  return apply_filters( 'em_events_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
429
  }
430
 
431
  /*
432
  * Adds custom Events search defaults
433
+ * @param array $array_or_defaults may be the array to override defaults
434
  * @param array $array
435
  * @return array
436
  * @uses EM_Object#get_default_search()
437
  */
438
+ public static function get_default_search( $array_or_defaults = array(), $array = array() ){
439
+ self::$context = EM_POST_TYPE_EVENT;
440
  $defaults = array(
441
  'orderby' => get_option('dbem_events_default_orderby'),
442
  'order' => get_option('dbem_events_default_order'),
443
+ 'bookings' => false, //if set to true, only events with bookings enabled are returned
444
  'status' => 1, //approved events only
445
  'format_header' => '', //events can have custom html above the list
446
  'format_footer' => '', //events can have custom html below the list
447
+ 'town' => false,
448
+ 'state' => false,
449
+ 'country' => false,
450
+ 'region' => false,
451
  'blog' => get_current_blog_id(),
452
+ 'private' => current_user_can('read_private_events'),
453
+ 'private_only' => false,
454
+ 'post_id' => false
455
  );
456
+ //sort out whether defaults were supplied or just the array of search values
457
+ if( empty($array) ){
458
+ $array = $array_or_defaults;
459
+ }else{
460
+ $defaults = array_merge($defaults, $array_or_defaults);
461
+ }
462
+ //specific functionality
463
+ if( EM_MS_GLOBAL && (!is_admin() || defined('DOING_AJAX')) ){
464
+ if( empty($array['blog']) && is_main_site() && get_site_option('dbem_ms_global_events') ){
465
+ $array['blog'] = false;
466
  }
467
  }
468
+ if( is_admin() && !defined('DOING_AJAX') ){
469
  //figure out default owning permissions
470
  $defaults['owner'] = !current_user_can('edit_others_events') ? get_current_user_id() : false;
471
  if( !array_key_exists('status', $array) && current_user_can('edit_others_events') ){
474
  }
475
  return apply_filters('em_events_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
476
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  }
478
  ?>
classes/em-location-post-admin.php ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Post_Admin{
3
+ public static function init(){
4
+ global $pagenow;
5
+ if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
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
13
+ add_action('before_delete_post',array('EM_Location_Post_Admin','before_delete_post'),10,1);
14
+ add_action('trashed_post',array('EM_Location_Post_Admin','trashed_post'),10,1);
15
+ add_action('untrash_post',array('EM_Location_Post_Admin','untrash_post'),10,1);
16
+ add_action('untrashed_post',array('EM_Location_Post_Admin','untrashed_post'),10,1);
17
+ //Notices
18
+ add_action('admin_notices',array('EM_Location_Post_Admin','admin_notices'));
19
+ add_action('post_updated_messages',array('EM_Location_Post_Admin','admin_notices_filter'),1,1);
20
+ }
21
+
22
+ public static function admin_head(){
23
+ global $post, $EM_Location;
24
+ if( !empty($post) && $post->post_type == EM_POST_TYPE_LOCATION ){
25
+ $EM_Location = em_get_location($post);
26
+ }
27
+ }
28
+
29
+ public static function admin_notices(){
30
+ //When editing
31
+ global $post, $EM_Notices;
32
+ if( !empty($post) && $post->post_type == EM_POST_TYPE_LOCATION){
33
+ }
34
+ }
35
+
36
+ public static function admin_notices_filter($messages){
37
+ //When editing
38
+ global $post, $EM_Notices;
39
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
40
+ if ( $EM_Notices->count_errors() > 0 ) {
41
+ unset($_GET['message']);
42
+ }
43
+ }
44
+ return $messages;
45
+ }
46
+
47
+ /**
48
+ * Hooks in just before a post is saves and does a quick post meta validation.
49
+ * This prevents the location from being temporarily published and firing hooks that indicate this before we come in on save_post and properly save data.
50
+ * @param array $data
51
+ * @param array $postarr
52
+ * @return array
53
+ */
54
+ public static function wp_insert_post_data( $data, $postarr ){
55
+ global $wpdb, $EM_Event, $EM_Location, $EM_Notices, $EM_SAVING_LOCATION;
56
+ if( !empty($EM_SAVING_LOCATION) ) return $data; //If we're saving a location via EM_Location::save() we should never run the below
57
+ $post_type = $data['post_type'];
58
+ $post_ID = !empty($postarr['ID']) ? $postarr['ID'] : false;
59
+ $is_post_type = $post_type == EM_POST_TYPE_LOCATION;
60
+ $saving_status = !in_array($data['post_status'], array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
61
+ $untrashing = $post_ID && defined('UNTRASHING_'.$post_ID);
62
+ if( !$untrashing && $is_post_type && $saving_status ){
63
+ if( !empty($_REQUEST['_emnonce']) && wp_verify_nonce($_REQUEST['_emnonce'], 'edit_location') ){
64
+ //this is only run if we know form data was submitted, hence the nonce
65
+ $EM_Location = em_get_location();
66
+ //Handle Errors by making post draft
67
+ $get_meta = $EM_Location->get_post_meta();
68
+ $validate_meta = $EM_Location->validate_meta();
69
+ if( !$get_meta || !$validate_meta ) $data['post_status'] = 'draft';
70
+ }
71
+ }
72
+ return $data;
73
+ }
74
+
75
+ /**
76
+ * Once the post is saved, saves EM meta data
77
+ * @param int $post_id
78
+ */
79
+ public static function save_post($post_id){
80
+ global $wpdb, $EM_Location, $EM_Notices, $EM_SAVING_LOCATION;
81
+ if( !empty($EM_SAVING_LOCATION) ) return; //If we're saving a location via EM_Location::save() we should never run the below
82
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
83
+ $is_post_type = get_post_type($post_id) == EM_POST_TYPE_LOCATION;
84
+ if(!defined('UNTRASHING_'.$post_id) && $is_post_type && $saving_status){
85
+ if( !empty($_REQUEST['_emnonce']) && wp_verify_nonce($_REQUEST['_emnonce'], 'edit_location')){
86
+ $EM_Location = em_get_location($post_id, 'post_id');
87
+ do_action('em_location_save_pre', $EM_Location);
88
+ $get_meta = $EM_Location->get_post_meta();
89
+ $save_meta = $EM_Location->save_meta();
90
+ //Handle Errors by making post draft
91
+ if( !$get_meta || !$save_meta ){
92
+ $EM_Location->set_status(null, true);
93
+ $EM_Notices->add_error( '<strong>'.sprintf(__('Your %s details are incorrect and cannot be published, please correct these errors first:','dbem'),__('location','dbem')).'</strong>', true); //Always seems to redirect, so we make it static
94
+ $EM_Notices->add_error($EM_Location->get_errors(), true); //Always seems to redirect, so we make it static
95
+ apply_filters('em_location_save', false , $EM_Location);
96
+ }else{
97
+ apply_filters('em_location_save', true , $EM_Location);
98
+ }
99
+ }else{
100
+ //do a quick and dirty update
101
+ $EM_Location = new EM_Location($post_id, 'post_id');
102
+ do_action('em_location_save_pre', $EM_Location);
103
+ //check for existence of index
104
+ $loc_truly_exists = $EM_Location->location_id > 0 && $wpdb->get_var('SELECT location_id FROM '.EM_LOCATIONS_TABLE." WHERE location_id={$EM_Location->location_id}") == $EM_Location->location_id;
105
+ if(empty($EM_Location->location_id) || !$loc_truly_exists){ $EM_Location->save_meta(); }
106
+ //continue
107
+ $EM_Location->get_previous_status(); //before we save anything
108
+ $location_status = $EM_Location->get_status(true);
109
+ $where_array = array($EM_Location->location_name, $EM_Location->location_owner, $EM_Location->location_slug, $EM_Location->location_private, $EM_Location->location_id);
110
+ $sql = $wpdb->prepare("UPDATE ".EM_LOCATIONS_TABLE." SET location_name=%s, location_owner=%s, location_slug=%s, location_private=%d, location_status={$location_status} WHERE location_id=%d", $where_array);
111
+ $wpdb->query($sql);
112
+ apply_filters('em_location_save', true , $EM_Location);
113
+ }
114
+ }
115
+ }
116
+
117
+ public static function before_delete_post($post_id){
118
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
119
+ $EM_Location = em_get_location($post_id,'post_id');
120
+ $EM_Location->delete_meta();
121
+ }
122
+ }
123
+
124
+ public static function trashed_post($post_id){
125
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
126
+ global $EM_Notices;
127
+ $EM_Location = em_get_location($post_id,'post_id');
128
+ $EM_Location->set_status(-1);
129
+ $EM_Notices->remove_all(); //no validation/notices needed
130
+ }
131
+ }
132
+
133
+ public static function untrash_post($post_id){
134
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
135
+ //set a constant so we know this event doesn't need 'saving'
136
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
137
+ }
138
+ }
139
+
140
+ public static function untrashed_post($post_id){
141
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
142
+ global $EM_Notices;
143
+ $EM_Location = new EM_Location($post_id,'post_id');
144
+ $EM_Location->set_status($EM_Location->get_status());
145
+ $EM_Notices->remove_all(); //no validation/notices needed
146
+ }
147
+ }
148
+
149
+ public static function meta_boxes(){
150
+ add_meta_box('em-location-where', __('Where','dbem'), array('EM_Location_Post_Admin','meta_box_where'),EM_POST_TYPE_LOCATION, 'normal','high');
151
+ //add_meta_box('em-location-metadump', __('EM_Location Meta Dump','dbem'), array('EM_Location_Post_Admin','meta_box_metadump'),EM_POST_TYPE_LOCATION, 'normal','high');
152
+ if( get_option('dbem_location_attributes_enabled') ){
153
+ add_meta_box('em-location-attributes', __('Attributes','dbem'), array('EM_Location_Post_Admin','meta_box_attributes'),EM_POST_TYPE_LOCATION, 'normal','default');
154
+ }
155
+ }
156
+
157
+ public static function meta_box_metadump(){
158
+ global $post,$EM_Location;
159
+ echo "<pre>"; print_r(get_post_custom($post->ID)); echo "</pre>";
160
+ echo "<pre>"; print_r($EM_Location); echo "</pre>";
161
+ }
162
+ public static function meta_box_where(){
163
+ ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_location'); ?>" /><?php
164
+ em_locate_template('forms/location/where.php',true);
165
+ }
166
+
167
+ public static function meta_box_attributes(){
168
+ em_locate_template('forms/location/attributes.php',true);
169
+ }
170
+ }
171
+ add_action('admin_init',array('EM_Location_Post_Admin','init'));
classes/em-location-post.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Post {
3
+ public static function init(){
4
+ //Front Side Modifiers
5
+ if( !is_admin() ){
6
+ //override single page with formats?
7
+ add_filter('the_content', array('EM_Location_Post','the_content'));
8
+ //override excerpts?
9
+ if( get_option('dbem_cp_locations_excerpt_formats') ){
10
+ add_filter('the_excerpt', array('EM_Location_Post','the_excerpt'));
11
+ }
12
+ //display as page or other template?
13
+ if( get_option('dbem_cp_locations_template') ){
14
+ add_filter('single_template',array('EM_Location_Post','single_template'));
15
+ }
16
+ //add classes to body and post_class()
17
+ if( get_option('dbem_cp_locations_post_class') ){
18
+ add_filter('post_class', array('EM_Location_Post','post_class'), 10, 3);
19
+ }
20
+ if( get_option('dbem_cp_locations_body_class') ){
21
+ add_filter('body_class', array('EM_Location_Post','body_class'), 10, 3);
22
+ }
23
+ }
24
+ add_action('parse_query', array('EM_Location_Post','parse_query'));
25
+ }
26
+
27
+ /**
28
+ * Overrides the default post format of a location and can display a location as a page, which uses the page.php template.
29
+ * @param string $template
30
+ * @return string
31
+ */
32
+ public static function single_template($template){
33
+ global $post;
34
+ if( !locate_template('single-'.EM_POST_TYPE_LOCATION.'.php') && $post->post_type == EM_POST_TYPE_LOCATION ){
35
+ //do we have a default template to choose for events?
36
+ if( get_option('dbem_cp_locations_template') == 'page' ){
37
+ $post_templates = array('page.php','index.php');
38
+ }else{
39
+ $post_templates = array(get_option('dbem_cp_locations_template'));
40
+ }
41
+ if( !empty($post_templates) ){
42
+ $post_template = locate_template($post_templates,false);
43
+ if( !empty($post_template) ) $template = $post_template;
44
+ }
45
+ }
46
+ return $template;
47
+ }
48
+
49
+ public static function post_class( $classes, $class, $post_id ){
50
+ $post = get_post($post_id);
51
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
52
+ foreach( explode(' ', get_option('dbem_cp_locations_post_class')) as $class ){
53
+ $classes[] = esc_attr($class);
54
+ }
55
+ }
56
+ return $classes;
57
+ }
58
+
59
+ public static function body_class( $classes ){
60
+ if( em_is_location_page() ){
61
+ foreach( explode(' ', get_option('dbem_cp_locations_body_class')) as $class ){
62
+ $classes[] = esc_attr($class);
63
+ }
64
+ }
65
+ return $classes;
66
+ }
67
+
68
+ /**
69
+ * Overrides the_excerpt if this is an location post type
70
+ */
71
+ public static function the_excerpt($content){
72
+ global $post;
73
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
74
+ $EM_Location = em_get_location($post);
75
+ $output = !empty($EM_Location->post_excerpt) ? get_option('dbem_location_excerpt_format'):get_option('dbem_location_excerpt_alt_format');
76
+ $content = $EM_Location->output($output);
77
+ }
78
+ return $content;
79
+ }
80
+
81
+ public static function the_content( $content ){
82
+ global $post, $EM_Location;
83
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
84
+ if( is_archive() || is_search() ){
85
+ if( get_option('dbem_cp_locations_archive_formats') ){
86
+ $EM_Location = em_get_location($post);
87
+ $content = $EM_Location->output(get_option('dbem_location_list_item_format'));
88
+ }
89
+ }else{
90
+ if( get_option('dbem_cp_locations_formats') && !post_password_required() ){
91
+ $EM_Location = em_get_location($post);
92
+ ob_start();
93
+ em_locate_template('templates/location-single.php',true);
94
+ $content = ob_get_clean();
95
+ }
96
+ }
97
+ }
98
+ return $content;
99
+ }
100
+
101
+ public static function parse_query(){
102
+ global $wp_query;
103
+ if( !empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] == EM_POST_TYPE_LOCATION ){
104
+ if( is_admin() ){
105
+ $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby']:'title';
106
+ $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
107
+ }else{
108
+ if( empty($wp_query->query_vars['location']) ) {
109
+ if( get_option('dbem_locations_default_archive_orderby') == 'title'){
110
+ $wp_query->query_vars['orderby'] = 'title';
111
+ }else{
112
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
113
+ $wp_query->query_vars['meta_key'] = get_option('dbem_locations_default_archive_orderby','_location_country');
114
+ }
115
+ $wp_query->query_vars['order'] = get_option('dbem_locations_default_archive_orderby','ASC');
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ EM_Location_Post::init();
classes/em-location-posts-admin.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Posts_Admin{
3
+ public static function init(){
4
+ global $pagenow;
5
+ if($pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == EM_POST_TYPE_LOCATION ){ //only needed if editing post
6
+ //hide some cols by default:
7
+ $screen = 'edit-'.EM_POST_TYPE_LOCATION;
8
+ $hidden = get_user_option( 'manage' . $screen . 'columnshidden' );
9
+ if( !$hidden ){
10
+ $hidden = array('location-id');
11
+ update_user_option(get_current_user_id(), "manage{$screen}columnshidden", $hidden, true);
12
+ }
13
+ add_action('admin_head', array('EM_Location_Posts_Admin','admin_head'));
14
+ }
15
+ add_filter('manage_edit-'.EM_POST_TYPE_LOCATION.'_columns' , array('EM_Location_Posts_Admin','columns_add'));
16
+ add_filter('manage_'.EM_POST_TYPE_LOCATION.'_posts_custom_column' , array('EM_Location_Posts_Admin','columns_output'),10,2 );
17
+ }
18
+
19
+ public static function admin_head(){
20
+ //quick hacks to make event admin table make more sense for events
21
+ ?>
22
+ <script type="text/javascript">
23
+ jQuery(document).ready( public static function($){
24
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
25
+ });
26
+ </script>
27
+ <style>
28
+ table.fixed{ table-layout:auto !important; }
29
+ .tablenav select[name="m"] { display:none; }
30
+ </style>
31
+ <?php
32
+ }
33
+
34
+ public static function admin_menu(){
35
+ global $menu, $submenu;
36
+ // Add a submenu to the custom top-level menu:
37
+ $plugin_pages = array();
38
+ $plugin_pages[] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Locations', 'dbem'), __('Locations', 'dbem'), 'edit_locations', 'events-manager-locations', "edit.php?post_type=event");
39
+ $plugin_pages = apply_filters('em_create_locationss_submenu',$plugin_pages);
40
+ }
41
+
42
+ public static function columns_add($columns) {
43
+ //prepend ID after checkbox
44
+ if( array_key_exists('cb', $columns) ){
45
+ $cb = $columns['cb'];
46
+ unset($columns['cb']);
47
+ $id_array = array('cb'=>$cb, 'location-id' => sprintf(__('%s ID','dbem'),__('Location','dbem')));
48
+ }else{
49
+ $id_array = array('location-id' => sprintf(__('%s ID','dbem'),__('Location','dbem')));
50
+ }
51
+ unset($columns['author']);
52
+ unset($columns['date']);
53
+ unset($columns['comments']);
54
+ return array_merge($id_array, $columns, array(
55
+ 'address' => __('Address','dbem'),
56
+ 'town' => __('Town','dbem'),
57
+ 'state' => __('State','dbem'),
58
+ 'country' => __('Country','dbem')
59
+ ));
60
+ }
61
+
62
+ public static function columns_output( $column ) {
63
+ global $post;
64
+ $post = em_get_location($post);
65
+ switch ( $column ) {
66
+ case 'location-id':
67
+ echo $post->location_id;
68
+ break;
69
+ case 'address':
70
+ echo $post->location_address;
71
+ break;
72
+ case 'town':
73
+ echo $post->location_town;
74
+ break;
75
+ case 'state':
76
+ echo $post->location_state;
77
+ break;
78
+ case 'country':
79
+ echo $post->location_country;
80
+ break;
81
+ }
82
+ }
83
+ }
84
+ add_action('admin_init', array('EM_Location_Posts_Admin','init'));
classes/em-location.php CHANGED
@@ -1,206 +1,538 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Object that holds location info and related functions
4
  * @author marcus
5
  */
6
  class EM_Location extends EM_Object {
7
  //DB Fields
8
- var $id = '';
9
- var $slug = '';
10
- var $name = '';
11
- var $address = '';
12
- var $town = '';
13
- var $state = '';
14
- var $postcode = '';
15
- var $region = '';
16
- var $country = '';
17
- var $latitude = '';
18
- var $longitude = '';
19
- var $description = '';
20
- var $owner = '';
 
 
 
21
  //Other Vars
22
  var $fields = array(
23
- 'location_id' => array('name'=>'id','type'=>'%d'),
24
- 'location_slug' => array('name'=>'slug','type'=>'%s'),
25
- 'location_name' => array('name'=>'name','type'=>'%s'),
26
- 'location_address' => array('name'=>'address','type'=>'%s'),
27
- 'location_town' => array('name'=>'town','type'=>'%s'),
28
- 'location_state' => array('name'=>'state','type'=>'%s'),
29
- 'location_postcode' => array('name'=>'postcode','type'=>'%s'),
30
- 'location_region' => array('name'=>'region','type'=>'%s'),
31
- 'location_country' => array('name'=>'country','type'=>'%s'),
32
- 'location_latitude' => array('name'=>'latitude','type'=>'%f'),
33
- 'location_longitude' => array('name'=>'longitude','type'=>'%f'),
34
- 'location_description' => array('name'=>'description','type'=>'%s'),
35
- 'location_owner' => array('name'=>'owner','type'=>'%d')
 
 
 
36
  );
 
 
37
  var $image_url = '';
38
  var $required_fields = array();
39
  var $feedback_message = "";
40
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
41
  var $errors = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  /**
44
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
45
  * @param $location_data
 
46
  * @return null
47
  */
48
- function EM_Location( $location_data = 0 ) {
 
49
  //Initialize
50
- $this->required_fields = array("name" => __('The location name', 'dbem'), "address" => __('The location address', 'dbem'), "town" => __('The location town', 'dbem'), "country" => __('The country', 'dbem'),);
51
- if( !empty($location_data) ){
52
- //Load location data
53
- if( is_array($location_data) && isset($location_data['location_name']) ){
54
- $location = $location_data;
55
- }elseif( !empty($location_data) ){
56
- //Retreiving from the database
57
- global $wpdb;
58
- if( is_numeric($location_data) ){
59
- $sql = "SELECT * FROM ". EM_LOCATIONS_TABLE ." WHERE location_id ='{$location_data}'";
60
- $location = $wpdb->get_row($sql, ARRAY_A);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }else{
62
- $sql = "SELECT * FROM ". EM_LOCATIONS_TABLE ." WHERE location_slug ='{$location_data}'";
63
- $location = $wpdb->get_row($sql, ARRAY_A);
64
  }
 
65
  }
66
- //If gmap is turned off, values may not be returned and set, so we set it here
67
- if(empty($location['location_latitude'])) {
68
- $location['location_latitude'] = 0;
69
- $location['location_longitude'] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
- //Save into the object
72
- $this->to_object($location, true);
73
- $this->get_image_url();
74
- add_filter('em_location_save',array(&$this,'image_upload'));
75
- }
76
- do_action('em_location', $this, $location_data);
 
 
 
 
 
77
  }
78
 
79
- function get_post(){
80
- //We are getting the values via POST or GET
 
 
 
 
 
81
  do_action('em_location_get_post_pre', $this);
82
- $location = array();
83
- $location['location_id'] = ( !empty($_POST['location_id']) ) ? $_POST['location_id']:'';
84
- $location['location_name'] = ( !empty($_POST['location_name']) ) ? stripslashes($_POST['location_name']):'';
85
- if( current_user_can('edit_others_events') ){
86
- $location['location_owner'] = ( !empty($_POST['location_owner']) && is_numeric($_POST['location_owner']) ) ? $_POST['location_owner']:'';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
- $location['location_address'] = ( !empty($_POST['location_address']) ) ? stripslashes($_POST['location_address']):'';
89
- $location['location_town'] = ( !empty($_POST['location_town']) ) ? stripslashes($_POST['location_town']):'';
90
- $location['location_state'] = ( !empty($_POST['location_state']) ) ? stripslashes($_POST['location_state']):'';
91
- $location['location_postcode'] = ( !empty($_POST['location_postcode']) ) ? stripslashes($_POST['location_postcode']):'';
92
- $location['location_region'] = ( !empty($_POST['location_region']) ) ? stripslashes($_POST['location_region']):'';
93
- $location['location_country'] = ( !empty($_POST['location_country']) ) ? stripslashes($_POST['location_country']):'';
94
- $location['location_latitude'] = ( !empty($_POST['location_latitude']) ) ? $_POST['location_latitude']:'';
95
- $location['location_longitude'] = ( !empty($_POST['location_longitude']) ) ? $_POST['location_longitude']:'';
96
- $location['location_description'] = ( !empty($_POST['content']) ) ? stripslashes($_POST['content']):'';
97
- $this->to_object( apply_filters('em_location_get_post', $location, $this) );
98
- return apply_filters('em_location_get_post',$this->validate(),$this);
99
  }
100
-
 
 
 
 
 
 
 
 
 
 
 
101
  /**
102
  * Validates the location. Should be run during any form submission or saving operation.
103
  * @return boolean
104
  */
105
- function validate(){
106
  //check required fields
107
  foreach ( $this->required_fields as $field => $description) {
108
- if( $field == 'country' && !array_key_exists($this->country, em_get_countries()) ){
109
  //country specific checking
110
- $this->add_error( $this->required_fields['country'].__(" is required.", "dbem") );
111
  }elseif ( $this->$field == "" ) {
112
  $this->add_error( $description.__(" is required.", "dbem") );
113
  }
114
  }
115
- $this->image_validate();
116
- return apply_filters('em_location_validate', ( count($this->errors) == 0 ), $this);
117
  }
118
 
119
  function save(){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  global $wpdb, $current_user;
121
- $table = EM_LOCATIONS_TABLE;
122
- if( $this->validate() ){
123
- if( $this->can_manage('edit_locations','edit_others_locations') ){
124
- //owner person can be anyone the admin wants, but the creator if not.
125
- if( current_user_can('edit_others_events') ){
126
- $this->owner = ( $this->owner > 0 ) ? $this->owner:0;
127
- }else{
128
- //force user id - user is either editing a location or making a new one, as can_manage checks ownership too.
129
- $this->owner = get_current_user_id();
 
 
 
130
  }
131
- get_currentuserinfo();
132
- do_action('em_location_save_pre', $this);
133
- $this->slug = $this->sanitize_title();
134
- $data = $this->to_array();
135
- unset($data['location_id']);
136
- unset($data['location_image_url']);
137
- if($this->id != ''){
138
- $where = array( 'location_id' => $this->id );
139
- $result = $wpdb->update($table, $data, $where, $this->get_types($data));
140
- if( $result !== false ){
141
- $this->feedback_message = sprintf(__('%s successfully updated.', 'dbem'), __('Location','dbem'));
142
- }else{
143
- $this->add_error( sprintf(__('Could not save the %s details due to a database error.', 'dbem'),__('location','dbem') ));
144
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  }else{
146
- $result = $wpdb->insert($table, $data, $this->get_types($data));
147
- $this->id = $wpdb->insert_id;
148
- if( $result !== false ){
149
- $this->feedback_message = sprintf(__('%s successfully added.', 'dbem'), __('Location','dbem'));
150
- }else{
151
- $this->add_error( sprintf(__('Could not save the %s details due to a database error.', 'dbem'),__('location','dbem') ));
152
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  }
154
- return apply_filters('em_location_save', ( $this->id > 0 && count($this->errors) == 0 ), $this);
 
 
 
155
  }else{
156
- $this->add_error( sprintf(__('You do not have permission to create/edit %s.','dbem'), __('locations','dbem')) );
 
 
 
 
 
 
 
 
 
157
  }
158
  }
159
- return apply_filters('em_location_save', false, $this, false);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
161
 
162
  /**
163
- * Takes the title and gives either a unique slug or returns the currently used slug if this record already has it.
164
- * @param unknown_type $title
 
 
165
  */
166
- function sanitize_title($iteration = 1){
167
  global $wpdb;
168
- //Generate the slug. If this is a new event, create the slug automatically, if not, verify it is still unique and if not rewrite
169
- if( empty($this->slug) ){
170
- $this->slug = sanitize_title($this->name);
171
- }
172
- $slug = $this->slug;
173
- $slug_matches = $wpdb->get_results('SELECT location_id FROM '.EM_LOCATIONS_TABLE." WHERE location_slug='{$slug}'", ARRAY_A);
174
- if( count($slug_matches) > 0 ){ //we will check that the slug is unique
175
- if( $slug_matches[0]['location_id'] != $this->id || count($slug_matches) > 1 ){
176
- //we have a conflict, so try another alternative
177
- $this->slug = preg_replace('/\-[0-9]+$/', '', $slug).'-'.($iteration+1);
178
- $this->sanitize_title($iteration+1);
179
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
- return apply_filters('em_location_sanitize_title', $this->slug, $this);
182
  }
183
 
184
- function delete(){
185
- global $wpdb;
186
- if( current_user_can('delete_locations') ){
187
- do_action('em_location_delete_pre', $this);
188
- $table_name = EM_LOCATIONS_TABLE;
189
- $sql = "DELETE FROM $table_name WHERE location_id = '{$this->id}';";
190
- $result = $wpdb->query($sql);
191
- $result = $this->image_delete() && $result;
192
- if( $result ){
193
- $this->feedback_message = sprintf(__('%s successfully deleted.', 'dbem'), __('Location','dbem')) ;
194
- }else{
195
- $this->add_error( sprintf(__('%s could not be deleted.', 'dbem'), __('Location','dbem')) );
196
- }
197
- }else{
198
- $this->add_error( sprintf(__('You do not have permission to delete %s.','dbem'), __('locations','dbem')) );
199
- $result = false;
200
  }
201
- return apply_filters('em_location_delete', $result, $this);
202
  }
203
-
204
  function load_similar($criteria){
205
  global $wpdb;
206
  if( !empty($criteria['location_name']) && !empty($criteria['location_name']) && !empty($criteria['location_name']) ){
@@ -219,7 +551,7 @@ class EM_Location extends EM_Object {
219
  function has_events(){
220
  global $wpdb;
221
  $events_table = EM_EVENTS_TABLE;
222
- $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE location_id = {$this->id}";
223
  $affected_events = $wpdb->get_row($sql);
224
  return apply_filters('em_location_has_events', (count($affected_events) > 0), $this);
225
  }
@@ -227,8 +559,103 @@ class EM_Location extends EM_Object {
227
  /**
228
  * Can the user manage this location?
229
  */
230
- function can_manage( $owner_capability = false, $admin_capability = false ){
231
- return apply_filters('em_location_can_manage', parent::can_manage($owner_capability, $admin_capability), $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  }
233
 
234
  function output_single($target = 'html'){
@@ -236,109 +663,287 @@ class EM_Location extends EM_Object {
236
  return apply_filters('em_location_output_single', $this->output($format, $target), $this, $target);
237
  }
238
 
239
- function output($format, $target="html") {
240
- preg_match_all('/\{([a-zA-Z0-9_]+)\}([^{]+)\{\/[a-zA-Z0-9_]+\}/', $format, $conditionals);
241
- if( count($conditionals[0]) > 0 ){
242
- //Check if the language we want exists, if not we take the first language there
243
- foreach($conditionals[1] as $key => $condition){
244
- $format = str_replace($conditionals[0][$key], apply_filters('em_location_output_condition', '', $conditionals[0][$key], $condition, $this), $format);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
- $location_string = $format;
248
- preg_match_all("/#_[A-Za-z]+/", $format, $placeholders);
249
- foreach($placeholders[0] as $result) {
250
- $match = true;
251
  $replace = '';
 
252
  switch( $result ){
253
  case '#_LOCATIONID':
254
- $replace = $this->id;
255
  break;
256
- case '#_NAME': //Depreciated
 
 
 
 
257
  case '#_LOCATIONNAME':
258
- $replace = $this->name;
259
  break;
260
- case '#_ADDRESS': //Depreciated
261
  case '#_LOCATIONADDRESS':
262
- $replace = $this->address;
263
  break;
264
- case '#_TOWN': //Depreciated
265
  case '#_LOCATIONTOWN':
266
- $replace = $this->town;
267
  break;
268
  case '#_LOCATIONSTATE':
269
- $replace = $this->id;
270
  break;
271
  case '#_LOCATIONPOSTCODE':
272
- $replace = $this->id;
 
 
 
273
  break;
274
  case '#_LOCATIONCOUNTRY':
275
- $replace = $this->id;
276
  break;
277
- case '#_MAP': //Depreciated
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
  case '#_LOCATIONMAP':
279
  ob_start();
280
- $template = em_locate_template('placeholders/locationmap.php', true, array('EM_Location'=>$this));
281
- $replace = ob_get_clean();
 
 
 
 
 
 
 
 
 
282
  break;
283
- case '#_DESCRIPTION': //Depreciated
284
- case '#_EXCERPT': //Depreciated
 
 
 
285
  case '#_LOCATIONNOTES':
286
  case '#_LOCATIONEXCERPT':
287
- $replace = $this->description;
288
  if($result == "#_EXCERPT" || $result == "#_LOCATIONEXCERPT"){
289
- $matches = explode('<!--more', $this->description);
290
- $replace = $matches[0];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  }
292
  break;
 
293
  case '#_LOCATIONIMAGE':
294
- if($this->image_url != ''){
295
- $replace = "<img src='".$this->image_url."' alt='".$this->name."'/>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
  }
297
  break;
298
  case '#_LOCATIONURL':
299
  case '#_LOCATIONLINK':
300
- case '#_LOCATIONPAGEURL': //Depreciated
301
- $joiner = (stristr(EM_URI, "?")) ? "&amp;" : "?";
302
- $link = EM_URI.$joiner."location_id=".$this->id;
303
- $replace = ($result == '#_LOCATIONURL' || $result == '#_LOCATIONPAGEURL') ? $link : '<a href="'.$link.'">'.$this->name.'</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  break;
305
- case '#_PASTEVENTS': //Depreciated
 
 
 
 
 
 
 
306
  case '#_LOCATIONPASTEVENTS':
307
- case '#_NEXTEVENTS': //Depreciated
308
  case '#_LOCATIONNEXTEVENTS':
309
- case '#_ALLEVENTS': //Depreciated
310
  case '#_LOCATIONALLEVENTS':
311
- if ($result == '#_PASTEVENTS' || $result == '#_LOCATIONPASTEVENTS'){ $scope = 'past'; }
312
- elseif ( $result == '#_NEXTEVENTS' || $result == '#_LOCATIONNEXTEVENTS' ){ $scope = 'future'; }
 
 
 
 
 
 
313
  else{ $scope = 'all'; }
314
- $events = EM_Events::get( array('location'=>$this->id, 'scope'=>$scope) );
315
- if ( count($events) > 0 ){
316
- foreach($events as $event){
317
- $replace .= $event->output(get_option('dbem_location_event_list_item_format'));
318
- }
 
 
 
 
319
  } else {
320
  $replace = get_option('dbem_location_no_events_message');
321
  }
322
  break;
 
 
 
 
 
 
 
323
  default:
324
- $match = false;
325
  break;
326
  }
327
- if($match){ //if true, we've got a placeholder that needs replacing
328
- //TODO FILTER - placeholder filter
329
- $replace = apply_filters('em_location_output_placeholder', $replace, $this, $result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
330
- $location_string = str_replace($result, $replace , $location_string );
 
 
 
 
 
 
 
 
 
 
 
 
331
  }
332
  }
333
- $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
334
- $location_string = str_replace('#_LOCATION', apply_filters($name_filter, $this->name) , $location_string ); //Depreciated
335
  return apply_filters('em_location_output', $location_string, $this, $format, $target);
336
  }
337
 
338
  function get_country(){
339
  $countries = em_get_countries();
340
- if( !empty($countries[$this->country]) ){
341
- return apply_filters('em_location_get_country', $countries[$this->country], $this);
342
  }
343
  return apply_filters('em_location_get_country', false, $this);
344
 
1
  <?php
2
+ /**
3
+ * gets a location
4
+ * @param mixed $id
5
+ * @param mixed $search_by
6
+ * @return EM_Location
7
+ */
8
+ function em_get_location($id = false, $search_by = 'location_id') {
9
+ if( is_object($id) && get_class($id) == 'EM_Location' ){
10
+ return apply_filters('em_get_location', $id);
11
+ }else{
12
+ return apply_filters('em_get_location', new EM_Location($id,$search_by));
13
+ }
14
+ }
15
  /**
16
  * Object that holds location info and related functions
17
  * @author marcus
18
  */
19
  class EM_Location extends EM_Object {
20
  //DB Fields
21
+ var $location_id = '';
22
+ var $post_id = '';
23
+ var $blog_id = '';
24
+ var $location_slug = '';
25
+ var $location_name = '';
26
+ var $location_address = '';
27
+ var $location_town = '';
28
+ var $location_state = '';
29
+ var $location_postcode = '';
30
+ var $location_region = '';
31
+ var $location_country = '';
32
+ var $location_latitude = 0;
33
+ var $location_longitude = 0;
34
+ var $post_content = '';
35
+ var $location_owner = '';
36
+ var $location_status = 0;
37
  //Other Vars
38
  var $fields = array(
39
+ 'location_id' => array('name'=>'id','type'=>'%d'),
40
+ 'post_id' => array('name'=>'post_id','type'=>'%d'),
41
+ 'blog_id' => array('name'=>'blog_id','type'=>'%d'),
42
+ 'location_slug' => array('name'=>'slug','type'=>'%s', 'null'=>true),
43
+ 'location_name' => array('name'=>'name','type'=>'%s', 'null'=>true),
44
+ 'location_address' => array('name'=>'address','type'=>'%s','null'=>true),
45
+ 'location_town' => array('name'=>'town','type'=>'%s','null'=>true),
46
+ 'location_state' => array('name'=>'state','type'=>'%s','null'=>true),
47
+ 'location_postcode' => array('name'=>'postcode','type'=>'%s','null'=>true),
48
+ 'location_region' => array('name'=>'region','type'=>'%s','null'=>true),
49
+ 'location_country' => array('name'=>'country','type'=>'%s','null'=>true),
50
+ 'location_latitude' => array('name'=>'latitude','type'=>'%f','null'=>true),
51
+ 'location_longitude' => array('name'=>'longitude','type'=>'%f','null'=>true),
52
+ 'post_content' => array('name'=>'description','type'=>'%s', 'null'=>true),
53
+ 'location_owner' => array('name'=>'owner','type'=>'%d', 'null'=>true),
54
+ 'location_status' => array('name'=>'status','type'=>'%d', 'null'=>true)
55
  );
56
+ var $post_fields = array('post_id','location_slug','location_name','post_content','location_owner');
57
+ var $location_attributes = array();
58
  var $image_url = '';
59
  var $required_fields = array();
60
  var $feedback_message = "";
61
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
62
  var $errors = array();
63
+ /**
64
+ * previous status of location
65
+ * @access protected
66
+ * @var mixed
67
+ */
68
+ var $previous_status = false;
69
+
70
+ /* Post Variables - copied out of post object for easy IDE reference */
71
+ var $ID;
72
+ var $post_author;
73
+ var $post_date;
74
+ var $post_date_gmt;
75
+ var $post_title;
76
+ var $post_excerpt;
77
+ var $post_status;
78
+ var $comment_status;
79
+ var $ping_status;
80
+ var $post_password;
81
+ var $post_name;
82
+ var $to_ping;
83
+ var $pinged;
84
+ var $post_modified;
85
+ var $post_modified_gmt;
86
+ var $post_content_filtered;
87
+ var $post_parent;
88
+ var $guid;
89
+ var $menu_order;
90
+ var $post_type;
91
+ var $post_mime_type;
92
+ var $comment_count;
93
+ var $ancestors;
94
+ var $filter;
95
+
96
 
97
  /**
98
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
99
  * @param $location_data
100
+ * @param $search_by can be set to post_id or a number for a blog id if in ms mode with global tables, default is location_id
101
  * @return null
102
  */
103
+ function __construct($id = false, $search_by = 'location_id' ) {
104
+ global $wpdb;
105
  //Initialize
106
+ $this->required_fields = array("location_address" => __('The location address', 'dbem'), "location_town" => __('The location town', 'dbem'), "location_country" => __('The country', 'dbem'));
107
+ //Get the post_id/location_id
108
+ $is_post = !empty($id->ID) && $id->post_type == EM_POST_TYPE_LOCATION;
109
+ if( $is_post || absint($id) > 0 ){ //only load info if $id is a number
110
+ $location_post = false;
111
+ if($search_by == 'location_id' && !$is_post){
112
+ //search by location_id, get post_id and blog_id (if in ms mode) and load the post
113
+ $results = $wpdb->get_row($wpdb->prepare("SELECT post_id, blog_id FROM ".EM_LOCATIONS_TABLE." WHERE location_id=%d",$id), ARRAY_A);
114
+ if( !empty($results['post_id']) ){
115
+ $this->post_id = $results['post_id'];
116
+ if( is_multisite() ){
117
+ if( empty($results['blog_id']) || (EM_MS_GLOBAL && get_site_option('dbem_ms_mainblog_locations')) ){
118
+ $results['blog_id'] = get_current_site()->blog_id;
119
+ }
120
+ $location_post = get_blog_post($results['blog_id'], $results['post_id']);
121
+ $search_by = $results['blog_id'];
122
+ }else{
123
+ $location_post = get_post($results['post_id']);
124
+ }
125
+ }
126
+ }else{
127
+ if(!$is_post){
128
+ if( EM_MS_GLOBAL && get_site_option('dbem_ms_mainblog_locations') ){
129
+ //blog_id will always be the main blog id if global locations are restricted only to the main blog
130
+ $search_by = get_current_site()->blog_id;
131
+ }
132
+ if( is_numeric($search_by) && is_multisite() ){
133
+ //we've been given a blog_id, so we're searching for a post id
134
+ $location_post = get_blog_post($search_by, $id);
135
+ }else{
136
+ //search for the post id only
137
+ $location_post = get_post($id);
138
+ }
139
  }else{
140
+ $location_post = $id;
 
141
  }
142
+ $this->post_id = !empty($id->ID) ? $id->ID : $id;
143
  }
144
+ $this->load_postdata($location_post, $search_by);
145
+ }
146
+ $this->compat_keys();
147
+ do_action('em_location', $this, $id, $search_by);
148
+ }
149
+
150
+ function load_postdata($location_post, $search_by = false){
151
+ if( is_object($location_post) ){
152
+ if( $location_post->post_status != 'auto-draft' ){
153
+ if( is_numeric($search_by) && is_multisite() ){
154
+ // if in multisite mode, switch blogs quickly to get the right post meta.
155
+ switch_to_blog($search_by);
156
+ $location_meta = get_post_custom($location_post->ID);
157
+ restore_current_blog();
158
+ $this->blog_id = $search_by;
159
+ }else{
160
+ $location_meta = get_post_custom($location_post->ID);
161
+ }
162
+ //Get custom fields
163
+ foreach($location_meta as $location_meta_key => $location_meta_val){
164
+ $found = false;
165
+ foreach($this->fields as $field_name => $field_info){
166
+ if( $location_meta_key == '_'.$field_name){
167
+ $this->$field_name = $location_meta_val[0];
168
+ $found = true;
169
+ }
170
+ }
171
+ if(!$found && $location_meta_key[0] != '_'){
172
+ $this->location_attributes[$location_meta_key] = ( count($location_meta_val) > 1 ) ? $location_meta_val:$location_meta_val[0];
173
+ }
174
+ }
175
+ }
176
+ //load post data - regardless
177
+ $this->post_id = $location_post->ID;
178
+ $this->location_name = $location_post->post_title;
179
+ $this->location_slug = $location_post->post_name;
180
+ $this->location_owner = $location_post->post_author;
181
+ $this->post_content = $location_post->post_content;
182
+ foreach( $location_post as $key => $value ){ //merge the post data into location object
183
+ $this->$key = $value;
184
  }
185
+ $this->get_status();
186
+ }elseif( !empty($this->post_id) ){
187
+ //we have an orphan... show it, so that we can at least remove it on the front-end
188
+ global $wpdb;
189
+ $location_array = $wpdb->get_row($wpdb->prepare("SELECT * FROM ".EM_LOCATIONS_TABLE." WHERE post_id=%d",$this->post_id), ARRAY_A);
190
+ if( is_array($location_array) ){
191
+ $this->orphaned_location = true;
192
+ $this->post_id = $this->ID = $event_array['post_id'] = null; //reset post_id because it doesn't really exist
193
+ $this->to_object($location_array);
194
+ }
195
+ }
196
  }
197
 
198
+ /**
199
+ * Retrieve event information via POST (used in situations where posts aren't submitted via WP)
200
+ * @param boolean $validate whether or not to run validation, default is true
201
+ * @return boolean
202
+ */
203
+ function get_post($validate = true){
204
+ global $allowedtags;
205
  do_action('em_location_get_post_pre', $this);
206
+ $this->location_name = ( !empty($_POST['location_name']) ) ? htmlspecialchars_decode(wp_kses_data(htmlspecialchars_decode(stripslashes($_POST['location_name'])))):'';
207
+ $this->post_content = ( !empty($_POST['content']) ) ? wp_kses( stripslashes($_POST['content']), $allowedtags):'';
208
+ $this->get_post_meta(false);
209
+ $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
210
+ $this->compat_keys();
211
+ return apply_filters('em_location_get_post', $result, $this);
212
+ }
213
+ /**
214
+ * Retrieve event post meta information via POST, which should be always be called when saving the event custom post via WP.
215
+ * @param boolean $validate whether or not to run validation, default is true
216
+ * @return mixed
217
+ */
218
+ function get_post_meta($validate = true){
219
+ //We are getting the values via POST or GET
220
+ do_action('em_location_get_post_meta_pre', $this);
221
+ $this->location_address = ( !empty($_POST['location_address']) ) ? wp_kses(stripslashes($_POST['location_address']), array()):'';
222
+ $this->location_town = ( !empty($_POST['location_town']) ) ? wp_kses(stripslashes($_POST['location_town']), array()):'';
223
+ $this->location_state = ( !empty($_POST['location_state']) ) ? wp_kses(stripslashes($_POST['location_state']), array()):'';
224
+ $this->location_postcode = ( !empty($_POST['location_postcode']) ) ? wp_kses(stripslashes($_POST['location_postcode']), array()):'';
225
+ $this->location_region = ( !empty($_POST['location_region']) ) ? wp_kses(stripslashes($_POST['location_region']), array()):'';
226
+ $this->location_country = ( !empty($_POST['location_country']) ) ? wp_kses(stripslashes($_POST['location_country']), array()):'';
227
+ $this->location_latitude = ( !empty($_POST['location_latitude']) && is_numeric($_POST['location_latitude']) ) ? $_POST['location_latitude']:'';
228
+ $this->location_longitude = ( !empty($_POST['location_longitude']) && is_numeric($_POST['location_longitude']) ) ? $_POST['location_longitude']:'';
229
+ //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
230
+ if(get_option('dbem_location_attributes_enabled')){
231
+ global $allowedtags;
232
+ if( !is_array($this->location_attributes) ){ $this->location_attributes = array(); }
233
+ $location_available_attributes = em_get_attributes(true); //lattributes only
234
+ if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
235
+ foreach($_POST['em_attributes'] as $att_key => $att_value ){
236
+ if( (in_array($att_key, $location_available_attributes['names']) || array_key_exists($att_key, $this->location_attributes) ) ){
237
+ $att_vals = count($location_available_attributes['values'][$att_key]);
238
+ if( $att_vals == 0 || ($att_vals > 0 && in_array($att_value, $location_available_attributes['values'][$att_key])) ){
239
+ $this->location_attributes[$att_key] = stripslashes($att_value);
240
+ }elseif($att_vals > 0){
241
+ $this->location_attributes[$att_key] = stripslashes(wp_kses($location_available_attributes['values'][$att_key][0], $allowedtags));
242
+ }
243
+ }
244
+ }
245
+ }
246
  }
247
+ $result = $validate ? $this->validate_meta():true; //post returns null
248
+ $this->compat_keys();
249
+ return apply_filters('em_location_get_post_meta',$result,$this);
 
 
 
 
 
 
 
 
250
  }
251
+
252
+ function validate(){
253
+ $validate_post = true;
254
+ if( empty($this->location_name) ){
255
+ $validate_post = false;
256
+ $this->add_error( __('Location name','dbem').__(" is required.", "dbem") );
257
+ }
258
+ $validate_image = $this->image_validate();
259
+ $validate_meta = $this->validate_meta();
260
+ return apply_filters('em_location_validate', $validate_post && $validate_image && $validate_meta, $this );
261
+ }
262
+
263
  /**
264
  * Validates the location. Should be run during any form submission or saving operation.
265
  * @return boolean
266
  */
267
+ function validate_meta(){
268
  //check required fields
269
  foreach ( $this->required_fields as $field => $description) {
270
+ if( $field == 'location_country' && !array_key_exists($this->location_country, em_get_countries()) ){
271
  //country specific checking
272
+ $this->add_error( $this->required_fields['location_country'].__(" is required.", "dbem") );
273
  }elseif ( $this->$field == "" ) {
274
  $this->add_error( $description.__(" is required.", "dbem") );
275
  }
276
  }
277
+ return apply_filters('em_location_validate_meta', ( count($this->errors) == 0 ), $this);
 
278
  }
279
 
280
  function save(){
281
+ global $wpdb, $current_user, $blog_id, $EM_SAVING_LOCATION;
282
+ $EM_SAVING_LOCATION = true;
283
+ //TODO shuffle filters into right place
284
+ if( get_site_option('dbem_ms_mainblog_locations') ){ self::ms_global_switch(); }
285
+ if( !$this->can_manage('edit_locations', 'edit_others_locations') && !( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
286
+ return apply_filters('em_location_save', false, $this);
287
+ }
288
+ remove_action('save_post',array('EM_Location_Post_Admin','save_post'),10,1); //disable the default save post action, we'll do it manually this way
289
+ do_action('em_location_save_pre', $this);
290
+ $post_array = array();
291
+ //Deal with updates to a location
292
+ if( !empty($this->post_id) ){
293
+ //get the full array of post data so we don't overwrite anything.
294
+ if( EM_MS_GLOBAL ){
295
+ if( !empty($this->blog_id) ){
296
+ $post_array = (array) get_blog_post($this->blog_id, $this->post_id);
297
+ }else{
298
+ $post_array = (array) get_blog_post(get_current_site()->blog_id, $this->post_id);
299
+ }
300
+ }else{
301
+ $post_array = (array) get_post($this->post_id);
302
+ }
303
+ }
304
+ //Overwrite new post info
305
+ $post_array['post_type'] = EM_POST_TYPE_LOCATION;
306
+ $post_array['post_title'] = $this->location_name;
307
+ $post_array['post_content'] = $this->post_content;
308
+ //decide on post status
309
+ if( count($this->errors) == 0 ){
310
+ if( EM_MS_GLOBAL && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
311
+ //if in global ms mode and user is a valid role to publish on their blog, then we will publish the location on the main blog
312
+ restore_current_blog();
313
+ $post_array['post_status'] = $this->can_manage('publish_locations') ? 'publish':'pending';
314
+ EM_Object::ms_global_switch(); //switch 'back' to main blog
315
+ }else{
316
+ $post_array['post_status'] = $this->can_manage('publish_locations') ? 'publish':'pending';
317
+ }
318
+ }else{
319
+ $post_array['post_status'] = 'draft';
320
+ }
321
+ //Anonymous submission
322
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->location_id) ){
323
+ $post_array['post_author'] = get_option('dbem_events_anonymous_user');
324
+ if( !is_numeric($post_array['post_author']) ) $post_array['post_author'] = 0;
325
+ }
326
+ //Save post and continue with meta
327
+ $post_id = wp_insert_post($post_array);
328
+ $post_save = false;
329
+ $meta_save = false;
330
+ if( !is_wp_error($post_id) && !empty($post_id) ){
331
+ $post_save = true;
332
+ //refresh this event with wp post
333
+ $post_data = get_post($post_id);
334
+ $this->post_id = $post_id;
335
+ $this->location_slug = $post_data->post_name;
336
+ $this->location_owner = $post_data->post_author;
337
+ $this->post_status = $post_data->post_status;
338
+ $this->get_status();
339
+ //now save the meta
340
+ $meta_save = $this->save_meta();
341
+ //save the image
342
+ $this->image_upload();
343
+ $image_save = (count($this->errors) == 0);
344
+ }elseif(is_wp_error($post_id)){
345
+ //location not saved, add an error
346
+ $this->add_error($post_id->get_error_message());
347
+ }
348
+ if( get_site_option('dbem_ms_mainblog_locations') ){ self::ms_global_switch_back(); }
349
+ $return = apply_filters('em_location_save', $post_save && $meta_save && $image_save, $this);
350
+ $EM_SAVING_LOCATION = false;
351
+ return $return;
352
+ }
353
+
354
+ function save_meta(){
355
+ //echo "<pre>"; print_r($this); echo "</pre>"; die();
356
  global $wpdb, $current_user;
357
+ if( $this->can_manage('edit_locations','edit_others_locations') || ( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
358
+ do_action('em_location_save_meta_pre', $this);
359
+ //Set Blog ID if in multisite mode
360
+ if( EM_MS_GLOBAL && get_site_option('dbem_ms_mainblog_locations') ){
361
+ $this->blog_id = get_current_site()->blog_id; //global locations restricted to main blog must have main site id
362
+ }elseif( is_multisite() && empty($this->blog_id) ){
363
+ $this->blog_id = get_current_blog_id();
364
+ }
365
+ //Update Post Meta
366
+ foreach( array_keys($this->fields) as $key ){
367
+ if( !in_array($key, $this->post_fields) ){
368
+ update_post_meta($this->post_id, '_'.$key, $this->$key);
369
  }
370
+ }
371
+ //Update Post Attributes
372
+ foreach($this->location_attributes as $location_attribute_key => $location_attribute){
373
+ update_post_meta($this->post_id, $location_attribute_key, $location_attribute);
374
+ }
375
+ $this->get_status();
376
+ $this->location_status = (count($this->errors) == 0) ? $this->location_status:null; //set status at this point, it's either the current status, or if validation fails, null
377
+ //Save to em_locations table
378
+ $location_array = $this->to_array(true);
379
+ unset($location_array['location_id']);
380
+ //decide whether or not event is private at this point
381
+ $location_array['location_private'] = ( $this->post_status == 'private' ) ? 1:0;
382
+ //check if location truly exists, meaning the location_id is actually a valid location id
383
+ if( !empty($this->location_id) ){
384
+ if( !empty($this->orphaned_location) && !empty($this->post_id) ){
385
+ //we're dealing with an orphaned event in wp_em_locations table, so we want to update the post_id and give it a post parent
386
+ $loc_truly_exists = true;
387
+ }else{
388
+ $loc_truly_exists = $wpdb->get_var('SELECT post_id FROM '.EM_LOCATIONS_TABLE." WHERE location_id={$this->location_id}") == $this->post_id;
389
+ }
390
+ }else{
391
+ $loc_truly_exists = false;
392
+ }
393
+ //save all the meta
394
+ if( empty($this->location_id) || !$loc_truly_exists ){
395
+ $this->previous_status = 0; //for sure this was previously status 0
396
+ if ( !$wpdb->insert(EM_LOCATIONS_TABLE, $location_array) ){
397
+ $this->add_error( sprintf(__('Something went wrong saving your %s to the index table. Please inform a site administrator about this.','dbem'),__('location','dbem')));
398
  }else{
399
+ //success, so link the event with the post via an event id meta value for easy retrieval
400
+ $this->location_id = $wpdb->insert_id;
401
+ update_post_meta($this->post_id, '_location_id', $this->location_id);
402
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Location','dbem'));
403
+ }
404
+ }else{
405
+ $this->get_previous_status();
406
+ if ( $wpdb->update(EM_LOCATIONS_TABLE, $location_array, array('location_id'=>$this->location_id)) === false ){
407
+ $this->add_error( sprintf(__('Something went wrong updating your %s to the index table. Please inform a site administrator about this.','dbem'),__('location','dbem')));
408
+ }else{
409
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Location','dbem'));
410
+ //Also set the status here if status != previous status
411
+ if( $this->previous_status != $this->get_status() ) $this->set_status($this->get_status());
412
+ }
413
+ }
414
+ }else{
415
+ $this->add_error( sprintf(__('You do not have permission to create/edit %s.','dbem'), __('locations','dbem')) );
416
+ }
417
+ $this->compat_keys();
418
+ return apply_filters('em_location_save_meta', count($this->errors) == 0, $this);
419
+ }
420
+
421
+ function delete($force_delete = false){
422
+ $result = false;
423
+ if( $this->can_manage('delete_locations','delete_others_locations') ){
424
+ if( !is_admin() ){
425
+ include_once('em-location-post-admin.php');
426
+ if( !defined('EM_LOCATION_DELETE_INCLUDE') ){
427
+ EM_Location_Post_Admin::init();
428
+ define('EM_LOCATION_DELETE_INCLUDE',true);
429
  }
430
+ }
431
+ do_action('em_location_delete_pre', $this);
432
+ if( $force_delete ){
433
+ $result = wp_delete_post($this->post_id,$force_delete);
434
  }else{
435
+ $result = wp_trash_post($this->post_id);
436
+ if( !$result && $this->post_status == 'trash' && $this->location_status != -1 ){
437
+ //we're probably dealing with a trashed post already, which will return a false with wp_trash_post, but the location_status is null from < v5.4.1 so refresh it
438
+ $this->set_status(-1);
439
+ $result = true;
440
+ }
441
+ }
442
+ if( !$result && !empty($this->orphaned_location) ){
443
+ //this is an orphaned event, so the wp delete posts would have never worked, so we just delete the row in our locations table
444
+ $result = $this->delete_meta();
445
  }
446
  }
447
+ return apply_filters('em_location_delete', $result != false, $this);
448
+ }
449
+
450
+ function delete_meta(){
451
+ global $wpdb;
452
+ $result = false;
453
+ if( $this->can_manage('delete_locations','delete_others_locations') ){
454
+ do_action('em_location_delete_meta_pre', $this);
455
+ $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_LOCATIONS_TABLE ." WHERE location_id=%d", $this->location_id) );
456
+ }
457
+ return apply_filters('em_location_delete_meta', $result !== false, $this);
458
+ }
459
+
460
+ function is_published(){
461
+ return apply_filters('em_location_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
462
  }
463
 
464
  /**
465
+ * Change the status of the location. This will save to the Database too.
466
+ * @param int $status
467
+ * @param boolean $set_post_status
468
+ * @return string
469
  */
470
+ function set_status($status, $set_post_status = false){
471
  global $wpdb;
472
+ if($status === null){
473
+ $set_status='NULL';
474
+ if($set_post_status){
475
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
476
+ }
477
+ $this->post_status = 'draft';
478
+ }elseif( $status == -1 ){ //trashed post
479
+ $set_status = -1;
480
+ if($set_post_status){
481
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'trash' ), array( 'ID' => $this->post_id ) );
 
482
  }
483
+ $this->post_status = 'trash'; //set post status in this instance
484
+ }else{
485
+ $set_status = $status ? 1:0;
486
+ $post_status = $set_status ? 'publish':'pending';
487
+ if($set_post_status){
488
+ if($this->post_status == 'pending' && empty($this->post_name)){
489
+ $this->post_name = sanitize_title($this->post_title);
490
+ }
491
+ $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_name' => $this->post_name ), array( 'ID' => $this->post_id ) );
492
+ }
493
+ $this->post_status = $post_status;
494
+ }
495
+ $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
496
+ $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)));
497
+ $this->get_status();
498
+ return apply_filters('em_location_set_status', $result !== false, $status, $this);
499
+ }
500
+
501
+ function get_status($db = false){
502
+ switch( $this->post_status ){
503
+ case 'private':
504
+ $this->location_private = 1;
505
+ $this->location_status = $status = 1;
506
+ break;
507
+ case 'publish':
508
+ $this->location_private = 0;
509
+ $this->location_status = $status = 1;
510
+ break;
511
+ case 'pending':
512
+ $this->location_private = 0;
513
+ $this->location_status = $status = 0;
514
+ break;
515
+ case 'trash':
516
+ $this->location_private = 0;
517
+ $this->location_status = $status = -1;
518
+ break;
519
+ default: //draft or unknown
520
+ $this->location_private = 0;
521
+ $status = $db ? 'NULL':null;
522
+ $this->location_status = null;
523
+ break;
524
  }
525
+ return $status;
526
  }
527
 
528
+ function get_previous_status( $force = false ){
529
+ global $wpdb;
530
+ if( $this->previous_status === false || $force ){
531
+ $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
 
 
 
 
 
 
 
 
 
 
 
 
532
  }
533
+ return $this->previous_status;
534
  }
535
+
536
  function load_similar($criteria){
537
  global $wpdb;
538
  if( !empty($criteria['location_name']) && !empty($criteria['location_name']) && !empty($criteria['location_name']) ){
551
  function has_events(){
552
  global $wpdb;
553
  $events_table = EM_EVENTS_TABLE;
554
+ $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE location_id = {$this->location_id}";
555
  $affected_events = $wpdb->get_row($sql);
556
  return apply_filters('em_location_has_events', (count($affected_events) > 0), $this);
557
  }
559
  /**
560
  * Can the user manage this location?
561
  */
562
+ function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
563
+ if( $this->location_id == '' && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
564
+ $user_to_check = get_option('dbem_events_anonymous_user');
565
+ }
566
+ if( $admin_capability && EM_MS_GLOBAL && get_site_option('dbem_ms_mainblog_locations') ){
567
+ //if in global mode with locations restricted to main blog, we check capabilities against the main blog
568
+ self::ms_global_switch();
569
+ $return = parent::can_manage($owner_capability, $admin_capability, $user_to_check);
570
+ self::ms_global_switch_back();
571
+ }else{
572
+ $return = parent::can_manage($owner_capability, $admin_capability, $user_to_check);
573
+ }
574
+ return apply_filters('em_location_can_manage', $return, $this, $owner_capability, $admin_capability, $user_to_check);
575
+ }
576
+
577
+ function get_permalink(){
578
+ if( EM_MS_GLOBAL ){
579
+ //if no blog id defined, assume it belongs to the main blog
580
+ $blog_id = empty($this->blog_id) ? get_current_site()->blog_id:$this->blog_id;
581
+ if( get_site_option('dbem_ms_mainblog_locations') ){
582
+ //all locations belong to the main blog
583
+ $link = get_blog_permalink( get_current_site()->blog_id, $this->post_id);
584
+ }elseif( $blog_id != get_current_blog_id() ){
585
+ //decide whether to give a link to the blog the location originates from or to show it on the main site
586
+ if( !get_site_option('dbem_ms_global_locations_links') && is_main_site() && get_option('dbem_locations_page') ){
587
+ //showing subsite locations on main site, create a custom link
588
+ $link = trailingslashit(get_permalink(get_option('dbem_locations_page')).get_site_option('dbem_ms_locations_slug',EM_LOCATION_SLUG).'/'.$this->location_slug.'-'.$this->location_id);
589
+ }else{
590
+ //if location doesn't belong to current blog and/or if main blog doesn't have a locations page, link directly to the blog it belongs to
591
+ $link = get_blog_permalink( $blog_id, $this->post_id);
592
+ }
593
+ }
594
+ }
595
+ if( empty($link) ){
596
+ $link = get_post_permalink($this->post_id);
597
+ }
598
+ return apply_filters('em_location_get_permalink', $link, $this); ;
599
+ }
600
+
601
+ function get_ical_url(){
602
+ global $wp_rewrite;
603
+ if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){
604
+ $return = trailingslashit($this->get_permalink()).'ical/';
605
+ }else{
606
+ $return = em_add_get_params($this->get_permalink(), array('ical'=>1));
607
+ }
608
+ return apply_filters('em_location_get_ical_url', $return);
609
+ }
610
+
611
+ function get_rss_url(){
612
+ global $wp_rewrite;
613
+ if( !empty($wp_rewrite) && $wp_rewrite->using_permalinks() ){
614
+ $return = trailingslashit($this->get_permalink()).'feed/';
615
+ }else{
616
+ $return = em_add_get_params($this->get_permalink(), array('feed'=>1));
617
+ }
618
+ return apply_filters('em_location_get_rss_url', $return);
619
+ }
620
+
621
+ function get_edit_url(){
622
+ if( $this->can_manage('edit_locations','edit_others_locations') ){
623
+ if( EM_MS_GLOBAL ){
624
+ global $current_site, $current_blog;
625
+ if( get_site_option('dbem_ms_mainblog_locations') ){
626
+ //location stored as post on main blog, but can be edited either in sub-blog admin area or if not on main blog
627
+ if( get_blog_option($this->blog_id, 'dbem_edit_locations_page') && !is_admin() ){
628
+ $link = em_add_get_params(get_blog_permalink($this->blog_id, get_blog_option($this->blog_id, 'dbem_edit_locations_page')), array('action'=>'edit','location_id'=>$this->location_id), false);
629
+ }
630
+ if( (is_main_site() || empty($link)) && get_blog_option($current_site->blog_id, 'dbem_edit_locations_page') && !is_admin() ){ //if editing on main site and edit page exists, stay on same site
631
+ $link = em_add_get_params(get_blog_permalink(get_option('dbem_edit_locations_page')), array('action'=>'edit','location_id'=>$this->location_id), false);
632
+ }
633
+ if( empty($link) && !is_main_site() ){
634
+ $link = get_admin_url($current_blog->blog_id, "edit.php?post_type=event&page=locations&action=edit&location_id={$this->location_id}");
635
+ }elseif( empty($link) && is_main_site() ){
636
+ $link = get_admin_url($current_site->blog_id, "post.php?post={$this->post_id}&action=edit");
637
+ }
638
+ }else{
639
+ //location stored as post on blog where location was created
640
+ if( get_blog_option($this->blog_id, 'dbem_edit_locations_page') && !is_admin() ){
641
+ $link = em_add_get_params(get_blog_permalink($this->blog_id, get_blog_option($this->blog_id, 'dbem_edit_locations_page')), array('action'=>'edit','location_id'=>$this->location_id), false);
642
+ }
643
+ if( (is_main_site() || empty($link)) && get_blog_option($current_site->blog_id, 'dbem_edit_locations_page') && !is_admin() ){ //if editing on main site and edit page exists, stay on same site
644
+ $link = em_add_get_params(get_blog_permalink($current_site->blog_id, get_blog_option($current_site->blog_id, 'dbem_edit_locations_page')), array('action'=>'edit','location_id'=>$this->location_id), false);
645
+ }
646
+ if( empty($link)){
647
+ $link = get_admin_url($this->blog_id, "post.php?post={$this->post_id}&action=edit");
648
+ }
649
+ }
650
+ }else{
651
+ if( get_option('dbem_edit_locations_page') && !is_admin() ){
652
+ $link = em_add_get_params(get_permalink(get_option('dbem_edit_locations_page')), array('action'=>'edit','location_id'=>$this->location_id), false);
653
+ }
654
+ if( empty($link))
655
+ $link = admin_url()."post.php?post={$this->post_id}&action=edit";
656
+ }
657
+ return apply_filters('em_location_get_edit_url', $link, $this);
658
+ }
659
  }
660
 
661
  function output_single($target = 'html'){
663
  return apply_filters('em_location_output_single', $this->output($format, $target), $this, $target);
664
  }
665
 
666
+ function output($format, $target="html") {
667
+ $location_string = $format;
668
+ //First let's do some conditional placeholder removals
669
+ for ($i = 0 ; $i < EM_CONDITIONAL_RECURSIONS; $i++){ //you can add nested recursions by modifying this setting in your wp_options table
670
+ preg_match_all('/\{([a-zA-Z0-9_]+)\}(.+?)\{\/\1\}/s', $location_string, $conditionals);
671
+ if( count($conditionals[0]) > 0 ){
672
+ //Check if the language we want exists, if not we take the first language there
673
+ foreach($conditionals[1] as $key => $condition){
674
+ $show_condition = false;
675
+ if ($condition == 'has_loc_image'){
676
+ //does this event have an image?
677
+ $show_condition = ( $this->get_image_url() != '' );
678
+ }elseif ($condition == 'no_loc_image'){
679
+ //does this event have an image?
680
+ $show_condition = ( $this->get_image_url() == '' );
681
+ }
682
+ $show_condition = apply_filters('em_location_output_show_condition', $show_condition, $condition, $conditionals[0][$key], $this);
683
+ if($show_condition){
684
+ //calculate lengths to delete placeholders
685
+ $placeholder_length = strlen($condition)+2;
686
+ $replacement = substr($conditionals[0][$key], $placeholder_length, strlen($conditionals[0][$key])-($placeholder_length *2 +1));
687
+ }else{
688
+ $replacement = '';
689
+ }
690
+ $location_string = str_replace($conditionals[0][$key], apply_filters('em_location_output_condition', $replacement, $condition, $conditionals[0][$key], $this), $location_string);
691
+ }
692
  }
693
+ }
694
+ //This is for the custom attributes
695
+ preg_match_all('/#_LATT\{([^}]+)\}(\{([^}]+)\})?/', $location_string, $results);
696
+ foreach($results[0] as $resultKey => $result) {
697
+ //Strip string of placeholder and just leave the reference
698
+ $attRef = substr( substr($result, 0, strpos($result, '}')), 7 );
699
+ $attString = '';
700
+ if( is_array($this->location_attributes) && array_key_exists($attRef, $this->location_attributes) && !empty($this->location_attributes[$attRef]) ){
701
+ $attString = $this->location_attributes[$attRef];
702
+ }elseif( !empty($results[3][$resultKey]) ){
703
+ //Check to see if we have a second set of braces;
704
+ $attString = $results[3][$resultKey];
705
+ }
706
+ $attString = apply_filters('em_location_output_placeholder', $attString, $this, $result, $target);
707
+ $location_string = str_replace($result, $attString ,$location_string );
708
  }
709
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([^}]+)})?/", $location_string, $placeholders);
710
+ $replaces = array();
711
+ foreach($placeholders[1] as $key => $result) {
 
712
  $replace = '';
713
+ $full_result = $placeholders[0][$key];
714
  switch( $result ){
715
  case '#_LOCATIONID':
716
+ $replace = $this->location_id;
717
  break;
718
+ case '#_LOCATIONPOSTID':
719
+ $replace = $this->post_id;
720
+ break;
721
+ case '#_NAME': //Depricated
722
+ case '#_LOCATION': //Depricated
723
  case '#_LOCATIONNAME':
724
+ $replace = $this->location_name;
725
  break;
726
+ case '#_ADDRESS': //Depricated
727
  case '#_LOCATIONADDRESS':
728
+ $replace = $this->location_address;
729
  break;
730
+ case '#_TOWN': //Depricated
731
  case '#_LOCATIONTOWN':
732
+ $replace = $this->location_town;
733
  break;
734
  case '#_LOCATIONSTATE':
735
+ $replace = $this->location_state;
736
  break;
737
  case '#_LOCATIONPOSTCODE':
738
+ $replace = $this->location_postcode;
739
+ break;
740
+ case '#_LOCATIONREGION':
741
+ $replace = $this->location_region;
742
  break;
743
  case '#_LOCATIONCOUNTRY':
744
+ $replace = $this->get_country();
745
  break;
746
+ case '#_LOCATIONFULLLINE':
747
+ $replace = $this->location_address;
748
+ $replace .= empty($this->location_town) ? '':', '.$this->location_town;
749
+ $replace .= empty($this->location_state) ? '':', '.$this->location_state;
750
+ $replace .= empty($this->location_postcode) ? '':', '.$this->location_postcode;
751
+ $replace .= empty($this->location_region) ? '':', '.$this->location_region;
752
+ break;
753
+ case '#_LOCATIONFULLBR':
754
+ $replace = $this->location_address;
755
+ $replace .= empty($this->location_town) ? '':'<br />'.$this->location_town;
756
+ $replace .= empty($this->location_state) ? '':'<br />'.$this->location_state;
757
+ $replace .= empty($this->location_postcode) ? '':'<br />'.$this->location_postcode;
758
+ $replace .= empty($this->location_region) ? '':'<br />'.$this->location_region;
759
+ break;
760
+ case '#_MAP': //Depricated (but will remain)
761
  case '#_LOCATIONMAP':
762
  ob_start();
763
+ $args = array();
764
+ if( !empty($placeholders[3][$key]) ){
765
+ $dimensions = explode(',', $placeholders[3][$key]);
766
+ if(!empty($dimensions[0])) $args['width'] = $dimensions[0];
767
+ if(!empty($dimensions[1])) $args['height'] = $dimensions[1];
768
+ }
769
+ $template = em_locate_template('placeholders/locationmap.php', true, array('args'=>$args,'EM_Location'=>$this));
770
+ $replace = ob_get_clean();
771
+ break;
772
+ case '#_LOCATIONLONGITUDE':
773
+ $replace = $this->location_longitude;
774
  break;
775
+ case '#_LOCATIONLATITUDE':
776
+ $replace = $this->location_latitude;
777
+ break;
778
+ case '#_DESCRIPTION': //Depricated
779
+ case '#_EXCERPT': //Depricated
780
  case '#_LOCATIONNOTES':
781
  case '#_LOCATIONEXCERPT':
782
+ $replace = $this->post_content;
783
  if($result == "#_EXCERPT" || $result == "#_LOCATIONEXCERPT"){
784
+ if( !empty($this->post_excerpt) ){
785
+ $replace = $this->post_excerpt;
786
+ }else{
787
+ $excerpt_length = 55;
788
+ $excerpt_more = apply_filters('em_excerpt_more', ' ' . '[...]');
789
+ if( !empty($placeholders[3][$key]) ){
790
+ $trim = true;
791
+ $ph_args = explode(',', $placeholders[3][$key]);
792
+ if( is_numeric($ph_args[0]) ) $excerpt_length = $ph_args[0];
793
+ if( !empty($ph_args[1]) ) $excerpt_more = $ph_args[1];
794
+ }
795
+ if ( preg_match('/<!--more(.*?)?-->/', $replace, $matches) ) {
796
+ $content = explode($matches[0], $replace, 2);
797
+ $replace = force_balance_tags($content[0]);
798
+ }
799
+ if( !empty($trim) ){
800
+ //shorten content by supplied number - copied from wp_trim_excerpt
801
+ $replace = strip_shortcodes( $replace );
802
+ $replace = str_replace(']]>', ']]&gt;', $replace);
803
+ $replace = wp_trim_words( $replace, $excerpt_length, $excerpt_more );
804
+ }
805
+ }
806
  }
807
  break;
808
+ case '#_LOCATIONIMAGEURL':
809
  case '#_LOCATIONIMAGE':
810
+ if($this->get_image_url() != ''){
811
+ $image_url = esc_url($this->get_image_url());
812
+ if($result == '#_LOCATIONIMAGEURL'){
813
+ $replace = $this->get_image_url();
814
+ }else{
815
+ if( empty($placeholders[3][$key]) ){
816
+ $replace = "<img src='".$image_url."' alt='".esc_attr($this->location_name)."'/>";
817
+ }else{
818
+ $image_size = explode(',', $placeholders[3][$key]);
819
+ if( self::array_is_numeric($image_size) && count($image_size) > 1 ){
820
+ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){
821
+ //get a thumbnail
822
+ if( get_option('dbem_disable_thumbnails') ){
823
+ $image_attr = '';
824
+ $image_args = array();
825
+ if( empty($image_size[1]) && !empty($image_size[0]) ){
826
+ $image_attr = 'width="'.$image_size[0].'"';
827
+ $image_args['w'] = $image_size[0];
828
+ }elseif( empty($image_size[0]) && !empty($image_size[1]) ){
829
+ $image_attr = 'height="'.$image_size[1].'"';
830
+ $image_args['h'] = $image_size[1];
831
+ }elseif( !empty($image_size[0]) && !empty($image_size[1]) ){
832
+ $image_attr = 'width="'.$image_size[0].'" height="'.$image_size[1].'"';
833
+ $image_args = array('w'=>$image_size[0], 'h'=>$image_size[1]);
834
+ }
835
+ $replace = "<img src='".esc_url(em_add_get_params($image_url, $image_args))."' alt='".esc_attr($this->location_name)."' $image_attr />";
836
+ }else{
837
+ //location belongs to another blog, so switch blog then call the default wp fucntion
838
+ if( EM_MS_GLOBAL && get_current_blog_id() != $this->blog_id ){
839
+ switch_to_blog($this->blog_id);
840
+ $switch_back = true;
841
+ }
842
+ $replace = get_the_post_thumbnail($this->ID, $image_size);
843
+ if( !empty($switch_back) ){ restore_current_blog(); }
844
+ }
845
+ }else{
846
+ $replace = get_the_post_thumbnail($this->ID, $image_size);
847
+ }
848
+ }else{
849
+ $replace = "<img src='".$image_url."' alt='".esc_attr($this->location_name)."'/>";
850
+ }
851
+ }
852
+ }
853
  }
854
  break;
855
  case '#_LOCATIONURL':
856
  case '#_LOCATIONLINK':
857
+ case '#_LOCATIONPAGEURL': //Depricated
858
+ $link = esc_url($this->get_permalink());
859
+ $replace = ($result == '#_LOCATIONURL' || $result == '#_LOCATIONPAGEURL') ? $link : '<a href="'.$link.'" title="'.esc_attr($this->location_name).'">'.esc_html($this->location_name).'</a>';
860
+ break;
861
+ case '#_LOCATIONEDITURL':
862
+ case '#_LOCATIONEDITLINK':
863
+ if( $this->can_manage('edit_locations','edit_others_locations') ){
864
+ $link = esc_url($this->get_edit_url());
865
+ $replace = ($result == '#_LOCATIONEDITURL') ? $link : '<a href="'.$link.'" title="'.esc_attr($this->location_name).'">'.esc_html(sprintf(__('Edit Location','dbem'))).'</a>';
866
+ }
867
+ break;
868
+ case '#_LOCATIONICALURL':
869
+ case '#_LOCATIONICALLINK':
870
+ $replace = $this->get_ical_url();
871
+ if( $result == '#_LOCATIONICALLINK' ){
872
+ $replace = '<a href="'.esc_url($replace).'">iCal</a>';
873
+ }
874
  break;
875
+ case '#_LOCATIONRSSURL':
876
+ case '#_LOCATIONRSSLINK':
877
+ $replace = $this->get_rss_url();
878
+ if( $result == '#_LOCATIONRSSLINK' ){
879
+ $replace = '<a href="'.esc_url($replace).'">RSS</a>';
880
+ }
881
+ break;
882
+ case '#_PASTEVENTS': //Depricated
883
  case '#_LOCATIONPASTEVENTS':
884
+ case '#_NEXTEVENTS': //Depricated
885
  case '#_LOCATIONNEXTEVENTS':
886
+ case '#_ALLEVENTS': //Depricated
887
  case '#_LOCATIONALLEVENTS':
888
+ //TODO: add limit to lists of events
889
+ //convert depreciated placeholders for compatability
890
+ $result = ($result == '#_PASTEVENTS') ? '#_LOCATIONPASTEVENTS':$result;
891
+ $result = ($result == '#_NEXTEVENTS') ? '#_LOCATIONNEXTEVENTS':$result;
892
+ $result = ($result == '#_ALLEVENTS') ? '#_LOCATIONALLEVENTS':$result;
893
+ //forget it ever happened? :/
894
+ if ( $result == '#_LOCATIONPASTEVENTS'){ $scope = 'past'; }
895
+ elseif ( $result == '#_LOCATIONNEXTEVENTS' ){ $scope = 'future'; }
896
  else{ $scope = 'all'; }
897
+ $events_count = EM_Events::count( array('location'=>$this->location_id, 'scope'=>$scope) );
898
+ if ( $events_count > 0 ){
899
+ $args = array('location'=>$this->location_id, 'scope'=>$scope, 'pagination'=>1, 'ajax'=>0);
900
+ $args['format_header'] = get_option('dbem_location_event_list_item_header_format');
901
+ $args['format_footer'] = get_option('dbem_location_event_list_item_footer_format');
902
+ $args['format'] = get_option('dbem_location_event_list_item_format');
903
+ $args['limit'] = get_option('dbem_location_event_list_limit');
904
+ $args['page'] = (!empty($_REQUEST['pno']) && is_numeric($_REQUEST['pno']) )? $_REQUEST['pno'] : 1;
905
+ $replace = EM_Events::output($args);
906
  } else {
907
  $replace = get_option('dbem_location_no_events_message');
908
  }
909
  break;
910
+ case '#_LOCATIONNEXTEVENT':
911
+ $events = EM_Events::get( array('location'=>$this->location_id, 'scope'=>'future', 'limit'=>1, 'orderby'=>'event_start_date,event_start_time') );
912
+ $replace = get_option('dbem_location_no_event_message');
913
+ foreach($events as $EM_Event){
914
+ $replace = $EM_Event->output(get_option('dbem_location_event_single_format'));
915
+ }
916
+ break;
917
  default:
918
+ $replace = $full_result;
919
  break;
920
  }
921
+ $replaces[$full_result] = apply_filters('em_location_output_placeholder', $replace, $this, $full_result, $target);
922
+ }
923
+ //sort out replacements so that during replacements shorter placeholders don't overwrite longer varieties.
924
+ krsort($replaces);
925
+ foreach($replaces as $full_result => $replacement){
926
+ if( !in_array($full_result, array('#_DESCRIPTION','#_LOCATIONNOTES')) ){
927
+ $location_string = str_replace($full_result, $replacement , $location_string );
928
+ }else{
929
+ $desc_replace[$full_result] = $replacement;
930
+ }
931
+ }
932
+
933
+ //Finally, do the location notes, so that previous placeholders don't get replaced within the content, which may use shortcodes
934
+ if( !empty($desc_replace) ){
935
+ foreach($desc_replace as $full_result => $replacement){
936
+ $location_string = str_replace($full_result, $replacement , $location_string );
937
  }
938
  }
939
+
 
940
  return apply_filters('em_location_output', $location_string, $this, $format, $target);
941
  }
942
 
943
  function get_country(){
944
  $countries = em_get_countries();
945
+ if( !empty($countries[$this->location_country]) ){
946
+ return apply_filters('em_location_get_country', $countries[$this->location_country], $this);
947
  }
948
  return apply_filters('em_location_get_country', false, $this);
949
 
classes/em-locations.php CHANGED
@@ -4,35 +4,19 @@
4
  * Optimized for specifically retreiving locations (whether eventful or not). If you want event data AND location information for each event, use EM_Events
5
  *
6
  */
7
- class EM_Locations extends EM_Object implements Iterator {
8
- /**
9
- * Array of EM_Location objects
10
- * @var array EM_Location
11
- */
12
- var $locations = array();
13
 
14
- function EM_Events( $args = array() ){
15
- if( is_array($args) ){
16
- if( is_object(current($args)) && get_class(current($args)) == 'EM_Event' ){
17
- $this->locations = $args;
18
- }else{
19
- $this->locations = EM_Events::get($args);
20
- }
21
- }else{
22
- $this->locations = EM_Events::get();
23
- }
24
- do_action('em_events',$this);
25
- }
26
  /**
27
  * Returns an array of EM_Location objects
28
  * @param boolean $eventful
29
  * @param boolean $return_objects
30
  * @return array
31
  */
32
- function get( $args = array(), $count=false ){
33
  global $wpdb;
34
  $events_table = EM_EVENTS_TABLE;
35
  $locations_table = EM_LOCATIONS_TABLE;
 
36
 
37
  //Quick version, we can accept an array of IDs, which is easy to retrieve
38
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
@@ -43,10 +27,10 @@ class EM_Locations extends EM_Object implements Iterator {
43
  foreach($results as $result){
44
  $locations[$result['location_id']] = new EM_Location($result);
45
  }
46
- return $locations; //We return all the events matched as an EM_Event array.
47
  }elseif( is_numeric($args) ){
48
  //return an event in the usual array format
49
- return apply_filters('em_locations_get', array(new EM_Event($args)), $args);
50
  }elseif( is_array($args) && is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
51
  return apply_filters('em_locations_get', $args, $args);
52
  }
@@ -72,38 +56,47 @@ class EM_Locations extends EM_Object implements Iterator {
72
  //Now, build orderby sql
73
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
74
 
75
- if( $count ){
76
- $fields = $locations_table.'.location_id';
 
 
 
77
  }
78
  //Create the SQL statement and execute
79
  $sql = "
80
- SELECT $fields FROM $locations_table
81
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
82
  $where
83
  GROUP BY {$locations_table}.location_id
84
  $orderby_sql
85
  $limit $offset
86
  ";
87
-
88
  //If we're only counting results, return the number of results
89
  if( $count ){
90
- return count($wpdb->get_results($sql));
91
  }
92
  $results = $wpdb->get_results($sql, ARRAY_A);
93
 
94
  //If we want results directly in an array, why not have a shortcut here?
95
  if( $args['array'] == true ){
96
- return $results;
97
  }
98
 
99
- $locations = array();
100
- foreach ($results as $location){
101
- $locations[] = new EM_Location($location);
 
 
 
 
 
 
102
  }
103
  return apply_filters('em_locations_get', $locations, $args);
104
  }
105
 
106
- function count( $args = array() ){
107
  return apply_filters('em_locations_count', self::get($args, true), $args);
108
  }
109
 
@@ -112,10 +105,14 @@ class EM_Locations extends EM_Object implements Iterator {
112
  * @param array $args
113
  * @return string
114
  */
115
- function output( $args ){
116
  global $EM_Location;
117
  $EM_Location_old = $EM_Location; //When looping, we can replace EM_Location global with the current event in the loop
118
  //Can be either an array for the get search or an array of EM_Location objects
 
 
 
 
119
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
120
  $func_args = func_get_args();
121
  $locations = $func_args[0];
@@ -124,46 +121,38 @@ class EM_Locations extends EM_Object implements Iterator {
124
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
125
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
126
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
 
127
  }else{
128
  $args = apply_filters('em_locations_output_args', self::get_default_search($args) );
129
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
130
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
131
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
132
- $args['limit'] = false;
133
- $args['offset'] = false;
134
- $args['page'] = false;
 
 
135
  $locations = self::get( $args );
136
  }
137
  //What format shall we output this to, or use default
138
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_location_list_item_format' ) : $args['format'] ;
139
 
140
  $output = "";
141
- $locations_count = count($locations);
142
  $locations = apply_filters('em_locations_output_locations', $locations);
143
  if ( count($locations) > 0 ) {
144
- $location_count = 0;
145
- $locations_shown = 0;
146
  foreach ( $locations as $EM_Location ) {
147
- if( ($locations_shown < $limit || empty($limit)) && ($location_count >= $offset || $offset === 0) ){
148
- $output .= $EM_Location->output($format);
149
- $locations_shown++;
150
- }
151
- $location_count++;
152
  }
153
  //Add headers and footers to output
154
  if( $format == get_option ( 'dbem_location_list_item_format' ) ){
155
  $single_event_format_header = get_option ( 'dbem_location_list_item_format_header' );
156
- $single_event_format_header = ( $single_event_format_header != '' ) ? $single_event_format_header : "<ul class='em-locations-list'>";
157
  $single_event_format_footer = get_option ( 'dbem_location_list_item_format_footer' );
158
- $single_event_format_footer = ( $single_event_format_footer != '' ) ? $single_event_format_footer : "</ul>";
159
  $output = $single_event_format_header . $output . $single_event_format_footer;
160
  }
161
  //Pagination (if needed/requested)
162
- if( !empty($args['pagination']) && !empty($limit) && $locations_count >= $limit ){
163
- //Show the pagination links (unless there's less than 10 events
164
- $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
165
- $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'));
166
- $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $locations_count, $limit, $page), $page_link_template, $locations_count, $limit, $page);
167
  }
168
  } else {
169
  $output = get_option ( 'dbem_no_locations_message' );
@@ -173,10 +162,22 @@ class EM_Locations extends EM_Object implements Iterator {
173
  return apply_filters('em_locations_output', $output, $locations, $args);
174
  }
175
 
176
- function delete( $args = array() ){
177
- if( !is_object(current($args)) && get_class((current($args))) != 'EM_Location' ){
 
 
 
 
 
 
 
 
 
 
 
178
  $locations = self::get($args);
179
- }else{
 
180
  $locations = $args;
181
  }
182
  $results = array();
@@ -186,33 +187,96 @@ class EM_Locations extends EM_Object implements Iterator {
186
  return apply_filters('em_locations_delete', in_array(false, $results), $locations);
187
  }
188
 
 
 
 
 
 
 
 
 
 
 
 
189
  /**
190
  * Builds an array of SQL query conditions based on regularly used arguments
191
  * @param array $args
192
  * @return array
193
  */
194
- function build_sql_conditions( $args = array() ){
 
195
  global $wpdb;
196
  $events_table = EM_EVENTS_TABLE;
197
  $locations_table = EM_LOCATIONS_TABLE;
198
 
199
  $conditions = parent::build_sql_conditions($args);
 
 
 
 
 
200
  //eventful locations
201
  if( true == $args['eventful'] ){
202
- $conditions['eventful'] = "{$events_table}.event_id IS NOT NULL";
203
  }elseif( true == $args['eventless'] ){
204
  $conditions['eventless'] = "{$events_table}.event_id IS NULL";
 
205
  }
206
  //owner lookup
207
- if( !empty($args['owner']) ){
208
  $conditions['owner'] = "location_owner=".$args['owner'];
 
 
 
 
209
  }
210
  //blog id in events table
211
- if( is_multisite() && array_key_exists('blog',$args) && is_numeric($args['blog']) ){
212
- if( is_main_site($args['blog']) ){
213
- $conditions['blog'] = "(`blog_id`={$args['blog']} OR blog_id IS NULL)";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  }else{
215
- $conditions['blog'] = "(`blog_id`={$args['blog']})";
216
  }
217
  }
218
  return apply_filters('em_locations_build_sql_conditions', $conditions, $args);
@@ -221,56 +285,57 @@ class EM_Locations extends EM_Object implements Iterator {
221
  /* Overrides EM_Object method to apply a filter to result
222
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
223
  */
224
- function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
 
225
  return apply_filters( 'em_locations_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
226
  }
227
 
228
  /*
229
  * Generate a search arguments array from defalut and user-defined.
230
- * @see wp-content/plugins/events-manager/classes/EM_Object::get_default_search()
 
 
 
231
  */
232
- function get_default_search($array = array()){
 
233
  $defaults = array(
234
  'eventful' => false, //Locations that have an event (scope will also play a part here
235
  'eventless' => false, //Locations WITHOUT events, eventful takes precedence
236
- 'orderby' => 'name',
 
237
  'state' => false,
238
  'country' => false,
 
 
239
  'scope' => 'all', //we probably want to search all locations by default, not like events
240
- 'blog' => get_current_blog_id()
 
 
 
241
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  $array['eventful'] = ( !empty($array['eventful']) && $array['eventful'] == true );
243
  $array['eventless'] = ( !empty($array['eventless']) && $array['eventless'] == true );
244
- if( is_admin() ){
245
  $defaults['owner'] = !current_user_can('read_others_locations') ? get_current_user_id():false;
246
  }
247
  return apply_filters('em_locations_get_default_search', parent::get_default_search($defaults, $array), $array, $defaults);
248
  }
249
-
250
- //Iteratior methods
251
- public function rewind(){
252
- reset($this->locations);
253
- }
254
-
255
- public function current(){
256
- $var = current($this->locations);
257
- return $var;
258
- }
259
-
260
- public function key(){
261
- $var = key($this->locations);
262
- return $var;
263
- }
264
-
265
- public function next(){
266
- $var = next($this->locations);
267
- return $var;
268
- }
269
-
270
- public function valid(){
271
- $key = key($this->locations);
272
- $var = ($key !== NULL && $key !== FALSE);
273
- return $var;
274
- }
275
  }
276
  ?>
4
  * Optimized for specifically retreiving locations (whether eventful or not). If you want event data AND location information for each event, use EM_Events
5
  *
6
  */
7
+ class EM_Locations extends EM_Object {
 
 
 
 
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  /**
10
  * Returns an array of EM_Location objects
11
  * @param boolean $eventful
12
  * @param boolean $return_objects
13
  * @return array
14
  */
15
+ public static function get( $args = array(), $count=false ){
16
  global $wpdb;
17
  $events_table = EM_EVENTS_TABLE;
18
  $locations_table = EM_LOCATIONS_TABLE;
19
+ $locations = array();
20
 
21
  //Quick version, we can accept an array of IDs, which is easy to retrieve
22
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
27
  foreach($results as $result){
28
  $locations[$result['location_id']] = new EM_Location($result);
29
  }
30
+ return apply_filters('em_locations_get', $locations, $args); //We return all the events matched as an EM_Event array.
31
  }elseif( is_numeric($args) ){
32
  //return an event in the usual array format
33
+ return apply_filters('em_locations_get', array(new EM_Location($args)), $args);
34
  }elseif( is_array($args) && is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
35
  return apply_filters('em_locations_get', $args, $args);
36
  }
56
  //Now, build orderby sql
57
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
58
 
59
+ $fields = ( $count ) ? $locations_table.'.location_id':$locations_table.'.post_id';
60
+ if( EM_MS_GLOBAL ){
61
+ $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id, '.$locations_table.'.blog_id';
62
+ }else{
63
+ $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id';
64
  }
65
  //Create the SQL statement and execute
66
  $sql = "
67
+ SELECT $selectors FROM $locations_table
68
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
69
  $where
70
  GROUP BY {$locations_table}.location_id
71
  $orderby_sql
72
  $limit $offset
73
  ";
74
+
75
  //If we're only counting results, return the number of results
76
  if( $count ){
77
+ return apply_filters('em_locations_get_array', count($wpdb->get_col($sql)), $args);
78
  }
79
  $results = $wpdb->get_results($sql, ARRAY_A);
80
 
81
  //If we want results directly in an array, why not have a shortcut here?
82
  if( $args['array'] == true ){
83
+ return apply_filters('em_locations_get_array', $results, $args);
84
  }
85
 
86
+ if( EM_MS_GLOBAL ){
87
+ foreach ( $results as $location ){
88
+ if( empty($location['blog_id']) ) $location['blog_id'] = get_current_site()->blog_id;
89
+ $locations[] = em_get_location($location['post_id'], $location['blog_id']);
90
+ }
91
+ }else{
92
+ foreach ( $results as $location ){
93
+ $locations[] = em_get_location($location['post_id'], 'post_id');
94
+ }
95
  }
96
  return apply_filters('em_locations_get', $locations, $args);
97
  }
98
 
99
+ public static function count( $args = array() ){
100
  return apply_filters('em_locations_count', self::get($args, true), $args);
101
  }
102
 
105
  * @param array $args
106
  * @return string
107
  */
108
+ public static function output( $args ){
109
  global $EM_Location;
110
  $EM_Location_old = $EM_Location; //When looping, we can replace EM_Location global with the current event in the loop
111
  //Can be either an array for the get search or an array of EM_Location objects
112
+ $page_queryvar = !empty($args['page_queryvar']) ? $args['page_queryvar'] : 'pno';
113
+ if( !empty($args['pagination']) && !array_key_exists('page',$args) && !empty($_REQUEST[$page_queryvar]) && is_numeric($_REQUEST[$page_queryvar]) ){
114
+ $page = $args['page'] = $_REQUEST[$page_queryvar];
115
+ }
116
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
117
  $func_args = func_get_args();
118
  $locations = $func_args[0];
121
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
122
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
123
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
124
+ $locations_count = count($locations);
125
  }else{
126
  $args = apply_filters('em_locations_output_args', self::get_default_search($args) );
127
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
128
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
129
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
130
+ $args_count = $args;
131
+ $args_count['limit'] = 0;
132
+ $args_count['offset'] = 0;
133
+ $args_count['page'] = 1;
134
+ $locations_count = self::count($args_count);
135
  $locations = self::get( $args );
136
  }
137
  //What format shall we output this to, or use default
138
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_location_list_item_format' ) : $args['format'] ;
139
 
140
  $output = "";
 
141
  $locations = apply_filters('em_locations_output_locations', $locations);
142
  if ( count($locations) > 0 ) {
 
 
143
  foreach ( $locations as $EM_Location ) {
144
+ $output .= $EM_Location->output($format);
 
 
 
 
145
  }
146
  //Add headers and footers to output
147
  if( $format == get_option ( 'dbem_location_list_item_format' ) ){
148
  $single_event_format_header = get_option ( 'dbem_location_list_item_format_header' );
 
149
  $single_event_format_footer = get_option ( 'dbem_location_list_item_format_footer' );
 
150
  $output = $single_event_format_header . $output . $single_event_format_footer;
151
  }
152
  //Pagination (if needed/requested)
153
+ if( !empty($args['pagination']) && !empty($limit) && $locations_count > $limit ){
154
+ //output pagination links
155
+ $output .= self::get_pagination_links($args, $locations_count);
 
 
156
  }
157
  } else {
158
  $output = get_option ( 'dbem_no_locations_message' );
162
  return apply_filters('em_locations_output', $output, $locations, $args);
163
  }
164
 
165
+ public static function get_pagination_links($args, $count, $search_action = 'search_locations', $default_args = array()){
166
+ //get default args if we're in a search, supply to parent since we can't depend on late static binding until WP requires PHP 5.3 or later
167
+ if( empty($default_args) && (!empty($args['ajax']) || !empty($_REQUEST['action']) && $_REQUEST['action'] == $search_action) ){
168
+ $default_args = self::get_default_search();
169
+ $default_args['limit'] = get_option('dbem_locations_default_limit'); //since we're paginating, get the default limit, which isn't obtained from get_default_search()
170
+ }
171
+ return parent::get_pagination_links($args, $count, $search_action, $default_args);
172
+ }
173
+
174
+ public static function delete( $args = array() ){
175
+ $locations = array();
176
+ if( !is_object(current($args)) ){
177
+ //we've been given an array or search arguments to find the relevant locations to delete
178
  $locations = self::get($args);
179
+ }elseif( get_class(current($args)) == 'EM_Location' ){
180
+ //we're deleting an array of locations
181
  $locations = $args;
182
  }
183
  $results = array();
187
  return apply_filters('em_locations_delete', in_array(false, $results), $locations);
188
  }
189
 
190
+ public static function get_post_search($args = array(), $filter = false, $request = array(), $accepted_args = array()){
191
+ //supply $accepted_args to parent argument since we can't depend on late static binding until WP requires PHP 5.3 or later
192
+ $accepted_args = !empty($accepted_args) ? $accepted_args : array_keys(self::get_default_search());
193
+ $return = parent::get_post_search($args, $filter, $request, $accepted_args);
194
+ //remove unwanted arguments or if not explicitly requested
195
+ if( empty($_REQUEST['scope']) && empty($request['scope']) && !empty($return['scope']) ){
196
+ unset($return['scope']);
197
+ }
198
+ return apply_filters('em_locations_get_post_search', $return);
199
+ }
200
+
201
  /**
202
  * Builds an array of SQL query conditions based on regularly used arguments
203
  * @param array $args
204
  * @return array
205
  */
206
+ public static function build_sql_conditions( $args = array(), $count=false ){
207
+ self::$context = EM_POST_TYPE_LOCATION;
208
  global $wpdb;
209
  $events_table = EM_EVENTS_TABLE;
210
  $locations_table = EM_LOCATIONS_TABLE;
211
 
212
  $conditions = parent::build_sql_conditions($args);
213
+ //search locations
214
+ if( !empty($args['search']) ){
215
+ $like_search = array($locations_table.'.post_content','location_name','location_address','location_town','location_postcode','location_state','location_region','location_country');
216
+ $conditions['search'] = "(".implode(" LIKE '%{$args['search']}%' OR ", $like_search). " LIKE '%{$args['search']}%')";
217
+ }
218
  //eventful locations
219
  if( true == $args['eventful'] ){
220
+ $conditions['eventful'] = "{$events_table}.event_id IS NOT NULL AND event_status=1";
221
  }elseif( true == $args['eventless'] ){
222
  $conditions['eventless'] = "{$events_table}.event_id IS NULL";
223
+ if( !empty($conditions['scope']) ) unset($conditions['scope']); //scope condition would render all queries return no results
224
  }
225
  //owner lookup
226
+ if( !empty($args['owner']) && is_numeric($args['owner'])){
227
  $conditions['owner'] = "location_owner=".$args['owner'];
228
+ }elseif( !empty($args['owner']) && $args['owner'] == 'me' && is_user_logged_in() ){
229
+ $conditions['owner'] = 'location_owner='.get_current_user_id();
230
+ }elseif( self::array_is_numeric($args['owner']) ){
231
+ $conditions['owner'] = 'location_owner IN ('.implode(',',$args['owner']).')';
232
  }
233
  //blog id in events table
234
+ if( EM_MS_GLOBAL && !empty($args['blog']) ){
235
+ if( is_numeric($args['blog']) ){
236
+ if( is_main_site($args['blog']) ){
237
+ $conditions['blog'] = "(".$locations_table.".blog_id={$args['blog']} OR ".$locations_table.".blog_id IS NULL)";
238
+ }else{
239
+ $conditions['blog'] = "(".$locations_table.".blog_id={$args['blog']})";
240
+ }
241
+ }else{
242
+ if( !is_array($args['blog']) && preg_match('/^([\-0-9],?)+$/', $args['blog']) ){
243
+ $conditions['blog'] = "(".$locations_table.".blog_id IN ({$args['blog']}) )";
244
+ }elseif( is_array($args['blog']) && self::array_is_numeric($args['blog']) ){
245
+ $conditions['blog'] = "(".$locations_table.".blog_id IN (".implode(',',$args['blog']).") )";
246
+ }
247
+ }
248
+ }
249
+ //status
250
+ $conditions['status'] = "(`location_status` >= 0)"; //pending and published if status is not explicitly defined (Default is 1)
251
+ if( array_key_exists('status',$args) ){
252
+ if( is_numeric($args['status']) ){
253
+ $conditions['status'] = "(`location_status`={$args['status']} )"; //trash (-1), pending, (0) or published (1)
254
+ }elseif( $args['status'] == 'pending' ){
255
+ $conditions['status'] = "(`location_status`=0)"; //pending
256
+ }elseif( $args['status'] == 'publish' ){
257
+ $conditions['status'] = "(`location_status`=1)"; //published
258
+ }elseif( $args['status'] === null || $args['status'] == 'draft' ){
259
+ $conditions['status'] = "(`location_status` IS NULL )"; //show draft items
260
+ }elseif( $args['status'] == 'trash' ){
261
+ $conditions['status'] = "(`location_status` = -1 )"; //show trashed items
262
+ }elseif( $args['status'] == 'all'){
263
+ $conditions['status'] = "(`location_status` >= 0 OR `location_status` IS NULL)"; //search all statuses that aren't trashed
264
+ }elseif( $args['status'] == 'everything'){
265
+ unset($conditions['status']); //search all statuses
266
+ }
267
+ }
268
+ //private locations
269
+ if( empty($args['private']) ){
270
+ $conditions['private'] = "(`location_private`=0 AND `event_private`=0)";
271
+ }elseif( !empty($args['private_only']) ){
272
+ $conditions['private_only'] = "(`location_private`=1 OR `event_private`=1)";
273
+ }
274
+ //post search
275
+ if( !empty($args['post_id'])){
276
+ if( is_array($args['post_id']) ){
277
+ $conditions['post_id'] = "($locations_table.post_id IN (".implode(',',$args['post_id'])."))";
278
  }else{
279
+ $conditions['post_id'] = "($locations_table.post_id={$args['post_id']})";
280
  }
281
  }
282
  return apply_filters('em_locations_build_sql_conditions', $conditions, $args);
285
  /* Overrides EM_Object method to apply a filter to result
286
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
287
  */
288
+ public static function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
289
+ self::$context = EM_POST_TYPE_LOCATION;
290
  return apply_filters( 'em_locations_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
291
  }
292
 
293
  /*
294
  * Generate a search arguments array from defalut and user-defined.
295
+ * @param array $array_or_defaults may be the array to override defaults
296
+ * @param array $array
297
+ * @return array
298
+ * @uses EM_Object#get_default_search()
299
  */
300
+ public static function get_default_search( $array_or_defaults = array(), $array = array() ){
301
+ self::$context = EM_POST_TYPE_LOCATION;
302
  $defaults = array(
303
  'eventful' => false, //Locations that have an event (scope will also play a part here
304
  'eventless' => false, //Locations WITHOUT events, eventful takes precedence
305
+ 'orderby' => 'location_name',
306
+ 'town' => false,
307
  'state' => false,
308
  'country' => false,
309
+ 'region' => false,
310
+ 'status' => 1, //approved locations only
311
  'scope' => 'all', //we probably want to search all locations by default, not like events
312
+ 'blog' => get_current_blog_id(),
313
+ 'private' => current_user_can('read_private_locations'),
314
+ 'private_only' => false,
315
+ 'post_id' => false
316
  );
317
+ //sort out whether defaults were supplied or just the array of search values
318
+ if( empty($array) ){
319
+ $array = $array_or_defaults;
320
+ }else{
321
+ $defaults = array_merge($defaults, $array_or_defaults);
322
+ }
323
+ //specific functionality
324
+ if( EM_MS_GLOBAL ){
325
+ if( get_site_option('dbem_ms_mainblog_locations') ){
326
+ //when searching in MS Global mode with all locations being stored on the main blog, blog_id becomes redundant as locations are stored in one blog table set
327
+ $array['blog'] = false;
328
+ }elseif( (!is_admin() || defined('DOING_AJAX')) && empty($array['blog']) && is_main_site() && get_site_option('dbem_ms_global_locations') ){
329
+ //if enabled, by default we display all blog locations on main site
330
+ $array['blog'] = false;
331
+ }
332
+ }
333
  $array['eventful'] = ( !empty($array['eventful']) && $array['eventful'] == true );
334
  $array['eventless'] = ( !empty($array['eventless']) && $array['eventless'] == true );
335
+ if( is_admin() && !defined('DOING_AJAX') ){
336
  $defaults['owner'] = !current_user_can('read_others_locations') ? get_current_user_id():false;
337
  }
338
  return apply_filters('em_locations_get_default_search', parent::get_default_search($defaults, $array), $array, $defaults);
339
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  }
341
  ?>
classes/em-mailer.php CHANGED
@@ -16,14 +16,59 @@ class EM_Mailer {
16
  * @param $body
17
  * @param $receiver
18
  */
19
- function send($subject="no title",$body="No message specified", $receiver='') {
20
  //TODO add an EM_Error global object, for this sort of error reporting. (@marcus like StatusNotice)
21
  global $smtpsettings, $phpmailer, $cformsSettings;
22
-
23
- if( preg_match('/^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$/i', $receiver) ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  $this->load_phpmailer();
25
  $mail = new EM_PHPMailer();
26
- //$mail->SMTPDebug = true;
 
 
 
27
  $mail->ClearAllRecipients();
28
  $mail->ClearAddresses();
29
  $mail->ClearAttachments();
@@ -37,34 +82,45 @@ class EM_Mailer {
37
  $mail->From = get_option('dbem_mail_sender_address');
38
  $mail->FromName = get_option('dbem_mail_sender_name'); // This is the from name in the email, you can put anything you like here
39
  $mail->Body = $body;
40
- $mail->Subject = $subject;
41
- $mail->AddAddress($receiver);
42
-
43
- //Protocols
44
- if ( get_option('dbem_rsvp_mail_send_method') == 'wp_mail' ){
45
- $mail->Mailer = 'wp_mail';
46
- $send = wp_mail($receiver, $subject, $body);
47
- if(!$send){
48
- global $phpmailer;
49
- $this->errors[] = $phpmailer->ErrorInfo;
 
 
 
 
 
 
 
50
  }
51
  }else{
52
- if( get_option('
16
  * @param $body
17
  * @param $receiver
18
  */
19
+ function send($subject="no title",$body="No message specified", $receiver='', $attachments = array() ) {
20
  //TODO add an EM_Error global object, for this sort of error reporting. (@marcus like StatusNotice)
21
  global $smtpsettings, $phpmailer, $cformsSettings;
22
+ $subject = html_entity_decode(wp_kses_data($subject)); //decode entities, but run kses first just in case users use placeholders containing html
23
+ if( is_array($receiver) ){
24
+ $receiver_emails = array();
25
+ foreach($receiver as $receiver_email){
26
+ $receiver_emails[] = is_email($receiver_email);
27
+ }
28
+ $emails_ok = !in_array(false, $receiver_emails);
29
+ }else{
30
+ $emails_ok = is_email($receiver);
31
+ }
32
+ if( get_option('dbem_smtp_html') && get_option('dbem_smtp_html_br') ){
33
+ $body = nl2br($body);
34
+ }
35
+ if ( $emails_ok && get_option('dbem_rsvp_mail_send_method') == 'wp_mail' ){
36
+ $from = get_option('dbem_mail_sender_address');
37
+ $headers = get_option('dbem_mail_sender_name') ? 'From: '.get_option('dbem_mail_sender_name').' <'.$from.'>':'From: '.$from;
38
+ if( get_option('dbem_smtp_html') ){ //create filter to change content type to html in wp_mail
39
+ add_filter('wp_mail_content_type',create_function('', 'return "text/html";'));
40
+ }
41
+ $send = wp_mail($receiver, $subject, $body, $headers);
42
+ if(!$send){
43
+ global $phpmailer;
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.', 'dbem');
63
+ }
64
+ return $send;
65
+ }elseif( $emails_ok ){
66
  $this->load_phpmailer();
67
  $mail = new EM_PHPMailer();
68
+ //$mail->SMTPDebug = true;
69
+ if( get_option('dbem_smtp_html') ){
70
+ $mail->isHTML();
71
+ }
72
  $mail->ClearAllRecipients();
73
  $mail->ClearAddresses();
74
  $mail->ClearAttachments();
82
  $mail->From = get_option('dbem_mail_sender_address');
83
  $mail->FromName = get_option('dbem_mail_sender_name'); // This is the from name in the email, you can put anything you like here
84
  $mail->Body = $body;
85
+ $mail->Subject = $subject;
86
+ //add attachments
87
+ if( is_array($attachments) ){
88
+ foreach($attachments as $attachment){
89
+ $att = array('name'=> '', 'encoding' => 'base64', 'type' => 'application/octet-stream');
90
+ if( is_array($attachment) ){
91
+ $att = array_merge($att, $attachment);
92
+ }else{
93
+ $att['path'] = $attachment;
94
+ }
95
+ $mail->AddAttachment($att['path'], $att['name'], $att['encoding'], $att['type']);
96
+ }
97
+ }
98
+ do_action('em_mailer', $mail); //$mail will still be modified
99
+ if(is_array($receiver)){
100
+ foreach($receiver as $receiver_email){
101
+ $mail->AddAddress($receiver_email);
102
  }
103
  }else{