Version Description
- added Location Types including URL and (via external free add-on) Zoom support!
- added native OAuth support for third party integrations (e.g. Zoom)
- added $EM_Event object to booking form template actions
- changed $EM_Booking->booking_status to protected so that status returns 1 even if approvals are disabled
- fixed XSS vulnerability (kudos to Jakob Wierzba)
- fixed potential SQL injection vulnerability (kudos to Antony Garand from Godaddy)
- fixed fatal errors in BuddyPress if notifications are disabled
- fixed minor PHP warning
- fixed Yoast SEO 14.0 conflict
Download this release
Release Info
Developer | netweblogic |
Plugin | Events Manager |
Version | 5.9.8 |
Comparing to | |
See all releases |
Code changes from version 5.9.7.3 to 5.9.8
- admin/em-options.php +5 -1
- admin/settings/tabs/general.php +62 -27
- buddypress/screens/my-bookings.php +0 -4
- classes/em-admin-notices.php +1 -0
- classes/em-booking.php +8 -4
- classes/em-datetime.php +2 -0
- classes/em-event-posts-admin.php +3 -1
- classes/em-event.php +141 -18
- classes/em-events.php +32 -1
- classes/em-exception.php +107 -0
- classes/em-locations.php +10 -0
- classes/em-oauth/oauth-admin-settings.php +186 -0
- classes/em-oauth/oauth-api-client.php +594 -0
- classes/em-oauth/oauth-api-token.php +88 -0
- classes/em-oauth/oauth-api.php +251 -0
- classes/em-object.php +2 -1
- classes/event-locations/em-event-location-url.php +72 -0
- classes/event-locations/em-event-location.php +167 -0
- classes/event-locations/em-event-locations.php +68 -0
- em-events.php +20 -1
- em-functions.php +7 -2
- em-install.php +9 -0
- events-manager.php +24 -5
- includes/css/events-manager-oauth-admin.css +16 -0
- includes/css/events_manager.css +8 -0
- includes/css/events_manager_admin.css +10 -1
- includes/js/admin-settings.js +15 -4
- includes/js/events-manager.js +5 -3
- multilingual/em-ml-admin.php +3 -1
- readme.txt +19 -4
- templates/forms/event/event-locations/url.php +11 -0
- templates/forms/event/location.php +151 -98
- templates/placeholders/bookingform.php +5 -3
- templates/tables/events.php +11 -3
admin/em-options.php
CHANGED
@@ -19,6 +19,10 @@ function em_options_save(){
|
|
19 |
//Do nothing, keep old setting.
|
20 |
}elseif( ($postKey == 'dbem_category_default_color' || $postKey == 'dbem_tag_default_color') && !sanitize_hex_color($postValue) ){
|
21 |
$EM_Notices->add_error( sprintf(esc_html_x('Colors must be in a valid %s format, such as #FF00EE.', 'hex format', 'events-manager'), '<a href="http://en.wikipedia.org/wiki/Web_colors">hex</a>').' '. esc_html__('This setting was not changed.', 'events-manager'), true);
|
|
|
|
|
|
|
|
|
22 |
}else{
|
23 |
//TODO slashes being added?
|
24 |
if( is_array($postValue) ){
|
@@ -845,7 +849,7 @@ function em_admin_option_box_uninstall(){
|
|
845 |
<th style="text-align:right;">
|
846 |
<a href="<?php echo $export_settings_url; ?>" class="button-secondary"><?php esc_html_e('Export Settings','events-manager'); ?></a>
|
847 |
</th>
|
848 |
-
<td><?php esc_html_e('Export your Events Manager settings and restore them here or on another website running this plugin.','events-manager'); ?></td>
|
849 |
</tr>
|
850 |
</table>
|
851 |
|
19 |
//Do nothing, keep old setting.
|
20 |
}elseif( ($postKey == 'dbem_category_default_color' || $postKey == 'dbem_tag_default_color') && !sanitize_hex_color($postValue) ){
|
21 |
$EM_Notices->add_error( sprintf(esc_html_x('Colors must be in a valid %s format, such as #FF00EE.', 'hex format', 'events-manager'), '<a href="http://en.wikipedia.org/wiki/Web_colors">hex</a>').' '. esc_html__('This setting was not changed.', 'events-manager'), true);
|
22 |
+
}elseif( $postKey == 'dbem_oauth' && is_array($postValue) ){
|
23 |
+
foreach($postValue as $postValue_key=>$postValue_val){
|
24 |
+
EM_Options::set($postValue_key, wp_unslash($postValue_val), 'dbem_oauth');
|
25 |
+
}
|
26 |
}else{
|
27 |
//TODO slashes being added?
|
28 |
if( is_array($postValue) ){
|
849 |
<th style="text-align:right;">
|
850 |
<a href="<?php echo $export_settings_url; ?>" class="button-secondary"><?php esc_html_e('Export Settings','events-manager'); ?></a>
|
851 |
</th>
|
852 |
+
<td><p><?php esc_html_e('Export your Events Manager settings and restore them here or on another website running this plugin.','events-manager'); ?></p></td>
|
853 |
</tr>
|
854 |
</table>
|
855 |
|
admin/settings/tabs/general.php
CHANGED
@@ -50,23 +50,6 @@
|
|
50 |
if( get_option('dbem_attributes_enabled') ){
|
51 |
em_options_textarea ( sprintf(__( '%s Attributes', 'events-manager'),__('Event','events-manager')), '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>", 'events-manager'), EM_ADMIN_URL .'&page=events-manager-help') );
|
52 |
}
|
53 |
-
if( get_option('dbem_locations_enabled') ){
|
54 |
-
/*default location*/
|
55 |
-
if( defined('EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS') && EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS ){
|
56 |
-
em_options_input_text( __( 'Default Location', 'events-manager'), 'dbem_default_location', __('Please enter your Location ID, or leave blank for no location.','events-manager').' '.__( 'This option allows you to select the default location when adding an event.','events-manager')." ".__('(not applicable with event ownership on presently, coming soon!)','events-manager') );
|
57 |
-
}else{
|
58 |
-
$location_options = array();
|
59 |
-
$location_options[0] = __('no default location','events-manager');
|
60 |
-
$EM_Locations = EM_Locations::get();
|
61 |
-
foreach($EM_Locations as $EM_Location){
|
62 |
-
$location_options[$EM_Location->location_id] = $EM_Location->location_name;
|
63 |
-
}
|
64 |
-
em_options_select ( __( 'Default Location', 'events-manager'), 'dbem_default_location', $location_options, __('Please enter your Location ID.','events-manager').' '.__( 'This option allows you to select the default location when adding an event.','events-manager')." ".__('(not applicable with event ownership on presently, coming soon!)','events-manager') );
|
65 |
-
}
|
66 |
-
|
67 |
-
/*default location country*/
|
68 |
-
em_options_select ( __( 'Default Location Country', 'events-manager'), 'dbem_location_default_country', em_get_countries(__('no default country', 'events-manager')), __('If you select a default country, that will be pre-selected when creating a new location.','events-manager') );
|
69 |
-
}
|
70 |
?>
|
71 |
<tr class="em-header">
|
72 |
<td colspan="2">
|
@@ -74,17 +57,69 @@
|
|
74 |
</td>
|
75 |
</tr>
|
76 |
<?php
|
77 |
-
em_options_radio_binary ( __( 'Enable locations?', 'events-manager'), '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>.','events-manager') );
|
78 |
-
if( get_option('dbem_locations_enabled') ){
|
79 |
-
em_options_radio_binary ( __( 'Require locations for events?', 'events-manager'), '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.','events-manager') );
|
80 |
-
em_options_radio_binary ( __( 'Use dropdown for locations?', 'events-manager'), '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','events-manager') );
|
81 |
-
em_options_radio_binary ( sprintf(__( 'Enable %s attributes?', 'events-manager'),__('location','events-manager')), 'dbem_location_attributes_enabled', __( 'Select yes to enable the attributes feature','events-manager') );
|
82 |
-
em_options_radio_binary ( sprintf(__( 'Enable %s custom fields?', 'events-manager'),__('location','events-manager')), '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.','events-manager') );
|
83 |
-
if( get_option('dbem_location_attributes_enabled') ){
|
84 |
-
em_options_textarea ( sprintf(__( '%s Attributes', 'events-manager'),__('Location','events-manager')), '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>", 'events-manager'), EM_ADMIN_URL .'&page=events-manager-help') );
|
85 |
-
}
|
86 |
-
}
|
87 |
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
<tr class="em-header">
|
89 |
<td colspan="2">
|
90 |
<h4><?php echo sprintf(__('%s Settings','events-manager'),__('Other','events-manager')); ?></h4>
|
50 |
if( get_option('dbem_attributes_enabled') ){
|
51 |
em_options_textarea ( sprintf(__( '%s Attributes', 'events-manager'),__('Event','events-manager')), '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>", 'events-manager'), EM_ADMIN_URL .'&page=events-manager-help') );
|
52 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
?>
|
54 |
<tr class="em-header">
|
55 |
<td colspan="2">
|
57 |
</td>
|
58 |
</tr>
|
59 |
<?php
|
60 |
+
em_options_radio_binary ( __( 'Enable locations?', 'events-manager'), '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>.','events-manager'), '', '.em-location-type-option' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
?>
|
62 |
+
<tbody class="em-location-type-option">
|
63 |
+
<?php
|
64 |
+
em_options_radio_binary ( __( 'Require locations for events?', 'events-manager'), '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.','events-manager') );
|
65 |
+
?>
|
66 |
+
<tr valign="top" id='dbem_location_types_row'>
|
67 |
+
<th scope="row"><?php esc_html_e('Location Types', 'events-manager'); ?></th>
|
68 |
+
<td>
|
69 |
+
<?php
|
70 |
+
$location_types = get_option('dbem_location_types', array());
|
71 |
+
?>
|
72 |
+
<label>
|
73 |
+
<input type="checkbox" name="dbem_location_types[location]" value="1" <?php if( !empty($location_types['location']) ) echo 'checked'; ?> data-trigger=".em-location-type-option-physical" class="em-trigger">
|
74 |
+
<?php esc_html_e('Physicial Locations', 'events-manager'); ?>
|
75 |
+
</label>
|
76 |
+
<?php foreach (EM_Event_Locations\Event_Locations::get_types() as $event_location_type => $EM_Event_Location_Class): /* @var EM_Event_Locations\Event_Location $EM_Event_Location_Class */ ?>
|
77 |
+
<br>
|
78 |
+
<label>
|
79 |
+
<input type="checkbox" name="dbem_location_types[<?php echo esc_attr($event_location_type); ?>]" value="1" <?php if( !empty($location_types[$event_location_type]) ) echo 'checked'; ?> data-trigger=".em-location-type-option-<?php echo esc_attr($event_location_type); ?>" class="em-trigger">
|
80 |
+
<?php echo $EM_Event_Location_Class::get_label('plural'); ?>
|
81 |
+
</label>
|
82 |
+
<?php endforeach; ?>
|
83 |
+
<p><em><?php echo sprintf( esc_html__('You can allow different location types which can be assigned to an event. For more information see our %s.', 'events-manager'), '<a href="http://wp-events-plugin.com/documentation/location-types/" target="_blank">'.esc_html__('documentation', 'events-manager').'</a>'); ?></em></p>
|
84 |
+
</td>
|
85 |
+
</tr>
|
86 |
+
</tbody>
|
87 |
+
</table>
|
88 |
+
<table class="form-table em-location-type-option">
|
89 |
+
<tbody class="em-location-type-option-physical">
|
90 |
+
<tr class="em-subheader">
|
91 |
+
<td colspan="2">
|
92 |
+
<h5><?php esc_html_e('Physicial Locations', 'events-manager'); ?></h5>
|
93 |
+
</td>
|
94 |
+
</tr>
|
95 |
+
<?php
|
96 |
+
if( get_option('dbem_locations_enabled') ){
|
97 |
+
em_options_radio_binary ( __( 'Use dropdown for locations?', 'events-manager'), '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','events-manager') );
|
98 |
+
em_options_radio_binary ( sprintf(__( 'Enable %s attributes?', 'events-manager'),__('location','events-manager')), 'dbem_location_attributes_enabled', __( 'Select yes to enable the attributes feature','events-manager') );
|
99 |
+
em_options_radio_binary ( sprintf(__( 'Enable %s custom fields?', 'events-manager'),__('location','events-manager')), '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.','events-manager') );
|
100 |
+
if( get_option('dbem_location_attributes_enabled') ){
|
101 |
+
em_options_textarea ( sprintf(__( '%s Attributes', 'events-manager'),__('Location','events-manager')), '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>", 'events-manager'), EM_ADMIN_URL .'&page=events-manager-help') );
|
102 |
+
}
|
103 |
+
/*default location*/
|
104 |
+
if( defined('EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS') && EM_OPTIMIZE_SETTINGS_PAGE_LOCATIONS ){
|
105 |
+
em_options_input_text( __( 'Default Location', 'events-manager'), 'dbem_default_location', __('Please enter your Location ID, or leave blank for no location.','events-manager').' '.__( 'This option allows you to select the default location when adding an event.','events-manager')." ".__('(not applicable with event ownership on presently, coming soon!)','events-manager') );
|
106 |
+
}else{
|
107 |
+
$location_options = array();
|
108 |
+
$location_options[0] = __('no default location','events-manager');
|
109 |
+
$EM_Locations = EM_Locations::get();
|
110 |
+
foreach($EM_Locations as $EM_Location){
|
111 |
+
$location_options[$EM_Location->location_id] = $EM_Location->location_name;
|
112 |
+
}
|
113 |
+
em_options_select ( __( 'Default Location', 'events-manager'), 'dbem_default_location', $location_options, __('Please enter your Location ID.','events-manager').' '.__( 'This option allows you to select the default location when adding an event.','events-manager')." ".__('(not applicable with event ownership on presently, coming soon!)','events-manager') );
|
114 |
+
}
|
115 |
+
|
116 |
+
/*default location country*/
|
117 |
+
em_options_select ( __( 'Default Location Country', 'events-manager'), 'dbem_location_default_country', em_get_countries(__('no default country', 'events-manager')), __('If you select a default country, that will be pre-selected when creating a new location.','events-manager') );
|
118 |
+
}
|
119 |
+
?>
|
120 |
+
</tbody>
|
121 |
+
</table>
|
122 |
+
<table class="form-table">
|
123 |
<tr class="em-header">
|
124 |
<td colspan="2">
|
125 |
<h4><?php echo sprintf(__('%s Settings','events-manager'),__('Other','events-manager')); ?></h4>
|
buddypress/screens/my-bookings.php
CHANGED
@@ -12,10 +12,6 @@ function bp_em_my_bookings() {
|
|
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();
|
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 |
}
|
16 |
|
17 |
em_load_event();
|
classes/em-admin-notices.php
CHANGED
@@ -200,4 +200,5 @@ class EM_Admin_Notices {
|
|
200 |
<?php
|
201 |
}
|
202 |
}
|
|
|
203 |
EM_Admin_Notices::init();
|
200 |
<?php
|
201 |
}
|
202 |
}
|
203 |
+
include('em-admin-notice.php');
|
204 |
EM_Admin_Notices::init();
|
classes/em-booking.php
CHANGED
@@ -27,6 +27,7 @@ function em_get_booking($id = false) {
|
|
27 |
}
|
28 |
/**
|
29 |
* Contains all information and relevant functions surrounding a single booking made with Events Manager
|
|
|
30 |
* @property string $language
|
31 |
*/
|
32 |
class EM_Booking extends EM_Object{
|
@@ -37,7 +38,7 @@ class EM_Booking extends EM_Object{
|
|
37 |
var $booking_price = null;
|
38 |
var $booking_spaces;
|
39 |
var $booking_comment;
|
40 |
-
|
41 |
var $booking_tax_rate = null;
|
42 |
var $booking_taxes = null;
|
43 |
var $booking_meta = array();
|
@@ -174,6 +175,8 @@ class EM_Booking extends EM_Object{
|
|
174 |
if( !empty($this->booking_meta['lang']) ){
|
175 |
return $this->booking_meta['lang'];
|
176 |
}
|
|
|
|
|
177 |
}
|
178 |
return null;
|
179 |
}
|
@@ -261,14 +264,14 @@ class EM_Booking extends EM_Object{
|
|
261 |
$this->email();
|
262 |
}
|
263 |
$this->compat_keys();
|
264 |
-
return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
|
265 |
}else{
|
266 |
$this->feedback_message = __('There was a problem saving the booking.', 'events-manager');
|
267 |
if( !$this->can_manage() ){
|
268 |
$this->add_error(sprintf(__('You cannot manage this %s.', 'events-manager'),__('Booking','events-manager')));
|
269 |
}
|
270 |
}
|
271 |
-
return apply_filters('em_booking_save', false, $this);
|
272 |
}
|
273 |
|
274 |
/**
|
@@ -889,11 +892,12 @@ class EM_Booking extends EM_Object{
|
|
889 |
$this->booking_status = false;
|
890 |
$this->feedback_message = sprintf(__('%s deleted', 'events-manager'), __('Booking','events-manager'));
|
891 |
$wpdb->delete( EM_META_TABLE, array('meta_key'=>'booking-note', 'object_id' => $this->booking_id), array('%s','%d'));
|
|
|
892 |
}else{
|
893 |
$this->add_error(sprintf(__('%s could not be deleted', 'events-manager'), __('Booking','events-manager')));
|
894 |
}
|
895 |
}
|
896 |
-
do_action('em_bookings_deleted', $result, array($this->booking_id));
|
897 |
return apply_filters('em_booking_delete',( $result !== false ), $this);
|
898 |
}
|
899 |
|
27 |
}
|
28 |
/**
|
29 |
* Contains all information and relevant functions surrounding a single booking made with Events Manager
|
30 |
+
* @property int|false $booking_status
|
31 |
* @property string $language
|
32 |
*/
|
33 |
class EM_Booking extends EM_Object{
|
38 |
var $booking_price = null;
|
39 |
var $booking_spaces;
|
40 |
var $booking_comment;
|
41 |
+
protected $booking_status = false;
|
42 |
var $booking_tax_rate = null;
|
43 |
var $booking_taxes = null;
|
44 |
var $booking_meta = array();
|
175 |
if( !empty($this->booking_meta['lang']) ){
|
176 |
return $this->booking_meta['lang'];
|
177 |
}
|
178 |
+
}elseif( $var == 'booking_status' ){
|
179 |
+
return ($this->booking_status == 0 && !get_option('dbem_bookings_approval') ) ? 1:$this->booking_status;
|
180 |
}
|
181 |
return null;
|
182 |
}
|
264 |
$this->email();
|
265 |
}
|
266 |
$this->compat_keys();
|
267 |
+
return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this, $update);
|
268 |
}else{
|
269 |
$this->feedback_message = __('There was a problem saving the booking.', 'events-manager');
|
270 |
if( !$this->can_manage() ){
|
271 |
$this->add_error(sprintf(__('You cannot manage this %s.', 'events-manager'),__('Booking','events-manager')));
|
272 |
}
|
273 |
}
|
274 |
+
return apply_filters('em_booking_save', false, $this, false);
|
275 |
}
|
276 |
|
277 |
/**
|
892 |
$this->booking_status = false;
|
893 |
$this->feedback_message = sprintf(__('%s deleted', 'events-manager'), __('Booking','events-manager'));
|
894 |
$wpdb->delete( EM_META_TABLE, array('meta_key'=>'booking-note', 'object_id' => $this->booking_id), array('%s','%d'));
|
895 |
+
do_action('em_booking_deleted', $this);
|
896 |
}else{
|
897 |
$this->add_error(sprintf(__('%s could not be deleted', 'events-manager'), __('Booking','events-manager')));
|
898 |
}
|
899 |
}
|
900 |
+
do_action('em_bookings_deleted', $result, array($this->booking_id), $this);
|
901 |
return apply_filters('em_booking_delete',( $result !== false ), $this);
|
902 |
}
|
903 |
|
classes/em-datetime.php
CHANGED
@@ -180,6 +180,8 @@ class EM_DateTime extends DateTime {
|
|
180 |
$timestamp = parent::format('U');
|
181 |
$server_offset = date('Z', $timestamp);
|
182 |
return date_i18n( $format, $timestamp - ($server_offset * 2) + $this->getOffset() );
|
|
|
|
|
183 |
}else{
|
184 |
return date_i18n( $format, $this->getTimestampWithOffset(true) );
|
185 |
}
|
180 |
$timestamp = parent::format('U');
|
181 |
$server_offset = date('Z', $timestamp);
|
182 |
return date_i18n( $format, $timestamp - ($server_offset * 2) + $this->getOffset() );
|
183 |
+
}elseif( function_exists('wp_date') ){
|
184 |
+
return wp_date( $format, $this->getTimestamp(), $this->getTimezone() );
|
185 |
}else{
|
186 |
return date_i18n( $format, $this->getTimestampWithOffset(true) );
|
187 |
}
|
classes/em-event-posts-admin.php
CHANGED
@@ -208,7 +208,7 @@ class EM_Event_Posts_Admin{
|
|
208 |
case 'location':
|
209 |
//get meta value to see if post has location, otherwise
|
210 |
$EM_Location = $EM_Event->get_location();
|
211 |
-
if(
|
212 |
$actions = array();
|
213 |
$actions[] = "<a href='". esc_url($EM_Location->get_permalink())."'>". esc_html__('View') ."</a>";
|
214 |
if( $EM_Location->can_manage('edit_locations', 'edit_others_locations') ) {
|
@@ -217,6 +217,8 @@ class EM_Event_Posts_Admin{
|
|
217 |
echo "<strong><a href='". $EM_Location->get_permalink()."'>" . $EM_Location->location_name . "</a></strong>";
|
218 |
echo "<span class='row-actions'> - ". implode(' | ', $actions) . "</span>";
|
219 |
echo "<br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
|
|
|
|
|
220 |
}else{
|
221 |
echo __('None','events-manager');
|
222 |
}
|
208 |
case 'location':
|
209 |
//get meta value to see if post has location, otherwise
|
210 |
$EM_Location = $EM_Event->get_location();
|
211 |
+
if( $EM_Event->has_location() ){
|
212 |
$actions = array();
|
213 |
$actions[] = "<a href='". esc_url($EM_Location->get_permalink())."'>". esc_html__('View') ."</a>";
|
214 |
if( $EM_Location->can_manage('edit_locations', 'edit_others_locations') ) {
|
217 |
echo "<strong><a href='". $EM_Location->get_permalink()."'>" . $EM_Location->location_name . "</a></strong>";
|
218 |
echo "<span class='row-actions'> - ". implode(' | ', $actions) . "</span>";
|
219 |
echo "<br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
|
220 |
+
}elseif( $EM_Event->has_event_location() ) {
|
221 |
+
echo $EM_Event->get_event_location()->get_admin_column();
|
222 |
}else{
|
223 |
echo __('None','events-manager');
|
224 |
}
|
classes/em-event.php
CHANGED
@@ -124,6 +124,14 @@ class EM_Event extends EM_Object{
|
|
124 |
var $event_spaces;
|
125 |
var $event_private;
|
126 |
var $location_id;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
var $recurrence_id;
|
128 |
var $event_status;
|
129 |
var $blog_id = 0;
|
@@ -173,6 +181,7 @@ class EM_Event extends EM_Object{
|
|
173 |
'event_rsvp_spaces' => array( 'name'=>'rsvp_spaces', 'type'=>'%d', 'null'=>true ),
|
174 |
'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d', 'null'=>true),
|
175 |
'location_id' => array( 'name'=>'location_id', 'type'=>'%d', 'null'=>true ),
|
|
|
176 |
'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d', 'null'=>true ),
|
177 |
'event_status' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
|
178 |
'event_private' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
|
@@ -227,6 +236,10 @@ class EM_Event extends EM_Object{
|
|
227 |
* @var EM_Location
|
228 |
*/
|
229 |
var $location;
|
|
|
|
|
|
|
|
|
230 |
/**
|
231 |
* @var EM_Bookings
|
232 |
*/
|
@@ -489,11 +502,12 @@ class EM_Event extends EM_Object{
|
|
489 |
//load meta data and other related information
|
490 |
if( $event_post->post_status != 'auto-draft' ){
|
491 |
$event_meta = $this->get_event_meta($search_by);
|
|
|
492 |
//Get custom fields and post meta
|
493 |
foreach($event_meta as $event_meta_key => $event_meta_val){
|
494 |
$field_name = substr($event_meta_key, 1);
|
495 |
if($event_meta_key[0] != '_'){
|
496 |
-
$this->event_attributes[$event_meta_key] = ( is_array($event_meta_val) ) ? $event_meta_val[0]:$event_meta_val;
|
497 |
}elseif( is_string($field_name) && !in_array($field_name, $this->post_fields) ){
|
498 |
if( array_key_exists($field_name, $this->fields) ){
|
499 |
$this->$field_name = $event_meta_val[0];
|
@@ -502,6 +516,7 @@ class EM_Event extends EM_Object{
|
|
502 |
}
|
503 |
}
|
504 |
}
|
|
|
505 |
//quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
|
506 |
if( empty($this->event_id) && !$this->is_recurring() ){
|
507 |
global $wpdb;
|
@@ -653,16 +668,40 @@ class EM_Event extends EM_Object{
|
|
653 |
//reset start and end objects so they are recreated with the new dates/times if and when needed
|
654 |
$this->start = $this->end = null;
|
655 |
|
656 |
-
//Get Location
|
657 |
-
if(
|
658 |
-
|
659 |
-
|
660 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
}else{
|
662 |
-
|
663 |
-
$this->
|
664 |
-
$this->get_location()->get_post(false);
|
665 |
-
$this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise
|
666 |
}
|
667 |
|
668 |
//Bookings
|
@@ -709,7 +748,7 @@ class EM_Event extends EM_Object{
|
|
709 |
if(get_option('dbem_attributes_enabled')){
|
710 |
global $allowedtags;
|
711 |
if( !is_array($this->event_attributes) ){ $this->event_attributes = array(); }
|
712 |
-
$event_available_attributes = em_get_attributes();
|
713 |
if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
|
714 |
foreach($_POST['em_attributes'] as $att_key => $att_value ){
|
715 |
if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->event_attributes) ) ){
|
@@ -898,11 +937,22 @@ class EM_Event extends EM_Object{
|
|
898 |
$this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','events-manager'));
|
899 |
}
|
900 |
}
|
901 |
-
if( get_option('dbem_locations_enabled')
|
902 |
-
if( get_option('dbem_require_location',true)
|
903 |
-
|
|
|
|
|
|
|
|
|
|
|
904 |
$this->add_error($this->get_location()->get_errors());
|
|
|
|
|
|
|
905 |
}
|
|
|
|
|
|
|
906 |
}
|
907 |
}
|
908 |
if ( count($missing_fields) > 0){
|
@@ -1086,6 +1136,12 @@ class EM_Event extends EM_Object{
|
|
1086 |
}
|
1087 |
}
|
1088 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1089 |
//update timestamps, dates and times
|
1090 |
update_post_meta($this->post_id, '_event_start_local', $this->start()->getDateTime());
|
1091 |
update_post_meta($this->post_id, '_event_end_local', $this->end()->getDateTime());
|
@@ -1280,9 +1336,10 @@ class EM_Event extends EM_Object{
|
|
1280 |
|
1281 |
/**
|
1282 |
* Delete whole event, including bookings, tickets, etc.
|
|
|
1283 |
* @return boolean
|
1284 |
*/
|
1285 |
-
function delete($force_delete = false){
|
1286 |
if( $this->can_manage('delete_events', 'delete_others_events') ){
|
1287 |
if( !is_admin() ){
|
1288 |
include_once('em-event-post-admin.php');
|
@@ -1579,7 +1636,7 @@ class EM_Event extends EM_Object{
|
|
1579 |
}
|
1580 |
|
1581 |
/**
|
1582 |
-
* Returns the location object this event belongs to.
|
1583 |
* @return EM_Location
|
1584 |
*/
|
1585 |
function get_location() {
|
@@ -1594,6 +1651,40 @@ class EM_Event extends EM_Object{
|
|
1594 |
return $this->location;
|
1595 |
}
|
1596 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1597 |
/**
|
1598 |
* Returns the location object this event belongs to.
|
1599 |
* @return EM_Person
|
@@ -1841,10 +1932,28 @@ class EM_Event extends EM_Object{
|
|
1841 |
$show_condition = (!$this->event_rsvp && get_option('dbem_rsvp_enabled'));
|
1842 |
}elseif ($condition == 'no_location'){
|
1843 |
//does this event have a valid location?
|
1844 |
-
$show_condition =
|
1845 |
}elseif ($condition == 'has_location'){
|
1846 |
//does this event have a valid location?
|
1847 |
-
$show_condition = (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1848 |
}elseif ($condition == 'has_image'){
|
1849 |
//does this event have an image?
|
1850 |
$show_condition = ( $this->get_image_url() != '' );
|
@@ -1961,6 +2070,12 @@ class EM_Event extends EM_Object{
|
|
1961 |
}elseif ( preg_match('/^no_tag_([a-zA-Z0-9_\-,]+)$/', $condition, $tag_match)){
|
1962 |
//event doesn't have this tag
|
1963 |
$show_condition = !has_term(explode(',', $tag_match[1]), EM_TAXONOMY_TAG, $this->post_id);
|
|
|
|
|
|
|
|
|
|
|
|
|
1964 |
}
|
1965 |
//other potential ones - has_attribute_... no_attribute_... has_categories_...
|
1966 |
$show_condition = apply_filters('em_event_output_show_condition', $show_condition, $condition, $conditionals[0][$key], $this);
|
@@ -2380,6 +2495,14 @@ class EM_Event extends EM_Object{
|
|
2380 |
$replace = '<a href="'.esc_url($replace).'" target="_blank"><img src="'.esc_url($img_url).'" alt="0" border="0"></a>';
|
2381 |
}
|
2382 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2383 |
default:
|
2384 |
$replace = $full_result;
|
2385 |
break;
|
124 |
var $event_spaces;
|
125 |
var $event_private;
|
126 |
var $location_id;
|
127 |
+
/**
|
128 |
+
* Key name of event location type associated to this event.
|
129 |
+
*
|
130 |
+
* Events can have an event-specific location type, such as a url, webinar or another custom type instead of a regular geographical location. If this value is set, then a registered event location type is loaded and relevant saved event meta is used.
|
131 |
+
*
|
132 |
+
* @var string
|
133 |
+
*/
|
134 |
+
public $event_location_type;
|
135 |
var $recurrence_id;
|
136 |
var $event_status;
|
137 |
var $blog_id = 0;
|
181 |
'event_rsvp_spaces' => array( 'name'=>'rsvp_spaces', 'type'=>'%d', 'null'=>true ),
|
182 |
'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d', 'null'=>true),
|
183 |
'location_id' => array( 'name'=>'location_id', 'type'=>'%d', 'null'=>true ),
|
184 |
+
'event_location_type' => array( 'type'=>'%s', 'null'=>true ),
|
185 |
'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d', 'null'=>true ),
|
186 |
'event_status' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
|
187 |
'event_private' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
|
236 |
* @var EM_Location
|
237 |
*/
|
238 |
var $location;
|
239 |
+
/**
|
240 |
+
* @var array
|
241 |
+
*/
|
242 |
+
var $event_location_data = array();
|
243 |
/**
|
244 |
* @var EM_Bookings
|
245 |
*/
|
502 |
//load meta data and other related information
|
503 |
if( $event_post->post_status != 'auto-draft' ){
|
504 |
$event_meta = $this->get_event_meta($search_by);
|
505 |
+
if( !empty($even_meta['_event_location_type']) ) $this->event_location_type = $even_meta['_event_location_type']; //load this directly so we know further down whether this has an event location type to load
|
506 |
//Get custom fields and post meta
|
507 |
foreach($event_meta as $event_meta_key => $event_meta_val){
|
508 |
$field_name = substr($event_meta_key, 1);
|
509 |
if($event_meta_key[0] != '_'){
|
510 |
+
$this->event_attributes[$event_meta_key] = ( is_array($event_meta_val) ) ? $event_meta_val[0]:$event_meta_val;
|
511 |
}elseif( is_string($field_name) && !in_array($field_name, $this->post_fields) ){
|
512 |
if( array_key_exists($field_name, $this->fields) ){
|
513 |
$this->$field_name = $event_meta_val[0];
|
516 |
}
|
517 |
}
|
518 |
}
|
519 |
+
if( $this->has_event_location() ) $this->get_event_location()->load_postdata($event_meta);
|
520 |
//quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
|
521 |
if( empty($this->event_id) && !$this->is_recurring() ){
|
522 |
global $wpdb;
|
668 |
//reset start and end objects so they are recreated with the new dates/times if and when needed
|
669 |
$this->start = $this->end = null;
|
670 |
|
671 |
+
//Get Location Info
|
672 |
+
if( get_option('dbem_locations_enabled') ){
|
673 |
+
// determine location type, with backward compatibility considerations for those overriding the location forms
|
674 |
+
$location_type = isset($_POST['location_type']) ? sanitize_key($_POST['location_type']) : 'location';
|
675 |
+
if( !empty($_POST['no_location']) ) $location_type = 0; //backwards compat
|
676 |
+
if( $location_type == 'location' && empty($_POST['location_id']) && get_option('dbem_use_select_for_locations')) $location_type = 0; //backward compat
|
677 |
+
// assign location data
|
678 |
+
if( $location_type === 0 || $location_type === '0' ){
|
679 |
+
// no location
|
680 |
+
$this->location_id = 0;
|
681 |
+
$this->event_location_type = null;
|
682 |
+
}elseif( $location_type == 'location' && EM_Locations::is_enabled() ){
|
683 |
+
// a physical location, old school
|
684 |
+
$this->event_location_type = null; // if location resides in locations table, location type is null since we have a location_id table value
|
685 |
+
if( !empty($_POST['location_id']) && is_numeric($_POST['location_id']) ){
|
686 |
+
// we're using a previously created location
|
687 |
+
$this->location_id = absint($_POST['location_id']);
|
688 |
+
}else{
|
689 |
+
$this->location_id = null;
|
690 |
+
//we're adding a new location place, so create an empty location and populate
|
691 |
+
$this->get_location()->get_post(false);
|
692 |
+
$this->get_location()->post_content = ''; //reset post content, as it'll grab the event description otherwise
|
693 |
+
}
|
694 |
+
}else{
|
695 |
+
// we're dealing with an event location such as a url or webinar
|
696 |
+
$this->location_id = null; // no location ID
|
697 |
+
$this->event_location_type = $location_type;
|
698 |
+
if( EM_Event_Locations\Event_Locations::is_enabled($location_type) ){
|
699 |
+
$this->get_event_location()->get_post();
|
700 |
+
}
|
701 |
+
}
|
702 |
}else{
|
703 |
+
$this->location_id = 0;
|
704 |
+
$this->event_location_type = null;
|
|
|
|
|
705 |
}
|
706 |
|
707 |
//Bookings
|
748 |
if(get_option('dbem_attributes_enabled')){
|
749 |
global $allowedtags;
|
750 |
if( !is_array($this->event_attributes) ){ $this->event_attributes = array(); }
|
751 |
+
$event_available_attributes = !empty($event_available_attributes) ? $event_available_attributes : em_get_attributes(); //we use this in locations, no need to repeat if needed
|
752 |
if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
|
753 |
foreach($_POST['em_attributes'] as $att_key => $att_value ){
|
754 |
if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->event_attributes) ) ){
|
937 |
$this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','events-manager'));
|
938 |
}
|
939 |
}
|
940 |
+
if( get_option('dbem_locations_enabled') ){
|
941 |
+
if( $this->location_id === 0 && get_option('dbem_require_location',true) ){
|
942 |
+
// no location chosen, yet we require a location
|
943 |
+
$this->add_error(__('No location associated with this event.', 'events-manager'));
|
944 |
+
}elseif( $this->has_location() ){
|
945 |
+
// physical location
|
946 |
+
if( empty($this->location_id) && !$this->get_location()->validate() ){
|
947 |
+
// new location doesn't validate
|
948 |
$this->add_error($this->get_location()->get_errors());
|
949 |
+
}elseif( !empty($this->location_id) && !$this->get_location()->location_id ){
|
950 |
+
// non-existent location selected
|
951 |
+
$this->add_error( __('Please select a valid location.', 'events-manager') );
|
952 |
}
|
953 |
+
}elseif( $this->has_event_location() ){
|
954 |
+
// event location, validation applies errors directly to $this
|
955 |
+
$this->get_event_location()->validate();
|
956 |
}
|
957 |
}
|
958 |
if ( count($missing_fields) > 0){
|
1136 |
}
|
1137 |
}
|
1138 |
}
|
1139 |
+
//update event location via post meta
|
1140 |
+
if( $this->has_event_location() ){
|
1141 |
+
$this->get_event_location()->save();
|
1142 |
+
}else{
|
1143 |
+
$this->get_event_location()->reset_data();
|
1144 |
+
}
|
1145 |
//update timestamps, dates and times
|
1146 |
update_post_meta($this->post_id, '_event_start_local', $this->start()->getDateTime());
|
1147 |
update_post_meta($this->post_id, '_event_end_local', $this->end()->getDateTime());
|
1336 |
|
1337 |
/**
|
1338 |
* Delete whole event, including bookings, tickets, etc.
|
1339 |
+
* @param boolean $force_delete
|
1340 |
* @return boolean
|
1341 |
*/
|
1342 |
+
function delete( $force_delete = false ){
|
1343 |
if( $this->can_manage('delete_events', 'delete_others_events') ){
|
1344 |
if( !is_admin() ){
|
1345 |
include_once('em-event-post-admin.php');
|
1636 |
}
|
1637 |
|
1638 |
/**
|
1639 |
+
* Returns the physical location object this event belongs to.
|
1640 |
* @return EM_Location
|
1641 |
*/
|
1642 |
function get_location() {
|
1651 |
return $this->location;
|
1652 |
}
|
1653 |
|
1654 |
+
/**
|
1655 |
+
* Returns whether this event has a phyisical location assigned to it.
|
1656 |
+
* @return bool
|
1657 |
+
*/
|
1658 |
+
public function has_location(){
|
1659 |
+
return !empty($this->location_id) || (!empty($this->location) && !empty($this->location->location_name));
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
/**
|
1663 |
+
* Gets the event's event location (note, different from a regular event location, which uses get_location())
|
1664 |
+
* Returns implementation of Event_Location or false if no event location assigned.
|
1665 |
+
* @return EM_Event_Locations\URL|EM_Event_Locations\Event_Location|false
|
1666 |
+
*/
|
1667 |
+
public function get_event_location(){
|
1668 |
+
if( $this->has_event_location() ){
|
1669 |
+
$EM_Location_Type = EM_Event_Locations\Event_Locations::get( $this->event_location_type, $this );
|
1670 |
+
}else{
|
1671 |
+
$EM_Location_Type = new EM_Event_Locations\Event_Location( $this );
|
1672 |
+
}
|
1673 |
+
return apply_filters('em_event_get_event_location', $EM_Location_Type, $this);
|
1674 |
+
}
|
1675 |
+
|
1676 |
+
/**
|
1677 |
+
* Returns whether the event has an event location associated with it (different from a physical location). If supplied, can check against a specific type.
|
1678 |
+
* @param string $event_location_type
|
1679 |
+
* @return bool
|
1680 |
+
*/
|
1681 |
+
public function has_event_location( $event_location_type = null ){
|
1682 |
+
if( !empty($event_location_type) ){
|
1683 |
+
return !empty($this->event_location_type) && $this->event_location_type === $event_location_type;
|
1684 |
+
}
|
1685 |
+
return !empty($this->event_location_type);
|
1686 |
+
}
|
1687 |
+
|
1688 |
/**
|
1689 |
* Returns the location object this event belongs to.
|
1690 |
* @return EM_Person
|
1932 |
$show_condition = (!$this->event_rsvp && get_option('dbem_rsvp_enabled'));
|
1933 |
}elseif ($condition == 'no_location'){
|
1934 |
//does this event have a valid location?
|
1935 |
+
$show_condition = !$this->has_event_location() && !$this->has_location();
|
1936 |
}elseif ($condition == 'has_location'){
|
1937 |
//does this event have a valid location?
|
1938 |
+
$show_condition = ( $this->has_location() && $this->get_location()->location_status ) || $this->has_event_location();
|
1939 |
+
}elseif ($condition == 'has_location_venue'){
|
1940 |
+
//does this event have a valid physical location?
|
1941 |
+
$show_condition = ( $this->has_location() && $this->get_location()->location_status ) || $this->has_event_location();
|
1942 |
+
}elseif ($condition == 'no_location_venue'){
|
1943 |
+
//does this event NOT have a valid physical location?
|
1944 |
+
$show_condition = !$this->has_location();
|
1945 |
+
}elseif ($condition == 'has_event_location'){
|
1946 |
+
//does this event have a valid event location?
|
1947 |
+
$show_condition = $this->has_event_location();
|
1948 |
+
}elseif ( preg_match('/^has_event_location_([a-zA-Z0-9_\-]+)$/', $condition, $type_match)){
|
1949 |
+
//event has a specific category
|
1950 |
+
$show_condition = $this->has_event_location($type_match[1]);
|
1951 |
+
}elseif ($condition == 'no_event_location'){
|
1952 |
+
//does this event not have a valid event location?
|
1953 |
+
$show_condition = !$this->has_event_location();
|
1954 |
+
}elseif ( preg_match('/^no_event_location_([a-zA-Z0-9_\-]+)$/', $condition, $type_match)){
|
1955 |
+
//does this event NOT have a specific event location?
|
1956 |
+
$show_condition = !$this->has_event_location($type_match[1]);
|
1957 |
}elseif ($condition == 'has_image'){
|
1958 |
//does this event have an image?
|
1959 |
$show_condition = ( $this->get_image_url() != '' );
|
2070 |
}elseif ( preg_match('/^no_tag_([a-zA-Z0-9_\-,]+)$/', $condition, $tag_match)){
|
2071 |
//event doesn't have this tag
|
2072 |
$show_condition = !has_term(explode(',', $tag_match[1]), EM_TAXONOMY_TAG, $this->post_id);
|
2073 |
+
}elseif ( preg_match('/^has_att_([a-zA-Z0-9_\-,]+)$/', $condition, $att_match)){
|
2074 |
+
//event has a specific custom field
|
2075 |
+
$show_condition = !empty($this->event_attributes[$att_match[1]]) || !empty($this->event_attributes[str_replace('_', ' ', $att_match[1])]);
|
2076 |
+
}elseif ( preg_match('/^no_att_([a-zA-Z0-9_\-,]+)$/', $condition, $att_match)){
|
2077 |
+
//event has a specific custom field
|
2078 |
+
$show_condition = empty($this->event_attributes[$att_match[1]]) && empty($this->event_attributes[str_replace('_', ' ', $att_match[1])]);
|
2079 |
}
|
2080 |
//other potential ones - has_attribute_... no_attribute_... has_categories_...
|
2081 |
$show_condition = apply_filters('em_event_output_show_condition', $show_condition, $condition, $conditionals[0][$key], $this);
|
2495 |
$replace = '<a href="'.esc_url($replace).'" target="_blank"><img src="'.esc_url($img_url).'" alt="0" border="0"></a>';
|
2496 |
}
|
2497 |
break;
|
2498 |
+
//Event location (not physical location)
|
2499 |
+
case '#_EVENTLOCATION':
|
2500 |
+
if( !empty($placeholders[3][$key]) ){
|
2501 |
+
$replace = $this->get_event_location()->output($placeholders[3][$key]);
|
2502 |
+
}else{
|
2503 |
+
$replace = $this->get_event_location()->output();
|
2504 |
+
}
|
2505 |
+
break;
|
2506 |
default:
|
2507 |
$replace = $full_result;
|
2508 |
break;
|
classes/em-events.php
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<?php
|
|
|
2 |
//TODO EM_Events is currently static, better we make this non-static so we can loop sets of events, and standardize with other objects.
|
3 |
/**
|
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.
|
@@ -579,6 +580,34 @@ $limit $offset";
|
|
579 |
$conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id={$args['post_id']})";
|
580 |
}
|
581 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
|
583 |
}
|
584 |
|
@@ -661,7 +690,9 @@ $limit $offset";
|
|
661 |
//event-specific search attributes
|
662 |
'has_location' => false, //search events with a location
|
663 |
'no_location' => false, //search events without a location
|
664 |
-
'location_status' => false //search events with locations of a specific publish status
|
|
|
|
|
665 |
);
|
666 |
//sort out whether defaults were supplied or just the array of search values
|
667 |
if( empty($array) ){
|
1 |
<?php
|
2 |
+
use EM_Event_Locations\Event_Locations;
|
3 |
//TODO EM_Events is currently static, better we make this non-static so we can loop sets of events, and standardize with other objects.
|
4 |
/**
|
5 |
* 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.
|
580 |
$conditions['post_id'] = "(".EM_EVENTS_TABLE.".post_id={$args['post_id']})";
|
581 |
}
|
582 |
}
|
583 |
+
// event locations
|
584 |
+
if( !empty($args['event_location_type']) ){
|
585 |
+
$event_location_types = explode(',', $args['event_location_type']);
|
586 |
+
$event_locations_search = array();
|
587 |
+
// generate array of clean and enabled event location types
|
588 |
+
foreach( $event_location_types as $event_location_type ){
|
589 |
+
$event_location_type = trim($event_location_type);
|
590 |
+
if( Event_Locations::is_enabled($event_location_type) ){
|
591 |
+
$event_locations_search[] = $event_location_type;
|
592 |
+
}
|
593 |
+
}
|
594 |
+
// add condition if at least one valid/clean type supplied
|
595 |
+
if( !empty($event_locations_search) ){
|
596 |
+
if( count($event_locations_search) === 1 ){
|
597 |
+
$event_location = current($event_locations_search);
|
598 |
+
$conditions['event_location'] = "event_location_type='$event_location'";
|
599 |
+
}else{
|
600 |
+
$conditions['event_location'] = "event_location_type IN ('". implode("','", $event_locations_search) ."')";
|
601 |
+
}
|
602 |
+
}
|
603 |
+
}
|
604 |
+
if( isset($args['has_event_location']) && $args['has_event_location'] !== false ){
|
605 |
+
if( $args['has_event_location'] ){
|
606 |
+
$conditions['has_event_location'] = "event_location_type IS NOT NULL";
|
607 |
+
}else{
|
608 |
+
$conditions['has_event_location'] = "event_location_type IS NULL";
|
609 |
+
}
|
610 |
+
}
|
611 |
return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
|
612 |
}
|
613 |
|
690 |
//event-specific search attributes
|
691 |
'has_location' => false, //search events with a location
|
692 |
'no_location' => false, //search events without a location
|
693 |
+
'location_status' => false, //search events with locations of a specific publish status
|
694 |
+
'event_location_type' => false,
|
695 |
+
'has_event_location' => false,
|
696 |
);
|
697 |
//sort out whether defaults were supplied or just the array of search values
|
698 |
if( empty($array) ){
|
classes/em-exception.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
//in case we include it in EM core code
|
3 |
+
if( !class_exists('EM_Exception') ){
|
4 |
+
/**
|
5 |
+
* Extended Exception class that allows for creating multiple error messages in an exception as an array and outputting them together at once.
|
6 |
+
* Class Exception
|
7 |
+
*/
|
8 |
+
class EM_Exception extends Exception {
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var WP_Error
|
12 |
+
*/
|
13 |
+
public $wp_error;
|
14 |
+
/**
|
15 |
+
* @var array
|
16 |
+
*/
|
17 |
+
public $error_messages = array();
|
18 |
+
/**
|
19 |
+
* @var int|string Allows for a custom code to be used rather than an integer.
|
20 |
+
*/
|
21 |
+
public $error_code;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Exception constructor.
|
25 |
+
* @param string $error
|
26 |
+
* @param int $code
|
27 |
+
* @param null $previous
|
28 |
+
*/
|
29 |
+
public function __construct($error = '', $code = 0, $previous = null ){
|
30 |
+
if( is_array($error) ) {
|
31 |
+
$this->error_messages = $error;
|
32 |
+
$message = $this->get_message();
|
33 |
+
}elseif( is_wp_error($error) ){ /* @var WP_Error $error */
|
34 |
+
$this->wp_error = $error;
|
35 |
+
$code = $error->get_error_code();
|
36 |
+
$message = $error->get_error_message();
|
37 |
+
}else{
|
38 |
+
$message = $error;
|
39 |
+
}
|
40 |
+
if( !is_numeric($code) ){
|
41 |
+
$this->error_code = $code;
|
42 |
+
$code = 0;
|
43 |
+
}
|
44 |
+
parent::__construct($message, $code, $previous);
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Returns either a string code reference, or a regular Exception code number.
|
49 |
+
* @return int|string
|
50 |
+
*/
|
51 |
+
public function get_error_code(){
|
52 |
+
if( $this->error_code ){
|
53 |
+
return $this->error_code;
|
54 |
+
}
|
55 |
+
return $this->getCode();
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Provides a paragraph-formatted message which may contain multiple paragraphs for multiple errors.
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
public function get_message(){
|
63 |
+
if( $this->is_wp_error() ){
|
64 |
+
$message = '<p>' . implode('</p><p>', $this->wp_error->get_error_messages()) . '</p>';
|
65 |
+
}elseif( !empty($this->error_messages) ){
|
66 |
+
$message = '<p>' . implode('</p><p>', $this->error_messages) . '</p>';
|
67 |
+
}else{
|
68 |
+
$message = '<p>' . $this->getMessage() . '</p>';
|
69 |
+
}
|
70 |
+
return $message;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @return array|string
|
75 |
+
*/
|
76 |
+
public function get_messages(){
|
77 |
+
if( $this->is_wp_error() ){
|
78 |
+
return $this->wp_error->get_error_messages();
|
79 |
+
}elseif( !empty($this->error_messages) ){
|
80 |
+
return $this->error_messages;
|
81 |
+
}else{
|
82 |
+
return array($this->getMessage());
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Whether or not this exception was triggered by a WP_Error
|
88 |
+
* @return bool
|
89 |
+
*/
|
90 |
+
public function is_wp_error(){
|
91 |
+
return is_wp_error( $this->wp_error );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Returns exception in WP_Error format, whether or not it was originally a WP_Error in the first place.
|
96 |
+
* @return WP_Error
|
97 |
+
*/
|
98 |
+
public function get_wp_error(){
|
99 |
+
if( $this->is_wp_error() ){
|
100 |
+
return $this->wp_error;
|
101 |
+
}
|
102 |
+
$WP_Error = new WP_Error();
|
103 |
+
$WP_Error->add_data( $this->get_messages(), $this->getCode() );
|
104 |
+
return $WP_Error;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
}
|
classes/em-locations.php
CHANGED
@@ -22,6 +22,16 @@ class EM_Locations extends EM_Object {
|
|
22 |
|
23 |
protected static $context = 'location';
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* Returns an array of EM_Location objects
|
27 |
* @param array $args
|
22 |
|
23 |
protected static $context = 'location';
|
24 |
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Returns whether or not locations are enabled for use with events.
|
28 |
+
* @return bool
|
29 |
+
*/
|
30 |
+
public static function is_enabled(){
|
31 |
+
$location_types = get_option('dbem_location_types', array());
|
32 |
+
return !empty($location_types['location']);
|
33 |
+
}
|
34 |
+
|
35 |
/**
|
36 |
* Returns an array of EM_Location objects
|
37 |
* @param array $args
|
classes/em-oauth/oauth-admin-settings.php
ADDED
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_OAuth;
|
3 |
+
use EM_Options, EM_Exception;
|
4 |
+
use Matrix\Exception;
|
5 |
+
|
6 |
+
class OAuth_API_Admin_Settings {
|
7 |
+
|
8 |
+
public static $option_name = 'em_oauth';
|
9 |
+
public static $service_name = 'EM OAuth 2.0';
|
10 |
+
/**
|
11 |
+
* @var OAuth_API Class name of base API class for this service type, used for static variable referencing
|
12 |
+
*/
|
13 |
+
public static $api_class = 'EM_OAuth\OAuth_API';
|
14 |
+
public static $service_url = 'http://example.com';
|
15 |
+
public static $icon_url = '';
|
16 |
+
|
17 |
+
|
18 |
+
public static function init(){
|
19 |
+
$class = get_called_class(); //get child class name to call
|
20 |
+
self::$icon_url = plugin_dir_url(__FILE__). 'icon.png';
|
21 |
+
//handle service app creds
|
22 |
+
add_action('em_options_page_footer', "$class::em_settings_apps");
|
23 |
+
add_action('em_options_save', "$class::em_settings_save_apps");
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @return OAuth_API
|
28 |
+
*/
|
29 |
+
public static function get_api_class(){
|
30 |
+
//set default API class name if not defined by parent
|
31 |
+
if( self::$api_class === static::$api_class && class_exists(str_replace('_Admin_Settings', '', get_called_class())) ){
|
32 |
+
static::$api_class = str_replace('_Admin_Settings', '', get_called_class());
|
33 |
+
}
|
34 |
+
return static::$api_class;
|
35 |
+
}
|
36 |
+
|
37 |
+
public static function em_settings_save_apps(){
|
38 |
+
$api = static::get_api_class();
|
39 |
+
if( $api::get_option_dataset() == 'dbem_oauth' ) return;
|
40 |
+
$option_names = array($api::get_option_name().'_app_id', $api::get_option_name().'_app_secret');
|
41 |
+
foreach( $option_names as $option_name ){
|
42 |
+
$value = !empty($_REQUEST[$api::get_option_dataset()][$option_name]) ? $_REQUEST[$api::get_option_dataset()][$option_name] : '';
|
43 |
+
EM_Options::set($option_name, $value, $api::get_option_dataset());
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
public static function em_settings_apps_header(){
|
48 |
+
// override this for extra content above settings meta box
|
49 |
+
}
|
50 |
+
|
51 |
+
public static function em_settings_apps(){
|
52 |
+
$desc = esc_html__("You'll need to create an App with %s and obtain the App credentials by going to %s.", 'events-manager');
|
53 |
+
$desc_url = esc_html__('You will also need supply an OAuth redirect url to %s. Your url for this site is : %s', 'events-manager');
|
54 |
+
$api = static::get_api_class(); /* @var OAuth_API $api */
|
55 |
+
$api_client_class = $api::get_client_class();
|
56 |
+
$callback_url = $api_client_class::get_oauth_callback_url();
|
57 |
+
$service_name = $api::get_service_name();
|
58 |
+
?>
|
59 |
+
<div class="postbox em-oaut-connect em-oauth-connect-<?php echo esc_attr($api::get_authorization_scope()); ?>" id="em-opt-<?php echo esc_attr($api::get_option_name()); ?>-app" >
|
60 |
+
<div class="handlediv" title="<?php __('Click to toggle', 'events-manager'); ?>"><br /></div><h3><span><?php echo esc_html($api::get_service_name()) ?></span></h3>
|
61 |
+
<div class="inside">
|
62 |
+
<?php static::em_settings_apps_header(); ?>
|
63 |
+
<h4><?php esc_html_e('Server API Credentials', 'events-manager-zoom'); ?></h4>
|
64 |
+
<p><?php printf( $desc, $service_name, '<a href="'. $api::get_service_url() .'">'. $api::get_service_url() .'</a>'); ?></p>
|
65 |
+
<p><?php printf( $desc_url, $service_name, "<code>$callback_url</code>") ?></p>
|
66 |
+
<p><?php printf( esc_html__('Once you have entered valid API information, you will see a button below to connect your site to %s.', 'events-manager-zoom'), $service_name); ?></p>
|
67 |
+
<table class='form-table'>
|
68 |
+
<?php
|
69 |
+
em_options_input_text(sprintf(__('%s App ID', 'events-manager'), $service_name), $api::get_option_dataset().'['.$api::get_option_name().'_app_id]', '');
|
70 |
+
em_options_input_text(sprintf(__('%s App Secret', 'events-manager'), $service_name), $api::get_option_dataset().'['.$api::get_option_name().'_app_secret]', '');
|
71 |
+
?>
|
72 |
+
</table>
|
73 |
+
<?php
|
74 |
+
static::em_settings_user_auth();
|
75 |
+
static::em_settings_apps_footer();
|
76 |
+
?>
|
77 |
+
</div> <!-- . inside -->
|
78 |
+
</div> <!-- .postbox -->
|
79 |
+
<?php
|
80 |
+
}
|
81 |
+
|
82 |
+
public static function em_settings_apps_footer(){
|
83 |
+
// override this for extra content above settings meta box
|
84 |
+
}
|
85 |
+
|
86 |
+
public static function em_settings_user_auth(){
|
87 |
+
//a fresh client with no token for generating oauth links
|
88 |
+
$api = static::get_api_class(); /* @var OAuth_API $api */
|
89 |
+
try{
|
90 |
+
$api_client = $api::get_client(false); /* @var OAuth_API_Client $api_client */
|
91 |
+
$service_name = $api::get_service_name();
|
92 |
+
$option_name = $api::get_option_name();
|
93 |
+
//get tokens if client is configured
|
94 |
+
if( !is_wp_error($api_client) ){ //oauth is not configured correctly...
|
95 |
+
$oauth_url = $api_client->get_oauth_url();
|
96 |
+
//we don't need to verify connections at this point, we just need to know if there are any
|
97 |
+
if( $api_client->authorization_scope == 'user' ){
|
98 |
+
$user_id = get_current_user_id();
|
99 |
+
$access_tokens = $api::get_user_tokens();
|
100 |
+
}else{
|
101 |
+
$user_id = null;
|
102 |
+
$access_tokens = $api::get_site_tokens();
|
103 |
+
}
|
104 |
+
$oauth_accounts = array();
|
105 |
+
$connected = $reconnect_required = false;
|
106 |
+
foreach( $access_tokens as $account_id => $oauth_account ){
|
107 |
+
try {
|
108 |
+
$api_client->load_token( $account_id, $user_id );
|
109 |
+
$verification = true;
|
110 |
+
} catch ( EM_Exception $e ) {
|
111 |
+
$verification = false;
|
112 |
+
}
|
113 |
+
$oauth_account['id'] = !empty($oauth_account['email']) ? $oauth_account['email'] : $account_id;
|
114 |
+
$disconnect_url_args = array( 'action' => 'em_oauth_'. $api::get_option_name(), 'callback' => 'disconnect', 'account' => $account_id, 'nonce' => wp_create_nonce('em-oauth-'. $option_name .'-disconnect-'.$account_id) );
|
115 |
+
$oauth_account['disconnect'] = add_query_arg( $disconnect_url_args, admin_url( 'admin-ajax.php' ) );
|
116 |
+
if( !$verification ){
|
117 |
+
$oauth_account['reconnect'] = true;
|
118 |
+
$reconnect_required = true;
|
119 |
+
}else{
|
120 |
+
$connected = true;
|
121 |
+
}
|
122 |
+
$oauth_accounts[] = $oauth_account;
|
123 |
+
}
|
124 |
+
if( $connected ){
|
125 |
+
$button_url = add_query_arg( array( 'action' => 'em_oauth_'. $option_name, 'callback' => 'disconnect', 'nonce' => wp_create_nonce('em-oauth-'. $option_name .'-disconnect') ), admin_url( 'admin-ajax.php' ) );
|
126 |
+
$button_text = count($oauth_accounts) > 1 ? __('Disconnect All', 'events-manager') : __('Disonnect', 'events-manager');
|
127 |
+
$button_class = 'button-secondary';
|
128 |
+
}else{
|
129 |
+
$button_url = $oauth_url;
|
130 |
+
$button_text = __('Connect', 'events-manager');
|
131 |
+
$button_class = 'button-primary';
|
132 |
+
}
|
133 |
+
}
|
134 |
+
?>
|
135 |
+
<div class="em-oauth-service-info">
|
136 |
+
<?php if( $api::get_authorization_scope() == 'user'): ?>
|
137 |
+
<h4><?php echo $service_name; ?></h4>
|
138 |
+
<?php else: ?>
|
139 |
+
<h4><?php esc_html_e('Account Connection', 'events-manager-zoom'); ?></h4>
|
140 |
+
<?php endif; ?>
|
141 |
+
<?php if( $connected || $reconnect_required ): ?>
|
142 |
+
<p><?php echo esc_html(sprintf(_n('You are successfully connected to the following %s account:', 'You are successfully connected to the following %s accounts:', count($oauth_accounts), 'events-manager-zoom'), $service_name)); ?></p>
|
143 |
+
<ul clss="em-oauth-service-accounts">
|
144 |
+
<?php foreach ( $oauth_accounts as $oauth_account ): ?>
|
145 |
+
<li class="em-oauth-service-account em-oauth-account-<?php echo empty($oauth_account['reconnect']) ? 'connected':'disconnected'; ?>">
|
146 |
+
<img src="<?php echo esc_url($oauth_account['photo']); ?>" width="25" height="25">
|
147 |
+
<div class="em-oauth-account-description">
|
148 |
+
<span class="em-oauth-account-label">
|
149 |
+
<?php if( !empty($oauth_account['reconnect']) ): ?><span class="dashicons dashicons-warning"></span><?php endif; ?>
|
150 |
+
<?php echo esc_html($oauth_account['name']) .' <em>('. esc_html($oauth_account['id']) .')</em>'; ?>
|
151 |
+
</span>
|
152 |
+
<span class="em-oauth-account-actions">
|
153 |
+
<?php if( count($oauth_accounts) > 1 ): ?>
|
154 |
+
<a href="<?php echo esc_url($oauth_account['disconnect']); ?>"><?php esc_html_e('Disconnect', 'events-manager'); ?></a>
|
155 |
+
<?php elseif( !empty($oauth_account['reconnect']) ): ?>
|
156 |
+
<a href="<?php echo esc_url($oauth_url); ?>"><?php esc_html_e('Reconnect', 'events-manager'); ?></a> |
|
157 |
+
<a href="<?php echo esc_url($oauth_account['disconnect']); ?>"><?php esc_html_e('Remove', 'events-manager'); ?></a>
|
158 |
+
<?php endif; ?>
|
159 |
+
</span>
|
160 |
+
</div>
|
161 |
+
</li>
|
162 |
+
<?php endforeach; ?>
|
163 |
+
</ul>
|
164 |
+
<p>
|
165 |
+
<a class="<?php echo $button_class; ?> em-oauth-connect-button" href="<?php echo esc_url($button_url); ?>"><?php echo esc_html($button_text); ?></a>
|
166 |
+
<?php if( $api::supports_multiple_tokens() ): ?>
|
167 |
+
<a class="button-secondary" href="<?php echo esc_url($oauth_url); ?>"><?php esc_html_e('Connect additional account') ?></a>
|
168 |
+
<?php endif; ?>
|
169 |
+
</p>
|
170 |
+
<?php do_action('em_settings_user_auth_after_connect_additional_'.$option_name); ?>
|
171 |
+
<p><em><?php esc_html_e('If you are experiencing errors when trying to use any of these accounts, try disconnecting and connecting again.', 'events-manager'); ?></em></p>
|
172 |
+
<?php else: ?>
|
173 |
+
<p><em><?php echo sprintf(esc_html__('Connect to import events and locations from %s.','events-manager'), $service_name); ?></em></p>
|
174 |
+
<a class="<?php echo $button_class; ?> em-oauth-connect-button" href="<?php echo esc_url($button_url); ?>"><?php echo esc_html($button_text); ?></a>
|
175 |
+
<?php endif; ?>
|
176 |
+
</div>
|
177 |
+
<?php
|
178 |
+
}catch( EM_Exception $ex ){
|
179 |
+
?>
|
180 |
+
<div class="em-oauth-service-info">
|
181 |
+
<p><em><?php echo $ex->get_message(); ?></em></p>
|
182 |
+
</div>
|
183 |
+
<?php
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
classes/em-oauth/oauth-api-client.php
ADDED
@@ -0,0 +1,594 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_OAuth;
|
3 |
+
use EM_Options, EM_Exception, stdClass;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class OAuth_API_Client
|
7 |
+
* @package EM_OAuth
|
8 |
+
* @property-read $service_name
|
9 |
+
* @property-read $option_name
|
10 |
+
* @property-read $option_dataset
|
11 |
+
* @property-read $authorization_scope
|
12 |
+
* @property-read $multiple_tokens
|
13 |
+
* @property-read $token_class
|
14 |
+
*/
|
15 |
+
class OAuth_API_Client {
|
16 |
+
/**
|
17 |
+
* The base class for this package of classes, used for accessing infromation such as $option_name, etc.
|
18 |
+
* If naming conventions are followed, for example SomeService_API > SomeService_API_Client, this will be automatically deduced.
|
19 |
+
* @var OAuth_API
|
20 |
+
*/
|
21 |
+
protected static $api_class;
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
public $id;
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
public $secret;
|
30 |
+
/**
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $scope;
|
34 |
+
/**
|
35 |
+
* @var
|
36 |
+
*/
|
37 |
+
public $client;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var OAuth_API_Token
|
41 |
+
*/
|
42 |
+
public $token;
|
43 |
+
/**
|
44 |
+
* @var string
|
45 |
+
*/
|
46 |
+
public $user_id;
|
47 |
+
/**
|
48 |
+
* @var bool
|
49 |
+
*/
|
50 |
+
public $authorized = false;
|
51 |
+
|
52 |
+
/**
|
53 |
+
* The URL without trailing slash for the API base URL, to which endpoints can be appended to.
|
54 |
+
* @var string
|
55 |
+
*/
|
56 |
+
public $api_base = 'https://api.oauth.com';
|
57 |
+
/**
|
58 |
+
* The URL that'll be used to request an authorization code from the user. Can include strings CLIENT_ID, ACCESS_SCOPE, REDIRECT_URI, and STATE which will be replaced dynamically.
|
59 |
+
* @var string
|
60 |
+
*/
|
61 |
+
public $oauth_authorize_url = 'https://api.oauth.com/authorize';
|
62 |
+
/**
|
63 |
+
* Required by child class unless it overrides the request_access_token() method.
|
64 |
+
* @var string
|
65 |
+
*/
|
66 |
+
public $oauth_request_token_url = 'https://api.oauth.com/token';
|
67 |
+
/**
|
68 |
+
* Defaults to $oauuth_request_token_url if not set.
|
69 |
+
* @var string
|
70 |
+
*/
|
71 |
+
public $oauth_refresh_token_url = null;
|
72 |
+
/**
|
73 |
+
* Required by child class unless it overrides the verify_access_token() method.
|
74 |
+
* @var string
|
75 |
+
*/
|
76 |
+
public $oauth_verification_url = 'https://api.oauth.com/verify_token';
|
77 |
+
/**
|
78 |
+
* Required by child class unless it overrides the revoke_access_token() method.
|
79 |
+
* @var string
|
80 |
+
*/
|
81 |
+
public $oauth_revoke_url = 'https://api.oauth.com/revoke';
|
82 |
+
public $oauth_authentication = 'parameters';
|
83 |
+
/**
|
84 |
+
* Whether or not an OAuth Service should pass on the state param for security check
|
85 |
+
* @var bool
|
86 |
+
*/
|
87 |
+
public $oauth_state = true;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* OAuth_API_Client constructor.
|
91 |
+
*
|
92 |
+
* @throws EM_Exception
|
93 |
+
*/
|
94 |
+
public function __construct(){
|
95 |
+
// check credentials
|
96 |
+
$creds = array(
|
97 |
+
'id' => EM_Options::get( $this->option_name. '_app_id', '', $this->option_dataset),
|
98 |
+
'secret' => EM_Options::get( $this->option_name. '_app_secret', '', $this->option_dataset)
|
99 |
+
);
|
100 |
+
foreach( array('id', 'secret', 'scope') as $k ){
|
101 |
+
if( !empty($creds[$k]) ){
|
102 |
+
$this->$k = $creds[$k];
|
103 |
+
}elseif( empty($this->$k) ) { // constructors can be overriden to add any of the above
|
104 |
+
throw new EM_Exception( __('OAuth application information incomplete.', 'events-manager') );
|
105 |
+
}
|
106 |
+
}
|
107 |
+
if( !$this->oauth_refresh_token_url ){
|
108 |
+
$this->oauth_refresh_token_url = $this->oauth_request_token_url;
|
109 |
+
}
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Shortcut for base class properties.
|
114 |
+
* @param $name
|
115 |
+
* @return mixed
|
116 |
+
*/
|
117 |
+
public function __get( $name ){
|
118 |
+
$api = static::get_api_class();
|
119 |
+
if( $name == 'option_name' ){
|
120 |
+
return $api::get_option_name();
|
121 |
+
}elseif( $name == 'option_dataset' ){
|
122 |
+
return $api::get_option_dataset();
|
123 |
+
}elseif( $name == 'authorization_scope' ){
|
124 |
+
return $api::get_authorization_scope();
|
125 |
+
}elseif( $name == 'multiple_tokens' ){
|
126 |
+
return $api::supports_multiple_tokens();
|
127 |
+
}elseif( $name == 'token_class' ){
|
128 |
+
return $api::get_token_class();
|
129 |
+
}
|
130 |
+
return null;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* @return OAuth_API
|
135 |
+
*/
|
136 |
+
public static function get_api_class(){
|
137 |
+
// set default API class name if not defined by parent
|
138 |
+
if( self::$api_class === static::$api_class && class_exists(str_replace('_Client', '', get_called_class())) ){
|
139 |
+
static::$api_class = str_replace('_Client', '', get_called_class());
|
140 |
+
}
|
141 |
+
return static::$api_class;
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* @return mixed
|
146 |
+
*/
|
147 |
+
public function get_oauth_url(){
|
148 |
+
$scope = is_array($this->scope) ? urlencode(implode('+', $this->scope)) : $this->scope;
|
149 |
+
$state_nonce = wp_create_nonce($this->option_name.'_authorize');
|
150 |
+
$replacements = array( urlencode($this->id), $scope, urlencode(static::get_oauth_callback_url()), $state_nonce );
|
151 |
+
$return = str_replace( array('CLIENT_ID','ACCESS_SCOPE','REDIRECT_URI', 'STATE'), $replacements, $this->oauth_authorize_url );
|
152 |
+
if( $this->oauth_state ){
|
153 |
+
// check there's a STATE value in the authorize url, otherwise add it proactively
|
154 |
+
if( !preg_match('/STATE/', $this->oauth_authorize_url) ){
|
155 |
+
$return = add_query_arg('state', $state_nonce, $return);
|
156 |
+
}
|
157 |
+
}
|
158 |
+
return $return;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* @return string
|
163 |
+
*/
|
164 |
+
public static function get_oauth_callback_url(){
|
165 |
+
$redirect_base_uri = defined('OAUTH_REDIRECT') ? OAUTH_REDIRECT : admin_url('admin-ajax.php'); // you can completely replace the oauth redirect link for testing locally via a proxy for example
|
166 |
+
if( defined('EM_OAUTH_TUNNEL') ){ // for local development or other reasons, you can replace the domain with a tunnel domain, which should be with http(s):// included
|
167 |
+
$redirect_base_uri = str_replace(get_home_url(), EM_OAUTH_TUNNEL, $redirect_base_uri);
|
168 |
+
}
|
169 |
+
$api = static::get_api_class();
|
170 |
+
$callback_action = 'em_oauth_'. $api::get_option_name();
|
171 |
+
return add_query_arg(array('action'=>strtolower($callback_action), 'callback'=>'authorize'), $redirect_base_uri);
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Returns a native client for this service, in the event we want to load an SDK provided by the service.
|
176 |
+
* @return stdClass
|
177 |
+
*/
|
178 |
+
public function client(){
|
179 |
+
return new stdClass();
|
180 |
+
}
|
181 |
+
|
182 |
+
// GET, POST, PUT, PATCH, DELETE functions
|
183 |
+
|
184 |
+
/**
|
185 |
+
* @param $endpoint
|
186 |
+
* @param array $request_args
|
187 |
+
* @param bool $json_decode
|
188 |
+
* @return array
|
189 |
+
* @throws EM_Exception
|
190 |
+
*/
|
191 |
+
public function http_request( $endpoint, array $request_args = array(), $json_decode = true ){
|
192 |
+
// clean up whether endpoint or full URL is provided
|
193 |
+
$endpoint = str_replace($this->api_base, '', $endpoint);
|
194 |
+
$request_url = $this->api_base. $endpoint;
|
195 |
+
//$request_url = add_query_arg('access_token', $this->token->access_token, $request_url);
|
196 |
+
// add oauth and method heaeders
|
197 |
+
if( empty($request_args['headers']) ) $request_args['headers'] = array();
|
198 |
+
$request_args['headers']['authorization'] = 'Bearer '.$this->token->access_token;
|
199 |
+
$request_args['method'] = in_array($request_args['method'], array('GET','POST','PUT','PATCH','DELETE')) ? $request_args['method'] : 'GET';
|
200 |
+
// prepare JSON format if sending via that content type
|
201 |
+
if( !empty($request_args['headers']['Content-Type']) && $request_args['headers']['Content-Type'] == 'application/json' ){
|
202 |
+
if( !empty($request_args['body']) && (is_array($request_args['body']) || is_object($request_args['body'])) ){
|
203 |
+
$request_args['body'] = json_encode($request_args['body']);
|
204 |
+
}
|
205 |
+
}
|
206 |
+
// request and parse
|
207 |
+
$response = wp_remote_request($request_url, $request_args); /* @var \Requests_Response_Headers $response['headers'] */
|
208 |
+
if( is_wp_error($response) ){
|
209 |
+
throw new EM_Exception($response);
|
210 |
+
}elseif( $response['response']['code'] >= 300 ){ //anything not 20x will indicate an issue
|
211 |
+
$errors = json_decode($response['body']);
|
212 |
+
if( is_array($errors) ){
|
213 |
+
$error = current($errors);
|
214 |
+
}elseif( !empty($errors->code) ){
|
215 |
+
$error = $errors;
|
216 |
+
}else{
|
217 |
+
$error = (object) array('code' => $response['response']['code'], 'message' => $response['body']);
|
218 |
+
}
|
219 |
+
throw new EM_Exception($error->message, $error->code);
|
220 |
+
}
|
221 |
+
if( $json_decode ){
|
222 |
+
$response['body'] = json_decode($response['body']);
|
223 |
+
}
|
224 |
+
return $response;
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Fetches event data from the given endpoint with supplied arguments according to Meetup API v3
|
229 |
+
*
|
230 |
+
* @param string $endpoint Full URL or endpoint accepted.
|
231 |
+
* @param array $args
|
232 |
+
* @param array $request_args
|
233 |
+
* @return array
|
234 |
+
* @throws EM_Exception
|
235 |
+
*/
|
236 |
+
public function get($endpoint, array $args = array(), array $request_args = array() ){
|
237 |
+
$request_url = add_query_arg( $args, $this->api_base.$endpoint );
|
238 |
+
$request_args['method'] = 'GET';
|
239 |
+
return static::http_request( $request_url, $request_args );
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* @param $endpoint
|
244 |
+
* @param array $vars
|
245 |
+
* @param array $request_args
|
246 |
+
* @param bool $json Shorthand for setting Content-Type in headers to application/json
|
247 |
+
* @return array|mixed
|
248 |
+
* @throws EM_Exception
|
249 |
+
*/
|
250 |
+
public function post($endpoint, array $vars = array(), array $request_args = array(), $json = false ){
|
251 |
+
$request_args['body'] = $vars;
|
252 |
+
$request_args = array_merge(array('method' => 'POST'), $request_args);
|
253 |
+
if( $json ){
|
254 |
+
if( empty($request_args['headers'])) $request_args['headers'] = array();
|
255 |
+
$request_args['headers']['Content-Type'] = 'application/json';
|
256 |
+
}
|
257 |
+
return static::http_request($endpoint, $request_args, $json);
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* @param $endpoint
|
262 |
+
* @param array $vars
|
263 |
+
* @param array $request_args
|
264 |
+
* @param bool $json
|
265 |
+
* @return array|mixed
|
266 |
+
* @throws EM_Exception
|
267 |
+
*/
|
268 |
+
public function patch($endpoint, array $vars = array(), array $request_args = array(), $json = false ){
|
269 |
+
$request_args['method'] = 'PATCH';
|
270 |
+
return static::post($endpoint, $vars, $request_args, $json);
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* @param $endpoint
|
275 |
+
* @param array $vars
|
276 |
+
* @param array $request_args
|
277 |
+
* @param bool $json
|
278 |
+
* @return array|mixed
|
279 |
+
* @throws EM_Exception
|
280 |
+
*/
|
281 |
+
public function put($endpoint, array $vars = array(), array $request_args = array(), $json = false ){
|
282 |
+
$request_args['method'] = 'PUT';
|
283 |
+
return static::post($endpoint, $vars, $request_args, $json);
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* @param $endpoint
|
288 |
+
* @param array $args
|
289 |
+
* @param array $request_args
|
290 |
+
* @return array|mixed
|
291 |
+
* @throws EM_Exception
|
292 |
+
*/
|
293 |
+
public function delete($endpoint, array $args = array(), array $request_args = array() ){
|
294 |
+
$request_url = add_query_arg( $args, $this->api_base.$endpoint );
|
295 |
+
$request_args['method'] = 'DELETE';
|
296 |
+
return static::http_request( $request_url, $request_args );
|
297 |
+
}
|
298 |
+
|
299 |
+
// Baseic OAuth interaction functions, loading a token into client as well as requesting, refreshing, verifying and revoking tokens.
|
300 |
+
|
301 |
+
/**
|
302 |
+
* @param int $user_id
|
303 |
+
* @param int $account_id
|
304 |
+
* @throws EM_Exception
|
305 |
+
*/
|
306 |
+
public function load_token( $account_id = null, $user_id = null ){
|
307 |
+
if( $this->authorization_scope !== 'user' ) $user_id = null; // user id is not relevant
|
308 |
+
// return value if already authorized
|
309 |
+
if( $this->authorized && $this->authorized = $user_id.'|'.$account_id && $this->user_id == $user_id && $this->token->id == $account_id) return;
|
310 |
+
// not authorized, re/load token
|
311 |
+
$this->authorized = $this->token = false;
|
312 |
+
$this->user_id = $user_id;
|
313 |
+
// get token information from user account
|
314 |
+
$this->get_access_token( $account_id );
|
315 |
+
// renew token if expired
|
316 |
+
if ( $this->token->is_expired() ) {
|
317 |
+
// Refresh the token if it's expired and update WP user meta.
|
318 |
+
$this->refresh();
|
319 |
+
}else{
|
320 |
+
$this->authorized = $user_id .'|'. $this->token->id;
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* Requests an access token from the supplied authorization code. The access token is further verified and populated with service account meta.
|
326 |
+
* If successful, token and meta information is saved for the user $user_id or current user if not specified.
|
327 |
+
* Throws an EM_Exception if unsuccessful at any stage in this process.
|
328 |
+
*
|
329 |
+
* @var string $code
|
330 |
+
* @var int $user_id
|
331 |
+
* @throws EM_Exception
|
332 |
+
*/
|
333 |
+
public function request($code, $user_id = null ){
|
334 |
+
if( $this->authorization_scope == 'user' ){
|
335 |
+
$this->user_id = empty($user_id) ? get_current_user_id() : $user_id; // used in $this->save_access_token()
|
336 |
+
}else{
|
337 |
+
$this->user_id = null;
|
338 |
+
}
|
339 |
+
$access_token = $this->request_access_token($code);
|
340 |
+
$this->token = new OAuth_API_Token($access_token);
|
341 |
+
if( $this->token->refresh_token === true ) $this->token->refresh_token = false; // if no token was provided, we may be able to obtain it here, otherwise validation will fail upon refresh.
|
342 |
+
// verify the access token so we can establish the id of this account and then save it to user profile
|
343 |
+
$access_token_meta = $this->verify_access_token();
|
344 |
+
// now, check for previous tokens and save to it instead of overwriting (we do this in case ppl reauthorize the same account and get a new token with no refresh_token)
|
345 |
+
if( empty($this->token->id) ){
|
346 |
+
$token = $this->token;
|
347 |
+
try{
|
348 |
+
$this->get_access_token($access_token_meta['id']);
|
349 |
+
$this->token->refresh( $token->to_array() ); // merge in new token info to old token
|
350 |
+
} catch ( EM_Exception $ex ){
|
351 |
+
$this->token = $token; // revert back to new token
|
352 |
+
}
|
353 |
+
}
|
354 |
+
// refresh current or new token with the meta info and save
|
355 |
+
$this->token->refresh( $access_token_meta );
|
356 |
+
$this->save_access_token();
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* @throws EM_Exception
|
361 |
+
*/
|
362 |
+
public function refresh(){
|
363 |
+
if ( $this->token->refresh_token ) {
|
364 |
+
try{
|
365 |
+
$access_token = $this->refresh_access_token();
|
366 |
+
$this->token->refresh($access_token, true);
|
367 |
+
$this->save_access_token();
|
368 |
+
$this->authorized = $this->user_id .'|'. $this->token->id;
|
369 |
+
}catch( EM_Exception $ex ){
|
370 |
+
throw new EM_Exception( array(
|
371 |
+
$this->option_name.'-error' => sprintf(esc_html__( 'There was an error connecting to %s: %s', 'events-manager' ), $this->service_name, "<code>{$ex->getMessage()}</code>"),
|
372 |
+
$this->option_name.'-token-expired' => $this->reauthorize_error_string()
|
373 |
+
));
|
374 |
+
}
|
375 |
+
}else{
|
376 |
+
throw new EM_Exception( $this->reauthorize_error_string() );
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Verify the token for this client by obtaining meta data of the account associated to this token and saving it to the current token.
|
382 |
+
* @var boolean $update_token
|
383 |
+
* @return boolean
|
384 |
+
* @throws EM_Exception
|
385 |
+
*/
|
386 |
+
public function verify( $update_token = true ){
|
387 |
+
$access_token_meta = $this->verify_access_token();
|
388 |
+
// refresh current or new token with the meta info and save
|
389 |
+
$updated = $this->token->refresh( $access_token_meta );
|
390 |
+
if( $updated && $update_token ) $this->save_access_token();
|
391 |
+
return true; // if we get here, verification passed.
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* @return boolean
|
396 |
+
* @throws EM_Exception
|
397 |
+
*/
|
398 |
+
public function revoke(){
|
399 |
+
return $this->revoke_access_token();
|
400 |
+
}
|
401 |
+
|
402 |
+
/* START OVERRIDABLE FUNCTIONS - THESE FUNCTIONS COULD BE OVERRIDDEN TO SPECIFICALLY DEAL WITH PARTICULAR OAUTH PROVIDERS */
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Specific function which requests the access token from the API Service and returns the access token array, an error array if service replies.
|
406 |
+
* Throws an EM_Exception if there are any other connection issues.
|
407 |
+
*
|
408 |
+
* @var string $code
|
409 |
+
* @return array
|
410 |
+
* @throws EM_Exception
|
411 |
+
*/
|
412 |
+
public function request_access_token( $code ){
|
413 |
+
$args = array(
|
414 |
+
'body' => array(
|
415 |
+
'client_id' => $this->id,
|
416 |
+
'grant_type' => 'authorization_code',
|
417 |
+
'redirect_uri' => static::get_oauth_callback_url(),
|
418 |
+
'code' => $code
|
419 |
+
)
|
420 |
+
);
|
421 |
+
return $this->oauth_request( 'post', $this->oauth_request_token_url, $args );
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* @return array
|
426 |
+
* @throws EM_Exception
|
427 |
+
*/
|
428 |
+
public function refresh_access_token(){
|
429 |
+
$args = array(
|
430 |
+
'body' => array(
|
431 |
+
'grant_type' => 'refresh_token',
|
432 |
+
'refresh_token' => $this->token->refresh_token,
|
433 |
+
)
|
434 |
+
);
|
435 |
+
return $this->oauth_request('post', $this->oauth_refresh_token_url, $args);
|
436 |
+
}
|
437 |
+
|
438 |
+
/**
|
439 |
+
* Verifies an access token by obtaining further meta data about the account associated with that token.
|
440 |
+
* Expected return is an associative array containing the id (service account id the token belongs to), name, photo and email (optional).
|
441 |
+
*
|
442 |
+
* @return array
|
443 |
+
* @throws EM_Exception
|
444 |
+
*/
|
445 |
+
public function verify_access_token(){
|
446 |
+
$request_url = str_replace('ACCESS_TOKEN', $this->token->access_token, $this->oauth_verification_url);
|
447 |
+
$access_token = $this->oauth_request('get', $request_url);
|
448 |
+
return $access_token; // we may want to override this depending on what's returned
|
449 |
+
}
|
450 |
+
|
451 |
+
/**
|
452 |
+
* @return bool
|
453 |
+
* @throws EM_Exception
|
454 |
+
*/
|
455 |
+
public function revoke_access_token(){
|
456 |
+
if( empty($this->oauth_revoke_url) ) return false;
|
457 |
+
$request_url = str_replace('ACCESS_TOKEN', $this->token->access_token, $this->oauth_revoke_url);
|
458 |
+
return $this->oauth_request('get', $request_url); // we may want to override this depending on what's returned
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* @param string $method
|
463 |
+
* @param $request_url
|
464 |
+
* @param array $args
|
465 |
+
* @return mixed
|
466 |
+
* @throws EM_Exception
|
467 |
+
*/
|
468 |
+
public function oauth_request($method, $request_url, $args = array() ){
|
469 |
+
$args = array_merge( array('headers' => array(), 'body' => array()), $args );
|
470 |
+
if( $this->oauth_authentication == 'basic' ){
|
471 |
+
$args['headers']['authorization'] = 'Basic '.base64_encode($this->id.':'.$this->secret);
|
472 |
+
}
|
473 |
+
if( $method === 'get'){
|
474 |
+
if( $this->oauth_authentication == 'parameters' ){
|
475 |
+
// add client params to URL if using get
|
476 |
+
$request_url = add_query_arg( array('client_id' => $this->id), $request_url );
|
477 |
+
}
|
478 |
+
$response = wp_remote_get($request_url, $args);
|
479 |
+
}elseif( $method === 'post' ){
|
480 |
+
if( $this->oauth_authentication == 'parameters' ){
|
481 |
+
// add auth params to body if using post
|
482 |
+
$args['body']['client_id'] = $this->id;
|
483 |
+
$args['body']['client_secret'] = $this->secret;
|
484 |
+
}
|
485 |
+
if( empty($args['Content-Type'])){
|
486 |
+
// by defaulut post will send this content type
|
487 |
+
$args['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
|
488 |
+
}
|
489 |
+
$response = wp_remote_post($request_url, $args);
|
490 |
+
}else{
|
491 |
+
throw new EM_Exception('Unknown request method.');
|
492 |
+
}
|
493 |
+
if( is_wp_error($response) ){
|
494 |
+
throw new EM_Exception($response->get_error_messages());
|
495 |
+
}elseif( $response['response']['code'] != '200' ){
|
496 |
+
$errors = json_decode($response['body']);
|
497 |
+
$error = current($errors);
|
498 |
+
if( !empty($error->message) ){
|
499 |
+
$message = $error->message;
|
500 |
+
}elseif( !empty($error->error) ){
|
501 |
+
$message = $error->error;
|
502 |
+
}elseif( !empty($error->reason) ){
|
503 |
+
$message = $error->reason;
|
504 |
+
}elseif( is_string($error) ){
|
505 |
+
$message = $error;
|
506 |
+
}elseif( is_string($errors) ){
|
507 |
+
$message = $errors;
|
508 |
+
}else{
|
509 |
+
$message = var_export($errors);
|
510 |
+
}
|
511 |
+
$error_code = !empty($error->code) ? $error->code : 'oauth-error';
|
512 |
+
throw new EM_Exception($message, $error_code);
|
513 |
+
}
|
514 |
+
return json_decode($response['body'], true); // we may want to override this depending on what's returned
|
515 |
+
}
|
516 |
+
|
517 |
+
/* END OVERRIDABLE FUNCTIONS */
|
518 |
+
|
519 |
+
/**
|
520 |
+
* @param int $api_user_id
|
521 |
+
* @return string
|
522 |
+
*/
|
523 |
+
public function reauthorize_error_string($api_user_id = 0 ){
|
524 |
+
$settings_page_url = '<a href="'.admin_url('admin.php?page=events-manager-options').'">'. esc_html__('settings page', 'events-manager-google').'</a>';
|
525 |
+
if( !$api_user_id && !empty($this->token->id) ){
|
526 |
+
$api_user_id = !empty($this->token->email) ? $this->token->email : $this->token->id;
|
527 |
+
}
|
528 |
+
if( $api_user_id ){
|
529 |
+
return sprintf(__('You need to reauthorize access to account %s by visiting the %s page.', 'events-manager-google'), $api_user_id, $settings_page_url);
|
530 |
+
}
|
531 |
+
return sprintf(__('You need to authorize access to your %s account by visiting the %s page.', 'events-manager-google'), $this->service_name, $settings_page_url);
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* Gets an access token for a specific account, or provides first account user has available, if any. If no access token is available, an EM_Exception is thrown.
|
536 |
+
*
|
537 |
+
* @param int $api_user_id The ID (e.g. number or email) of the OAuth account
|
538 |
+
* @return OAuth_API_Token
|
539 |
+
* @throws EM_Exception
|
540 |
+
*/
|
541 |
+
public function get_access_token( $api_user_id = 0 ){
|
542 |
+
if( $this->authorization_scope == 'site' ){
|
543 |
+
$site_tokens = EM_Options::get($this->option_name.'_token', array(), $this->option_dataset);
|
544 |
+
if( !empty($site_tokens) ){
|
545 |
+
if( $this->multiple_tokens && !empty($api_user_id) && !empty($site_tokens[$api_user_id]) ){
|
546 |
+
$token_data = $site_tokens[$api_user_id];
|
547 |
+
$token_data['id'] = $api_user_id;
|
548 |
+
}else{
|
549 |
+
$token_data = current($site_tokens);
|
550 |
+
$token_data['id'] = key($site_tokens);
|
551 |
+
}
|
552 |
+
}
|
553 |
+
}elseif( $this->authorization_scope == 'user' ){
|
554 |
+
$user_tokens = get_user_meta( $this->user_id, $this->option_dataset.'_'.$this->option_name, true );
|
555 |
+
if( !empty($user_tokens) ){
|
556 |
+
if( $api_user_id ){
|
557 |
+
if( !empty($user_tokens[$api_user_id]) ){
|
558 |
+
$token_data = $user_tokens[$api_user_id];
|
559 |
+
$token_data['id'] = $api_user_id;
|
560 |
+
}
|
561 |
+
}elseif( !empty($user_tokens) ){
|
562 |
+
$token_data = current($user_tokens);
|
563 |
+
$token_data['id'] = key($user_tokens);
|
564 |
+
}
|
565 |
+
}
|
566 |
+
}
|
567 |
+
if( empty($token_data) ) throw new EM_Exception( $this->reauthorize_error_string($api_user_id) );
|
568 |
+
$this->token = new $this->token_class($token_data);
|
569 |
+
return $this->token;
|
570 |
+
}
|
571 |
+
|
572 |
+
/**
|
573 |
+
* Sets the access token to the user meta storage where all connected accounts for the user of that token are stored.
|
574 |
+
*/
|
575 |
+
public function save_access_token(){
|
576 |
+
if( $this->authorization_scope == 'site' ){
|
577 |
+
$token = $this->token->to_array();
|
578 |
+
if( $this->multiple_tokens ){
|
579 |
+
$site_tokens = EM_Options::get($this->option_name.'_token', array(), $this->option_dataset);
|
580 |
+
}
|
581 |
+
if( empty($site_tokens) ) $site_tokens = array();
|
582 |
+
$site_tokens[$this->token->id] = $token;
|
583 |
+
EM_Options::set($this->option_name.'_token', $site_tokens, $this->option_dataset);
|
584 |
+
}elseif( $this->authorization_scope == 'user' ){
|
585 |
+
if( $this->multiple_tokens ){
|
586 |
+
$user_tokens = get_user_meta($this->user_id, $this->option_dataset.'_'.$this->option_name, true);
|
587 |
+
}
|
588 |
+
if( empty($user_tokens) ) $user_tokens = array();
|
589 |
+
$token = $this->token->to_array();
|
590 |
+
$user_tokens[$this->token->id] = $token;
|
591 |
+
update_user_meta($this->user_id, $this->option_dataset.'_'.$this->option_name, $user_tokens);
|
592 |
+
}
|
593 |
+
}
|
594 |
+
}
|
classes/em-oauth/oauth-api-token.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_OAuth;
|
3 |
+
use EM_Exception;
|
4 |
+
|
5 |
+
class OAuth_API_Token {
|
6 |
+
|
7 |
+
public $access_token = '';
|
8 |
+
public $refresh_token = '';
|
9 |
+
public $token_type = '';
|
10 |
+
public $expires_in = 0;
|
11 |
+
/**
|
12 |
+
* @var int Timestamp when a token will expire at, which can be supplied instead of expires_in and that value will be generated from this one.
|
13 |
+
*/
|
14 |
+
public $expires_at = 0;
|
15 |
+
public $created = 0;
|
16 |
+
|
17 |
+
public $id = '';
|
18 |
+
public $email = '';
|
19 |
+
public $name = '';
|
20 |
+
public $photo = '';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param array $token
|
24 |
+
* @throws EM_Exception
|
25 |
+
*/
|
26 |
+
public function __construct( $token ){
|
27 |
+
$this->refresh($token);
|
28 |
+
if( empty($token['created']) ) $this->created = time();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @param array $token
|
33 |
+
* @return boolean $updated
|
34 |
+
* @throws EM_Exception
|
35 |
+
*/
|
36 |
+
public function refresh( $token, $reset = false ){
|
37 |
+
$updated = false;
|
38 |
+
// reset values
|
39 |
+
if( $reset ){
|
40 |
+
$this->expires_in = $this->expires_at = $this->created = 0;
|
41 |
+
$this->access_token = $this->refresh_token = $this->token_type = '';
|
42 |
+
}
|
43 |
+
// add new values
|
44 |
+
foreach( $token as $k => $v ){
|
45 |
+
if( empty($this->$k) || $this->$k != $token[$k] ){
|
46 |
+
$this->$k = $token[$k];
|
47 |
+
$updated = true;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
// set values that may not have been added
|
51 |
+
if( empty($this->id) && !empty($this->email) ) $this->id = $this->email;
|
52 |
+
if( !$this->created ) $this->created = time();
|
53 |
+
// set expires_at, which is what we'll use for expiry checking
|
54 |
+
if( $this->expires_at ){
|
55 |
+
$this->expires_in = $this->expires_at - time();
|
56 |
+
}elseif( $this->created && $this->expires_in ){
|
57 |
+
$this->expires_at = $this->expires_in + $this->created;
|
58 |
+
}else{
|
59 |
+
$this->expires_in = $this->expires_at = time();
|
60 |
+
}
|
61 |
+
$this->verify();
|
62 |
+
return $updated;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* @throws EM_Exception
|
67 |
+
*/
|
68 |
+
public function verify(){
|
69 |
+
$missing = array();
|
70 |
+
foreach( array('access_token', 'expires_at') as $k ){
|
71 |
+
if( empty($this->$k) ) $missing[] = $k;
|
72 |
+
}
|
73 |
+
if( !empty($missing) ) throw new EM_Exception( sprintf(__('Involid token credentials, the folloiwng are missing: %s.', 'events-manager'), implode(', ', $missing)) );
|
74 |
+
}
|
75 |
+
|
76 |
+
public function is_expired(){
|
77 |
+
return $this->expires_at < time();
|
78 |
+
}
|
79 |
+
|
80 |
+
public function to_array(){
|
81 |
+
$array = array();
|
82 |
+
$ignore = array('id');
|
83 |
+
foreach( get_object_vars($this) as $k => $v ){
|
84 |
+
if( !in_array($k, $ignore) && !empty($this->$k) ) $array[$k] = $this->$k;
|
85 |
+
}
|
86 |
+
return $array;
|
87 |
+
}
|
88 |
+
}
|
classes/em-oauth/oauth-api.php
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_OAuth;
|
3 |
+
use EM_Exception, EM_Notices, EM_Options;
|
4 |
+
|
5 |
+
class OAuth_API {
|
6 |
+
/**
|
7 |
+
* The name of this service to be displayed to the end user in notices etc.
|
8 |
+
* @var string
|
9 |
+
*/
|
10 |
+
protected static $service_name = 'EM OAuth 2.0';
|
11 |
+
/**
|
12 |
+
* @var string
|
13 |
+
*/
|
14 |
+
protected static $service_url = 'http://example.com';
|
15 |
+
/**
|
16 |
+
* Ths option/key name used to differentiate this from other OAuth objects stored in the database tables.
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
protected static $option_name = 'oauth';
|
20 |
+
/**
|
21 |
+
* Where data about this API is stored, which is by default in a serialized array with option name 'em_oauth'
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected static $option_dataset = 'dbem_oauth';
|
25 |
+
/**
|
26 |
+
* Allows overriding the default client class to be loaded, set this to the token class name you'd like to use instead.
|
27 |
+
* By default, the extended classname preceded by _Client will be used if it exists, otherwise OAuth_API_Client.
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
protected static $client_class;
|
31 |
+
/**
|
32 |
+
* Allows overriding the default token class to be loaded, set this to the token class name you'd like to use instead.
|
33 |
+
* By default, the extended classname preceded by _Token will be used if it exists, otherwise OAuth_API_Token.
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected static $token_class;
|
37 |
+
/**
|
38 |
+
* Defines whether authorization tokens are stored at a site, user or (eventually) network level.
|
39 |
+
* @var string 'site' or 'user' level (future consideration for 'network')
|
40 |
+
*/
|
41 |
+
protected static $authorization_scope = 'site';
|
42 |
+
/**
|
43 |
+
* Whether or not storage destination supports multiple accounts (e.g. multiple accounts for a site or a user)
|
44 |
+
* @var bool
|
45 |
+
*/
|
46 |
+
protected static $multiple_tokens = false;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @return string
|
50 |
+
*/
|
51 |
+
public static function get_service_name() {
|
52 |
+
return static::$service_name;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @return string
|
57 |
+
*/
|
58 |
+
public static function get_service_url() {
|
59 |
+
return static::$service_url;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* @return string
|
64 |
+
*/
|
65 |
+
public static function get_option_name() {
|
66 |
+
return static::$option_name;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public static function get_option_dataset() {
|
73 |
+
return static::$option_dataset;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* @return OAuth_API_Client|string String representation of token class, used for instantiation or static function/property reference
|
78 |
+
*/
|
79 |
+
public static function get_client_class() {
|
80 |
+
if( static::$client_class !== null && class_exists(static::$client_class) ) return static::$client_class;
|
81 |
+
if( static::$client_class === null && class_exists(get_called_class().'_Client') ){
|
82 |
+
static::$client_class = get_called_class().'_Client';
|
83 |
+
return static::$client_class;
|
84 |
+
}
|
85 |
+
return 'EM_OAuth\OAuth_API_Client';
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @return OAuth_API_Token|string String representation of token class, used for instantiation or static function/property reference
|
90 |
+
*/
|
91 |
+
public static function get_token_class() {
|
92 |
+
if( static::$token_class !== null && class_exists(static::$token_class) ) return static::$token_class;
|
93 |
+
if( static::$token_class === null && class_exists(get_called_class().'_Token') ){
|
94 |
+
static::$token_class = get_called_class().'_Token';
|
95 |
+
return static::$token_class;
|
96 |
+
}
|
97 |
+
return 'EM_OAuth\OAuth_API_Token';
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @return string
|
102 |
+
*/
|
103 |
+
public static function get_authorization_scope() {
|
104 |
+
return static::$authorization_scope;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @return bool
|
109 |
+
*/
|
110 |
+
public static function supports_multiple_tokens() {
|
111 |
+
return static::$multiple_tokens;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Loads the service credentials into an abstract client api object. If a user ID is supplied and there's an issue retrieving an access token, an exception will be returned.
|
116 |
+
* @param int $user_id The User ID in WordPress
|
117 |
+
* @param int $api_user_id The ID of the account in Google (i.e. the email)
|
118 |
+
* @return OAuth_API_Client
|
119 |
+
* @throws EM_Exception
|
120 |
+
*/
|
121 |
+
public static function get_client( $user_id = 0, $api_user_id = 0 ) {
|
122 |
+
//set up the client
|
123 |
+
$client_class = static::get_client_class();
|
124 |
+
$client = new $client_class(); /* @var OAuth_API_Client $client */
|
125 |
+
//load user access token
|
126 |
+
if( $user_id !== false ) {
|
127 |
+
if ( empty($user_id) ) $user_id = get_current_user_id();
|
128 |
+
$client->load_token( $user_id, $api_user_id );
|
129 |
+
}
|
130 |
+
return $client;
|
131 |
+
}
|
132 |
+
|
133 |
+
public static function get_user_tokens( $user_id = false ){
|
134 |
+
if( static::$authorization_scope !== 'user' ) return array();
|
135 |
+
if( empty($user_id) ) $user_id = get_current_user_id();
|
136 |
+
$user_tokens = get_user_meta( $user_id, static::$option_dataset.'_'.static::$option_name, true );
|
137 |
+
if( empty($user_tokens) ) $user_tokens = array();
|
138 |
+
return $user_tokens;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* @return array[OAuth_API_Token]
|
143 |
+
*/
|
144 |
+
public static function get_site_tokens(){
|
145 |
+
if( static::$authorization_scope !== 'site' ) return array();
|
146 |
+
$site_tokens = EM_Options::get(static::$option_name.'_token', array(), static::$option_dataset);
|
147 |
+
if( empty($site_tokens) ) $site_tokens = array();
|
148 |
+
return $site_tokens;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Includes and calls the code required to handle a callback from FB to store user auth token.
|
153 |
+
*/
|
154 |
+
public static function oauth_authorize() {
|
155 |
+
global $EM_Notices;
|
156 |
+
if( !empty($EM_Notices) ) $EM_Notices = new EM_Notices();
|
157 |
+
if( !empty($_REQUEST['code']) ){
|
158 |
+
try{
|
159 |
+
$client = static::get_client(false);
|
160 |
+
if( !$client->oauth_state || (!empty($_REQUEST['state']) && !wp_verify_nonce( $_REQUEST['state'], static::$option_name.'_authorize')) ){
|
161 |
+
$EM_Notices->add_error( sprintf( esc_html__( 'There was an error connecting to %s: %s', 'events-manager' ), static::$service_name, '<code>No State Provided</code>'), true );
|
162 |
+
}else{
|
163 |
+
try {
|
164 |
+
$client->request( $_REQUEST['code'] );
|
165 |
+
$EM_Notices->add_confirm( sprintf( esc_html__( 'Your account has been successfully connected with %s!', 'events-manager' ), static::$service_name ), true);
|
166 |
+
} catch ( EM_Exception $e ){
|
167 |
+
$EM_Notices->add_error( sprintf( esc_html__( 'There was an error connecting to %s: %s', 'events-manager' ), static::$service_name, '<code>'.$e->getMessage().'</code>' ), true );
|
168 |
+
}
|
169 |
+
}
|
170 |
+
} catch ( EM_Exception $ex ){
|
171 |
+
$EM_Notices->add_error($ex->get_messages(), true);
|
172 |
+
}
|
173 |
+
}else{
|
174 |
+
$EM_Notices->add_error( sprintf( esc_html__( 'There was an error connecting to %s: %s', 'events-manager' ), static::$service_name, '<code>No Authorization Code Provided</code>'), true );
|
175 |
+
}
|
176 |
+
// Redirect to settings page
|
177 |
+
$query_args = array( 'page' => 'events-manager-options' );
|
178 |
+
$url = add_query_arg( $query_args, admin_url( 'admin.php' ) );
|
179 |
+
wp_redirect( $url );
|
180 |
+
die();
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Handles disconnecting a user from one or all their connected Google accounts, attempting to revoke their key in the process.
|
185 |
+
*/
|
186 |
+
public static function oauth_disconnect(){
|
187 |
+
global $EM_Notices;
|
188 |
+
if( !empty($EM_Notices) ) $EM_Notices = new EM_Notices();
|
189 |
+
|
190 |
+
if( static::$authorization_scope == 'user' ){
|
191 |
+
$account_tokens = static::get_user_tokens();
|
192 |
+
}else{
|
193 |
+
$account_tokens = static::get_site_tokens();
|
194 |
+
}
|
195 |
+
$accounts_to_disconnect = array();
|
196 |
+
if( empty($_REQUEST['user']) && !empty($_REQUEST['nonce']) && wp_verify_nonce($_REQUEST['nonce'], 'em-oauth-'. static::$option_name .'-disconnect') ){
|
197 |
+
$accounts_to_disconnect = array_keys($account_tokens);
|
198 |
+
}elseif( !empty($_REQUEST['account']) && !empty($_REQUEST['nonce']) && wp_verify_nonce($_REQUEST['nonce'], 'em-oauth-'. static::$option_name .'-disconnect-'.$_REQUEST['account']) ){
|
199 |
+
if( !empty($account_tokens[$_REQUEST['account']]) ){
|
200 |
+
$accounts_to_disconnect[] = $_REQUEST['account'];
|
201 |
+
}
|
202 |
+
}else{
|
203 |
+
$EM_Notices->add_error('Missing nonce, please contact your administrator.', true);
|
204 |
+
}
|
205 |
+
if( !empty($accounts_to_disconnect) ){
|
206 |
+
$errors = $disconnected_accounts = array();
|
207 |
+
foreach( $accounts_to_disconnect as $account_id ){
|
208 |
+
try{
|
209 |
+
$client = static::get_client( get_current_user_id(), $account_id);
|
210 |
+
$client->revoke();
|
211 |
+
} catch ( EM_Exception $ex ){
|
212 |
+
$account_name = !empty( $client->token->email ) ? $client->token->email : $client->token->name;
|
213 |
+
$errors[] = "<em>$account_name</em> - " . $ex->getMessage();
|
214 |
+
} finally{
|
215 |
+
$disconnected_accounts[] = $account_id;
|
216 |
+
unset($account_tokens[$account_id]);
|
217 |
+
}
|
218 |
+
}
|
219 |
+
if( !empty($disconnected_accounts) ){
|
220 |
+
if( static::$authorization_scope == 'user' ){
|
221 |
+
if( empty($account_tokens) ){
|
222 |
+
delete_user_meta( get_current_user_id(), 'em_oauth_'.static::$option_name );
|
223 |
+
}else{
|
224 |
+
update_user_meta( get_current_user_id(), 'em_oauth_'.static::$option_name, $account_tokens );
|
225 |
+
}
|
226 |
+
}else{
|
227 |
+
EM_Options::set(static::$option_name.'_token', $account_tokens, static::$option_dataset);
|
228 |
+
}
|
229 |
+
$success = _n('You have successfully disconnected from your %s account.', 'You have successfully disconnected from your %s accounts.', count($accounts_to_disconnect), 'events-manager');
|
230 |
+
$EM_Notices->add_confirm(sprintf($success, static::$service_name), true);
|
231 |
+
}
|
232 |
+
if( !empty($errors) ){
|
233 |
+
$error_msg = sprintf( esc_html__('There were some issues whilst disconnecting from your %s account(s) :', 'events-manager'), static::$service_name );
|
234 |
+
array_unshift( $errors, $error_msg );
|
235 |
+
$EM_Notices->add_error( $errors, true );
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
// Redirect to settings page
|
240 |
+
$query_args = array( 'page' => 'events-manager-options' );
|
241 |
+
$url = add_query_arg( $query_args, admin_url( 'admin.php' ) );
|
242 |
+
wp_redirect( $url );
|
243 |
+
die();
|
244 |
+
}
|
245 |
+
}
|
246 |
+
//include dependents
|
247 |
+
include('oauth-api-token.php');
|
248 |
+
include('oauth-api-client.php');
|
249 |
+
if( is_admin() ){
|
250 |
+
include('oauth-admin-settings.php');
|
251 |
+
}
|
classes/em-object.php
CHANGED
@@ -634,7 +634,7 @@ class EM_Object {
|
|
634 |
//non default taxonomy, so create new item for the taxonomies array
|
635 |
$tax_name = str_replace('-','_',$tax_name);
|
636 |
$prefix = !array_key_exists($tax_name, $taxonomies_array) ? '':'post_';
|
637 |
-
if( is_array($tax->object_type) ){
|
638 |
if( $event_tax || $loc_tax ){
|
639 |
$taxonomies_array[$prefix.$tax_name] = array('name'=>$tax_name, 'context'=>array(), 'slug'=> $tax->rewrite['slug'], 'query_var'=> $tax->query_var );
|
640 |
}
|
@@ -1028,6 +1028,7 @@ class EM_Object {
|
|
1028 |
if( empty($request) ) $request = $_REQUEST;
|
1029 |
if( !empty($request['em_search']) && empty($args['search']) ) $request['search'] = $request['em_search']; //em_search is included to circumvent wp search GET/POST clashes
|
1030 |
$accepted_searches = !empty($accepted_searches) ? $accepted_searches : self::get_default_search();
|
|
|
1031 |
$accepted_searches = apply_filters('em_accepted_searches', $accepted_searches, $args);
|
1032 |
//merge variables from the $request into $args
|
1033 |
foreach($request as $post_key => $post_value){
|
634 |
//non default taxonomy, so create new item for the taxonomies array
|
635 |
$tax_name = str_replace('-','_',$tax_name);
|
636 |
$prefix = !array_key_exists($tax_name, $taxonomies_array) ? '':'post_';
|
637 |
+
if( is_array($tax->object_type) && !empty($tax->rewrite) ){
|
638 |
if( $event_tax || $loc_tax ){
|
639 |
$taxonomies_array[$prefix.$tax_name] = array('name'=>$tax_name, 'context'=>array(), 'slug'=> $tax->rewrite['slug'], 'query_var'=> $tax->query_var );
|
640 |
}
|
1028 |
if( empty($request) ) $request = $_REQUEST;
|
1029 |
if( !empty($request['em_search']) && empty($args['search']) ) $request['search'] = $request['em_search']; //em_search is included to circumvent wp search GET/POST clashes
|
1030 |
$accepted_searches = !empty($accepted_searches) ? $accepted_searches : self::get_default_search();
|
1031 |
+
$accepted_searches = array_diff($accepted_searches, array('format', 'format_header', 'format_footer'));
|
1032 |
$accepted_searches = apply_filters('em_accepted_searches', $accepted_searches, $args);
|
1033 |
//merge variables from the $request into $args
|
1034 |
foreach($request as $post_key => $post_value){
|
classes/event-locations/em-event-location-url.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_Event_Locations;
|
3 |
+
/**
|
4 |
+
* Adds a URL event location type by extending EM_Event_Location and registering itself with EM_Event_Locations
|
5 |
+
*
|
6 |
+
* @property string url The url of this event location.
|
7 |
+
* @property string text The text used in a link for the url.
|
8 |
+
*/
|
9 |
+
class URL extends Event_Location {
|
10 |
+
|
11 |
+
public static $type = 'url';
|
12 |
+
public static $admin_template = '/forms/event/event-locations/url.php';
|
13 |
+
|
14 |
+
public $properties = array('url', 'text');
|
15 |
+
|
16 |
+
public function get_post(){
|
17 |
+
$return = parent::get_post();
|
18 |
+
if( !empty($_POST['event_location_url']) ){
|
19 |
+
$this->event->event_location_data['url'] = esc_url_raw($_POST['event_location_url']);
|
20 |
+
}
|
21 |
+
if( !empty($_POST['event_location_url_text']) ){
|
22 |
+
$this->event->event_location_data['text'] = sanitize_text_field($_POST['event_location_url_text']);
|
23 |
+
}
|
24 |
+
return $return;
|
25 |
+
}
|
26 |
+
|
27 |
+
public function validate(){
|
28 |
+
$result = false;
|
29 |
+
if( empty($this->event->event_location_data['url']) ){
|
30 |
+
$this->event->add_error( __('Please enter a valid URL for this event location.', 'events-manager') );
|
31 |
+
$result = false;
|
32 |
+
}
|
33 |
+
if( empty($this->event->event_location_data['text']) ){
|
34 |
+
$this->event->add_error( __('Please provide some link text for this event location URL.', 'events-manager') );
|
35 |
+
$result = false;
|
36 |
+
}
|
37 |
+
return $result;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function get_link( $new_target = true ){
|
41 |
+
return '<a href="'.esc_url($this->url).'">'. esc_html($this->text).'</a>';
|
42 |
+
}
|
43 |
+
|
44 |
+
public function get_admin_column() {
|
45 |
+
return '<strong>'. static::get_label() . ' - ' . $this->get_link().'</strong>';
|
46 |
+
}
|
47 |
+
|
48 |
+
public static function get_label( $label_type = 'singular' ){
|
49 |
+
switch( $label_type ){
|
50 |
+
case 'plural':
|
51 |
+
return esc_html__('URLs', 'events-manager');
|
52 |
+
break;
|
53 |
+
case 'singular':
|
54 |
+
return esc_html__('URL', 'events-manager');
|
55 |
+
break;
|
56 |
+
}
|
57 |
+
return parent::get_label($label_type);
|
58 |
+
}
|
59 |
+
|
60 |
+
public function output( $what = null ){
|
61 |
+
if( $what === null ){
|
62 |
+
return '<a href="'. esc_url($this->url) .'" target="_blank">'. esc_html($this->text) .'</a>';
|
63 |
+
}elseif( $what === '_self' ){
|
64 |
+
return '<a href="'. esc_url($this->url) .'">'. esc_html($this->text) .'</a>';
|
65 |
+
}elseif( $what === '_parent' || $what === '_top' ){
|
66 |
+
return '<a href="'. esc_url($this->url) .'" target="'.$what.'">'. esc_html($this->text) .'</a>';
|
67 |
+
}else{
|
68 |
+
return parent::output($what);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
}
|
72 |
+
URL::init();
|
classes/event-locations/em-event-location.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_Event_Locations;
|
3 |
+
/**
|
4 |
+
* Class EM_Event_Location
|
5 |
+
* This class is to be extended by any event location type. The only time this class is not used when not extended is if
|
6 |
+
* @property-read string type
|
7 |
+
*/
|
8 |
+
class Event_Location {
|
9 |
+
/**
|
10 |
+
* @var \EM_Event
|
11 |
+
*/
|
12 |
+
protected $event;
|
13 |
+
/**
|
14 |
+
* The type name of this location type, used to store in the database. Use alphanmeric characters (a-z, A-Z, 0-9), dashes and underscores only.
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public static $type;
|
18 |
+
/**
|
19 |
+
* Represents shortcut property names for an event location child object that can be accessed safely which then refers to the EM_Event object.
|
20 |
+
* This is a map of property names as keys to custom field names in the event_attributes array property of EM_Event.
|
21 |
+
* Naming conventions should follow the lines of lowercase event_location_{static::$type}(_$property_name), for example a url would have event_location_url as a url, and event_location_url_text for link text
|
22 |
+
* @var array
|
23 |
+
*/
|
24 |
+
public $properties = array();
|
25 |
+
/**
|
26 |
+
* The admin template path, if there is one.
|
27 |
+
* @var string
|
28 |
+
* @see EM_Event_Location::load_admin_template()
|
29 |
+
*/
|
30 |
+
public static $admin_template;
|
31 |
+
|
32 |
+
public static function init(){
|
33 |
+
Event_Locations::register( static::$type, get_called_class() );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* EM_Event_Location constructor.
|
38 |
+
* @param \EM_Event $EM_Event
|
39 |
+
*/
|
40 |
+
public function __construct( $EM_Event ) {
|
41 |
+
if( is_object($EM_Event) && property_exists($EM_Event, 'event_id') ){
|
42 |
+
$this->event = $EM_Event;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @param $name
|
48 |
+
* @return string|null
|
49 |
+
*/
|
50 |
+
public function __get( $name ) {
|
51 |
+
if( $name == 'type' ){
|
52 |
+
return static::$type;
|
53 |
+
}elseif( in_array($name, $this->properties) ){
|
54 |
+
return isset($this->event->event_location_data[$name]) ? $this->event->event_location_data[$name] : null;
|
55 |
+
}
|
56 |
+
return null;
|
57 |
+
}
|
58 |
+
|
59 |
+
public function __set($name, $value) {
|
60 |
+
if( in_array($name, $this->properties) ){
|
61 |
+
$this->event->event_location_data[$name] = $value;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
public function __isset($name) {
|
66 |
+
if( in_array($name, $this->properties) ){
|
67 |
+
return isset($this->event->event_location_data[$name]);
|
68 |
+
}
|
69 |
+
return false;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function load_postdata( $event_meta = array() ){
|
73 |
+
if( empty($event_meta) ) $event_meta = $this->event->get_event_meta();
|
74 |
+
$base_key = '_event_location_'.static::$type;
|
75 |
+
foreach( $event_meta as $event_meta_key => $event_meta_val ){
|
76 |
+
if( $event_meta_key == $base_key ){
|
77 |
+
$this->event->event_location_data[static::$type] = ( is_array($event_meta_val) ) ? $event_meta_val[0]:$event_meta_val;
|
78 |
+
$this->event->event_location_data[static::$type] = maybe_unserialize($this->event->event_location_data[static::$type]);
|
79 |
+
}elseif( substr($event_meta_key, 0, strlen($base_key) ) == $base_key ){
|
80 |
+
//event location data is placed directly into the event_location_data array and referenced via get_event_location()
|
81 |
+
$key = str_replace('_event_location_'.static::$type.'_', '', $event_meta_key);
|
82 |
+
$this->event->event_location_data[$key] = ( is_array($event_meta_val) ) ? $event_meta_val[0]:$event_meta_val;
|
83 |
+
$this->event->event_location_data[$key] = maybe_unserialize($this->event->event_location_data[$key]);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @param array $post
|
90 |
+
* @return boolean
|
91 |
+
*/
|
92 |
+
public function get_post(){
|
93 |
+
$this->event->event_location_data = array();
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* @return boolean
|
99 |
+
*/
|
100 |
+
public function validate(){
|
101 |
+
return false;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function save(){
|
105 |
+
if( is_numeric($this->event->post_id) && $this->event->post_id > 0 && static::$type !== null ){
|
106 |
+
$this->reset_data();
|
107 |
+
foreach( $this->event->event_location_data as $prop => $value ){
|
108 |
+
$meta_key = $prop == static::$type ? '_event_location_'.$prop : '_event_location_'.static::$type.'_'.$prop;
|
109 |
+
if( $value !== null ){
|
110 |
+
update_post_meta( $this->event->post_id, $meta_key, $value );
|
111 |
+
}else{
|
112 |
+
delete_post_meta( $this->event->post_id, $meta_key );
|
113 |
+
}
|
114 |
+
}
|
115 |
+
}
|
116 |
+
return true;
|
117 |
+
}
|
118 |
+
|
119 |
+
final function reset_data( $preserve_type_data = false ){
|
120 |
+
if( is_numeric($this->event->post_id) && $this->event->post_id > 0 ){
|
121 |
+
global $wpdb;
|
122 |
+
$result = $wpdb->query( $wpdb->prepare('DELETE FROM '.$wpdb->postmeta." WHERE post_id=%d AND meta_key LIKE '_event_location_%' AND meta_key != '_event_location_type'", $this->event->post_id) );
|
123 |
+
wp_cache_delete( $this->event->post_id, 'post_meta' ); //refresh cache to prevent looking at old data
|
124 |
+
return $result;
|
125 |
+
}
|
126 |
+
return false;
|
127 |
+
}
|
128 |
+
|
129 |
+
public function get_admin_column(){
|
130 |
+
return $this->get_label('singular');
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Returns whether or not this event location is enabled for use.
|
135 |
+
* @return bool
|
136 |
+
*/
|
137 |
+
public static function is_enabled(){
|
138 |
+
$location_types = get_option('dbem_location_types', array());
|
139 |
+
return !empty($location_types[static::$type]);
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Loads admin template automatically if static $admin_template is set to a valid path in templates folder.
|
144 |
+
* Classes with custom forms outside of template folders can override this function and provide their own HTML that will go in the loop of event location type forms.
|
145 |
+
*/
|
146 |
+
public static function load_admin_template(){
|
147 |
+
if( static::$admin_template ){
|
148 |
+
em_locate_template( static::$admin_template, true );
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
public static function get_label( $label_type = 'siingular' ){
|
153 |
+
//override and return plural name.
|
154 |
+
return static::$type;
|
155 |
+
}
|
156 |
+
|
157 |
+
public function output( $what = null ){
|
158 |
+
if( $what !== null && $what !== 'type' ){
|
159 |
+
return esc_html($this->$what);
|
160 |
+
}else{
|
161 |
+
return static::get_label();
|
162 |
+
}
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
//include default Event Locations
|
167 |
+
include('em-event-location-url.php');
|
classes/event-locations/em-event-locations.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace EM_Event_Locations;
|
3 |
+
/**
|
4 |
+
* Handles registration and retrival of EM_Event_Location child classes for use with events.
|
5 |
+
* Class EM_Event_Locations
|
6 |
+
*/
|
7 |
+
class Event_Locations {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Associative array with type key => class name.
|
11 |
+
* @var array
|
12 |
+
*/
|
13 |
+
private static $types = array();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @return array[EM_Event_Location::]
|
17 |
+
*/
|
18 |
+
public static function get_types(){
|
19 |
+
return static::$types;
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param string $type
|
24 |
+
* @param string $classname
|
25 |
+
* @return bool
|
26 |
+
*/
|
27 |
+
public static function register( $type, $classname ){
|
28 |
+
self::$types[$type] = $classname;
|
29 |
+
return true;
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @param string $type
|
34 |
+
* @return bool
|
35 |
+
*/
|
36 |
+
public static function unregister( $type ){
|
37 |
+
if( !empty(self::$types[$type]) ){
|
38 |
+
unset(self::$types[$type]);
|
39 |
+
return true;
|
40 |
+
}
|
41 |
+
return false;
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @param string $type
|
46 |
+
* @param \EM_Event $EM_Event
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
+
public static function get( $type = null, $EM_Event = null ){
|
50 |
+
if( !empty(self::$types[$type]) && class_exists(self::$types[$type]) ){
|
51 |
+
$location_type = self::$types[$type];
|
52 |
+
return new $location_type( $EM_Event );
|
53 |
+
}
|
54 |
+
return false;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Returns whether or not the supplied event location $type is enabled for use.
|
59 |
+
* @param string $type
|
60 |
+
* @return bool
|
61 |
+
*/
|
62 |
+
public static function is_enabled( $type ){
|
63 |
+
$location_types = get_option('dbem_location_types', array());
|
64 |
+
return !empty($location_types[$type]);
|
65 |
+
}
|
66 |
+
|
67 |
+
}
|
68 |
+
require('em-event-location.php');
|
em-events.php
CHANGED
@@ -245,7 +245,26 @@ function em_content_wp_title($title, $sep = '', $seplocation = ''){
|
|
245 |
return $title;
|
246 |
}
|
247 |
add_filter ( 'wp_title', 'em_content_wp_title',100,3 ); //override other plugin SEO due to way EM works.
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
/**
|
251 |
* Makes sure we're in "THE Loop", which is determinied by a flag set when the_post() (start) is first called, and when have_posts() (end) returns false.
|
245 |
return $title;
|
246 |
}
|
247 |
add_filter ( 'wp_title', 'em_content_wp_title',100,3 ); //override other plugin SEO due to way EM works.
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Yoast SEO friendly short circuit, fixes issues in Yoast 14 update by changing the $sep function into the actual separator.
|
251 |
+
* @param $title
|
252 |
+
* @param string|mixed $sep
|
253 |
+
* @param string $seplocation
|
254 |
+
* @return string
|
255 |
+
*/
|
256 |
+
function em_content_wpseo_title($title, $sep = '', $seplocation = ''){
|
257 |
+
if( class_exists('WPSEO_Utils') && method_exists('WPSEO_Utils', 'get_title_separator') ){
|
258 |
+
$sep = WPSEO_Utils::get_title_separator();
|
259 |
+
}elseif( !is_string( $sep ) ){
|
260 |
+
$sep = '';
|
261 |
+
}
|
262 |
+
if( !is_string($seplocation) ){
|
263 |
+
$seplocation = '';
|
264 |
+
}
|
265 |
+
return em_content_wp_title( $title, $sep, $seplocation = '' );
|
266 |
+
}
|
267 |
+
add_filter( 'wpseo_title', 'em_content_wpseo_title', 100, 2 ); //WP SEO friendly
|
268 |
|
269 |
/**
|
270 |
* Makes sure we're in "THE Loop", which is determinied by a flag set when the_post() (start) is first called, and when have_posts() (end) returns false.
|
em-functions.php
CHANGED
@@ -653,11 +653,16 @@ function em_checkbox_items($name, $array, $saved_values, $horizontal = true) {
|
|
653 |
}
|
654 |
function em_options_input_text($title, $name, $description ='', $default='') {
|
655 |
$translate = EM_ML::is_option_translatable($name);
|
|
|
|
|
|
|
|
|
|
|
656 |
?>
|
657 |
<tr valign="top" id='<?php echo esc_attr($name);?>_row'>
|
658 |
<th scope="row"><?php echo esc_html($title); ?></th>
|
659 |
<td>
|
660 |
-
<input name="<?php echo esc_attr($name) ?>" type="text" id="<?php echo esc_attr($name) ?>" value="<?php echo esc_attr(
|
661 |
<?php if( $translate ): ?><span class="em-translatable dashicons dashicons-admin-site"></span><?php endif; ?>
|
662 |
<br />
|
663 |
<?php
|
@@ -672,7 +677,7 @@ function em_options_input_text($title, $name, $description ='', $default='') {
|
|
672 |
</tr>
|
673 |
<?php
|
674 |
}else{
|
675 |
-
$default_lang = '<input name="'.esc_attr($name).'_ml['.EM_ML::$wplang.']" type="hidden" id="'. esc_attr($name.'_'. EM_ML::$wplang) .'" value="'. esc_attr(
|
676 |
}
|
677 |
}
|
678 |
echo '</table>';
|
653 |
}
|
654 |
function em_options_input_text($title, $name, $description ='', $default='') {
|
655 |
$translate = EM_ML::is_option_translatable($name);
|
656 |
+
if( preg_match('/^(.+)\[(.+)?\]$/', $name, $matches) ){
|
657 |
+
$value = EM_Options::get($matches[2], $default, $matches[1]);
|
658 |
+
}else{
|
659 |
+
$value = get_option($name, $default);
|
660 |
+
}
|
661 |
?>
|
662 |
<tr valign="top" id='<?php echo esc_attr($name);?>_row'>
|
663 |
<th scope="row"><?php echo esc_html($title); ?></th>
|
664 |
<td>
|
665 |
+
<input name="<?php echo esc_attr($name) ?>" type="text" id="<?php echo esc_attr($name) ?>" value="<?php echo esc_attr($value, ENT_QUOTES); ?>" size="45" />
|
666 |
<?php if( $translate ): ?><span class="em-translatable dashicons dashicons-admin-site"></span><?php endif; ?>
|
667 |
<br />
|
668 |
<?php
|
677 |
</tr>
|
678 |
<?php
|
679 |
}else{
|
680 |
+
$default_lang = '<input name="'.esc_attr($name).'_ml['.EM_ML::$wplang.']" type="hidden" id="'. esc_attr($name.'_'. EM_ML::$wplang) .'" value="'. esc_attr($value, ENT_QUOTES).'" />';
|
681 |
}
|
682 |
}
|
683 |
echo '</table>';
|
em-install.php
CHANGED
@@ -156,6 +156,7 @@ function em_create_events_table() {
|
|
156 |
event_spaces int(5) NULL DEFAULT 0,
|
157 |
event_private tinyint(1) unsigned NOT NULL DEFAULT 0,
|
158 |
location_id bigint(20) unsigned NULL DEFAULT NULL,
|
|
|
159 |
recurrence_id bigint(20) unsigned NULL DEFAULT NULL,
|
160 |
event_date_created datetime NULL DEFAULT NULL,
|
161 |
event_date_modified datetime NULL DEFAULT NULL,
|
@@ -676,6 +677,7 @@ function em_add_options() {
|
|
676 |
'dbem_timezone_default' => EM_DateTimeZone::create()->getName(),
|
677 |
'dbem_require_location' => 0,
|
678 |
'dbem_locations_enabled' => 1,
|
|
|
679 |
'dbem_use_select_for_locations' => 0,
|
680 |
'dbem_attributes_enabled' => 1,
|
681 |
'dbem_recurrence_enabled'=> 1,
|
@@ -1123,6 +1125,13 @@ function em_upgrade_current_installation(){
|
|
1123 |
update_option('dbem_smtp_encryption', 0);
|
1124 |
}
|
1125 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1126 |
}
|
1127 |
|
1128 |
function em_set_mass_caps( $roles, $caps ){
|
156 |
event_spaces int(5) NULL DEFAULT 0,
|
157 |
event_private tinyint(1) unsigned NOT NULL DEFAULT 0,
|
158 |
location_id bigint(20) unsigned NULL DEFAULT NULL,
|
159 |
+
event_location_type VARCHAR(15) NULL DEFAULT NULL,
|
160 |
recurrence_id bigint(20) unsigned NULL DEFAULT NULL,
|
161 |
event_date_created datetime NULL DEFAULT NULL,
|
162 |
event_date_modified datetime NULL DEFAULT NULL,
|
677 |
'dbem_timezone_default' => EM_DateTimeZone::create()->getName(),
|
678 |
'dbem_require_location' => 0,
|
679 |
'dbem_locations_enabled' => 1,
|
680 |
+
'dbem_location_types' => array('location' => 1, 'url' => 1),
|
681 |
'dbem_use_select_for_locations' => 0,
|
682 |
'dbem_attributes_enabled' => 1,
|
683 |
'dbem_recurrence_enabled'=> 1,
|
1125 |
update_option('dbem_smtp_encryption', 0);
|
1126 |
}
|
1127 |
}
|
1128 |
+
if( get_option('dbem_version') != '' && get_option('dbem_version') < 5.975 ){
|
1129 |
+
update_option('dbem_location_types', array('location'=>1));
|
1130 |
+
$message = esc_html__('Events Manager has introduced location types, which can include online locations such as a URL or integrations with webinar platforms such as Zoom! Enable different location types in your settings page, for more information see our %s.', 'events-manager');
|
1131 |
+
$message = sprintf( $message, '<a href="http://wp-events-plugin.com/documentation/location-types/" target="_blank">'. esc_html__('documentation', 'events-manager')).'</a>';
|
1132 |
+
$EM_Admin_Notice = new EM_Admin_Notice(array( 'name' => 'location-types-update', 'who' => 'admin', 'where' => 'all', 'message' => "$message" ));
|
1133 |
+
EM_Admin_Notices::add($EM_Admin_Notice, is_multisite());
|
1134 |
+
}
|
1135 |
}
|
1136 |
|
1137 |
function em_set_mass_caps( $roles, $caps ){
|
events-manager.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Events Manager
|
4 |
-
Version: 5.9.
|
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.
|
32 |
define('EM_PRO_MIN_VERSION', 2.6712); //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
|
@@ -66,6 +66,7 @@ function dbem_debug_mode(){
|
|
66 |
|
67 |
// INCLUDES
|
68 |
//Base classes
|
|
|
69 |
include('classes/em-options.php');
|
70 |
include('classes/em-object.php');
|
71 |
include('classes/em-datetime.php');
|
@@ -99,6 +100,7 @@ include('classes/em-category.php');
|
|
99 |
include('classes/em-categories.php');
|
100 |
include('classes/em-categories-frontend.php');
|
101 |
include('classes/em-event.php');
|
|
|
102 |
include('classes/em-event-post.php');
|
103 |
include('classes/em-events.php');
|
104 |
include('classes/em-location.php');
|
@@ -118,7 +120,6 @@ include('classes/em-tickets-bookings.php');
|
|
118 |
include('classes/em-tickets.php');
|
119 |
//Admin Files
|
120 |
if( is_admin() ){
|
121 |
-
include('classes/em-admin-notice.php');
|
122 |
include('classes/em-admin-notices.php');
|
123 |
include('admin/em-admin.php');
|
124 |
include('admin/em-bookings.php');
|
@@ -189,6 +190,22 @@ if( file_exists($upload_dir['basedir'].'/locations-pics' ) ){
|
|
189 |
define("EM_IMAGE_DS",'/');
|
190 |
}
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
/**
|
193 |
* @author marcus
|
194 |
* Contains functions for loading styles on both admin and public sides.
|
@@ -515,7 +532,8 @@ function em_load_event(){
|
|
515 |
if( preg_match('/\-([0-9]+)$/', $_REQUEST['event_slug'], $matches) ){
|
516 |
$event_id = $matches[1];
|
517 |
}else{
|
518 |
-
$
|
|
|
519 |
}
|
520 |
$EM_Event = em_get_event($event_id);
|
521 |
}
|
@@ -530,7 +548,8 @@ function em_load_event(){
|
|
530 |
if( preg_match('/\-([0-9]+)$/', $_REQUEST['location_slug'], $matches) ){
|
531 |
$location_id = $matches[1];
|
532 |
}else{
|
533 |
-
$
|
|
|
534 |
}
|
535 |
$EM_Location = em_get_location($location_id);
|
536 |
}
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Events Manager
|
4 |
+
Version: 5.9.8
|
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.98); //self expanatory
|
32 |
define('EM_PRO_MIN_VERSION', 2.6712); //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
|
66 |
|
67 |
// INCLUDES
|
68 |
//Base classes
|
69 |
+
include('classes/em-exception.php');
|
70 |
include('classes/em-options.php');
|
71 |
include('classes/em-object.php');
|
72 |
include('classes/em-datetime.php');
|
100 |
include('classes/em-categories.php');
|
101 |
include('classes/em-categories-frontend.php');
|
102 |
include('classes/em-event.php');
|
103 |
+
include('classes/event-locations/em-event-locations.php');
|
104 |
include('classes/em-event-post.php');
|
105 |
include('classes/em-events.php');
|
106 |
include('classes/em-location.php');
|
120 |
include('classes/em-tickets.php');
|
121 |
//Admin Files
|
122 |
if( is_admin() ){
|
|
|
123 |
include('classes/em-admin-notices.php');
|
124 |
include('admin/em-admin.php');
|
125 |
include('admin/em-bookings.php');
|
190 |
define("EM_IMAGE_DS",'/');
|
191 |
}
|
192 |
|
193 |
+
/**
|
194 |
+
* Provides a way to proactively load groups of files, once, when needed.
|
195 |
+
* @since 5.9.7.4
|
196 |
+
*/
|
197 |
+
class EM_Loader {
|
198 |
+
public static $oauth = false;
|
199 |
+
|
200 |
+
public static function oauth(){
|
201 |
+
require_once('classes/em-oauth/oauth-api.php');
|
202 |
+
add_action('em_enqueue_admin_styles', function(){
|
203 |
+
wp_enqueue_style('events-manager-oauth-admin', plugins_url('includes/css/events-manager-oauth-admin.css',__FILE__), array(), EM_VERSION);
|
204 |
+
});
|
205 |
+
self::$oauth = true;
|
206 |
+
}
|
207 |
+
}
|
208 |
+
|
209 |
/**
|
210 |
* @author marcus
|
211 |
* Contains functions for loading styles on both admin and public sides.
|
532 |
if( preg_match('/\-([0-9]+)$/', $_REQUEST['event_slug'], $matches) ){
|
533 |
$event_id = $matches[1];
|
534 |
}else{
|
535 |
+
$query = $wpdb->prepare('SELECT event_id FROM '.EM_EVENTS_TABLE.' WHERE event_slug = %s AND blog_id != %d', $_REQUEST['event_slug'], get_current_blog_id());
|
536 |
+
$event_id = $wpdb->get_var($query);
|
537 |
}
|
538 |
$EM_Event = em_get_event($event_id);
|
539 |
}
|
548 |
if( preg_match('/\-([0-9]+)$/', $_REQUEST['location_slug'], $matches) ){
|
549 |
$location_id = $matches[1];
|
550 |
}else{
|
551 |
+
$query = $wpdb->prepare('SELECT location_id FROM '.EM_LOCATIONS_TABLE." WHERE location_slug = %s AND blog_id != %d", $_REQUEST['location_slug'], get_current_blog_id());
|
552 |
+
$location_id = $wpdb->get_var($query);
|
553 |
}
|
554 |
$EM_Location = em_get_location($location_id);
|
555 |
}
|
includes/css/events-manager-oauth-admin.css
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Settings Page */
|
2 |
+
#em-options-form .postbox.em-oaut-connect-user .em-oauth-service-info { max-width:1000px; min-height: 75px; }
|
3 |
+
#em-options-form .postbox.em-oaut-connect-user .em-oauth-service-logo { float:left; width:50px; height:50px; }
|
4 |
+
|
5 |
+
#em-options-form .postbox.em-oaut-connect li.em-oauth-service-account { clear:both; height:16px; padding-bottom:10px; }
|
6 |
+
#em-options-form .postbox.em-oaut-connect li.em-oauth-service-account img, #em-options-form .postbox.em-oaut-connect li.em-oauth-service-account > div { float:left; }
|
7 |
+
#em-options-form .postbox.em-oaut-connect li.em-oauth-service-account > div { padding: 5px 0 5px 8px; }
|
8 |
+
#em-options-form .postbox.em-oaut-connect li.em-oauth-account-disconnected img, #em-options-form .postbox.em-oaut-connect li.em-oauth-account-disconnected .em-oauth-account-label { opacity:0.5; }
|
9 |
+
#em-options-form .postbox.em-oaut-connect li.em-oauth-account-disconnected .dashicons { width:16px; height: 16px; font-size: 16px; }
|
10 |
+
|
11 |
+
@media screen and (max-width: 600px) {
|
12 |
+
#em-options-form .postbox.em-oaut-connect .em-oauth-service-logo { margin:0px 10px 10px 0px; }
|
13 |
+
#em-options-form .postbox.em-oaut-connect .em-oauth-connect-button { margin: 10px 0px 10px 10px; }
|
14 |
+
#em-options-form .postbox.em-oaut-connect .em-oauth-service-info h2 { margin: 0px 0px 5px; padding:0px 5px; }
|
15 |
+
#em-options-form .postbox.em-oaut-connect .em-oauth-service-info { clear:both; margin:0px; }
|
16 |
+
}
|
includes/css/events_manager.css
CHANGED
@@ -161,6 +161,14 @@ div#em-loading { position:absolute; width:100%; height:100%; background:#FFFFFF
|
|
161 |
/* The editor */
|
162 |
#wp-em-editor-content-wrap table { margin-bottom:0px; }
|
163 |
/* Location form */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
#em-location-data table.em-location-data td, #em-location-data table.em-location-data th { vertical-align:top; border:none; }
|
165 |
#em-location-data table.em-location-data select { width:100%; }
|
166 |
#em-location-data table.em-location-data { width:50%; float:left; border:none; }
|
161 |
/* The editor */
|
162 |
#wp-em-editor-content-wrap table { margin-bottom:0px; }
|
163 |
/* Location form */
|
164 |
+
#event-form .em-location-type { border-top: 1px solid #dedede; margin-top:20px; padding-top:20px; }
|
165 |
+
#event-form .em-location-type p:first-child { margin-top:0; }
|
166 |
+
#event-form div.em-location-data table { float:left; margin:0px 15px 0px 0px; }
|
167 |
+
#event-form .em-event-location-data h4 { padding-bottom:5px; border-bottom:1px solid #dedede; margin-bottom:15px; }
|
168 |
+
#event-form .em-input-field { margin-bottom:10px; }
|
169 |
+
#event-form .em-input-field label { display: block; margin-bottom:5px; }
|
170 |
+
#event-form .em-input-field.em-input-field-boolean label { display: inline-block; }
|
171 |
+
#event-form .em-input-field em { display: block; margin-top:2px; }
|
172 |
#em-location-data table.em-location-data td, #em-location-data table.em-location-data th { vertical-align:top; border:none; }
|
173 |
#em-location-data table.em-location-data select { width:100%; }
|
174 |
#em-location-data table.em-location-data { width:50%; float:left; border:none; }
|
includes/css/events_manager_admin.css
CHANGED
@@ -32,10 +32,19 @@ table.events-table .category { color:#888; }
|
|
32 |
#event-form .recurrence-reschedule-warning, #post .recurrence-reschedule-warning { margin-bottom:25px; color:#c45500; }
|
33 |
#event-form .recurrence-reschedule-warning p, #post .recurrence-reschedule-warning p { margin-top:0px; font-size:14px; }
|
34 |
/*Locations*/
|
|
|
|
|
35 |
div.em-location-data table { float:left; margin:0px 15px 0px 0px; }
|
|
|
|
|
|
|
|
|
|
|
36 |
/* Location form */
|
|
|
37 |
div.em-location-data table.em-location-data td, div.em-location-data table.em-location-data th { vertical-align:top; border:none; }
|
38 |
div.em-location-data table.em-location-data { width:50%; float:left; border:none; }
|
|
|
39 |
div.em-location-data .em-location-map-container, div.em-location-data .em-location-map-404, div.em-location-data .em-location-map-content { width: 400px; height: 300px; float:left; }
|
40 |
div.em-location-data .em-location-map-404 { vertical-align:middle; text-align: center; }
|
41 |
/* MS Global Categories */
|
@@ -151,7 +160,7 @@ table.em-tickets-bookings-table tbody td { text-align:center; }
|
|
151 |
#em-options-form th { padding: 15px 20px; margin:0 !important; font-size:0.97em; }
|
152 |
#em-options-form .em-boxheader { font-style:italic; margin:0; padding:10px 5px; }
|
153 |
#em-options-form tr.em-header td { font-style:italic; padding:10px 5px; margin:0; }
|
154 |
-
#em-options-form tr.em-header h4 { font-weight:bold; font-size:15px; font-style:normal; border-bottom: 1px solid #dedede; margin:0 0 10px; padding:0 0 10px; }
|
155 |
#em-options-form tr.em-subheader td { font-style:italic; margin:0; padding:5px 20px 2px; }
|
156 |
#em-options-form tr.em-subheader h5 { font-style:normal; margin:10px 0; padding:0 0 5px; font-weight:bold; font-size:15px; border-bottom: 1px solid #efefef; color:#000; }
|
157 |
#em-options-form tbody.em-subsection th { padding-left:35px; }
|
32 |
#event-form .recurrence-reschedule-warning, #post .recurrence-reschedule-warning { margin-bottom:25px; color:#c45500; }
|
33 |
#event-form .recurrence-reschedule-warning p, #post .recurrence-reschedule-warning p { margin-top:0px; font-size:14px; }
|
34 |
/*Locations*/
|
35 |
+
.em-location-type { border-top: 1px solid #dedede; margin-top:20px; padding-top:20px; }
|
36 |
+
.em-location-type p:first-child { margin-top:0; }
|
37 |
div.em-location-data table { float:left; margin:0px 15px 0px 0px; }
|
38 |
+
.em-event-location-data h4 { padding-bottom:5px; border-bottom:1px solid #dedede; margin-bottom:15px; }
|
39 |
+
.em-input-field { margin-bottom:10px; }
|
40 |
+
.em-input-field label { display: block; margin-bottom:5px; }
|
41 |
+
.em-input-field.em-input-field-boolean label { display: inline-block; }
|
42 |
+
.em-input-field em { display: block; margin-top:2px; }
|
43 |
/* Location form */
|
44 |
+
div.em-location-types-single { display:none; }
|
45 |
div.em-location-data table.em-location-data td, div.em-location-data table.em-location-data th { vertical-align:top; border:none; }
|
46 |
div.em-location-data table.em-location-data { width:50%; float:left; border:none; }
|
47 |
+
div.em-location-data table.em-location-data .em-location-data-url input { width:100%; }
|
48 |
div.em-location-data .em-location-map-container, div.em-location-data .em-location-map-404, div.em-location-data .em-location-map-content { width: 400px; height: 300px; float:left; }
|
49 |
div.em-location-data .em-location-map-404 { vertical-align:middle; text-align: center; }
|
50 |
/* MS Global Categories */
|
160 |
#em-options-form th { padding: 15px 20px; margin:0 !important; font-size:0.97em; }
|
161 |
#em-options-form .em-boxheader { font-style:italic; margin:0; padding:10px 5px; }
|
162 |
#em-options-form tr.em-header td { font-style:italic; padding:10px 5px; margin:0; }
|
163 |
+
#em-options-form tr.em-header h4, #em-options-form .postbox h4 { font-weight:bold; font-size:15px; font-style:normal; border-bottom: 1px solid #dedede; margin:0 0 10px; padding:0 0 10px; }
|
164 |
#em-options-form tr.em-subheader td { font-style:italic; margin:0; padding:5px 20px 2px; }
|
165 |
#em-options-form tr.em-subheader h5 { font-style:normal; margin:10px 0; padding:0 0 5px; font-weight:bold; font-size:15px; border-bottom: 1px solid #efefef; color:#000; }
|
166 |
#em-options-form tbody.em-subsection th { padding-left:35px; }
|
includes/js/admin-settings.js
CHANGED
@@ -104,16 +104,27 @@ jQuery(document).ready(function($){
|
|
104 |
$(this).nextAll('.em-ml-options').toggle();
|
105 |
});
|
106 |
//radio triggers
|
107 |
-
$('input.em-trigger').change(function(e){
|
108 |
var el = $(this);
|
109 |
el.val() == '1' ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
110 |
});
|
111 |
-
$('input.em-trigger:checked').trigger('change');
|
112 |
-
$('input.em-untrigger').change(function(e){
|
113 |
var el = $(this);
|
114 |
el.val() == '0' ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
115 |
});
|
116 |
-
$('input.em-untrigger:checked').trigger('change');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
//admin tools confirm
|
118 |
$('a.admin-tools-db-cleanup').click( function( e ){
|
119 |
if( !confirm(EM.admin_db_cleanup_warning) ){
|
104 |
$(this).nextAll('.em-ml-options').toggle();
|
105 |
});
|
106 |
//radio triggers
|
107 |
+
$('input[type="radio"].em-trigger').change(function(e){
|
108 |
var el = $(this);
|
109 |
el.val() == '1' ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
110 |
});
|
111 |
+
$('input[type="radio"].em-trigger:checked').trigger('change');
|
112 |
+
$('input[type="radio"].em-untrigger').change(function(e){
|
113 |
var el = $(this);
|
114 |
el.val() == '0' ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
115 |
});
|
116 |
+
$('input[type="radio"].em-untrigger:checked').trigger('change');
|
117 |
+
//checkbox triggers
|
118 |
+
$('input[type="checkbox"].em-trigger').change(function(e){
|
119 |
+
var el = $(this);
|
120 |
+
el.prop('checked') ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
121 |
+
});
|
122 |
+
$('input[type="checkbox"].em-trigger').trigger('change');
|
123 |
+
$('input[type="checkbox"].em-untrigger').change(function(e){
|
124 |
+
var el = $(this);
|
125 |
+
!el.prop('checked') ? $(el.attr('data-trigger')).show() : $(el.attr('data-trigger')).hide();
|
126 |
+
});
|
127 |
+
$('input[type="checkbox"].em-untrigger').trigger('change');
|
128 |
//admin tools confirm
|
129 |
$('a.admin-tools-db-cleanup').click( function( e ){
|
130 |
if( !confirm(EM.admin_db_cleanup_warning) ){
|
includes/js/events-manager.js
CHANGED
@@ -703,7 +703,8 @@ jQuery(document).ready( function($){
|
|
703 |
}else{
|
704 |
jQuery('select#location-country option[value="'+ui.item.country+'"]').attr('selected', 'selected');
|
705 |
}
|
706 |
-
jQuery('div.em-location-data input
|
|
|
707 |
jQuery('#em-location-reset').show();
|
708 |
jQuery('#em-location-search-tip').hide();
|
709 |
jQuery(document).triggerHandler('em_locations_autocomplete_selected', [event, ui]);
|
@@ -715,7 +716,7 @@ jQuery(document).ready( function($){
|
|
715 |
};
|
716 |
jQuery('#em-location-reset a').click( function(){
|
717 |
jQuery('div.em-location-data input').css('background-color','#fff').val('').prop('readonly', false);
|
718 |
-
jQuery('div.em-location-data select').css('background-color','#fff');
|
719 |
jQuery('div.em-location-data option:selected').removeAttr('selected');
|
720 |
jQuery('input#location-id').val('');
|
721 |
jQuery('#em-location-reset').hide();
|
@@ -730,7 +731,8 @@ jQuery(document).ready( function($){
|
|
730 |
return false;
|
731 |
});
|
732 |
if( jQuery('input#location-id').val() != '0' && jQuery('input#location-id').val() != '' ){
|
733 |
-
jQuery('div.em-location-data input
|
|
|
734 |
jQuery('#em-location-reset').show();
|
735 |
jQuery('#em-location-search-tip').hide();
|
736 |
}
|
703 |
}else{
|
704 |
jQuery('select#location-country option[value="'+ui.item.country+'"]').attr('selected', 'selected');
|
705 |
}
|
706 |
+
jQuery('div.em-location-data input').css('background-color','#ccc').prop('readonly', true);
|
707 |
+
jQuery('div.em-location-data select').css('background-color','#ccc').css('color', '#666666').prop('disabled', true);
|
708 |
jQuery('#em-location-reset').show();
|
709 |
jQuery('#em-location-search-tip').hide();
|
710 |
jQuery(document).triggerHandler('em_locations_autocomplete_selected', [event, ui]);
|
716 |
};
|
717 |
jQuery('#em-location-reset a').click( function(){
|
718 |
jQuery('div.em-location-data input').css('background-color','#fff').val('').prop('readonly', false);
|
719 |
+
jQuery('div.em-location-data select').css('background-color','#fff').css('color', 'auto').prop('disabled', false);
|
720 |
jQuery('div.em-location-data option:selected').removeAttr('selected');
|
721 |
jQuery('input#location-id').val('');
|
722 |
jQuery('#em-location-reset').hide();
|
731 |
return false;
|
732 |
});
|
733 |
if( jQuery('input#location-id').val() != '0' && jQuery('input#location-id').val() != '' ){
|
734 |
+
jQuery('div.em-location-data input').css('background-color','#ccc').prop('readonly', true);
|
735 |
+
jQuery('div.em-location-data select').css('background-color','#ccc').css('color', '#666666').prop('disabled', true);
|
736 |
jQuery('#em-location-reset').show();
|
737 |
jQuery('#em-location-search-tip').hide();
|
738 |
}
|
multilingual/em-ml-admin.php
CHANGED
@@ -17,11 +17,13 @@ class EM_ML_Admin{
|
|
17 |
}
|
18 |
|
19 |
public static function meta_boxes(){
|
20 |
-
global $EM_Event, $EM_Location;
|
21 |
//decide if it's a master event, if not then hide the meta boxes
|
22 |
if( !empty($EM_Event) && !EM_ML::is_original($EM_Event) ){
|
23 |
//remove meta boxes for events
|
24 |
remove_meta_box('em-event-when', EM_POST_TYPE_EVENT, 'side');
|
|
|
|
|
25 |
remove_meta_box('em-event-recurring', 'event-recurring', 'normal');
|
26 |
remove_meta_box('em-event-when-recurring', 'event-recurring', 'side');
|
27 |
remove_meta_box('em-event-where', EM_POST_TYPE_EVENT, 'normal');
|
17 |
}
|
18 |
|
19 |
public static function meta_boxes(){
|
20 |
+
global $EM_Event, $EM_Location, $wp_meta_boxes;
|
21 |
//decide if it's a master event, if not then hide the meta boxes
|
22 |
if( !empty($EM_Event) && !EM_ML::is_original($EM_Event) ){
|
23 |
//remove meta boxes for events
|
24 |
remove_meta_box('em-event-when', EM_POST_TYPE_EVENT, 'side');
|
25 |
+
//if( isset($wp_meta_boxes[convert_to_screen(EM_POST_TYPE_EVENT)->id]['side']['high']['em-event-when']) ) unset($wp_meta_boxes[convert_to_screen(EM_POST_TYPE_EVENT)->id]['side']['high']['em-event-when']);
|
26 |
+
//if( isset($wp_meta_boxes[convert_to_screen(EM_POST_TYPE_EVENT)->id]['side']['core']['em-event-when']) ) unset($wp_meta_boxes[convert_to_screen(EM_POST_TYPE_EVENT)->id]['side']['core']['em-event-when']);
|
27 |
remove_meta_box('em-event-recurring', 'event-recurring', 'normal');
|
28 |
remove_meta_box('em-event-when-recurring', 'event-recurring', 'side');
|
29 |
remove_meta_box('em-event-where', EM_POST_TYPE_EVENT, 'normal');
|
readme.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
=== Events Manager ===
|
2 |
Contributors: netweblogic, nutsmuggler
|
3 |
Donate link: http://wp-events-plugin.com
|
4 |
-
Tags: bookings, calendar, tickets, events, buddypress, event management, google maps, maps, locations, registration
|
5 |
Text Domain: events-manager
|
6 |
-
Requires at least:
|
7 |
Tested up to: 5.4
|
8 |
-
Stable tag: 5.9.
|
9 |
Requires PHP: 5.3
|
10 |
|
11 |
Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
|
@@ -27,6 +27,10 @@ Version 5 now makes events and locations WordPress Custom Post Types, allowing f
|
|
27 |
* Bookings Management (including approval/rejections, export CVS, and more!)
|
28 |
* Multiple Tickets
|
29 |
* MultiSite Support
|
|
|
|
|
|
|
|
|
30 |
* BuddyPress Support
|
31 |
* Submit Events
|
32 |
* Group Events
|
@@ -62,7 +66,7 @@ We provide the tools to [help you be GDPR compliant](http://wp-events-plugin.com
|
|
62 |
= Go Pro =
|
63 |
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:
|
64 |
|
65 |
-
* PayPal, Authorize.net and Offline Payments
|
66 |
* Custom booking forms
|
67 |
* Individual Attendee custom forms
|
68 |
* Coupon Codes
|
@@ -111,6 +115,17 @@ See our [FAQ](http://wp-events-plugin.com/documentation/faq/) page, which is upd
|
|
111 |
6. Manage attendees with various booking reports
|
112 |
|
113 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
= 5.9.7.3 =
|
115 |
* minor JS conflict fix for those overriding the tickets admin template (or those incorrectly overriding ALL EM templates) in their theme with older HTML structure
|
116 |
|
1 |
=== Events Manager ===
|
2 |
Contributors: netweblogic, nutsmuggler
|
3 |
Donate link: http://wp-events-plugin.com
|
4 |
+
Tags: bookings, calendar, tickets, events, buddypress, event management, google maps, maps, locations, registration, zoom
|
5 |
Text Domain: events-manager
|
6 |
+
Requires at least: 5.2
|
7 |
Tested up to: 5.4
|
8 |
+
Stable tag: 5.9.8
|
9 |
Requires PHP: 5.3
|
10 |
|
11 |
Fully featured event registration management including recurring events, locations management, calendar, Google map integration, booking management
|
27 |
* Bookings Management (including approval/rejections, export CVS, and more!)
|
28 |
* Multiple Tickets
|
29 |
* MultiSite Support
|
30 |
+
* Multiple Location Types
|
31 |
+
* Physical Locations
|
32 |
+
* Online Events (URLs)
|
33 |
+
* [Zoom Webinars/Meetings Integration](https://wordpress.org/plugins/events-manager-zoom/)
|
34 |
* BuddyPress Support
|
35 |
* Submit Events
|
36 |
* Group Events
|
66 |
= Go Pro =
|
67 |
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:
|
68 |
|
69 |
+
* PayPal, Stripe, Authorize.net and Offline Payments
|
70 |
* Custom booking forms
|
71 |
* Individual Attendee custom forms
|
72 |
* Coupon Codes
|
115 |
6. Manage attendees with various booking reports
|
116 |
|
117 |
== Changelog ==
|
118 |
+
= 5.9.8 =
|
119 |
+
* added Location Types including URL and (via external free add-on) Zoom support!
|
120 |
+
* added native OAuth support for third party integrations (e.g. Zoom)
|
121 |
+
* added $EM_Event object to booking form template actions
|
122 |
+
* changed $EM_Booking->booking_status to protected so that status returns 1 even if approvals are disabled
|
123 |
+
* fixed XSS vulnerability (kudos to Jakob Wierzba)
|
124 |
+
* fixed potential SQL injection vulnerability (kudos to Antony Garand from Godaddy)
|
125 |
+
* fixed fatal errors in BuddyPress if notifications are disabled
|
126 |
+
* fixed minor PHP warning
|
127 |
+
* fixed Yoast SEO 14.0 conflict
|
128 |
+
|
129 |
= 5.9.7.3 =
|
130 |
* minor JS conflict fix for those overriding the tickets admin template (or those incorrectly overriding ALL EM templates) in their theme with older HTML structure
|
131 |
|
templates/forms/event/event-locations/url.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
global $EM_Event;
|
3 |
+
?>
|
4 |
+
<div class="em-input-field em-input-field-text em-location-data-url">
|
5 |
+
<label for="event_location_url"><?php esc_html_e( 'URL', 'events-manager')?></label>
|
6 |
+
<input id="event_location_url" type="text" name="event_location_url" value="<?php echo esc_attr($EM_Event->get_event_location()->url); ; ?>" />
|
7 |
+
</div>
|
8 |
+
<div class="em-input-field em-input-field-text em-location-data-url-text">
|
9 |
+
<label for="event_location_url_text"><?php esc_html_e( 'Link Text', 'events-manager')?></label>
|
10 |
+
<input id="event_location_url_text" type="text" name="event_location_url_text" value="<?php echo esc_attr($EM_Event->get_event_location()->text); ; ?>" />
|
11 |
+
</div>
|
templates/forms/event/location.php
CHANGED
@@ -1,66 +1,100 @@
|
|
1 |
<?php
|
2 |
global $EM_Event;
|
3 |
$required = apply_filters('em_required_html','<i>*</i>');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
?>
|
5 |
-
<?php if(
|
6 |
-
<
|
7 |
-
<
|
8 |
-
|
9 |
-
<?php
|
10 |
-
|
|
|
|
|
|
|
11 |
<script type="text/javascript">
|
12 |
jQuery(document).ready(function($){
|
13 |
-
$('
|
14 |
-
|
15 |
-
|
|
|
16 |
}else{
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
19 |
}).trigger('change');
|
20 |
});
|
21 |
</script>
|
22 |
</div>
|
23 |
-
<?php
|
24 |
-
<div id="em-location-data" class="em-location-data">
|
25 |
<div id="location_coordinates" style='display: none;'>
|
26 |
<input id='location-latitude' name='location_latitude' type='text' value='<?php echo esc_attr($EM_Event->get_location()->location_latitude); ?>' size='15' />
|
27 |
<input id='location-longitude' name='location_longitude' type='text' value='<?php echo esc_attr($EM_Event->get_location()->location_longitude); ?>' size='15' />
|
28 |
</div>
|
29 |
-
<?php if( get_option('dbem_use_select_for_locations') || !$EM_Event->can_manage('edit_locations','edit_others_locations') ) : ?>
|
30 |
<table class="em-location-data">
|
31 |
-
|
32 |
-
|
33 |
-
<
|
34 |
-
<
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
if( empty($found_location) && !empty($EM_Event->location_id) ){
|
49 |
-
$EM_Location = $EM_Event->get_location();
|
50 |
-
if( $EM_Location->post_id ){
|
51 |
-
?>
|
52 |
-
<option value="<?php echo esc_attr($EM_Location->location_id) ?>" title="<?php echo esc_attr("{$EM_Location->location_latitude},{$EM_Location->location_longitude}"); ?>" selected="selected"><?php echo esc_html($EM_Location->location_name); ?></option>
|
53 |
-
<?php
|
54 |
}
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
global $EM_Location;
|
65 |
if( $EM_Event->location_id !== 0 ){
|
66 |
$EM_Location = $EM_Event->get_location();
|
@@ -69,60 +103,79 @@ $required = apply_filters('em_required_html','<i>*</i>');
|
|
69 |
}else{
|
70 |
$EM_Location = new EM_Location();
|
71 |
}
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
</table>
|
|
|
|
|
125 |
<?php endif; ?>
|
126 |
-
<?php if ( get_option( 'dbem_gmap_is_active' ) ) em_locate_template('forms/map-container.php',true); ?>
|
127 |
<br style="clear:both;" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
</div>
|
1 |
<?php
|
2 |
global $EM_Event;
|
3 |
$required = apply_filters('em_required_html','<i>*</i>');
|
4 |
+
|
5 |
+
//determine location types (if neexed)
|
6 |
+
$location_types = array();
|
7 |
+
if( !get_option('dbem_require_location') && !get_option('dbem_use_select_for_locations') ){
|
8 |
+
$location_types[0] = array(
|
9 |
+
'selected' => $EM_Event->location_id === '0' || $EM_Event->location_id === 0,
|
10 |
+
'description' => esc_html__('No Location','events-manager'),
|
11 |
+
);
|
12 |
+
}
|
13 |
+
if( EM_Locations::is_enabled() ){
|
14 |
+
$location_types['location'] = array(
|
15 |
+
'selected' => !empty($EM_Event->location_id),
|
16 |
+
'display-class' => 'em-location-type-place',
|
17 |
+
'description' => esc_html__('Physical Location','events-manager'),
|
18 |
+
);
|
19 |
+
}
|
20 |
+
foreach( EM_Event_Locations\Event_Locations::get_types() as $event_location_type => $EM_Event_Location_Class ){ /* @var EM_Event_Locations\Event_Location $EM_Event_Location_Class */
|
21 |
+
if( $EM_Event_Location_Class::is_enabled() ){
|
22 |
+
$location_types[$EM_Event_Location_Class::$type] = array(
|
23 |
+
'display-class' => 'em-event-location-type-'. $EM_Event_Location_Class::$type,
|
24 |
+
'selected' => $EM_Event_Location_Class::$type == $EM_Event->event_location_type,
|
25 |
+
'description' => $EM_Event_Location_Class::get_label(),
|
26 |
+
);
|
27 |
+
}
|
28 |
+
}
|
29 |
?>
|
30 |
+
<div class="em-input-field em-input-field-select em-location-types <?php if( count($location_types) == 1 ) echo 'em-location-types-single'; ?>">
|
31 |
+
<label><?php esc_html_e ( 'Location Type', 'events-manager')?></label>
|
32 |
+
<select name="location_type" class="em-location-types-select">
|
33 |
+
<?php foreach( $location_types as $location_type => $location_type_option ): ?>
|
34 |
+
<option value="<?php echo esc_attr($location_type); ?>" <?php if( !empty($location_type_option['selected']) ) echo 'selected="selected"'; ?> data-display-class="<?php if( !empty($location_type_option['display-class']) ) echo esc_attr($location_type_option['display-class']); ?>">
|
35 |
+
<?php echo esc_html($location_type_option['description']); ?>
|
36 |
+
</option>
|
37 |
+
<?php endforeach; ?>
|
38 |
+
</select>
|
39 |
<script type="text/javascript">
|
40 |
jQuery(document).ready(function($){
|
41 |
+
$('.em-location-types .em-location-types-select').change(function(){
|
42 |
+
let el = $(this);
|
43 |
+
if( el.val() == 0 ){
|
44 |
+
$('.em-location-type').hide();
|
45 |
}else{
|
46 |
+
let location_type = el.find('option:selected').data('display-class');
|
47 |
+
$('.em-location-type').hide();
|
48 |
+
$('.em-location-type.'+location_type).show();
|
49 |
+
if( location_type != 'em-location-type-place' ){
|
50 |
+
jQuery('#em-location-reset a').trigger('click');
|
51 |
+
}
|
52 |
}
|
53 |
}).trigger('change');
|
54 |
});
|
55 |
</script>
|
56 |
</div>
|
57 |
+
<?php if( EM_Locations::is_enabled() ): ?>
|
58 |
+
<div id="em-location-data" class="em-location-data em-location-type em-location-type-place">
|
59 |
<div id="location_coordinates" style='display: none;'>
|
60 |
<input id='location-latitude' name='location_latitude' type='text' value='<?php echo esc_attr($EM_Event->get_location()->location_latitude); ?>' size='15' />
|
61 |
<input id='location-longitude' name='location_longitude' type='text' value='<?php echo esc_attr($EM_Event->get_location()->location_longitude); ?>' size='15' />
|
62 |
</div>
|
|
|
63 |
<table class="em-location-data">
|
64 |
+
<?php if( get_option('dbem_use_select_for_locations') || !$EM_Event->can_manage('edit_locations','edit_others_locations') ) : ?>
|
65 |
+
<tbody class="em-location-data">
|
66 |
+
<tr class="em-location-data-select">
|
67 |
+
<th><?php esc_html_e('Location:','events-manager') ?> </th>
|
68 |
+
<td>
|
69 |
+
<select name="location_id" id='location-select-id' size="1">
|
70 |
+
<?php
|
71 |
+
$ddm_args = array('private'=>$EM_Event->can_manage('read_private_locations'));
|
72 |
+
$ddm_args['owner'] = (is_user_logged_in() && !current_user_can('read_others_locations')) ? get_current_user_id() : false;
|
73 |
+
$locations = EM_Locations::get($ddm_args);
|
74 |
+
$selected_location = !empty($EM_Event->location_id) || !empty($EM_Event->event_id) ? $EM_Event->location_id:get_option('dbem_default_location');
|
75 |
+
foreach($locations as $EM_Location) {
|
76 |
+
$selected = ($selected_location == $EM_Location->location_id) ? "selected='selected' " : '';
|
77 |
+
if( $selected ) $found_location = true;
|
78 |
+
?>
|
79 |
+
<option value="<?php echo esc_attr($EM_Location->location_id) ?>" title="<?php echo esc_attr("{$EM_Location->location_latitude},{$EM_Location->location_longitude}"); ?>" <?php echo $selected ?>><?php echo esc_html($EM_Location->location_name); ?></option>
|
80 |
+
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
+
if( empty($found_location) && !empty($EM_Event->location_id) ){
|
83 |
+
$EM_Location = $EM_Event->get_location();
|
84 |
+
if( $EM_Location->post_id ){
|
85 |
+
?>
|
86 |
+
<option value="<?php echo esc_attr($EM_Location->location_id) ?>" title="<?php echo esc_attr("{$EM_Location->location_latitude},{$EM_Location->location_longitude}"); ?>" selected="selected"><?php echo esc_html($EM_Location->location_name); ?></option>
|
87 |
+
<?php
|
88 |
+
}
|
89 |
+
}
|
90 |
+
?>
|
91 |
+
</select>
|
92 |
+
</td>
|
93 |
+
</tr>
|
94 |
+
</tbody>
|
95 |
+
<?php else : ?>
|
96 |
+
<tbody class="em-location-data">
|
97 |
+
<?php
|
98 |
global $EM_Location;
|
99 |
if( $EM_Event->location_id !== 0 ){
|
100 |
$EM_Location = $EM_Event->get_location();
|
103 |
}else{
|
104 |
$EM_Location = new EM_Location();
|
105 |
}
|
106 |
+
?>
|
107 |
+
<tr class="em-location-data-name">
|
108 |
+
<th><?php _e ( 'Location Name:', 'events-manager')?></th>
|
109 |
+
<td>
|
110 |
+
<input id='location-id' name='location_id' type='hidden' value='<?php echo esc_attr($EM_Location->location_id); ?>' size='15' />
|
111 |
+
<input id="location-name" type="text" name="location_name" value="<?php echo esc_attr($EM_Location->location_name, ENT_QUOTES); ?>" /><?php echo $required; ?>
|
112 |
+
<br />
|
113 |
+
<em id="em-location-search-tip"><?php esc_html_e( 'Create a location or start typing to search a previously created location.', 'events-manager')?></em>
|
114 |
+
<em id="em-location-reset" style="display:none;"><?php esc_html_e('You cannot edit saved locations here.', 'events-manager'); ?> <a href="#"><?php esc_html_e('Reset this form to create a location or search again.', 'events-manager')?></a></em>
|
115 |
+
</td>
|
116 |
+
</tr>
|
117 |
+
<tr class="em-location-data-address">
|
118 |
+
<th><?php _e ( 'Address:', 'events-manager')?> </th>
|
119 |
+
<td>
|
120 |
+
<input id="location-address" type="text" name="location_address" value="<?php echo esc_attr($EM_Location->location_address); ; ?>" /><?php echo $required; ?>
|
121 |
+
</td>
|
122 |
+
</tr>
|
123 |
+
<tr class="em-location-data-town">
|
124 |
+
<th><?php _e ( 'City/Town:', 'events-manager')?> </th>
|
125 |
+
<td>
|
126 |
+
<input id="location-town" type="text" name="location_town" value="<?php echo esc_attr($EM_Location->location_town); ?>" /><?php echo $required; ?>
|
127 |
+
</td>
|
128 |
+
</tr>
|
129 |
+
<tr class="em-location-data-state">
|
130 |
+
<th><?php _e ( 'State/County:', 'events-manager')?> </th>
|
131 |
+
<td>
|
132 |
+
<input id="location-state" type="text" name="location_state" value="<?php echo esc_attr($EM_Location->location_state); ?>" />
|
133 |
+
</td>
|
134 |
+
</tr>
|
135 |
+
<tr class="em-location-data-postcode">
|
136 |
+
<th><?php _e ( 'Postcode:', 'events-manager')?> </th>
|
137 |
+
<td>
|
138 |
+
<input id="location-postcode" type="text" name="location_postcode" value="<?php echo esc_attr($EM_Location->location_postcode); ?>" />
|
139 |
+
</td>
|
140 |
+
</tr>
|
141 |
+
<tr class="em-location-data-region">
|
142 |
+
<th><?php _e ( 'Region:', 'events-manager')?> </th>
|
143 |
+
<td>
|
144 |
+
<input id="location-region" type="text" name="location_region" value="<?php echo esc_attr($EM_Location->location_region); ?>" />
|
145 |
+
</td>
|
146 |
+
</tr>
|
147 |
+
<tr class="em-location-data-country">
|
148 |
+
<th><?php _e ( 'Country:', 'events-manager')?> </th>
|
149 |
+
<td>
|
150 |
+
<select id="location-country" name="location_country">
|
151 |
+
<option value="0" <?php echo ( $EM_Location->location_country == '' && $EM_Location->location_id == '' && get_option('dbem_location_default_country') == '' ) ? 'selected="selected"':''; ?>><?php _e('none selected','events-manager'); ?></option>
|
152 |
+
<?php foreach(em_get_countries() as $country_key => $country_name): ?>
|
153 |
+
<option value="<?php echo esc_attr($country_key); ?>" <?php echo ( $EM_Location->location_country == $country_key || ($EM_Location->location_country == '' && $EM_Location->location_id == '' && get_option('dbem_location_default_country')==$country_key) ) ? 'selected="selected"':''; ?>><?php echo esc_html($country_name); ?></option>
|
154 |
+
<?php endforeach; ?>
|
155 |
+
</select><?php echo $required; ?>
|
156 |
+
</td>
|
157 |
+
</tr>
|
158 |
+
<tr class="em-location-data-url">
|
159 |
+
<th><?php esc_html_e( 'URL:', 'events-manager')?> </th>
|
160 |
+
<td>
|
161 |
+
<input id="location-url" type="text" name="location_url" value="<?php echo esc_attr($EM_Location->location_url); ; ?>" />
|
162 |
+
</td>
|
163 |
+
</tr>
|
164 |
+
</tbody>
|
165 |
</table>
|
166 |
+
<?php if ( get_option( 'dbem_gmap_is_active' ) ):?>
|
167 |
+
<?php em_locate_template('forms/map-container.php',true); ?>
|
168 |
<?php endif; ?>
|
|
|
169 |
<br style="clear:both;" />
|
170 |
+
<?php endif; ?>
|
171 |
+
</div>
|
172 |
+
<?php endif; ?>
|
173 |
+
<div class="em-event-location-data">
|
174 |
+
<?php foreach( EM_Event_Locations\Event_Locations::get_types() as $event_location_type => $EM_Event_Location_Class ): /* @var EM_Event_Locations\Event_Location $EM_Event_Location_Class */ ?>
|
175 |
+
<?php if( $EM_Event_Location_Class::is_enabled() ): ?>
|
176 |
+
<div class="em-location-type em-event-location-type-<?php echo esc_attr($event_location_type); ?>">
|
177 |
+
<?php $EM_Event_Location_Class::load_admin_template(); ?>
|
178 |
+
</div>
|
179 |
+
<?php endif; ?>
|
180 |
+
<?php endforeach; ?>
|
181 |
</div>
|
templates/placeholders/bookingform.php
CHANGED
@@ -29,7 +29,7 @@ if( !$is_open && !is_user_logged_in() && $EM_Event->get_bookings()->is_open(true
|
|
29 |
<?php
|
30 |
// We are firstly checking if the user has already booked a ticket at this event, if so offer a link to view their bookings.
|
31 |
$EM_Booking = $EM_Event->get_bookings()->has_booking();
|
32 |
-
do_action('em_booking_form_top');
|
33 |
?>
|
34 |
<?php if( is_object($EM_Booking) && !get_option('dbem_bookings_double') ): //Double bookings not allowed ?>
|
35 |
<p>
|
@@ -47,7 +47,7 @@ if( !$is_open && !is_user_logged_in() && $EM_Event->get_bookings()->is_open(true
|
|
47 |
<?php if( $tickets_count > 0) : ?>
|
48 |
<?php //Tickets exist, so we show a booking form. ?>
|
49 |
<form class="em-booking-form" name='booking-form' method='post' action='<?php echo apply_filters('em_booking_form_action_url',''); ?>#em-booking'>
|
50 |
-
<?php do_action('em_booking_form_header'); ?>
|
51 |
<input type='hidden' name='action' value='booking_add'/>
|
52 |
<input type='hidden' name='event_id' value='<?php echo $EM_Event->get_bookings()->event_id; ?>'/>
|
53 |
<input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_add'); ?>'/>
|
@@ -107,5 +107,7 @@ if( !$is_open && !is_user_logged_in() && $EM_Event->get_bookings()->is_open(true
|
|
107 |
<br class="clear" style="clear:left;" />
|
108 |
<?php endif; ?>
|
109 |
<?php endif; ?>
|
110 |
-
<?php
|
|
|
|
|
111 |
</div>
|
29 |
<?php
|
30 |
// We are firstly checking if the user has already booked a ticket at this event, if so offer a link to view their bookings.
|
31 |
$EM_Booking = $EM_Event->get_bookings()->has_booking();
|
32 |
+
do_action('em_booking_form_top', $EM_Event);
|
33 |
?>
|
34 |
<?php if( is_object($EM_Booking) && !get_option('dbem_bookings_double') ): //Double bookings not allowed ?>
|
35 |
<p>
|
47 |
<?php if( $tickets_count > 0) : ?>
|
48 |
<?php //Tickets exist, so we show a booking form. ?>
|
49 |
<form class="em-booking-form" name='booking-form' method='post' action='<?php echo apply_filters('em_booking_form_action_url',''); ?>#em-booking'>
|
50 |
+
<?php do_action('em_booking_form_header', $EM_Event); ?>
|
51 |
<input type='hidden' name='action' value='booking_add'/>
|
52 |
<input type='hidden' name='event_id' value='<?php echo $EM_Event->get_bookings()->event_id; ?>'/>
|
53 |
<input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_add'); ?>'/>
|
107 |
<br class="clear" style="clear:left;" />
|
108 |
<?php endif; ?>
|
109 |
<?php endif; ?>
|
110 |
+
<?php
|
111 |
+
do_action('em_booking_form_bottom', $EM_Event);
|
112 |
+
?>
|
113 |
</div>
|
templates/tables/events.php
CHANGED
@@ -118,9 +118,17 @@
|
|
118 |
</a>
|
119 |
</td>
|
120 |
<?php if( get_option('dbem_locations_enabled') ): ?>
|
121 |
-
|
122 |
-
|
123 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
<?php endif; ?>
|
125 |
<td>
|
126 |
<?php echo $EM_Event->output_dates(); ?>
|
118 |
</a>
|
119 |
</td>
|
120 |
<?php if( get_option('dbem_locations_enabled') ): ?>
|
121 |
+
<td>
|
122 |
+
<?php
|
123 |
+
if( $EM_Event->has_location() ){
|
124 |
+
echo "<b>" . esc_html($EM_Event->get_location()->location_name) . "</b><br/>" . esc_html($EM_Event->get_location()->location_address) . " - " . esc_html($EM_Event->get_location()->location_town);
|
125 |
+
}elseif( $EM_Event->has_event_location() ) {
|
126 |
+
echo $EM_Event->get_event_location()->get_admin_column();
|
127 |
+
}else{
|
128 |
+
echo __('None','events-manager');
|
129 |
+
}
|
130 |
+
?>
|
131 |
+
</td>
|
132 |
<?php endif; ?>
|
133 |
<td>
|
134 |
<?php echo $EM_Event->output_dates(); ?>
|