Events Manager - Version 5.9.4

Version Description

  • added em_rewrite_rules_array filter for final permalink rule manipulation
  • fixed privacy consent blocking certain actions such as single booking button and admin-side submissions
  • fixed fatal errors when showing the consent checkbox in WordPress 5.9.5 and earlier
  • fixed the quick booking button not working in ajax search results
  • fixed privacy policy consent form label not being translatable for multilingual sites
  • fixed inconsistent date headers in certain situations with UTC manual offset dates
  • fixed incorrect link to .eot dashicon file for IE11
  • added anonymous submitter data to locations for new event submissions and integrated this with GDPR export/erase tools
  • fixed location slug blanks when directly published from front-end via submitting an event
  • added default ical and rss feed limits to avoid overloading as number of events grow
  • corrected docs to include 'recurrences' search attribute
  • added timezone pre-formatting to functions that produced incorrect output for timezone date placeholders
  • fixed default categories not being applied for events with no categories
  • fixed locations being selectable for events in other blogs within a multisite global mode when locations don't all reside on main blog
Download this release

Release Info

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

Code changes from version 5.9.3 to 5.9.4

admin/em-admin.php CHANGED
@@ -91,7 +91,7 @@ function em_admin_dashicon(){
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';
91
<style type="text/css">
92
@font-face {
93
font-family: 'em_dashicons';
94
+ src: url('<?php echo EM_DIR_URI; ?>includes/fonts/em-dashicons.eot'); // this is for IE
95
}
96
@font-face {
97
font-family: 'em_dashicons';
admin/em-data-privacy.php CHANGED
@@ -112,14 +112,16 @@ class EM_Data_Privacy {
112
$done = true;
113
}else{
114
//get event IDs submitted by user or "anonymously" by email
115
- $events = self::get_events($email_address, $page, $post_type);
116
117
foreach( $events as $post_id ){
118
$EM_Event = em_get_event($post_id, 'post_id');
119
//erase the location first
120
$EM_Location = $EM_Event->get_location();
121
if( $EM_Location->location_id && get_option('dbem_data_privacy_erase_locations', 2) ){
122
- if( ($user !== false && $EM_Location->location_owner == $user->ID) || ($user === false && $EM_Location->location_owner == get_option('dbem_events_anonymous_user')) ){
123
//depending on settings delete location only if it has no other events (eventually if we're deleting the last event of this user with the same location, it'll only have one event)
124
if( get_option('dbem_data_privacy_erase_locations', 2) == 1 || EM_Events::count(array('location_id' => $EM_Location->location_id, 'status' => 'all')) <= 1 ){
125
if( $EM_Location->delete(true) ){
@@ -150,30 +152,25 @@ class EM_Data_Privacy {
150
}
151
152
public static function erase_locations( $email_address, $page = 1 ) {
153
- $user = get_user_by('email', $email_address); //is user or no-user?
154
$page = (int) $page;
155
$limit = apply_filters('em_data_privacy_erase_limit', 100);
156
- $offset = ($page -1) * $limit;
157
$items_removed = $items_retained = false;
158
$messages = array();
159
-
160
- if( get_option('dbem_data_privacy_erase_locations') == 2 ){ //for locations, we currently don't store anon info about locations
161
- //we're only deleting anonymous events, and letting WP handle CPT deletion the traditional way for registered accounts
162
- $done = true;
163
- }elseif( $user !== false ){
164
- $locations_count = 0;
165
- foreach( EM_Locations::get(array('owner' => $user->ID, 'limit' => $limit, 'offset' => $offset, 'status'=>'everything')) as $EM_Location ){ /* @var EM_Location $EM_Location */
166
- if( $EM_Location->delete(true) ){
167
- $items_removed = true;
168
- }else{
169
- $items_retained = true;
170
- $messages = array_merge($messages, $EM_Location->get_errors());
171
- }
172
- $locations_count++;
173
}
174
- // Tell core if we have more comments to work on still
175
- $done = $locations_count < $limit;
176
}
177
return array(
178
'items_removed' => $items_removed,
179
'items_retained' => $items_retained, // always false in this example
@@ -360,7 +357,7 @@ class EM_Data_Privacy {
360
$event_export_default['group_label'] = $post_type == 'event-recurring' ? __('Recurring Events', 'events-manager'):__('Events', 'events-manager');
361
362
//get event IDs submitted by user or "anonymously" by email
363
- $events = self::get_events($email_address, $page, $post_type);
364
365
foreach( $events as $post_id ){
366
$EM_Event = em_get_event($post_id, 'post_id');
@@ -383,8 +380,10 @@ class EM_Data_Privacy {
383
$export_item['data'][] = array('name' => __('Location','events-manager'), 'value' => $EM_Location->location_name . ', '. $EM_Location->get_full_address() .', '. $EM_Location->location_country);
384
//put this location as a new export item
385
$already_exported = in_array($EM_Location->location_id, $locations_exported);
386
- $user_owns_location = ($user !== false && $EM_Location->location_owner == $user->ID) || ($user === false && $EM_Location->location_owner == get_option('dbem_events_anonymous_user'));
387
- if( !$already_exported && $user_owns_location ){
388
$location_export_item = $locations_export_default;
389
$location_export_item['item_id'] = 'location-post-'.$EM_Location->post_id;
390
$location_export_item['data'][] = array('name' => __('Name','events-manager'), 'value' => $EM_Location->location_name );
@@ -439,9 +438,6 @@ class EM_Data_Privacy {
439
$export_items = array();
440
$items_count = 0;
441
442
- //check if we're only exporting locations to those who submitted anonymously - eventual since currently it's not possible to submit anonymously
443
- if( $user !== false && get_option('dbem_data_privacy_export_locations') == 2 ) return array( 'data' => $export_items, 'done' => true ); //return if user is registered and we're only exporting anon events
444
-
445
$locations_export_default = array(
446
'group_id' => 'events-manager-'.EM_POST_TYPE_LOCATION,
447
'group_label' => __('Locations', 'events-manager'),
@@ -449,9 +445,14 @@ class EM_Data_Privacy {
449
'data' => array() // replace this with assoc array of name/value key arrays
450
);
451
452
- //Locations - here we only get event-less events submitted by registered users. Anonymous submissions would have been handled above as event/locations come in pairs.
453
- if( $user !== false ){
454
- foreach( EM_Locations::get(array('eventless' => get_option('dbem_data_privacy_export_events') != 0, 'owner' => $user->ID, 'limit' => $limit, 'offset' => $offset, 'status'=>'everything')) as $EM_Location ){ /* @var EM_Location $EM_Location */
455
$location_export_item = $locations_export_default;
456
$location_export_item['item_id'] = 'event-post-'.$EM_Location->post_id;
457
$location_export_item['data'][] = array('name' => __('Name','events-manager'), 'value' => $EM_Location->location_name );
@@ -467,11 +468,12 @@ class EM_Data_Privacy {
467
$location_export_item = apply_filters('em_data_privacy_export_locations_item', $location_export_item, $EM_Location);
468
$export_items[] = $location_export_item;
469
$export_items = apply_filters('em_data_privacy_export_locations_items_after_item', $export_items, $location_export_item, $EM_Location); //could be used for cross-referencing and add-ing other groups e.g. Multiple Bookings in Pro
470
$items_count++;
471
if( $items_count == $limit ) break;
472
}
473
}
474
-
475
$done = $items_count < $limit; //if we didn't reach limit of bookings then we must be done
476
return array(
477
'data' => $export_items,
@@ -479,12 +481,13 @@ class EM_Data_Privacy {
479
);
480
}
481
482
- public static function get_events( $email_address, $page, $post_type ){
483
global $wpdb;
484
$page = (int) $page;
485
$limit = apply_filters('em_data_privacy_export_limit', 100);
486
$offset = ($page -1) * $limit;
487
$user = get_user_by('email', $email_address); //is user or no-user?
488
//get event IDs submitted by user or "anonymously" by email
489
$events = array();
490
if( $user !== false ){
@@ -492,7 +495,7 @@ class EM_Data_Privacy {
492
$events = $wpdb->get_col($sql);
493
}
494
//if user ever submitted anonymous events with same email, we also process these
495
- $sql = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='_event_owner_email' AND meta_value=%s) AND post_type = %s LIMIT %d OFFSET %d", $email_address, $post_type, $limit, $offset);
496
$events = array_merge($events, $wpdb->get_col($sql));
497
return $events;
498
}
112
$done = true;
113
}else{
114
//get event IDs submitted by user or "anonymously" by email
115
+ $events = self::get_cpts($email_address, $page, $post_type);
116
117
foreach( $events as $post_id ){
118
$EM_Event = em_get_event($post_id, 'post_id');
119
//erase the location first
120
$EM_Location = $EM_Event->get_location();
121
if( $EM_Location->location_id && get_option('dbem_data_privacy_erase_locations', 2) ){
122
+ //prior to 5.9.3 locations submitted alongside anonymous events didn't store email info, so for older locations we can only assume if the location is guest submitted and only linked to this one event
123
+ $user_probably_owns_location = $user === false && empty($EM_Location->owner_email) && $EM_Location->location_owner == get_option('dbem_events_anonymous_user');
124
+ if( $user_probably_owns_location ){
125
//depending on settings delete location only if it has no other events (eventually if we're deleting the last event of this user with the same location, it'll only have one event)
126
if( get_option('dbem_data_privacy_erase_locations', 2) == 1 || EM_Events::count(array('location_id' => $EM_Location->location_id, 'status' => 'all')) <= 1 ){
127
if( $EM_Location->delete(true) ){
152
}
153
154
public static function erase_locations( $email_address, $page = 1 ) {
155
$page = (int) $page;
156
$limit = apply_filters('em_data_privacy_erase_limit', 100);
157
$items_removed = $items_retained = false;
158
$messages = array();
159
+
160
+ $locations_count = 0;
161
+ $locations = self::get_cpts($email_address, $page, EM_POST_TYPE_LOCATION);
162
+ foreach( $locations as $post_id ){
163
+ $EM_Location = em_get_location( $post_id, 'post_id' ); /* @var EM_Location $EM_Location */
164
+ if( $EM_Location->delete(true) ){
165
+ $items_removed = true;
166
+ }else{
167
+ $items_retained = true;
168
+ $messages = array_merge($messages, $EM_Location->get_errors());
169
}
170
+ $locations_count++;
171
}
172
+ // Tell core if we have more comments to work on still
173
+ $done = $locations_count < $limit;
174
return array(
175
'items_removed' => $items_removed,
176
'items_retained' => $items_retained, // always false in this example
357
$event_export_default['group_label'] = $post_type == 'event-recurring' ? __('Recurring Events', 'events-manager'):__('Events', 'events-manager');
358
359
//get event IDs submitted by user or "anonymously" by email
360
+ $events = self::get_cpts($email_address, $page, $post_type);
361
362
foreach( $events as $post_id ){
363
$EM_Event = em_get_event($post_id, 'post_id');
380
$export_item['data'][] = array('name' => __('Location','events-manager'), 'value' => $EM_Location->location_name . ', '. $EM_Location->get_full_address() .', '. $EM_Location->location_country);
381
//put this location as a new export item
382
$already_exported = in_array($EM_Location->location_id, $locations_exported);
383
+ $user_probably_owns_location = $user === false && empty($EM_Location->owner_email) && $EM_Location->location_owner == get_option('dbem_events_anonymous_user');
384
+ $user_submitted_location = $user === false && $EM_Location->owner_email == $email_address;
385
+ $user_owns_location = $user !== false && $EM_Location->location_owner == $user->ID;
386
+ if( !$already_exported && ($user_owns_location || $user_submitted_location || $user_probably_owns_location) ){
387
$location_export_item = $locations_export_default;
388
$location_export_item['item_id'] = 'location-post-'.$EM_Location->post_id;
389
$location_export_item['data'][] = array('name' => __('Name','events-manager'), 'value' => $EM_Location->location_name );
438
$export_items = array();
439
$items_count = 0;
440
441
$locations_export_default = array(
442
'group_id' => 'events-manager-'.EM_POST_TYPE_LOCATION,
443
'group_label' => __('Locations', 'events-manager'),
445
'data' => array() // replace this with assoc array of name/value key arrays
446
);
447
448
+ //Locations - previous to 5.9.4 locations submitted anonymously did nint include
449
+ $locations_exported = get_post_meta( $_REQUEST['id'], '_em_locations_exported', true);
450
+ if( empty($locations_exported) ) $locations_exported = array();
451
+
452
+ $locations = self::get_cpts($email_address, $page, EM_POST_TYPE_LOCATION);
453
+ foreach( $locations as $post_id ){
454
+ $EM_Location = em_get_location( $post_id, 'post_id' ); /* @var EM_Location $EM_Location */
455
+ if( !in_array($EM_Location->location_id, $locations_exported) ){
456
$location_export_item = $locations_export_default;
457
$location_export_item['item_id'] = 'event-post-'.$EM_Location->post_id;
458
$location_export_item['data'][] = array('name' => __('Name','events-manager'), 'value' => $EM_Location->location_name );
468
$location_export_item = apply_filters('em_data_privacy_export_locations_item', $location_export_item, $EM_Location);
469
$export_items[] = $location_export_item;
470
$export_items = apply_filters('em_data_privacy_export_locations_items_after_item', $export_items, $location_export_item, $EM_Location); //could be used for cross-referencing and add-ing other groups e.g. Multiple Bookings in Pro
471
+ $locations_exported[] = $EM_Location->location_id;
472
$items_count++;
473
if( $items_count == $limit ) break;
474
}
475
}
476
+ update_post_meta( $_REQUEST['id'], '_em_locations_exported', $locations_exported);
477
$done = $items_count < $limit; //if we didn't reach limit of bookings then we must be done
478
return array(
479
'data' => $export_items,
481
);
482
}
483
484
+ public static function get_cpts($email_address, $page, $post_type ){
485
global $wpdb;
486
$page = (int) $page;
487
$limit = apply_filters('em_data_privacy_export_limit', 100);
488
$offset = ($page -1) * $limit;
489
$user = get_user_by('email', $email_address); //is user or no-user?
490
+ $anon_email_key = $post_type == EM_POST_TYPE_LOCATION ? '_owner_email':'_event_owner_email';
491
//get event IDs submitted by user or "anonymously" by email
492
$events = array();
493
if( $user !== false ){
495
$events = $wpdb->get_col($sql);
496
}
497
//if user ever submitted anonymous events with same email, we also process these
498
+ $sql = $wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key=%s AND meta_value=%s) AND post_type = %s LIMIT %d OFFSET %d", $anon_email_key, $email_address, $post_type, $limit, $offset);
499
$events = array_merge($events, $wpdb->get_col($sql));
500
return $events;
501
}
admin/em-docs.php CHANGED
@@ -25,8 +25,9 @@ function em_docs_init($force_init = false){
25
'post_id' => array( 'desc' => sprintf('Supply a single id or comma-separated ids (e.g. "1,2,3") to limit the search to %s with the %s.','events', 'post_id(s)')),
26
'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.'),
27
'private_only' => array( 'desc' =>sprintf('Display only private %s ?','events'), 'args' => '1 = yes, 0 = no', 'default' => '0'),
28
'recurrence' => array( 'desc'=> 'If set to the event id of the recurring event, this will show only events this event recurrences.', 'default'=>0),
29
- '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),
30
'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 separated 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")),
31
'search' => array( 'desc'=> 'Do a search for this string within event name, details and location address.' ),
32
'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','events'), 'default'=>1),
25
'post_id' => array( 'desc' => sprintf('Supply a single id or comma-separated ids (e.g. "1,2,3") to limit the search to %s with the %s.','events', 'post_id(s)')),
26
'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.'),
27
'private_only' => array( 'desc' =>sprintf('Display only private %s ?','events'), 'args' => '1 = yes, 0 = no', 'default' => '0'),
28
+ 'recurrences' => array( 'desc'=> 'Show only recurrences if set to 1 or non-recurrences if set to 0, shows all events if not used.'),
29
'recurrence' => array( 'desc'=> 'If set to the event id of the recurring event, this will show only events this event recurrences.', 'default'=>0),
30
+ 'recurring' => array( 'desc'=> 'If set to 1, will only show recurring event templates. Only useful if you know what you\'re doing, use recurrence or recurrences if you want to filter event recurrences.', 'default'=>0),
31
'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 separated 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")),
32
'search' => array( 'desc'=> 'Do a search for this string within event name, details and location address.' ),
33
'status' => array( 'desc' => sprintf('Limit search to %s with a spefic status (1 is active, 0 is pending approval)','events'), 'default'=>1),
classes/em-datetime.php CHANGED
@@ -81,6 +81,7 @@ class EM_DateTime extends DateTime {
81
if( !$this->valid && ($format == 'Y-m-d' || $format == em_get_date_format())) return '';
82
//if we deal with offsets, then we offset UTC time by that much
83
if( $this->timezone_manual_offset !== false ){
84
if( function_exists('date_timestamp_get') ){
85
return date($format, $this->getTimestampWithOffset(true) );
86
}else{
@@ -93,6 +94,60 @@ class EM_DateTime extends DateTime {
93
return parent::format($format);
94
}
95
96
/**
97
* Returns a date and time representation in the format stored in Events Manager settings.
98
* @param string $include_hour
@@ -112,6 +167,8 @@ class EM_DateTime extends DateTime {
112
*/
113
public function i18n( $format = 'Y-m-d H:i:s' ){
114
if( !$this->valid && $format == em_get_date_format()) return '';
115
//if we deal with offsets, then we offset UTC time by that much
116
if( !function_exists('date_timestamp_get') && $this->timezone_manual_offset !== false ){
117
//PHP < 5.3 fallback :/ Messed up, but it works...
@@ -196,17 +253,17 @@ class EM_DateTime extends DateTime {
196
* action: set the time to 12:00
197
* result: 2018-01-01 02:00 UTC => 2018-01-01 12:00 UTC+10 -> after offset handling
198
* expected: 2018-01-02 02:00 UTC => 2018-01-02 12:00 UTC+10 -> after offset handling
199
- * solution : change date AFTER setting the time and BEFORE offset handling
200
*/
201
if( $this->timezone_manual_offset !== false ){
202
$date_array = explode('-', $this->format('Y-m-d'));
203
}
204
$return = parent::setTime( $hour, $minute, $second );
205
- //pre-handle offsets for time changes where dates change as stated above
206
if( $this->timezone_manual_offset !== false ){
207
$this->setDate($date_array[0], $date_array[1], $date_array[2]);
208
}
209
- $this->handleOffsets();
210
$this->valid = $return !== false;
211
return $this;
212
}
81
if( !$this->valid && ($format == 'Y-m-d' || $format == em_get_date_format())) return '';
82
//if we deal with offsets, then we offset UTC time by that much
83
if( $this->timezone_manual_offset !== false ){
84
+ $format = $this->formatTimezones( $format );
85
if( function_exists('date_timestamp_get') ){
86
return date($format, $this->getTimestampWithOffset(true) );
87
}else{
94
return parent::format($format);
95
}
96
97
+ /**
98
+ * Formats timezone placeholders when there is a manual offset, which would be passed onto date formatting functions and usually output UTC timezone information.
99
+ * The $force_format flag is also useful if passing a format to any date() type of function, such as date_i18n, which will not inherit this function's timezone settings.
100
+ * @param string $format The format to be parsed.
101
+ * @param bool $force_format If set to true timezone placeholders will be formatted regardless.
102
+ * @return string
103
+ */
104
+ public function formatTimezones($format, $force_format = false ){
105
+ $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
106
+ $timezone_formats_regex = "/P|I|O|T|Z|e/";
107
+ if( $this->timezone_manual_offset !== false ){
108
+ if ( preg_match( $timezone_formats_regex, $format ) ) {
109
+ foreach ( $timezone_formats as $timezone_format ) {
110
+ if ( false !== strpos( $format, $timezone_format ) ) {
111
+ switch( $timezone_format ){
112
+ case 'P':
113
+ case 'O':
114
+ $offset = $this->getOffset();
115
+ $formatted_format = $timezone_format == 'P' ? 'H:i':'Hi';
116
+ $plus_minus = $offset < 0 ? '-':'+';
117
+ $formatted = $plus_minus . gmdate($formatted_format, absint($offset));
118
+ break;
119
+ case 'I':
120
+ $formatted = '0';
121
+ break;
122
+ case 'T':
123
+ case 'e':
124
+ $formatted = $this->getTimezone()->getName();
125
+ break;
126
+ case 'Z':
127
+ $formatted = $this->getOffset();
128
+ break;
129
+ }
130
+ $format = ' '.$format;
131
+ $format = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $format );
132
+ $format = substr( $format, 1, strlen( $format ) -1 );
133
+ }
134
+ }
135
+ }
136
+ }elseif( $force_format ){
137
+ //useful in cases where we may pass a format onto a date() function e.g. date_i18n, where the timezone is not relative to this object
138
+ if ( preg_match( $timezone_formats_regex, $format ) ) {
139
+ foreach ( $timezone_formats as $timezone_format ) {
140
+ if ( false !== strpos( $format, $timezone_format ) ) {
141
+ $format = ' '.$format;
142
+ $format = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $this->format( $timezone_format ) ), $format );
143
+ $format = substr( $format, 1, strlen( $format ) -1 );
144
+ }
145
+ }
146
+ }
147
+ }
148
+ return $format;
149
+ }
150
+
151
/**
152
* Returns a date and time representation in the format stored in Events Manager settings.
153
* @param string $include_hour
167
*/
168
public function i18n( $format = 'Y-m-d H:i:s' ){
169
if( !$this->valid && $format == em_get_date_format()) return '';
170
+ //since we use WP's date functions which don't use DateTime (and if so, don't inherit our timezones), we need to preformat timezone related formats, adapted from date_i18n
171
+ $format = $this->formatTimezones( $format, true );
172
//if we deal with offsets, then we offset UTC time by that much
173
if( !function_exists('date_timestamp_get') && $this->timezone_manual_offset !== false ){
174
//PHP < 5.3 fallback :/ Messed up, but it works...
253
* action: set the time to 12:00
254
* result: 2018-01-01 02:00 UTC => 2018-01-01 12:00 UTC+10 -> after offset handling
255
* expected: 2018-01-02 02:00 UTC => 2018-01-02 12:00 UTC+10 -> after offset handling
256
+ * solution : change date AFTER setting the time and offset handling
257
*/
258
if( $this->timezone_manual_offset !== false ){
259
$date_array = explode('-', $this->format('Y-m-d'));
260
}
261
$return = parent::setTime( $hour, $minute, $second );
262
+ $this->handleOffsets();
263
+ //post-handle offsets for time changes where dates change as stated above
264
if( $this->timezone_manual_offset !== false ){
265
$this->setDate($date_array[0], $date_array[1], $date_array[2]);
266
}
267
$this->valid = $return !== false;
268
return $this;
269
}
classes/em-event-post-admin.php CHANGED
@@ -56,7 +56,7 @@ class EM_Event_Post_Admin{
56
57
public static function admin_notices_filter($messages){
58
//When editing
59
- global $post, $EM_Notices;
60
if( $post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring' ){
61
if ( $EM_Notices->count_errors() > 0 ) {
62
unset($_GET['message']);
@@ -96,7 +96,7 @@ class EM_Event_Post_Admin{
96
}
97
98
public static function save_post($post_id, $post = false){
99
- global $wpdb, $EM_Event, $EM_Location, $EM_Notices, $EM_SAVING_EVENT, $EM_EVENT_SAVE_POST;
100
if( !empty($EM_SAVING_EVENT) ) return; //never proceed with this if using EM_Event::save();
101
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
102
$post_type = get_post_type($post_id);
@@ -306,7 +306,7 @@ class EM_Event_Post_Admin{
306
public static function meta_box_anonymous(){
307
global $EM_Event;
308
?>
309
- <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','events-manager')?></p></div>
310
<p><strong><?php _e('Name','events-manager'); ?> :</strong> <?php echo $EM_Event->event_owner_name; ?></p>
311
<p><strong><?php _e('Email','events-manager'); ?> :</strong> <?php echo $EM_Event->event_owner_email; ?></p>
312
<?php
56
57
public static function admin_notices_filter($messages){
58
//When editing
59
+ global $post, $EM_Notices; /* @var EM_Notices $EM_Notices */
60
if( $post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring' ){
61
if ( $EM_Notices->count_errors() > 0 ) {
62
unset($_GET['message']);
96
}
97
98
public static function save_post($post_id, $post = false){
99
+ global $wpdb, $EM_Event, $EM_Notices, $EM_SAVING_EVENT, $EM_EVENT_SAVE_POST; /* @var EM_Notices $EM_Notices */
100
if( !empty($EM_SAVING_EVENT) ) return; //never proceed with this if using EM_Event::save();
101
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
102
$post_type = get_post_type($post_id);
306
public static function meta_box_anonymous(){
307
global $EM_Event;
308
?>
309
+ <div class='updated'><p><?php echo sprintf(__('This %s was submitted by a guest. You will find their details in the <em>Anonymous Submitter Info</em> box','events-manager'), __('event', 'events-manager')); ?></p></div>
310
<p><strong><?php _e('Name','events-manager'); ?> :</strong> <?php echo $EM_Event->event_owner_name; ?></p>
311
<p><strong><?php _e('Email','events-manager'); ?> :</strong> <?php echo $EM_Event->event_owner_email; ?></p>
312
<?php
classes/em-event-post.php CHANGED
@@ -7,7 +7,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?
@@ -41,7 +40,7 @@ class EM_Event_Post {
41
}
42
43
public static function publish_future_post($post_id){
44
- global $wpdb, $EM_Event, $EM_Location, $EM_Notices;
45
$post_type = get_post_type($post_id);
46
$is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
47
$saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
7
class EM_Event_Post {
8
9
public static function init(){
10
//Front Side Modifiers
11
if( !is_admin() ){
12
//override single page with formats?
40
}
41
42
public static function publish_future_post($post_id){
43
+ global $EM_Event;
44
$post_type = get_post_type($post_id);
45
$is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
46
$saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
classes/em-event.php CHANGED
@@ -553,14 +553,20 @@ class EM_Event extends EM_Object{
553
$this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
554
//don't forget categories!
555
if( get_option('dbem_categories_enabled') ) $this->get_categories()->get_post();
556
//anonymous submissions and guest basic info
557
if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){
558
$this->event_owner_anonymous = 1;
559
$this->event_owner_name = !empty($_POST['event_owner_name']) ? wp_kses_data(wp_unslash($_POST['event_owner_name'])):'';
560
$this->event_owner_email = !empty($_POST['event_owner_email']) ? wp_kses_data($_POST['event_owner_email']):'';
561
}
562
- //get the rest and validate (optional)
563
- $this->get_post_meta(false);
564
$result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
565
return apply_filters('em_event_get_post', $result, $this);
566
}
@@ -1120,13 +1126,21 @@ class EM_Event extends EM_Object{
1120
}
1121
}
1122
$result = count($this->errors) == 0;
1123
- //If we're saving event categories in MS Global mode, we'll add them here, saving by term id (cat ids are gone now)
1124
- if( EM_MS_GLOBAL && get_option('dbem_categories_enabled') ){ //EM_MS_Globals should look up original blog
1125
- if( !is_main_site() ){
1126
- $this->get_categories()->save(); //it'll know what to do
1127
- }else{
1128
- $this->get_categories()->save_index(); //just save to index, we assume cats are saved in $this->save();
1129
- }
1130
}
1131
$this->compat_keys(); //compatability keys, loaded before saving recurrences
1132
//build recurrences if needed
553
$this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
554
//don't forget categories!
555
if( get_option('dbem_categories_enabled') ) $this->get_categories()->get_post();
556
+ //get the rest and validate (optional)
557
+ $this->get_post_meta(false);
558
//anonymous submissions and guest basic info
559
if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){
560
$this->event_owner_anonymous = 1;
561
$this->event_owner_name = !empty($_POST['event_owner_name']) ? wp_kses_data(wp_unslash($_POST['event_owner_name'])):'';
562
$this->event_owner_email = !empty($_POST['event_owner_email']) ? wp_kses_data($_POST['event_owner_email']):'';
563
+ if( empty($this->location_id) && !($this->location_id === 0 && !get_option('dbem_require_location',true)) ){
564
+ $this->get_location()->owner_anonymous = 1;
565
+ $this->location->owner_email = $this->event_owner_email;
566
+ $this->location->owner_name = $this->event_owner_name;
567
+ }
568
}
569
+ //validate and return results
570
$result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
571
return apply_filters('em_event_get_post', $result, $this);
572
}
1126
}
1127
}
1128
$result = count($this->errors) == 0;
1129
+ //deal with categories
1130
+ if( get_option('dbem_categories_enabled') ){
1131
+ if( EM_MS_GLOBAL ){ //EM_MS_Globals should look up original blog
1132
+ //If we're saving event categories in MS Global mode, we'll add them here, saving by term id (cat ids are gone now)
1133
+ if( !is_main_site() ){
1134
+ $this->get_categories()->save(); //it'll know what to do
1135
+ }else{
1136
+ $this->get_categories()->save_index(); //just save to index, we assume cats are saved in $this->save();
1137
+ }
1138
+ }elseif( get_option('dbem_default_category') > 0 ){
1139
+ //double-check for default category in other instances
1140
+ if( count($this->get_categories()) == 0 ){
1141
+ $this->get_categories()->save(); //let the object deal with this...
1142
+ }
1143
+ }
1144
}
1145
$this->compat_keys(); //compatability keys, loaded before saving recurrences
1146
//build recurrences if needed
classes/em-location-post-admin.php CHANGED
@@ -180,6 +180,10 @@ class EM_Location_Post_Admin{
180
if( get_option('dbem_location_attributes_enabled') ){
181
add_meta_box('em-location-attributes', __('Attributes','events-manager'), array('EM_Location_Post_Admin','meta_box_attributes'),EM_POST_TYPE_LOCATION, 'normal','default');
182
}
183
}
184
185
public static function meta_box_metadump(){
@@ -187,6 +191,7 @@ class EM_Location_Post_Admin{
187
echo "<pre>"; print_r(get_post_custom($post->ID)); echo "</pre>";
188
echo "<pre>"; print_r($EM_Location); echo "</pre>";
189
}
190
public static function meta_box_where(){
191
?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_location'); ?>" /><?php
192
em_locate_template('forms/location/where.php',true);
@@ -195,5 +200,14 @@ class EM_Location_Post_Admin{
195
public static function meta_box_attributes(){
196
em_locate_template('forms/location/attributes.php',true);
197
}
198
}
199
add_action('admin_init',array('EM_Location_Post_Admin','init'));
180
if( get_option('dbem_location_attributes_enabled') ){
181
add_meta_box('em-location-attributes', __('Attributes','events-manager'), array('EM_Location_Post_Admin','meta_box_attributes'),EM_POST_TYPE_LOCATION, 'normal','default');
182
}
183
+ //anonymous submission meta
184
+ if( !empty($EM_Location->owner_anonymous) ){
185
+ add_meta_box('em-location-anonymous', __('Anonymous Submitter Info','events-manager'), array('EM_Location_Post_Admin','meta_box_anonymous'),EM_POST_TYPE_LOCATION, 'side','high');
186
+ }
187
}
188
189
public static function meta_box_metadump(){
191
echo "<pre>"; print_r(get_post_custom($post->ID)); echo "</pre>";
192
echo "<pre>"; print_r($EM_Location); echo "</pre>";
193
}
194
+
195
public static function meta_box_where(){
196
?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_location'); ?>" /><?php
197
em_locate_template('forms/location/where.php',true);
200
public static function meta_box_attributes(){
201
em_locate_template('forms/location/attributes.php',true);
202
}
203
+
204
+ public static function meta_box_anonymous(){
205
+ global $EM_Location; /* @var EM_Location $EM_Location */
206
+ ?>
207
+ <div class='updated'><p><?php echo sprintf(__('This %s was submitted by a guest. You will find their details in the <em>Anonymous Submitter Info</em> box','events-manager'), __('location', 'events-manager')); ?></p></div>
208
+ <p><strong><?php _e('Name','events-manager'); ?> :</strong> <?php echo $EM_Location->owner_name; ?></p>
209
+ <p><strong><?php _e('Email','events-manager'); ?> :</strong> <?php echo $EM_Location->owner_email; ?></p>
210
+ <?php
211
+ }
212
}
213
add_action('admin_init',array('EM_Location_Post_Admin','init'));
classes/em-location.php CHANGED
@@ -64,6 +64,10 @@ class EM_Location extends EM_Object {
64
var $post_content = '';
65
var $location_owner = '';
66
var $location_status = 0;
67
//Other Vars
68
var $fields = array(
69
'location_id' => array('name'=>'id','type'=>'%d'),
@@ -199,16 +203,16 @@ class EM_Location extends EM_Object {
199
}
200
//Get custom fields
201
foreach($location_meta as $location_meta_key => $location_meta_val){
202
- $found = false;
203
- foreach($this->fields as $field_name => $field_info){
204
- if( $location_meta_key == '_'.$field_name){
205
$this->$field_name = $location_meta_val[0];
206
- $found = true;
207
}
208
}
209
- if(!$found && $location_meta_key[0] != '_'){
210
- $this->location_attributes[$location_meta_key] = ( is_array($location_meta_val) ) ? $location_meta_val[0]:$location_meta_val;
211
- }
212
}
213
}
214
//load post data - regardless
@@ -244,6 +248,12 @@ class EM_Location extends EM_Object {
244
$this->location_name = ( !empty($_POST['location_name']) ) ? sanitize_post_field('post_title', $_POST['location_name'], $this->post_id, 'db'):'';
245
$this->post_content = ( !empty($_POST['content']) ) ? wp_kses( wp_unslash($_POST['content']), $allowedtags):'';
246
$this->get_post_meta(false);
247
$result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
248
$this->compat_keys();
249
return apply_filters('em_location_get_post', $result, $this);
@@ -294,6 +304,15 @@ class EM_Location extends EM_Object {
294
$validate_post = false;
295
$this->add_error( __('Location name','events-manager').__(" is required.", 'events-manager') );
296
}
297
$validate_image = $this->image_validate();
298
$validate_meta = $this->validate_meta();
299
return apply_filters('em_location_validate', $validate_post && $validate_image && $validate_meta, $this );
@@ -377,6 +396,12 @@ class EM_Location extends EM_Object {
377
$this->location_owner = $post_data->post_author;
378
$this->post_status = $post_data->post_status;
379
$this->get_status();
380
//save the image, errors here will surface during $this->save_meta()
381
$this->image_upload();
382
//now save the meta
@@ -390,18 +415,20 @@ class EM_Location extends EM_Object {
390
$EM_SAVING_LOCATION = false;
391
//reload post data and add this location to the cache, after any other hooks have done their thing
392
//cache refresh when saving via admin area is handled in EM_Event_Post_Admin::save_post/refresh_cache
393
- if( $post_save && $meta_save && $this->is_published() ){
394
- //we won't depend on hooks, if we saved the event and it's still published in its saved state, refresh the cache regardless
395
$this->load_postdata($post_data);
396
- wp_cache_set($this->location_id, $this, 'em_locations');
397
- wp_cache_set($this->post_id, $this->location_id, 'em_locations_ids');
398
}
399
return $return;
400
}
401
402
function save_meta(){
403
//echo "<pre>"; print_r($this); echo "</pre>"; die();
404
- global $wpdb, $current_user;
405
if( $this->can_manage('edit_locations','edit_others_locations') || ( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
406
do_action('em_location_save_meta_pre', $this);
407
//Set Blog ID if in multisite mode
@@ -470,6 +497,14 @@ class EM_Location extends EM_Object {
470
//Also set the status here if status != previous status
471
if( $this->previous_status != $this->get_status() ) $this->set_status($this->get_status());
472
}
473
}
474
}else{
475
$this->add_error( sprintf(__('You do not have permission to create/edit %s.','events-manager'), __('locations','events-manager')) );
64
var $post_content = '';
65
var $location_owner = '';
66
var $location_status = 0;
67
+ /* anonymous submission information */
68
+ var $owner_anonymous;
69
+ var $owner_name;
70
+ var $owner_email;
71
//Other Vars
72
var $fields = array(
73
'location_id' => array('name'=>'id','type'=>'%d'),
203
}
204
//Get custom fields
205
foreach($location_meta as $location_meta_key => $location_meta_val){
206
+ $field_name = substr($location_meta_key, 1);
207
+ if($location_meta_key[0] != '_'){
208
+ $this->event_attributes[$location_meta_key] = ( is_array($location_meta_val) ) ? $location_meta_val[0]:$location_meta_val;
209
+ }elseif( is_string($field_name) && !in_array($field_name, $this->post_fields) ){
210
+ if( array_key_exists($field_name, $this->fields) ){
211
+ $this->$field_name = $location_meta_val[0];
212
+ }elseif( in_array($field_name, array('owner_name','owner_anonymous','owner_email')) ){
213
$this->$field_name = $location_meta_val[0];
214
}
215
}
216
}
217
}
218
//load post data - regardless
248
$this->location_name = ( !empty($_POST['location_name']) ) ? sanitize_post_field('post_title', $_POST['location_name'], $this->post_id, 'db'):'';
249
$this->post_content = ( !empty($_POST['content']) ) ? wp_kses( wp_unslash($_POST['content']), $allowedtags):'';
250
$this->get_post_meta(false);
251
+ //anonymous submissions and guest basic info
252
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->location_id) ){
253
+ $this->owner_anonymous = 1;
254
+ $this->owner_name = !empty($_POST['owner_name']) ? wp_kses_data(wp_unslash($_POST['owner_name'])):'';
255
+ $this->owner_email = !empty($_POST['owner_email']) ? wp_kses_data($_POST['owner_email']):'';
256
+ }
257
$result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
258
$this->compat_keys();
259
return apply_filters('em_location_get_post', $result, $this);
304
$validate_post = false;
305
$this->add_error( __('Location name','events-manager').__(" is required.", 'events-manager') );
306
}
307
+ //anonymous submissions and guest basic info
308
+ if( !empty($this->owner_anonymous) ){
309
+ if( !is_email($this->owner_email) ){
310
+ $this->add_error( sprintf(__("%s is required.", 'events-manager'), __('A valid email','events-manager')) );
311
+ }
312
+ if( empty($this->owner_name) ){
313
+ $this->add_error( sprintf(__("%s is required.", 'events-manager'), __('Your name','events-manager')) );
314
+ }
315
+ }
316
$validate_image = $this->image_validate();
317
$validate_meta = $this->validate_meta();
318
return apply_filters('em_location_validate', $validate_post && $validate_image && $validate_meta, $this );
396
$this->location_owner = $post_data->post_author;
397
$this->post_status = $post_data->post_status;
398
$this->get_status();
399
+ //anonymous submissions should save this information
400
+ if( !empty($this->owner_anonymous) ){
401
+ update_post_meta($this->post_id, '_owner_anonymous', 1);
402
+ update_post_meta($this->post_id, '_owner_name', $this->owner_name);
403
+ update_post_meta($this->post_id, '_owner_email', $this->owner_email);
404
+ }
405
//save the image, errors here will surface during $this->save_meta()
406
$this->image_upload();
407
//now save the meta
415
$EM_SAVING_LOCATION = false;
416
//reload post data and add this location to the cache, after any other hooks have done their thing
417
//cache refresh when saving via admin area is handled in EM_Event_Post_Admin::save_post/refresh_cache
418
+ if( $post_save && $meta_save ){
419
$this->load_postdata($post_data);
420
+ if( $this->is_published() ){
421
+ //we won't depend on hooks, if we saved the event and it's still published in its saved state, refresh the cache regardless
422
+ wp_cache_set($this->location_id, $this, 'em_locations');
423
+ wp_cache_set($this->post_id, $this->location_id, 'em_locations_ids');
424
+ }
425
}
426
return $return;
427
}
428
429
function save_meta(){
430
//echo "<pre>"; print_r($this); echo "</pre>"; die();
431
+ global $wpdb;
432
if( $this->can_manage('edit_locations','edit_others_locations') || ( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
433
do_action('em_location_save_meta_pre', $this);
434
//Set Blog ID if in multisite mode
497
//Also set the status here if status != previous status
498
if( $this->previous_status != $this->get_status() ) $this->set_status($this->get_status());
499
}
500
+ //check anonymous submission information
501
+ if( !empty($this->owner_anonymous) && get_option('dbem_events_anonymous_user') != $this->location_owner ){
502
+ //anonymous user owner has been replaced with a valid wp user account, so we remove anonymous status flag but leave email and name for future reference
503
+ update_post_meta($this->post_id, '_owner_anonymous', 0);
504
+ }elseif( get_option('dbem_events_anonymous_submissions') && get_option('dbem_events_anonymous_user') == $this->location_owner && is_email($this->owner_email) && !empty($this->owner_name) ){
505
+ //anonymous user account has been reinstated as the owner, so we can restore anonymous submission status
506
+ update_post_meta($this->post_id, '_owner_anonymous', 1);
507
+ }
508
}
509
}else{
510
$this->add_error( sprintf(__('You do not have permission to create/edit %s.','events-manager'), __('locations','events-manager')) );
classes/em-permalinks.php CHANGED
@@ -214,6 +214,7 @@ if( !class_exists('EM_Permalinks') ){
214
if( get_option('dbem_locations_enabled') ){
215
$em_rules[EM_POST_TYPE_LOCATION_SLUG."/([^/]+)/rss/?quot;] = 'index.php?'.EM_POST_TYPE_LOCATION.'=$matches[1]&rss=1';
216
}
217
return $em_rules + $rules;
218
}
219
214
if( get_option('dbem_locations_enabled') ){
215
$em_rules[EM_POST_TYPE_LOCATION_SLUG."/([^/]+)/rss/?quot;] = 'index.php?'.EM_POST_TYPE_LOCATION.'=$matches[1]&rss=1';
216
}
217
+ $em_rules = apply_filters('em_rewrite_rules_array', $em_rules);
218
return $em_rules + $rules;
219
}
220
classes/em-taxonomy-terms.php CHANGED
@@ -93,14 +93,16 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator, Countable{
93
}
94
95
public function save(){
96
- $term_slugs = array();
97
- foreach($this->terms as $EM_Taxonomy_Term){
98
- /* @var $EM_Taxonomy_Term EM_Taxonomy_Term */
99
- if( !empty($EM_Taxonomy_Term->slug) ) $term_slugs[] = $EM_Taxonomy_Term->slug; //save of taxonomy will soft-fail if slug is empty
100
- }
101
- if( count($term_slugs) == 0 && get_option('dbem_default_'.$this->singular) > 0 ){
102
- $default_term = get_term_by('id',get_option('dbem_default_'.$this->singular), $this->taxonomy);
103
- if($default_term) $term_slugs[] = $default_term->slug;
104
}
105
if( is_multisite() && $this->is_ms_global ){
106
//In MS Global mode, we also save taxonomy meta information for global lookups
@@ -109,10 +111,10 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator, Countable{
109
$this->save_index();
110
}
111
if( !EM_MS_GLOBAL || is_main_site() ){
112
- wp_set_object_terms($this->post_id, $term_slugs, $this->taxonomy);
113
}
114
}else{
115
- wp_set_object_terms($this->post_id, $term_slugs, $this->taxonomy);
116
}
117
do_action('em_'. $this->terms_name .'_save', $this);
118
}
@@ -155,6 +157,14 @@ class EM_Taxonomy_Terms extends EM_Object implements Iterator, Countable{
155
return $ids;
156
}
157
158
/**
159
* Gets the event for this object, or a blank event if none exists
160
* @return EM_Event
93
}
94
95
public function save(){
96
+ if( empty($this->terms) ){
97
+ $EM_Taxonomy_Term = new $this->term_class();
98
+ $opt = 'dbem_default_'.$EM_Taxonomy_Term->option_name;
99
+ $default_category = EM_MS_GLOBAL && $this->is_ms_global ? get_blog_option( get_current_site()->blog_id, $opt ) : get_option($opt);
100
+ if( $default_category > 0 ){
101
+ $EM_Taxonomy_Term = new $this->term_class($default_category);
102
+ if( !empty($EM_Taxonomy_Term->slug) ){
103
+ $this->terms[] = $EM_Taxonomy_Term;
104
+ }
105
+ }
106
}
107
if( is_multisite() && $this->is_ms_global ){
108
//In MS Global mode, we also save taxonomy meta information for global lookups
111
$this->save_index();
112
}
113
if( !EM_MS_GLOBAL || is_main_site() ){
114
+ wp_set_object_terms($this->post_id, $this->get_slugs(), $this->taxonomy);
115
}
116
}else{
117
+ wp_set_object_terms($this->post_id, $this->get_slugs(), $this->taxonomy);
118
}
119
do_action('em_'. $this->terms_name .'_save', $this);
120
}
157
return $ids;
158
}
159
160
+ public function get_slugs(){
161
+ $term_slugs = array();
162
+ foreach( $this->terms as $EM_Taxonomy_Term ){ /* @var EM_Taxonomy_Term $EM_Taxonomy_Term */
163
+ $term_slugs[] = $EM_Taxonomy_Term->slug;
164
+ }
165
+ return $term_slugs;
166
+ }
167
+
168
/**
169
* Gets the event for this object, or a blank event if none exists
170
* @return EM_Event
em-actions.php CHANGED
@@ -221,6 +221,9 @@ function em_init_actions() {
221
}elseif( !is_user_logged_in() ){
222
$location_cond = " AND location_private=0";
223
}
224
$location_cond = apply_filters('em_actions_locations_search_cond', $location_cond);
225
$term = (isset($_REQUEST['term'])) ? '%'.$wpdb->esc_like(wp_unslash($_REQUEST['term'])).'%' : '%'.$wpdb->esc_like(wp_unslash($_REQUEST['q'])).'%';
226
$sql = $wpdb->prepare("
221
}elseif( !is_user_logged_in() ){
222
$location_cond = " AND location_private=0";
223
}
224
+ if( EM_MS_GLOBAL && !get_site_option('dbem_ms_mainblog_locations') ){
225
+ $location_cond .= " AND blog_id=". absint(get_current_blog_id());
226
+ }
227
$location_cond = apply_filters('em_actions_locations_search_cond', $location_cond);
228
$term = (isset($_REQUEST['term'])) ? '%'.$wpdb->esc_like(wp_unslash($_REQUEST['term'])).'%' : '%'.$wpdb->esc_like(wp_unslash($_REQUEST['q'])).'%';
229
$sql = $wpdb->prepare("
em-data-privacy.php CHANGED
@@ -5,7 +5,8 @@
5
*/
6
function em_data_privacy_consent_checkbox( $EM_Object = false ){
7
if( !empty($EM_Object) && (!empty($EM_Object->booking_id) || !empty($EM_Object->post_id)) ) return; //already saved so consent was given at one point
8
- $label = sprintf(get_option('dbem_data_privacy_consent_text'), get_the_privacy_policy_link());
9
if( is_user_logged_in() ){
10
//check if consent was previously given and check box if true
11
$consent_given_already = get_user_meta( get_current_user_id(), 'em_data_privacy_consent', true );
@@ -65,7 +66,9 @@ function em_data_privacy_consent_hooks(){
65
add_action('em_location_save', 'em_data_privacy_cpt_save', 10, 2);
66
}
67
}
68
- add_action('init', 'em_data_privacy_consent_hooks');
69
70
/**
71
* Gets consent information for the submitted booking and and add it to the booking object for saving later.
5
*/
6
function em_data_privacy_consent_checkbox( $EM_Object = false ){
7
if( !empty($EM_Object) && (!empty($EM_Object->booking_id) || !empty($EM_Object->post_id)) ) return; //already saved so consent was given at one point
8
+ $label = get_option('dbem_data_privacy_consent_text');
9
+ if( function_exists('get_the_privacy_policy_link') ) $label = sprintf($label, get_the_privacy_policy_link());
10
if( is_user_logged_in() ){
11
//check if consent was previously given and check box if true
12
$consent_given_already = get_user_meta( get_current_user_id(), 'em_data_privacy_consent', true );
66
add_action('em_location_save', 'em_data_privacy_cpt_save', 10, 2);
67
}
68
}
69
+ if( !is_admin() || ( defined('DOING_AJAX') && DOING_AJAX && !empty($_REQUEST['action']) && !in_array($_REQUEST['action'], array('booking_add_one')) ) ){
70
+ add_action('init', 'em_data_privacy_consent_hooks');
71
+ }
72
73
/**
74
* Gets consent information for the submitted booking and and add it to the booking object for saving later.
em-install.php CHANGED
@@ -603,18 +603,17 @@ function em_add_options() {
603
'dbem_tag_event_list_order' => 'ASC',
604
'dbem_tag_default_color' => '#a8d145',
605
//RSS Stuff
606
- 'dbem_rss_limit' => 0,
607
'dbem_rss_scope' => 'future',
608
'dbem_rss_main_title' => get_bloginfo('title')." - ".__('Events', 'events-manager'),
609
'dbem_rss_main_description' => get_bloginfo('description')." - ".__('Events', 'events-manager'),
610
'dbem_rss_description_format' => "#_EVENTDATES - #_EVENTTIMES <br/>#_LOCATIONNAME <br/>#_LOCATIONADDRESS <br/>#_LOCATIONTOWN",
611
'dbem_rss_title_format' => "#_EVENTNAME",
612
- 'dbem_rss_scope' =>'future',
613
'dbem_rss_order' => get_option('dbem_events_default_order', 'ASC'), //get event order and orderby or use same new installation defaults
614
'dbem_rss_orderby' => get_option('dbem_events_default_orderby', 'event_start_date,event_start_time,event_name'),
615
'em_rss_pubdate' => date('D, d M Y H:i:s +0000'),
616
//iCal Stuff
617
- 'dbem_ical_limit' => 0,
618
'dbem_ical_scope' => "future",
619
'dbem_ical_description_format' => "#_EVENTNAME",
620
'dbem_ical_real_description_format' => "#_EVENTEXCERPT",
@@ -1081,7 +1080,7 @@ function em_upgrade_current_installation(){
1081
}
1082
if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.93 ){
1083
$message = __('Events Manager has introduced new privacy tools to help you comply with international laws such as the GDPR, <a href="%s">see our documentation</a> for more information.','events-manager');
1084
- $message = sprintf( $message, 'https://wp-events-plugin.com/documentation/data-privacy-protection/?utm_source=plugin&utm_campaign=gdpr_update');
1085
$EM_Admin_Notice = new EM_Admin_Notice(array( 'name' => 'gdpr_update', 'who' => 'admin', 'where' => 'all', 'message' => $message ));
1086
EM_Admin_Notices::add($EM_Admin_Notice, is_multisite());
1087
}
603
'dbem_tag_event_list_order' => 'ASC',
604
'dbem_tag_default_color' => '#a8d145',
605
//RSS Stuff
606
+ 'dbem_rss_limit' => 50,
607
'dbem_rss_scope' => 'future',
608
'dbem_rss_main_title' => get_bloginfo('title')." - ".__('Events', 'events-manager'),
609
'dbem_rss_main_description' => get_bloginfo('description')." - ".__('Events', 'events-manager'),
610
'dbem_rss_description_format' => "#_EVENTDATES - #_EVENTTIMES <br/>#_LOCATIONNAME <br/>#_LOCATIONADDRESS <br/>#_LOCATIONTOWN",
611
'dbem_rss_title_format' => "#_EVENTNAME",
612
'dbem_rss_order' => get_option('dbem_events_default_order', 'ASC'), //get event order and orderby or use same new installation defaults
613
'dbem_rss_orderby' => get_option('dbem_events_default_orderby', 'event_start_date,event_start_time,event_name'),
614
'em_rss_pubdate' => date('D, d M Y H:i:s +0000'),
615
//iCal Stuff
616
+ 'dbem_ical_limit' => 50,
617
'dbem_ical_scope' => "future",
618
'dbem_ical_description_format' => "#_EVENTNAME",
619
'dbem_ical_real_description_format' => "#_EVENTEXCERPT",
1080
}
1081
if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.93 ){
1082
$message = __('Events Manager has introduced new privacy tools to help you comply with international laws such as the GDPR, <a href="%s">see our documentation</a> for more information.','events-manager');
1083
+ $message = sprintf( $message, 'https://wp-events-plugin.com/documentation/data-privacy-gdpr-compliance/?utm_source=plugin&utm_campaign=gdpr_update');
1084
$EM_Admin_Notice = new EM_Admin_Notice(array( 'name' => 'gdpr_update', 'who' => 'admin', 'where' => 'all', 'message' => $message ));
1085
EM_Admin_Notices::add($EM_Admin_Notice, is_multisite());
1086
}
events-manager.php CHANGED
@@ -1,7 +1,7 @@
1
<?php
2
/*
3
Plugin Name: Events Manager
4
- Version: 5.9.3
5
Plugin URI: http://wp-events-plugin.com
6
Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
Author: Marcus Sykes
@@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28
*/
29
30
// Setting constants
31
- define('EM_VERSION', 5.93); //self expanatory
32
define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
1
<?php
2
/*
3
Plugin Name: Events Manager
4
+ Version: 5.9.4
5
Plugin URI: http://wp-events-plugin.com
6
Description: Event registration and booking management for WordPress. Recurring events, locations, google maps, rss, ical, booking registration and more!
7
Author: Marcus Sykes
28
*/
29
30
// Setting constants
31
+ define('EM_VERSION', 5.94); //self expanatory
32
define('EM_PRO_MIN_VERSION', 2.392); //self expanatory
33
define('EM_PRO_MIN_VERSION_CRITICAL', 2.377); //self expanatory
34
define('EM_DIR', dirname( __FILE__ )); //an absolute path to this directory
includes/js/events-manager.js CHANGED
@@ -532,7 +532,7 @@ jQuery(document).ready( function($){
532
}
533
534
//Manual Booking
535
- $('a.em-booking-button').click(function(e){
536
e.preventDefault();
537
var button = $(this);
538
if( button.text() != EM.bb_booked && $(this).text() != EM.bb_booking){
@@ -559,7 +559,7 @@ jQuery(document).ready( function($){
559
}
560
return false;
561
});
562
- $('a.em-cancel-button').click(function(e){
563
e.preventDefault();
564
var button = $(this);
565
if( button.text() != EM.bb_cancelled && button.text() != EM.bb_canceling){
532
}
533
534
//Manual Booking
535
+ $(document).on('click', 'a.em-booking-button', function(e){
536
e.preventDefault();
537
var button = $(this);
538
if( button.text() != EM.bb_booked && $(this).text() != EM.bb_booking){
559
}
560
return false;
561
});
562
+ $(document).on('click', 'a.em-cancel-button', function(e){
563
e.preventDefault();
564
var button = $(this);
565
if( button.text() != EM.bb_cancelled && button.text() != EM.bb_canceling){
multilingual/em-ml-options.php CHANGED
@@ -13,6 +13,8 @@ class EM_ML_Options {
13
'dbem_events_anonymous_result_success',
14
'dbem_events_form_result_success',
15
'dbem_events_form_result_success_updated',
16
//FORMATTING TAB
17
//events
18
'dbem_event_list_groupby_format',
13
'dbem_events_anonymous_result_success',
14
'dbem_events_form_result_success',
15
'dbem_events_form_result_success_updated',
16
+ //privacy policy consent
17
+ 'dbem_data_privacy_consent_text',
18
//FORMATTING TAB
19
//events
20
'dbem_event_list_groupby_format',
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: bookings, calendar, tickets, events, buddypress, event management, google
5
Text Domain: events-manager
6
Requires at least: 3.5
7
Tested up to: 4.9.6
8
- Stable tag: 5.9.3
9
10
Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
@@ -56,7 +56,7 @@ We provide the tools to [help you be GDPR compliant](http://wp-events-plugin.com
56
* export/erasure of data via the WordPress Privacy Tools, including booking, event and location data
57
* consent checkboxes on our booking, event and location forms on the frontend
58
* settings to control what can be exported/erased as well as where/when to place consent requests
59
- * privacy policy sample describing what Events Manager does with personal data
60
61
= Go Pro =
62
We have a premium "Pro" add-on for Events Manager which not only demonstrates the flexibility of Events Manager, but also adds some important features including but not limited to:
@@ -110,6 +110,22 @@ See our [FAQ](http://wp-events-plugin.com/documentation/faq/) page, which is upd
110
6. Manage attendees with various booking reports
111
112
== Changelog ==
113
= 5.9.3 =
114
* added Data Privacy and GDPR features
115
* fixed user deletion not properly deleting events and not deleting locations if content is set to be deleted not reassigned
5
Text Domain: events-manager
6
Requires at least: 3.5
7
Tested up to: 4.9.6
8
+ Stable tag: 5.9.4
9
10
Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
11
56
* export/erasure of data via the WordPress Privacy Tools, including booking, event and location data
57
* consent checkboxes on our booking, event and location forms on the frontend
58
* settings to control what can be exported/erased as well as where/when to place consent requests
59
+ * sample text for your site privacy policy describing what Events Manager does with personal data
60
61
= Go Pro =
62
We have a premium "Pro" add-on for Events Manager which not only demonstrates the flexibility of Events Manager, but also adds some important features including but not limited to:
110
6. Manage attendees with various booking reports
111
112
== Changelog ==
113
+ = 5.9.4 =
114
+ * added em_rewrite_rules_array filter for final permalink rule manipulation
115
+ * fixed privacy consent blocking certain actions such as single booking button and admin-side submissions
116
+ * fixed fatal errors when showing the consent checkbox in WordPress 5.9.5 and earlier
117
+ * fixed the quick booking button not working in ajax search results
118
+ * fixed privacy policy consent form label not being translatable for multilingual sites
119
+ * fixed inconsistent date headers in certain situations with UTC manual offset dates
120
+ * fixed incorrect link to .eot dashicon file for IE11
121
+ * added anonymous submitter data to locations for new event submissions and integrated this with GDPR export/erase tools
122
+ * fixed location slug blanks when directly published from front-end via submitting an event
123
+ * added default ical and rss feed limits to avoid overloading as number of events grow
124
+ * corrected docs to include 'recurrences' search attribute
125
+ * added timezone pre-formatting to functions that produced incorrect output for timezone date placeholders
126
+ * fixed default categories not being applied for events with no categories
127
+ * fixed locations being selectable for events in other blogs within a multisite global mode when locations don't all reside on main blog
128
+
129
= 5.9.3 =
130
* added Data Privacy and GDPR features
131
* fixed user deletion not properly deleting events and not deleting locations if content is set to be deleted not reassigned
templates/forms/event/location.php CHANGED
@@ -33,8 +33,8 @@ $required = apply_filters('em_required_html','<i>*</i>');
33
<td>
34
<select name="location_id" id='location-select-id' size="1">
35
<?php if(!get_option('dbem_require_location',true)): ?><option value="0"><?php esc_html_e('No Location','events-manager'); ?></option><?php endif; ?>
36
- <?php
37
- $ddm_args = array('blog'=>false, 'private'=>$EM_Event->can_manage('read_private_locations'));
38
$ddm_args['owner'] = (is_user_logged_in() && !current_user_can('read_others_locations')) ? get_current_user_id() : false;
39
$locations = EM_Locations::get($ddm_args);
40
$selected_location = !empty($EM_Event->location_id) || !empty($EM_Event->event_id) ? $EM_Event->location_id:get_option('dbem_default_location');
33
<td>
34
<select name="location_id" id='location-select-id' size="1">
35
<?php if(!get_option('dbem_require_location',true)): ?><option value="0"><?php esc_html_e('No Location','events-manager'); ?></option><?php endif; ?>
36
+ <?php
37
+ $ddm_args = array('private'=>$EM_Event->can_manage('read_private_locations'));
38
$ddm_args['owner'] = (is_user_logged_in() && !current_user_can('read_others_locations')) ? get_current_user_id() : false;
39
$locations = EM_Locations::get($ddm_args);
40
$selected_location = !empty($EM_Event->location_id) || !empty($EM_Event->event_id) ? $EM_Event->location_id:get_option('dbem_default_location');