PluginProbe
Event Post / 6.1.2
Event Post v6.1.2
6.1.2 6.1.1 6.1.0 6.0.1 6.0.0 5.12.0 trunk 3.9 4.0 4.2 4.3 4.4 4.5 5.0 5.1 5.10.0 5.10.1 5.10.2 5.10.3 5.10.4 5.11.0 5.11.1 5.2 5.5 5.6 All 47 releases
← All changes | eventpost.php +1617 -576 5.5 → 6.1.2 View file →
@@ -1,23 +1,23 @@
1 1 <?php
2 -/*
3 - Plugin Name: Event Post
4 - Plugin URI: https://event-post.com?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard
5 - Description: Add calendar and/or geolocation metadata on any posts.
6 - Version: 5.5
7 - Author: N.O.U.S. Open Useful and Simple
8 - Contributors: bastho, sabrinaleroy, unecologeek, agencenous
9 - Author URI: https://apps.avecnous.eu/?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard
10 - License: GPLv2
11 - Text Domain: event-post
12 - Domain Path: /languages/
13 - Tags: Post,posts,event,date,geolocalization,gps,widget,map,openstreetmap,EELV,calendar,agenda,blocks
14 - */
15 -
16 2 /**
3 + * Plugin Name: Event Post
4 + * Plugin URI: https://event-post.com?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard&mtm_source=plugin-uri
5 + * Description: Add calendar and/or geolocation metadata on any posts.
6 + * Version: 6.1.2
7 + * Author: N.O.U.S. Open Useful and Simple
8 + * Contributors: bastho, sabrinaleroy, unecologeek, agencenous
9 + * Author URI: https://apps.avecnous.eu/?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard&mtm_source=author
10 + * License: GPLv2
11 + * Text Domain: event-post
12 + * Domain Path: /languages/
13 + * Tags: Post,posts,event,date,geolocalization,gps,widget,map,openstreetmap,EELV,calendar,agenda,blocks
17 14 *
18 15 * @package event-post
19 16 */
17 +
18 +if ( ! defined( 'ABSPATH' ) ) exit;
19 +
20 20 global $EventPost;
21 21 $EventPost = new EventPost();
22 22
23 23 $EventPost_cache=array();
@@ -25,9 +25,18 @@
25 25 function EventPost(){
26 26 global $EventPost;
27 27 return $EventPost;
28 28 }
29 +function event_post_format_color($color){
30 + return str_replace('#', '', $color);
31 +}
32 +function event_post_get_all_terms($post_id){
33 + $taxonomies= get_taxonomies('','names');
29 34
35 + return wp_get_post_terms($post_id, $taxonomies);
36 +}
37 +
38 +
30 39 /**
31 40 * The main class where everything begins.
32 41 *
33 42 * Add calendar and/or geolocation metadata on posts
@@ -32,45 +41,336 @@
32 41 *
33 42 * Add calendar and/or geolocation metadata on posts
34 43 */
35 44 class EventPost {
36 - const META_START = 'event_begin';
37 - const META_END = 'event_end';
38 - const META_COLOR = 'event_color';
39 - // http://codex.wordpress.org/Geodata
40 - const META_ADD = 'geo_address';
41 - const META_LAT = 'geo_latitude';
42 - const META_LONG = 'geo_longitude';
43 - // https://schema.org/eventStatus
44 - const META_STATUS = 'event_status';
45 - // https://schema.org/location
46 - const META_VIRTUAL_LOCATION = 'event_virtual_location';
47 - // https://pending.schema.org/eventAttendanceMode
48 - const META_ATTENDANCE_MODE = 'event_attendance_mode';
45 + /**
46 + * The current version
47 + *
48 + * Must be kept in sync with the `Version:` plugin header above: `bin/bump`
49 + * only rewrites header-style declarations, not this literal.
50 + *
51 + * @var string
52 + */
53 + public $version = '6.1.2';
49 54
55 + // --------------------------------------------------------------------------------
56 + // Post metas
57 +
58 + /**
59 + * The meta name for event start date
60 + *
61 + * @var string
62 + */
63 + public $META_START = 'event_begin';
64 +
65 + /**
66 + * The meta name for event end date
67 + *
68 + * @var string
69 + */
70 + public $META_END = 'event_end';
71 +
72 + /**
73 + * The meta name for event color
74 + *
75 + * @var string
76 + */
77 + public $META_COLOR = 'event_color';
78 +
79 + /**
80 + * The meta name for event icon
81 + *
82 + * @var string
83 + */
84 + public $META_ICON = 'event_icon';
85 +
86 + // --------------------------------------------------------------------------------
87 + // Post metas related to location
88 +
89 + /**
90 + * The meta name for event address
91 + *
92 + * @var string
93 + */
94 + public $META_ADD = 'geo_address';
95 +
96 + /**
97 + * The meta name for event latitude
98 + *
99 + * @var string
100 + *
101 + * @see http://codex.wordpress.org/Geodata
102 + */
103 + public $META_LAT = 'geo_latitude';
104 +
105 + /**
106 + * The meta name for event longitude
107 + *
108 + * @var string
109 + *
110 + * @see http://codex.wordpress.org/Geodata
111 + */
112 + public $META_LONG = 'geo_longitude';
113 +
114 + /**
115 + * The meta name for event location
116 + *
117 + * @var string
118 + *
119 + * @see https://schema.org/location
120 + */
121 + public $META_VIRTUAL_LOCATION = 'event_virtual_location';
122 +
123 + // --------------------------------------------------------------------------------
124 + // Post metas related to status
125 +
126 + /**
127 + * The meta name for event status
128 + *
129 + * @var string
130 + *
131 + * @see https://schema.org/eventStatus
132 + */
133 + public $META_STATUS = 'event_status';
134 +
135 + /**
136 + * The meta name for event attendance mode
137 + *
138 + * @var string
139 + *
140 + * @see https://schema.org/eventAttendanceMode
141 + */
142 + public $META_ATTENDANCE_MODE = 'event_attendance_mode';
143 +
144 + /**
145 + * The meta name for event organizer
146 + *
147 + * @var string
148 + *
149 + * @see https://schema.org/Organization
150 + */
151 + public $META_ORGANIZATION = 'event_organization';
152 +
153 + /**
154 + * The meta name for event organizer
155 + *
156 + * @var string
157 + * @see https://schema.org/Offer
158 + */
159 + public $META_OFFER = 'event_offer';
160 +
161 + // --------------------------------------------------------------------------------
162 + // Usefull variables
163 +
164 + /**
165 + * ID of the current list
166 + *
167 + * @var int
168 + */
50 169 public $list_id;
170 +
171 + /**
172 + * ID of the current map
173 + *
174 + * @var int
175 + */
176 + public $map_id=0;
177 +
178 + /**
179 + * Schema as been outputed or not
180 + *
181 + * @var bool
182 + */
183 + private $is_schema_output=false;
184 +
185 + /**
186 + * Month names
187 + *
188 + * @var array
189 + */
51 190 public $NomDuMois;
191 +
192 + /**
193 + * Week days
194 + *
195 + * @var array
196 + */
52 197 public $Week;
53 - public $settings;
198 +
199 + /**
200 + * Currencies
201 + *
202 + * @var array
203 + */
204 + public $currencies = array();
205 +
206 + /**
207 + * Date format
208 + *
209 + * @var string
210 + */
54 211 public $dateformat;
55 212
213 + /**
214 + * Pagination
215 + *
216 + * @var array
217 + */
56 218 private $pagination;
57 - public $version = '5.3';
58 - public $plugin_path ;
219 +
220 + /**
221 + * Plugin path
222 + *
223 + * @var string
224 + */
225 + public $plugin_path;
226 +
227 + /**
228 + * Script suffix
229 + *
230 + * @var string
231 + */
59 232 private $script_sufix;
60 233
234 + /**
235 + * Settings values
236 + *
237 + * @var array
238 + */
239 + public $settings;
240 +
241 + // --------------------------------------------------------------------------------
242 + // Option values
243 +
244 + /**
245 + * Map interractions (from openlayers)
246 + *
247 + * @var array
248 + */
61 249 public $map_interactions;
250 +
251 + /**
252 + * Fields supported by quick-edit
253 + *
254 + * @var array
255 + */
62 256 public $quick_edit_fields;
63 257
64 - public $Shortcodes;
258 + /**
259 + * Fields supported by bulk-edit
260 + *
261 + * @var array
262 + */
263 + public $bulk_edit_fields;
65 264
265 + /**
266 + * Supported attendance modes
267 + *
268 + * @var array
269 + */
66 270 public $attendance_modes;
271 +
272 + /**
273 + * Supported statuses
274 + *
275 + * @var array
276 + */
67 277 public $statuses;
68 - private $is_schema_output=false;
69 278
279 + /**
280 + * Default list schema (HTML template)
281 + *
282 + * @var string
283 + */
284 + public $default_list_shema;
285 +
286 + /**
287 + * Default timeline schema (HTML template)
288 + *
289 + * @var string
290 + */
291 + public $default_timeline_shema;
292 +
293 + /**
294 + * Current list schema (HTML template)
295 + *
296 + * @var string
297 + */
298 + public $list_shema;
299 +
300 + /**
301 + * Current timeline schema (HTML template)
302 + *
303 + * @var string
304 + */
305 + public $timeline_shema;
306 +
307 + // Map variables
308 + /**
309 + * Map tiles
310 + *
311 + * @var array
312 + */
313 + public $maps;
314 +
315 + /**
316 + * Dirpath for map tiles
317 + *
318 + * @var string
319 + */
320 + public $markpath;
321 +
322 + /**
323 + * Base URL for map tiles
324 + *
325 + * @var string
326 + */
327 + public $markurl;
328 +
329 + // --------------------------------------------------------------------------------
330 + // Classes
331 +
332 + /**
333 + * Taxonomies object
334 + *
335 + * @var \EventPost\Taxonomies
336 + */
337 + public $Taxonomies;
338 +
339 + /**
340 + * Icons object
341 + *
342 + * @var \EventPost\Icons
343 + */
344 + public $DashIcons;
345 +
346 + /**
347 + * Settings object
348 + *
349 + * @var \EventPost\Settings
350 + */
351 + public $Settings;
352 +
353 + /**
354 + * Shortcodes object
355 + *
356 + * @var \EventPost\Shortcodes
357 + */
358 + public $Shortcodes;
359 +
360 + /**
361 + * Allowed tags in main outputs
362 + *
363 + * @var array
364 + */
365 + public $kses_tags;
366 +
367 +
70 368 public function __construct() {
71 369 add_action('init', array(&$this,'init'), 1);
72 - add_action('widgets_init', array(&$this,'widgets_init'), 1);
370 + add_action('init', array(&$this,'widgets_init'), 10);
371 + add_action('init', array(&$this, 'register_widgets'), 30, 1);
372 +
73 373 add_action('save_post', array(&$this, 'save_postdata'));
74 374 add_filter('dashboard_glance_items', array(&$this, 'dashboard_right_now'));
75 375
76 376 // Scripts
@@ -76,8 +376,10 @@
76 376 // Scripts
77 377 add_action( 'admin_init', array(&$this, 'editor_styles'));
78 378 add_action('admin_enqueue_scripts', array(&$this, 'admin_head'));
79 379 add_action('admin_print_scripts', array(&$this, 'admin_scripts'));
380 + add_action('admin_print_scripts', array(&$this, 'load_scripts'), 1);
381 + add_action('wp_enqueue_scripts', array(&$this, 'load_scripts'), 1);
80 382 add_action('wp_enqueue_scripts', array(&$this, 'load_styles'));
81 383
82 384 // Single
83 385 add_filter('the_content', array(&$this, 'display_single'), 9999);
@@ -89,8 +391,11 @@
89 391 // Ajax
90 392 add_action('wp_ajax_EventPostGetLatLong', array(&$this, 'GetLatLong'));
91 393 add_action('wp_ajax_EventPostHumanDate', array(&$this, 'HumanDate'));
92 394 add_action('wp_ajax_EventPostList', array(&$this, 'ajaxlist'));
395 + add_action('wp_ajax_EventPostTimeline', array(&$this, 'ajaxTimeline'));
396 + add_action('wp_ajax_EventPostNextPage', array(&$this, 'ajaxGetNextPage'));
397 + add_action('wp_ajax_nopriv_EventPostNextPage', array(&$this, 'ajaxGetNextPage'));
93 398 add_action('wp_ajax_EventPostMap', array(&$this, 'ajaxmap'));
94 399 add_action('wp_ajax_EventPostCalendar', array(&$this, 'ajaxcal'));
95 400 add_action('wp_ajax_nopriv_EventPostCalendar', array(&$this, 'ajaxcal'));
96 401 add_action('wp_ajax_EventPostCalendarDate', array(&$this, 'ajaxdate'));
@@ -102,35 +407,37 @@
102 407 add_action('wp_ajax_nopriv_EventPostExport', array(&$this, 'export'));
103 408 add_action('wp_ajax_EventPostFeed', array(&$this, 'feed'));
104 409 add_action('wp_ajax_nopriv_EventPostFeed', array(&$this, 'feed'));
105 410
106 - //
411 + // Internal filters
107 412 add_filter('eventpost_list_shema',array(&$this, 'custom_shema'),10,1);
108 413
109 -
110 - add_action('widgets_init', array(&$this, 'register_widgets'),1,1);
111 -
112 414 // Quick edit
113 415 add_action( 'bulk_edit_custom_box', array( &$this, 'bulk_edit' ), 10, 2 );
114 416 add_action( 'quick_edit_custom_box', array( &$this, 'quick_edit' ), 10, 2 );
115 417 add_action( 'admin_print_scripts-edit.php', array(&$this, 'scripts_edit') );
116 418 add_action( 'wp_ajax_inline-save', array(&$this, 'inline_save'), 1 );
117 - add_action( 'wp_ajax_eventpost_save_bulk', array(&$this, 'save_bulkdatas') );
419 + add_action( 'bulk_edit_posts', array(&$this, 'save_bulkdatas'), 10, 2 );
118 420 add_filter( 'eventpost_inline_field', array(&$this, 'inline_field_color'), 10, 3);
421 + add_filter( 'eventpost_inline_field', array(&$this, 'inline_field_icon'), 10, 3);
119 422
120 423 $inc_path = plugin_dir_path(__FILE__).'inc/';
121 424 $this->plugin_path = plugin_dir_path(__FILE__);
122 - include_once ($inc_path . 'settings.php');
425 + include_once ($inc_path . 'class-settings.php');
123 426 include_once ($inc_path . 'wrappers.php');
124 - include_once ($inc_path . 'widget.php');
125 - include_once ($inc_path . 'widget.cal.php');
126 - include_once ($inc_path . 'widget.map.php');
127 - include_once ($inc_path . 'multisite.php');
128 - include_once ($inc_path . 'shortcodes.php');
427 + include_once ($inc_path . 'deprecated/widget.php');
428 + include_once ($inc_path . 'deprecated/widget.cal.php');
429 + include_once ($inc_path . 'deprecated/widget.map.php');
430 + include_once ($inc_path . 'class-multisite.php');
431 + include_once ($inc_path . 'class-shortcodes.php');
129 432 include_once ($inc_path . 'openweathermap.php');
130 - include_once ($inc_path . 'children.php');
433 + include_once ($inc_path . 'class-children.php');
434 + include_once ($inc_path . 'class-icons.php');
435 + include_once ($inc_path . 'class-taxonomies.php');
131 436
132 - $this->Settings = new EventPost\Settings;
437 + $this->DashIcons = new EventPost\Icons();
438 + $this->Settings = new EventPost\Settings($this->DashIcons);
439 + $this->Taxonomies = new EventPost\Taxonomies($this->DashIcons);
133 440 }
134 441
135 442 /**
136 443 * PHP4 constructor
@@ -139,33 +446,15 @@
139 446 $this->__construct();
140 447 }
141 448
142 449 public function init(){
143 - add_rewrite_rule('event-feed/?', admin_url('admin-ajax.php?action=EventPostFeed'), 'top');
144 - add_rewrite_rule('eventpost/([0-9]*)\.(ics|vcs)?', plugins_url('export/ics.php', __FILE__), 'top');
145 - }
146 -
147 - /**
148 - * Init all variables when WP is ready
149 - *
150 - * @action evenpost_init
151 - * @filter eventpost_default_list_shema
152 - * @filter eventpost_list_shema
153 - */
154 - public function widgets_init(){
155 - $this->META_START = 'event_begin';
156 - $this->META_END = 'event_end';
157 - $this->META_COLOR = 'event_color';
158 - // http://codex.wordpress.org/Geodata
159 - $this->META_ADD = 'geo_address';
160 - $this->META_LAT = 'geo_latitude';
161 - $this->META_LONG = 'geo_longitude';
162 - // https://schema.org/eventStatus
163 - $this->META_STATUS = 'event_status';
164 - // https://schema.org/location
165 - $this->META_VIRTUAL_LOCATION = 'event_virtual_location';
166 - // https://pending.schema.org/eventAttendanceMode
167 - $this->META_ATTENDANCE_MODE = 'event_attendance_mode';
450 + $admin_url = admin_url('admin-ajax.php?action=EventPostFeed');
451 + $admin_url = str_replace(site_url(), '', $admin_url);
452 + $plugins_url = plugins_url('export/ics.php', __FILE__);
453 + $plugins_url = str_replace(site_url(), '', $plugins_url);
454 + add_rewrite_rule('event-feed/?', $admin_url , 'top');
455 + add_rewrite_rule('eventpost/([0-9]*)\.(ics|vcs)?',$plugins_url, 'top');
456 +
168 457 $this->list_id = 0;
169 458 $this->NomDuMois = array('', __('Jan', 'event-post'), __('Feb', 'event-post'), __('Mar', 'event-post'), __('Apr', 'event-post'), __('May', 'event-post'), __('Jun', 'event-post'), __('Jul', 'event-post'), __('Aug', 'event-post'), __('Sept', 'event-post'), __('Oct', 'event-post'), __('Nov', 'event-post'), __('Dec', 'event-post'));
170 459 $this->Week = array(__('Sunday', 'event-post'), __('Monday', 'event-post'), __('Tuesday', 'event-post'), __('Wednesday', 'event-post'), __('Thursday', 'event-post'), __('Friday', 'event-post'), __('Saturday', 'event-post'));
171 460 $this->attendance_modes = array(
@@ -173,29 +462,21 @@
173 462 'MixedEventAttendanceMode' => _x('Mixed', 'Attendance Mode', 'event-post'),
174 463 'OnlineEventAttendanceMode' => _x('Online', 'Attendance Mode', 'event-post'),
175 464 );
176 465 $this->statuses = array(
177 - 'EventScheduled' =>_x('Scheduled', 'Event Status', 'event-post'),
178 - 'EventCancelled'=>_x('Cancelled', 'Event Status', 'event-post'),
179 - 'EventMovedOnline'=>_x('Moved Online', 'Event Status', 'event-post'),
180 - 'EventPostponed'=>_x('Postoned', 'Event Status', 'event-post'),
181 - 'EventRescheduled'=>_x('Rescheduled', 'Event Status', 'event-post'),
466 + 'EventScheduled' => _x('Scheduled', 'Event Status', 'event-post'),
467 + 'EventCancelled' => _x('Cancelled', 'Event Status', 'event-post'),
468 + 'EventMovedOnline' => _x('Moved Online', 'Event Status', 'event-post'),
469 + 'EventPostponed' => _x('Postoned', 'Event Status', 'event-post'),
470 + 'EventRescheduled' => _x('Rescheduled', 'Event Status', 'event-post'),
471 + 'EventCompleted' => _x('Completed', 'Event Status', 'event-post'),
182 472 );
183 -
473 +
184 474 $this->maps = $this->get_maps();
185 475 $this->settings = $this->get_settings();
186 -
476 +
187 477 do_action('evenpost_init', $this);
188 478
189 - $this->Shortcodes = new EventPost_Shortcodes();
190 -
191 - if(function_exists('register_block_type')){
192 - $block_path = plugin_dir_path(__FILE__).'inc/blocks/';
193 - include_once ($block_path . 'eventslist.php');
194 - include_once ($block_path . 'eventsmap.php');
195 - include_once ($block_path . 'eventscalendar.php');
196 - }
197 -
198 479 // Edit
199 480 add_action('add_meta_boxes', array(&$this, 'add_custom_box'));
200 481 foreach($this->settings['posttypes'] as $posttype){
201 482 add_filter('manage_'.$posttype.'_posts_columns', array(&$this, 'columns_head'), 2);
@@ -200,39 +481,66 @@
200 481 foreach($this->settings['posttypes'] as $posttype){
201 482 add_filter('manage_'.$posttype.'_posts_columns', array(&$this, 'columns_head'), 2);
202 483 add_action('manage_'.$posttype.'_posts_custom_column', array(&$this, 'columns_content'), 10, 2);
203 484 }
485 + $this->Taxonomies->add_fields_to_taxonomies($this->settings['posttypes']);
204 486
205 -
487 + $this->markpath = '';
488 + $this->markurl = '';
206 489 if (!empty($this->settings['markpath']) && !empty($this->settings['markurl'])) {
207 490 $this->markpath = ABSPATH.'/'.$this->settings['markpath'];
208 491 $this->markurl = $this->settings['markurl'];
209 492 } else {
210 - $this->markpath = plugin_dir_path(__FILE__) . 'markers/';
211 - $this->markurl = plugins_url('/markers/', __FILE__);
493 + // $this->markpath = plugin_dir_path(__FILE__) . 'markers/';
494 + // $this->markurl = plugins_url('/markers/', __FILE__);
212 495 }
213 496
497 + $this->currencies = include (plugin_dir_path(__FILE__) . 'inc/data/currencies.php');
498 +
214 499 $this->dateformat = str_replace(array('yy', 'mm', 'dd'), array('Y', 'm', 'd'), __('yy-mm-dd', 'event-post'));
215 500
216 501 $this->default_list_shema = apply_filters('eventpost_default_list_shema', array(
502 + 'container' => '<%type% class="event_loop %id% %class%" id="%listid%" style="%style%" %attributes%>'.
503 + '%list%'.
504 + '%pagination%'.
505 + '</%type%><!-- .event_loop -->',
506 + 'item' => '<%child% class="event_item %class%" data-color="%color%" style="%style%">'.
507 + '<a href="%event_link%">'.
508 + '%event_thumbnail%'.
509 + '<h5>%event_title% </h5>'.
510 + '</a>'.
511 + '%event_price%'.
512 + '%event_date%'.
513 + '%event_cat%'.
514 + '%event_location%'.
515 + '%event_excerpt%'.
516 + '</%child%><!-- .event_item -->'
517 + ));
518 + $this->list_shema = apply_filters('eventpost_list_shema',$this->default_list_shema);
519 +
520 + $this->default_timeline_shema = apply_filters('eventpost_default_timeline_shema', array(
217 521 'container' => '
218 522 <%type% class="event_loop %id% %class%" id="%listid%" style="%style%" %attributes%>
219 - %list%
220 - %pagination%
523 + %prev_arrow%
524 + <div class="track">
525 + %list%
526 + </div>
527 + %next_arrow%
221 528 </%type%><!-- .event_loop -->',
222 - 'item' => '
223 - <%child% class="event_item %class%" data-color="%color%">
529 + 'item' => '<%child% class="event_item %class%" data-color="%color%" style="%style%">
530 + <div class="anchor" style="background-color:#%color%"></div>
531 + %event_date%
532 + %event_location%
533 + %event_cat%
534 + %event_excerpt%
224 535 <a href="%event_link%">
225 536 %event_thumbnail%
226 537 <h5>%event_title%</h5>
227 538 </a>
228 - %event_date%
229 - %event_cat%
230 - %event_location%
231 - %event_excerpt%
539 + %event_price%
232 540 </%child%><!-- .event_item -->'
233 541 ));
234 - $this->list_shema = apply_filters('eventpost_list_shema',$this->default_list_shema);
542 + $this->timeline_shema = apply_filters('eventpost_timeline_shema',$this->default_timeline_shema);
235 543
236 544 $this->map_interactions=array(
237 545 'DragRotate'=>__('Drag Rotate', 'event-post'),
238 546 'DoubleClickZoom'=>__('Double Click Zoom', 'event-post'),
@@ -249,8 +557,9 @@
249 557 'event'=>array(
250 558 $this->META_START=>__('Begin:', 'event-post'),
251 559 $this->META_END=>__('End:', 'event-post'),
252 560 $this->META_COLOR=>__('Color:', 'event-post'),
561 + $this->META_ICON=>__('Icon:', 'event-post'),
253 562 ),
254 563 'location'=>array(
255 564 $this->META_ADD=>__('Address:', 'event-post'),
256 565 $this->META_LAT=>__('Latitude:', 'event-post'),
@@ -260,14 +569,47 @@
260 569 );
261 570 $this->bulk_edit_fields = apply_filters('eventpost_bulk_edit_fields', array(
262 571 'event'=>array(
263 572 $this->META_COLOR=>__('Color:', 'event-post'),
573 + $this->META_ICON=>__('Icon:', 'event-post'),
264 574 ),
265 575 )
266 576 );
267 577
578 + $this->kses_tags = apply_filters('eventpost_kses_tags', json_decode(
579 + file_get_contents(plugin_dir_path(__FILE__).'inc/data/kses-tags.json'),
580 + true
581 + ));
582 +
583 +
268 584 }
269 585
586 + /**
587 + * Init all variables when WP is ready
588 + *
589 + * @action evenpost_init
590 + * @filter eventpost_default_list_shema
591 + * @filter eventpost_list_shema
592 + */
593 + public function widgets_init(){
594 + $this->Shortcodes = new EventPost\Shortcodes();
595 +
596 + if(function_exists('register_block_type')){
597 + $block_path = plugin_dir_path(__FILE__).'inc/blocks/';
598 + include_once ($block_path . 'eventslist.php');
599 + include_once ($block_path . 'eventstimeline.php');
600 + include_once ($block_path . 'eventsmap.php');
601 + include_once ($block_path . 'eventscalendar.php');
602 + include_once ($block_path . 'eventdetails.php');
603 + }
604 +
605 +
606 + // WooCommerce
607 + if (class_exists('WooCommerce') && in_array('product', $this->settings['posttypes'])) {
608 + include_once (plugin_dir_path(__FILE__).'inc/woocommerce.php');
609 + }
610 + }
611 +
270 612 public function register_widgets(){
271 613 register_widget('EventPost_List');
272 614 register_widget('EventPost_Map');
273 615 register_widget('EventPost_Cal');
@@ -274,24 +616,32 @@
274 616 }
275 617
276 618 /**
277 619 * Usefull hexadecimal to decimal converter. Returns an array of RGB from a given hexadecimal color.
620 + *
278 621 * @param string $color
622 + *
279 623 * @return array $color($R, $G, $B)
280 624 */
281 625 public function hex2dec($color = '000000') {
282 626 $tbl_color = array();
283 - if (!strstr('#', $color)){
627 + if(!is_string($color) || empty($color)){
628 + $color = '000000';
629 + }
630 + if (substr($color, 0, 1)!='#'){
284 631 $color = '#' . $color;
285 - }
632 + }
286 633 $tbl_color['R'] = hexdec(substr($color, 1, 2));
287 634 $tbl_color['G'] = hexdec(substr($color, 3, 2));
288 635 $tbl_color['B'] = hexdec(substr($color, 5, 2));
289 636 return $tbl_color;
290 637 }
638 +
291 639 /**
292 640 * Fetch all registered image sizes
641 + *
293 642 * @global array $_wp_additional_image_sizes
643 + *
294 644 * @return array
295 645 */
296 646 function get_thumbnail_sizes(){
297 647 global $_wp_additional_image_sizes;
@@ -304,12 +654,13 @@
304 654
305 655 /**
306 656 * Get blog settings, load and saves default settings if needed. Can be filterred using
307 657 *
308 - * `<?php add_filter('eventpost_getsettings', 'some_function'); ?>`
658 + * @example `<?php add_filter('eventpost_getsettings', 'some_function'); ?>`
309 659 *
310 660 * @action eventpost_getsettings_action
311 661 * @filter eventpost_getsettings
662 + *
312 663 * @return array
313 664 */
314 665 public function get_settings() {
315 666 $ep_settings = $this->Settings->get_settings();
@@ -317,9 +668,11 @@
317 668 }
318 669
319 670 /**
320 671 * Checks if HTML schemas are not empty
672 + *
321 673 * @param array $shema
674 + *
322 675 * @return array
323 676 */
324 677 public function custom_shema($shema){
325 678 if(!empty($this->settings['container_shema'])){
@@ -352,8 +705,9 @@
352 705 * ?>
353 706 * ```
354 707 *
355 708 * @filter eventpost_maps
709 + *
356 710 * @return array of map arrays ['name', 'id', 'urls']
357 711 */
358 712 public function get_maps() {
359 713 $maps = array();
@@ -369,9 +723,10 @@
369 723 return $maps;
370 724 }
371 725
372 726 /**
373 - *
727 + * Get colors
728 + *
374 729 * @return array
375 730 */
376 731 public function get_colors() {
377 732 $colors = array();
@@ -386,10 +741,64 @@
386 741 return $colors;
387 742 }
388 743
389 744 /**
390 - *
745 + * Get color of a post
746 + *
747 + * @param int $post_id
748 + * @param bool $default
749 + * @param bool $check_taxo
750 + *
751 + * @return string color
752 + */
753 + public function get_post_color($post_id, $default = false, $check_taxo = false) {
754 + $color = get_post_meta($post_id, $this->META_COLOR,true);
755 + if($color && !empty($color)){
756 + return event_post_format_color($color);
757 + }else{
758 + if($check_taxo){
759 + foreach(event_post_get_all_terms($post_id) as $term){
760 + $taxo_color = $this->Taxonomies->get_taxonomy_color($term->term_id);
761 + if($taxo_color){
762 + return event_post_format_color($taxo_color);
763 + }
764 + }
765 + }
766 + }
767 + return event_post_format_color($default);
768 + }
769 +
770 + /**
771 + * Get icon of a post
772 + *
773 + * @param int $post_id
774 + * @param bool $default
775 + * @param bool $check_taxo
776 + *
777 + * @return string|false icon
778 + */
779 + public function get_post_icon($post_id, $default = false, $check_taxo = false) {
780 + $icon = get_post_meta($post_id, $this->META_ICON,true);
781 + if($icon && !empty($icon)){
782 + return $icon;
783 + }else{
784 + if($check_taxo){
785 + foreach(event_post_get_all_terms($post_id) as $term){
786 + $taxo_icon = $this->Taxonomies->get_taxonomy_icon($term->term_id);
787 + if($taxo_icon){
788 + return event_post_format_color($taxo_icon);
789 + }
790 + }
791 + }
792 + }
793 + return $default;
794 + }
795 +
796 + /**
797 + * Get the URL of a marker
798 + *
391 799 * @param string $color
800 + *
392 801 * @return sring
393 802 */
394 803 public function get_marker($color) {
395 804 if (is_file($this->markpath . $color . '.png')) {
@@ -394,15 +803,15 @@
394 803 public function get_marker($color) {
395 804 if (is_file($this->markpath . $color . '.png')) {
396 805 return $this->markurl . $color . '.png';
397 806 }
398 - return plugins_url('/markers/ffffff.png', __FILE__);
807 + return "";
399 808 }
400 809
401 810 /**
402 811 * Enqueue CSS files
403 812 */
404 - public function load_styles() {
813 + public function load_styles($deps = null) {
405 814 //CSS
406 815 if(!empty($this->settings['customcss'])){
407 816 wp_enqueue_style('event-post-custom', $this->settings['customcss']);
408 817 }
@@ -409,30 +818,28 @@
409 818 elseif(is_file(get_stylesheet_directory().'/event-post.css') || is_file(get_template_directory().'/event-post.css')){
410 819 wp_enqueue_style('event-post-custom', get_theme_file_uri('event-post.css'));
411 820 }
412 821 else{
413 - wp_register_style('event-post', plugins_url('/css/event-post.css', __FILE__), false, filemtime( "{$this->plugin_path}/css/event-post.css" ));
822 + wp_register_style('event-post', plugins_url('/build/front/front.css', __FILE__), $deps, filemtime( "{$this->plugin_path}/build/front/front.css" ));
414 823 wp_enqueue_style('event-post');
415 824 }
416 825
417 826 // Lib scripts
418 - wp_enqueue_style('openlayers', plugins_url('/css/ol.css', __FILE__), false, filemtime( "{$this->plugin_path}/css/ol.css" ));
419 827 wp_enqueue_style('dashicons', includes_url('/css/dashicons.min.css'));
420 828 }
829 +
421 830 /**
422 831 * Enqueue Editor style
423 832 */
424 833 public function editor_styles() {
425 - add_editor_style( plugins_url('/css/event-post.css', __FILE__) );
834 + add_editor_style( plugins_url('/build/front/front.css', __FILE__) );
426 835 }
427 836
428 837 /**
429 838 * Enqueue JS files
430 839 */
431 - public function load_scripts($deps = array('jquery')) {
432 - // JS
433 - wp_enqueue_script('jquery', false, false, false, true);
434 - wp_enqueue_script('event-post', plugins_url('/js/event-post.min.js', __FILE__), $deps, filemtime( "{$this->plugin_path}/js/event-post.min.js" ), true);
840 + public function load_scripts() {
841 + wp_enqueue_script('event-post', plugins_url('/build/front/front.js', __FILE__), array(), filemtime( "{$this->plugin_path}/build/front/front.js" ), true);
435 842 $maps = $this->maps;
436 843 foreach($maps as $m=>$map){
437 844 if(isset($map['api_param']) && $this->settings['tile_api_key']){
438 845 foreach($map['urls'] as $i=>$url){
@@ -439,9 +846,12 @@
439 846 $maps[$m]['urls'][$i] = add_query_arg($map['api_param'], $this->settings['tile_api_key'], $url);
440 847 }
441 848 }
442 849 }
443 - wp_localize_script('event-post', 'eventpost_params', array(
850 + wp_add_inline_script('event-post', 'var EventPost = EventPost || {}; EventPost.front='.wp_json_encode(array(
851 + 'scripts' => array(
852 + 'map' => plugins_url('/build/map/event-map.js', __FILE__)
853 + ),
444 854 'imgpath' => plugins_url('/img/', __FILE__),
445 855 'maptiles' => $maps,
446 856 'defaulttile' => $this->settings['tile'],
447 857 'zoom' => $this->settings['zoom'],
@@ -446,19 +856,18 @@
446 856 'defaulttile' => $this->settings['tile'],
447 857 'zoom' => $this->settings['zoom'],
448 858 'ajaxurl' => admin_url() . 'admin-ajax.php',
449 859 'map_interactions'=>$this->map_interactions,
450 - ));
860 + )), 'before');
451 861 }
452 862 /**
453 863 * Enqueue JS files for maps
454 864 */
455 865 public function load_map_scripts() {
866 + $this->load_styles(array('event-post-map'));
456 867 // JS
457 - wp_enqueue_script('openlayers', plugins_url('/js/ol.js', __FILE__), false, filemtime( "{$this->plugin_path}/js/ol.js" ), true);
458 - $this->load_scripts(array('jquery', 'openlayers'));
459 868 if(is_admin()){
460 - $this->admin_scripts(array('jquery', 'openlayers'));
869 + $this->admin_scripts(array('jquery', 'event-post-map'));
461 870 }
462 871 }
463 872
464 873 /**
@@ -465,14 +874,12 @@
465 874 * Enqueue CSS files in admin
466 875 */
467 876 public function admin_head() {
468 877 $page = basename($_SERVER['SCRIPT_NAME']);
469 - if( $page!='post-new.php' && !($page=='post.php' && filter_input(INPUT_GET, 'action')=='edit') && !($page=='options-general.php' && filter_input(INPUT_GET, 'page')=='event-settings') ){
878 + if( $page!='post-new.php' && $page!='edit-tags.php' && !($page=='post.php' && filter_input(INPUT_GET, 'action')=='edit') && !($page=='options-general.php' && filter_input(INPUT_GET, 'page')=='event-settings') ){
470 879 return;
471 880 }
472 - wp_enqueue_style('openlayers', plugins_url('/css/ol.css', __FILE__), false, filemtime( "{$this->plugin_path}/css/ol.css" ));
473 - wp_enqueue_style('jquery-ui', plugins_url('/css/jquery-ui.css', __FILE__), false, filemtime( "{$this->plugin_path}/css/jquery-ui.css" ));
474 - wp_enqueue_style('event-post-admin', plugins_url('/css/event-post-admin.css', __FILE__), false, filemtime( "{$this->plugin_path}/css/event-post-admin.css" ));
881 + wp_enqueue_style('event-post-admin', plugins_url('/build/admin/admin.css', __FILE__), false, filemtime( "{$this->plugin_path}/build/admin/admin.css" ));
475 882 }
476 883
477 884 /**
478 885 * Enqueue JS files in admin
@@ -478,30 +885,38 @@
478 885 * Enqueue JS files in admin
479 886 */
480 887 public function admin_scripts($deps = array('jquery'), $force=false) {
481 888 $page = basename($_SERVER['SCRIPT_NAME']);
482 - if(!$force && $page!='post-new.php' && !($page=='post.php' && filter_input(INPUT_GET, 'action')=='edit') && !($page=='options-general.php' && filter_input(INPUT_GET, 'page')=='event-settings')){
889 + if(!$force &&
890 + $page!='post-new.php' &&
891 + $page!='edit-tags.php' &&
892 + $page!='term.php' &&
893 + !($page=='post.php' && filter_input(INPUT_GET, 'action')=='edit') &&
894 + !($page=='options-general.php' && filter_input(INPUT_GET, 'page')=='event-settings')
895 + ){
483 896 return;
484 897 }
485 898 wp_enqueue_script('jquery');
486 899 wp_enqueue_script('jquery-effects-core');
487 900 wp_enqueue_script('jquery-effects-shake');
901 + wp_enqueue_style( 'wp-color-picker');
902 + wp_enqueue_script( 'wp-color-picker');
488 903 if(!is_array($deps)){
489 - $deps = array('jquery');
904 + $deps = array('jquery','wp-color-picker');
490 905 }
491 906 if($this->settings['datepicker']=='simple' || !is_admin() || (isset($_GET['page']) && $_GET['page']=='event-settings')){
492 907 wp_enqueue_script('jquery-ui-datepicker');
493 908 $deps[] = 'jquery-ui-datepicker';
494 909 }
495 - wp_enqueue_script('event-post-admin', plugins_url('/js/event-post-admin.min.js', __FILE__), $deps, filemtime( "{$this->plugin_path}/js/event-post-admin.min.js" ), true);
910 + wp_enqueue_script('event-post-admin', plugins_url('/build/admin/admin.js', __FILE__), $deps, filemtime( "{$this->plugin_path}/build/admin/admin.js" ), true);
496 911 $language = get_bloginfo('language');
497 912 if (strpos($language, '-') > -1) {
498 913 $language = strtolower(substr($language, 0, 2));
499 914 }
500 - wp_localize_script('event-post-admin', 'eventpost', array(
915 + wp_add_inline_script('event-post-admin', 'var EventPost = EventPost || {}; EventPost.admin='.wp_json_encode(array(
501 916 'ajaxurl' => admin_url('admin-ajax.php'),
502 917 'imgpath' => plugins_url('/img/', __FILE__),
503 - 'date_choose' => '<span class="screen-reader-text">'.__('Choose', 'event-post').'</span><i class="dashicons dashicons-calendar-alt"></i>',
918 + 'date_choose' => __('Choose', 'event-post'),
504 919 'date_format' => __('yy-mm-dd', 'event-post'),
505 920 'more_icons' => __('More icons', 'event-post'),
506 921 'pick_a_date'=>__('Pick a date','event-post'),
507 922 'use_current_location'=>__('Use my current location','event-post'),
@@ -507,10 +922,13 @@
507 922 'use_current_location'=>__('Use my current location','event-post'),
508 923 'start_drag'=>__('Click to<br>drag the map<br>and change location','event-post'),
509 924 'empty_address'=>__('Be kind to fill a non empty address:)', 'event-post'),
510 925 'search'=>__('Type an address', 'event-post'),
926 + 'search_button'=>__('Search', 'event-post'),
927 + 'geocoding_attribution'=>__('Geocoding by <a href="https://nominatim.openstreetmap.org/" target="_blank">OpenStreetmap Nominatim</a>', 'event-post'),
511 928 'stop_drag'=>_x('Done','Stop allowing to drag the map', 'event-post'),
512 929 'datepickeri18n'=>array(
930 + // Translators: %1$s is the month name, %2$s is the day number, %3$s is the year, %4$s is the hour, %5$s is the minute
513 931 'order'=>__( '%1$s %2$s, %3$s @ %4$s:%5$s', 'event-post'),
514 932 'day'=>__('Day', 'event-post'),
515 933 'month'=>__('Month', 'event-post'),
516 934 'year'=>__('Day', 'event-post'),
@@ -530,25 +948,27 @@
530 948 'META_STATUS' => $this->META_STATUS,
531 949 'META_ATTENDANCE_MODE' => $this->META_ATTENDANCE_MODE,
532 950 'lang'=>$language,
533 951 'maptiles' => $this->maps,
534 - 'defaulttile' => $this->settings['tile']
535 - ));
952 + 'defaulttile' => $this->settings['tile'],
953 + 'palette' => $this->get_theme_palette("hex"),
954 + 'available_images' => $this->get_colors(),
955 + )));
536 956 }
537 957 function scripts_edit() {
538 958 // load only when editing a supported post type
539 959 $current_post_type = isset($_GET['post_type']) ? $_GET['post_type'] : 'post';
540 960 if ( in_array( $current_post_type, $this->settings['posttypes'] ) ) {
541 - wp_enqueue_script( 'eventpost-inline-edit', plugins_url( 'js/inline-edit.min.js', __FILE__ ), array( 'jquery', 'inline-edit-post' ), '', true );
542 - wp_localize_script('eventpost-inline-edit', 'eventpost_inline_edit', array(
961 + wp_enqueue_script( 'eventpost-inline-edit', plugins_url( 'build/admin/inline-edit.js', __FILE__ ), array( 'jquery', 'inline-edit-post' ), '', true );
962 + wp_add_inline_script('eventpost-inline-edit', 'var EventPost = EventPost || {}; EventPost.inlineEdit='.wp_json_encode(array(
543 963 'quick'=>$this->quick_edit_fields,
544 - 'bulk'=>$this->bulk_edit_fields
545 - ));
964 + 'bulk'=>$this->bulk_edit_fields,
965 + )));
546 966 }
547 967 }
548 968
549 969 function get_rich_result($event){
550 - /**
970 + /*
551 971 * https://search.google.com/test/rich-results
552 972 {
553 973 "@context": "https://schema.org",
554 974 "@type": "Event",
@@ -600,9 +1020,9 @@
600 1020 $absmin = abs($min);
601 1021 $gmt_offset = sprintf("%s%02d:%02d", $sign, $absmin/60, $absmin%60);
602 1022 $time_format = (is_numeric($event->time_start) && is_numeric($event->time_end) && date('H:i', $event->time_start) != date('H:i', $event->time_end) && date('H:i', $event->time_start) != '00:00' && date('H:i', $event->time_end) != '00:00') ? 'Y-m-d\Th:i:00'.$gmt_offset : 'Y-m-d';
603 1023
604 - return apply_filters('event-post-rich-result', array(
1024 + $rich_data = array(
605 1025 '@context'=>'https://schema.org',
606 1026 '@type'=>'event',
607 1027 'name'=>$event->post_title,
608 1028 'datePublished'=>str_replace(' ', 'T', $event->post_date_gmt).$gmt_offset,
@@ -617,21 +1037,65 @@
617 1037 get_the_post_thumbnail_url($event->ID, 'medium'),
618 1038 get_the_post_thumbnail_url($event->ID, 'large'),
619 1039 get_the_post_thumbnail_url($event->ID, 'full'),
620 1040 ) : null,
621 - 'description'=>$event->post_excerpt,
622 - ), $event);
1041 + 'description'=>$event->description,
1042 + );
1043 + if(!empty($event->organization)){
1044 + $rich_data['organizer'] = array(
1045 + '@type'=>'Organization',
1046 + 'name'=>$event->organization,
1047 + );
1048 + }
1049 + if(!empty($event->offer)){
1050 + $rich_data['offers'] = array(
1051 + '@type'=>'Offer',
1052 + // 'availability'=>$event->availability,
1053 + // 'validFrom'=>date($time_format, $event->time_start),
1054 + );
1055 + if(!empty($event->offer['url'])){
1056 + $rich_data['offers']['url'] = $event->offer['url'];
1057 + }
1058 + if(!empty($event->offer['price'])){
1059 + $rich_data['offers']['price'] = $event->offer['price'];
1060 + }
1061 + if(!empty($event->offer['currency'])){
1062 + $rich_data['offers']['priceCurrency'] = $event->offer['currency'];
1063 + }
1064 + }
1065 +
1066 + return apply_filters('event-post-rich-result', $rich_data, $event);
623 1067 }
624 1068
625 1069 function wpseo_schema_webpage($rich_result){
626 1070 $event = $this->retreive();
627 - if ($event->time_start != '' && $event->time_end != '') {
628 - $rich_result = array_merge($rich_result, $this->get_rich_result($event));
1071 + if ($event != false){
1072 + if ($event->time_start != '' && $event->time_end != '') {
1073 + $rich_result = array_merge($rich_result, $this->get_rich_result($event));
1074 + }
1075 + $this->is_schema_output = true;
629 1076 }
630 - $this->is_schema_output = true;
631 1077 return $rich_result;
632 1078 }
633 1079
1080 + function get_theme_palette($return = "hex"){
1081 + $theme_options = wp_get_global_settings();
1082 + $colors = [];
1083 + if(isset($theme_options['color']['palette']['theme'])){
1084 + $colors = $theme_options['color']['palette']['theme'];
1085 + }elseif(isset($theme_options['color']['palette']['default'])){
1086 + $colors = $theme_options['color']['palette']['default'];
1087 + }
1088 + if($return == "hex"){
1089 + $color_hexs = [];
1090 + foreach($colors as $color){
1091 + $color_hexs[] = $color["color"];
1092 + }
1093 + return $color_hexs;
1094 + }
1095 + return $colors;
1096 + }
1097 +
634 1098 /**
635 1099 * Add custom header meta for single events
636 1100 */
637 1101 public function single_header() {
@@ -638,47 +1102,51 @@
638 1102 if (is_single()) {
639 1103 $twitter_label_id=0;
640 1104 $event = $this->retreive();
641 1105 $has_location = $has_time = false;
642 - if ($event->address != '' || ($event->lat != '' && $event->long != '')) {
643 - $twitter_label_id++;
644 - $has_location = true;
645 - ?>
646 -<meta name="geo.placename" content="<?php echo esc_attr($event->address) ?>" />
647 -<meta name="geo.position" content="<?php echo esc_attr($event->lat) ?>;<?php echo esc_attr($event->long) ?>" />
648 -<meta name="ICBM" content="<?php echo $event->lat ?>;<?php echo esc_attr($event->long) ?>" />
649 -<meta property="place:location:latitude" content="<?php echo esc_attr($event->lat) ?>" />
650 -<meta property="place:location:longitude" content="<?php echo esc_attr($event->long) ?>" />
651 -<meta name="twitter:label<?php echo $twitter_label_id; ?>" content="<?php _e('Location', 'event-post'); ?>"/>
652 -<meta name="twitter:data<?php echo $twitter_label_id; ?>" content="<?php echo esc_attr($event->address) ?>"/>
1106 + if ($event != false) {
1107 + if ($event->address != '' || ($event->lat != '' && $event->long != '')) {
1108 + $twitter_label_id++;
1109 + $has_location = true;
1110 + ?>
1111 +<meta name="geo.placename" content="<?php echo esc_attr($event->address) ?>" />
1112 +<meta name="geo.position" content="<?php echo esc_attr($event->lat) ?>;<?php echo esc_attr($event->long) ?>" />
1113 +<meta name="ICBM" content="<?php echo esc_attr($event->lat) ?>;<?php echo esc_attr($event->long) ?>" />
1114 +<meta property="place:location:latitude" content="<?php echo esc_attr($event->lat) ?>" />
1115 +<meta property="place:location:longitude" content="<?php echo esc_attr($event->long) ?>" />
1116 +<meta name="twitter:label<?php echo esc_attr($twitter_label_id); ?>" content="<?php esc_attr_e('Location', 'event-post'); ?>"/>
1117 +<meta name="twitter:data<?php echo esc_attr($twitter_label_id); ?>" content="<?php echo esc_attr($event->address) ?>"/>
653 1118 <?php
654 - }
655 - if ($event->start != '' && $event->end != '') {
656 - $has_time = true;
657 - $twitter_label_id++;
658 - ?>
659 -<meta name="datetime-coverage-start" content="<?php echo date('c', $event->time_start) ?>" />
660 -<meta name="datetime-coverage-end" content="<?php echo date('c', $event->time_end) ?>" />
661 -<meta name="twitter:label<?php echo $twitter_label_id; ?>" content="<?php _e('Date', 'event-post'); ?>"/>
662 -<meta name="twitter:data<?php echo $twitter_label_id; ?>" content="<?php echo esc_attr($this->human_date($event->time_start)) ?>"/>
1119 + }
1120 + if ($event->start != '' && $event->end != '') {
1121 + $has_time = true;
1122 + $twitter_label_id++;
1123 + ?>
1124 +<meta name="datetime-coverage-start" content="<?php echo esc_attr(date('c', $event->time_start)) ?>" />
1125 +<meta name="datetime-coverage-end" content="<?php echo esc_attr(date('c', $event->time_end)) ?>" />
1126 +<meta name="twitter:label<?php echo esc_attr($twitter_label_id); ?>" content="<?php echo esc_attr('Date', 'event-post'); ?>"/>
1127 +<meta name="twitter:data<?php echo esc_attr($twitter_label_id); ?>" content="<?php echo esc_attr($this->human_date($event->time_start)) ?>"/>
663 1128 <?php
1129 + }
1130 + if(($has_location || $has_time) && !$this->is_schema_output){
1131 + $rich_result = $this->get_rich_result($event);
1132 + $this->is_schema_output = true;
1133 + ?>
1134 + <script type="application/ld+json"><?php echo \wp_json_encode($rich_result); ?></script>
1135 + <?php
1136 + }
664 1137 }
665 - if(($has_location || $has_time) && !$this->is_schema_output){
666 - $rich_result = $this->get_rich_result($event);
667 - $this->is_schema_output = true;
668 - ?>
669 - <script type="application/ld+json"><?php echo json_encode($rich_result); ?></script>
670 - <?php
671 - }
672 -
673 1138 }
674 1139 }
675 1140
676 1141 /**
677 - *
1142 + * Cleanups a date
1143 + *
678 1144 * @param type $str
1145 + *
1146 + * @since 5.0.1
1147 + *
679 1148 * @return string
680 - * @since 5.0.1
681 1149 */
682 1150 public function date_cleanup($str){
683 1151 return trim(str_replace(array('0', ' ', ':', '-'), '', $str));
684 1152 }
@@ -683,10 +1151,12 @@
683 1151 return trim(str_replace(array('0', ' ', ':', '-'), '', $str));
684 1152 }
685 1153
686 1154 /**
687 - *
1155 + * Checks if a date is valid or not
1156 + *
688 1157 * @param string $str
1158 + *
689 1159 * @return boolean
690 1160 */
691 1161 public function dateisvalid($str) {
692 1162 return is_string($str) && $this->date_cleanup($str) != '';
@@ -692,11 +1162,13 @@
692 1162 return is_string($str) && $this->date_cleanup($str) != '';
693 1163 }
694 1164
695 1165 /**
696 - *
1166 + * Parse a date from a string
1167 + *
697 1168 * @param string $date
698 1169 * @param string $sep
1170 + *
699 1171 * @return string
700 1172 */
701 1173 public function parsedate($date, $sep = '') {
702 1174 if (!empty($date)) {
@@ -706,11 +1178,27 @@
706 1178 }
707 1179 }
708 1180
709 1181 /**
710 - *
1182 + * Sanitize a coordinate string
1183 + * Only keeps, numbers, dots and commas
1184 + *
1185 + * @param string $str
1186 + *
1187 + * @since 5.9.9
1188 + *
1189 + * @return string
1190 + */
1191 + public function sanitize_coordinate($str){
1192 + return preg_replace('/[^0-9\.,-]/', '', $str);
1193 + }
1194 +
1195 + /**
1196 + * Format a date for humans
1197 + *
711 1198 * @param mixed $date
712 1199 * @param string $format
1200 + *
713 1201 * @return type
714 1202 */
715 1203 public function human_date($date, $format = 'l j F Y') {
716 1204 if($this->settings['dateforhumans']){
@@ -725,11 +1213,13 @@
725 1213 return date_i18n($format, $date);
726 1214 }
727 1215
728 1216 /**
729 - *
1217 + * Returns a range of dates
1218 + *
730 1219 * @param timestamp $time_start
731 1220 * @param timestamp $time_end
1221 + *
732 1222 * @return string
733 1223 */
734 1224 public function delta_date($time_start, $time_end){
735 1225 if(!$time_start || !$time_end){
@@ -735,11 +1225,15 @@
735 1225 if(!$time_start || !$time_end){
736 1226 return;
737 1227 }
738 1228
1229 + // Translators: %1$s, %4$s are opening tags, %2$s and %5$s are closing tag, %3$s is the first date, %6$s is the second date
739 1230 $from_to_days = _x('%1$sfrom%2$s %3$s %4$sto%5$s %6$s', 'Days', 'event-post');
1231 + // Translators: %1$s is the first date, %4$s is the second date, %2$s is an opening tag, %3$s is a closing tag
740 1232 $single_day_at = _x('%1$s%2$s,%3$s %4$s', 'From/To single day at time', 'event-post');
1233 + // Translators: %1$s, %4$s are opening tags, %2$s and %5$s are closing tag, %3$s is the first hour, %6$s is the second hour
741 1234 $from_to_hours = _x('%1$sfrom%2$s %3$s %4$sto%5$s %6$s', 'Hours', 'event-post');
1235 + // Translators: %1$s is an opening tag, %2$s is a closing tag, %3$s is the time
742 1236 $at_time = _x('%1$sat%2$s %3$s', 'Time', 'event-post');
743 1237
744 1238 //Display dates
745 1239 $dates="\t\t\t\t".'<div class="event_date" data-start="' . $this->human_date($time_start) . '" data-end="' . $this->human_date($time_end) . '">';
@@ -794,89 +1288,93 @@
794 1288 return $dates;
795 1289 }
796 1290
797 1291 /**
798 - *
1292 + * Displays a date
1293 + *
799 1294 * @param WP_Post object $post
800 1295 * @param mixed $links
1296 + *
801 1297 * @return string
802 1298 */
803 1299 public function print_date($post = null, $links = 'deprecated', $context='') {
804 1300 $dates = '';
805 1301 $event = $this->retreive($post);
806 - if ($event->start != '' && $event->end != '') {
1302 + if ($event != false){
1303 + if ($event->start != '' && $event->end != '') {
807 1304
808 - $dates.=$this->delta_date($event->time_start, $event->time_end);
809 - if( // Status setting
810 - $this->settings['displaystatus'] == 'both' ||
811 - ($this->settings['displaystatus'] == 'single' && is_single() ) ||
812 - ($this->settings['displaystatus'] == 'list' && !is_single() )
813 - ){
814 - $dates.='<span class="eventpost-status">'.$this->statuses[$event->status].'</span>';
815 - }
816 - $timezone_string = get_option('timezone_string');
817 - $gmt_offset = $gmt = $this->get_gmt_offset();
1305 + $dates.=$this->delta_date($event->time_start, $event->time_end);
1306 + if( // Status setting
1307 + $this->settings['displaystatus'] == 'both' ||
1308 + ($this->settings['displaystatus'] == 'single' && is_single() ) ||
1309 + ($this->settings['displaystatus'] == 'list' && !is_single() )
1310 + ){
1311 + $dates.='<span class="eventpost-status">'.$this->statuses[$event->status].'</span>';
1312 + }
1313 + $timezone_string = get_option('timezone_string');
1314 + $gmt_offset = $gmt = $this->get_gmt_offset();
818 1315
819 - if (
820 - !is_admin()
821 - && ( // Export when setting
822 - $this->settings['export_when'] == 'both' ||
823 - ( $this->settings['export_when'] == 'future' && $this->is_future($event) ) ||
824 - ( $this->settings['export_when'] == 'past' && $this->is_past($event) )
825 - )
826 - && ( // Export setting
827 - $this->settings['export'] == 'both' ||
828 - ($this->settings['export'] == 'single' && is_single() ) ||
829 - ($this->settings['export'] == 'list' && !is_single() )
830 - )
831 - ) {
832 - // Export event
833 - $title = urlencode($post->post_title);
834 - $address = urlencode($post->address);
835 - $desc = urlencode($event->post_excerpt."\\n\\n".$post->permalink);
836 - $allday = ($post->time_start && $post->time_end && date('H:i:s', $post->time_start) == '00:00:00' && date('H:i:s', $post->time_end) == '00:00:00');
837 - $d_s = date("Ymd", $event->time_start) . ($allday ? '' : 'T' . date("His", $event->time_start));
838 - $d_e = date("Ymd", $event->time_end) . ($allday ? '' : 'T' . date("His", $event->time_end));
839 - $uid = $post->ID . '-' . $post->blog_id;
840 - $url = $event->permalink;
1316 + if (
1317 + !is_admin()
1318 + && ( // Export when setting
1319 + $this->settings['export_when'] == 'both' ||
1320 + ( $this->settings['export_when'] == 'future' && $this->is_future($event) ) ||
1321 + ( $this->settings['export_when'] == 'past' && $this->is_past($event) )
1322 + )
1323 + && ( // Export setting
1324 + $this->settings['export'] == 'both' ||
1325 + ($this->settings['export'] == 'single' && is_single() ) ||
1326 + ($this->settings['export'] == 'list' && !is_single() )
1327 + )
1328 + ) {
1329 + // Export event
1330 + $title = urlencode($post->post_title);
1331 + $address = urlencode($post->address);
1332 + $desc = urlencode($event->description."\n\n".$post->permalink);
1333 + $allday = ($post->time_start && $post->time_end && date('H:i:s', $post->time_start) == '00:00:00' && date('H:i:s', $post->time_end) == '00:00:00');
1334 + $d_s = date("Ymd", $event->time_start) . ($allday ? '' : 'T' . date("His", $event->time_start));
1335 + $d_e = date("Ymd", $event->time_end) . ($allday ? '' : 'T' . date("His", $event->time_end));
1336 + $uid = $post->ID . '-' . $post->blog_id;
1337 + $url = $event->permalink;
841 1338
842 - // format de date ICS
843 - $permalink_structure = get_option( 'permalink_structure' );
844 - if($permalink_structure != ""){
845 - $ics_url = site_url('eventpost/'.$event->ID.'.ics');
846 - $vcs_url = site_url('eventpost/'.$event->ID.'.vcs');
847 - }
848 - else{
849 - $ics_url = add_query_arg(array('action'=>'EventPostExport', 'event_id'=>$event->ID, 'format'=>'ics'), admin_url('admin-ajax.php'));
850 - $vcs_url = add_query_arg(array('action'=>'EventPostExport', 'event_id'=>$event->ID, 'format'=>'vcs'), admin_url('admin-ajax.php'));
1339 + // format de date ICS
1340 + $permalink_structure = get_option( 'permalink_structure' );
1341 + if($permalink_structure != ""){
1342 + $ics_url = site_url('eventpost/'.$event->ID.'.ics');
1343 + $vcs_url = site_url('eventpost/'.$event->ID.'.vcs');
1344 + }
1345 + else{
1346 + $ics_url = add_query_arg(array('action'=>'EventPostExport', 'event_id'=>$event->ID, 'format'=>'ics'), admin_url('admin-ajax.php'));
1347 + $vcs_url = add_query_arg(array('action'=>'EventPostExport', 'event_id'=>$event->ID, 'format'=>'vcs'), admin_url('admin-ajax.php'));
851 1348
852 - }
1349 + }
853 1350
854 - // format de date Google cal
855 - //$google_url = 'https://www.google.com/calendar/event?action=TEMPLATE&amp;text=' . $title . '&amp;dates=' . $d_s . 'Z/' . $d_e . 'Z&amp;details=' . $url . '&amp;ctz='.$timezone_string.'&amp;location=' . $address . '&amp;trp=false&amp;sprop=&amp;sprop=name';
856 - $google_url = add_query_arg(array(
857 - 'action'=>'TEMPLATE',
858 - 'trp'=>'false',
859 - 'sprop'=>'name',
860 - 'text'=>$title,
861 - 'dates'=>$d_s.'/'.$d_e.'', // Removed Z to fix TZ issue
862 - 'location'=>$address,
863 - 'details'=>$desc,
864 - 'gmt'=> urlencode($gmt_offset)
865 - ), 'https://www.google.com/calendar/event');
866 - if(!empty($timezone_string)){
867 - $google_url = add_query_arg(array(
868 - 'ctz'=>$timezone_string,
869 - ), $google_url);
1351 + // format de date Google cal
1352 + //$google_url = 'https://www.google.com/calendar/event?action=TEMPLATE&amp;text=' . $title . '&amp;dates=' . $d_s . 'Z/' . $d_e . 'Z&amp;details=' . $url . '&amp;ctz='.$timezone_string.'&amp;location=' . $address . '&amp;trp=false&amp;sprop=&amp;sprop=name';
1353 + $google_url = add_query_arg(array(
1354 + 'action'=>'TEMPLATE',
1355 + 'trp'=>'false',
1356 + 'sprop'=>'name',
1357 + 'text'=>$title,
1358 + 'dates'=>$d_s.'/'.$d_e.'', // Removed Z to fix TZ issue
1359 + 'location'=>$address,
1360 + 'details'=>$desc,
1361 + 'gmt'=> urlencode($gmt_offset)
1362 + ), 'https://www.google.com/calendar/event');
1363 + if(!empty($timezone_string)){
1364 + $google_url = add_query_arg(array(
1365 + 'ctz'=>$timezone_string,
1366 + ), $google_url);
1367 + }
1368 +
1369 + $dates.='
1370 + <span class="eventpost-date-export">
1371 + <a href="' . $ics_url . '" class="event_link event-export ics" target="_blank" title="' . __('Download ICS file', 'event-post') . '">ical</a>
1372 + <a href="' . $google_url . '" class="event_link event-export gcal" target="_blank" title="' . __('Add to Google calendar', 'event-post') . '">Google</a>
1373 + <a href="' . $vcs_url . '" class="event_link event-export vcs" target="_blank" title="' . __('Add to Outlook', 'event-post') . '">outlook</a>
1374 + <i class="dashicons-before dashicons-calendar"></i>
1375 + </span>';
870 1376 }
871 -
872 - $dates.='
873 - <span class="eventpost-date-export">
874 - <a href="' . $ics_url . '" class="event_link event-export ics" target="_blank" title="' . __('Download ICS file', 'event-post') . '">ical</a>
875 - <a href="' . $google_url . '" class="event_link event-export gcal" target="_blank" title="' . __('Add to Google calendar', 'event-post') . '">Google</a>
876 - <a href="' . $vcs_url . '" class="event_link event-export vcs" target="_blank" title="' . __('Add to Outlook', 'event-post') . '">outlook</a>
877 - <i class="dashicons-before dashicons-calendar"></i>
878 - </span>';
879 1377 }
880 1378 }
881 1379 return apply_filters('eventpost_printdate', $dates);
882 1380 }
@@ -881,10 +1379,12 @@
881 1379 return apply_filters('eventpost_printdate', $dates);
882 1380 }
883 1381
884 1382 /**
885 - *
1383 + * Outputs location of an event
1384 + *
886 1385 * @param WP_Post object $post
1386 + *
887 1387 * @return string
888 1388 */
889 1389 public function print_location($post=null, $context='') {
890 1390 $location = '';
@@ -895,45 +1395,73 @@
895 1395 }
896 1396 if (!isset($post->start)) {
897 1397 $post = $this->retreive($post);
898 1398 }
899 - $address = $post->address;
900 - $lat = $post->lat;
901 - $long = $post->long;
902 - $color = $post->color;
903 - $virtual_location = $post->virtual_location;
904 - $attendance_mode = $post->attendance_mode;
1399 + if ($post != false){
1400 + $this->map_id++;
1401 + $address = $post->address;
1402 + $lat = $post->lat;
1403 + $long = $post->long;
1404 + $color = $this->get_post_color($post->ID, $this->settings['default_color'], true);
1405 + $icon = $this->DashIcons->icons[$this->get_post_icon($post->ID, $this->settings['default_icon'], true)];
1406 + $virtual_location = $post->virtual_location;
1407 + $attendance_mode = $post->attendance_mode;
905 1408
906 - if ($this->is_online($post) && $virtual_location) {
907 - $location.="\t\t\t\t".'<div><a href="'.esc_url($virtual_location).'" class="eventpost-virtual-location-link" target="_blank" rel="noopener">'
908 - .__('Join link', 'event-post')
909 - .'</a></div>'
910 - ."\n";
911 - }
912 - if ($this->is_offline($post) && ($address != '' || ($lat != '' && $long != ''))) {
913 - $location.="\t\t\t\t".'<address';
914 - if ($lat != '' && $long != '') {
915 - $location.=' data-id="' . $post->ID . '" data-latitude="' . $lat . '" data-longitude="' . $long . '" data-marker="' . $this->get_marker($color) . '" ';
1409 + if ($this->is_online($post) && $virtual_location) {
1410 + $location.="\t\t\t\t".'<div><a href="'.esc_url($virtual_location).'" class="eventpost-virtual-location-link" target="_blank" rel="noopener">'
1411 + .__('Join link', 'event-post')
1412 + .'</a></div>'
1413 + ."\n";
916 1414 }
917 - $location.=' itemprop="adr" class="eventpost-address">'
918 - . "\n\t\t\t\t\t\t\t".'<span>'
919 - . "\n".$address
920 - . "\n\t\t\t\t\t\t\t". '</span>';
921 - if ($context=='single' && $lat != '' && $long != '') {
922 - $location.="\n\t\t\t\t\t\t\t".'<a class="event_link gps dashicons-before dashicons-location-alt" href="https://www.openstreetmap.org/?lat=' . $lat .'&amp;lon=' . $long . '&amp;zoom=13" target="_blank" itemprop="geo">' . __('Map', 'event-post') . '</a>';
1415 + if ($this->is_offline($post) && ($address != '' || ($lat != '' && $long != ''))) {
1416 + $location.="\t\t\t\t".'<address';
1417 + if ($lat != '' && $long != '') {
1418 + $geo_attributes = ' data-latitude="' . esc_attr($lat) . '"
1419 + data-longitude="' . esc_attr($long) . '"
1420 + data-marker="' . esc_attr($this->get_marker($color)) . '"
1421 + data-iconcode="' .esc_attr($icon). '"
1422 + data-icon="' . esc_attr(mb_convert_encoding('&#x'.$icon.';', 'UTF-8', 'HTML-ENTITIES')). '"
1423 + data-color="#' . esc_attr($color). '"
1424 + data-id="' . $post->ID . '-'.$this->map_id.'"';
1425 + $location.=' '.$geo_attributes;
1426 + }
1427 + $location.=' itemprop="adr" class="eventpost-address">'
1428 + . "\n\t\t\t\t\t\t\t".'<span>'
1429 + . "\n".$address
1430 + . "\n\t\t\t\t\t\t\t". '</span>';
1431 + if ($context=='single' && $lat != '' && $long != '') {
1432 + $location.="\n\t\t\t\t\t\t\t".'<a class="event_link gps dashicons-before dashicons-location-alt" href="https://www.openstreetmap.org/?lat=' . esc_attr($lat) .'&amp;lon=' . esc_attr($long) . '&amp;zoom=13" target="_blank" itemprop="geo" ' . $geo_attributes . '>' . __('Map', 'event-post') . '</a>';
1433 + }
1434 + $location.="\n\t\t\t\t\t\t".'</address>';
1435 + if (wp_is_mobile() && $lat != '' && $long != '') {
1436 + $location.="\n\t\t\t\t\t\t".'<a class="event_link gps-geo-link" href="geo:' . esc_attr($lat) . ',' . esc_attr($long) . '" target="_blank" itemprop="geo" ' . $geo_attributes . '><i class="dashicons-before dashicons-location"></i> ' . __('Open in app', 'event-post') . '</a>';
1437 + }
923 1438 }
924 - $location.="\n\t\t\t\t\t\t".'</address>';
925 - if (wp_is_mobile() && $lat != '' && $long != '') {
926 - $location.="\n\t\t\t\t\t\t".'<a class="event_link gps-geo-link" href="geo:' . $lat . ',' . $long . '" target="_blank" itemprop="geo"><i class="dashicons-before dashicons-location"></i> ' . __('Open in app', 'event-post') . '</a>';
927 - }
928 1439 }
1440 + return apply_filters('eventpost_printlocation', $location);
1441 + }
929 1442
930 - return apply_filters('eventpost_printlocation', $location);
1443 + /**
1444 + * Compute darkness of the color
1445 + *
1446 + * @param string $color
1447 + *
1448 + * @return float
1449 + */
1450 + public function color_darkness($color){
1451 + $color = str_replace('#', '', $color);
1452 + $rgb = array();
1453 + for ($x=0;$x<3;$x++) {
1454 + $rgb[$x] = hexdec(substr($color,(2*$x),2));
1455 + }
1456 + return (max($rgb) + min($rgb)) / 510;
931 1457 }
932 1458
933 1459 /**
934 - *
1460 + * Outputs categories of an event
1461 + *
935 1462 * @param WP_Post object $post
1463 + *
936 1464 * @return string
937 1465 */
938 1466 public function print_categories($post=null, $context='') {
939 1467 if ($post == null)
@@ -944,20 +1472,36 @@
944 1472 if (!isset($post->start)) {
945 1473 $post = $this->retreive($post);
946 1474 }
947 1475 $cats = '';
948 - $categories = $post->categories;
949 - if ($categories) {
950 - $cats.="\t\t\t\t".'<span class="event_category"';
951 - $color = $post->color;
952 - if ($color != '') {
953 - $cats.=' style="color:#' . $color . '"';
1476 + if ($post != false){
1477 + $categories = $post->Taxonomies;
1478 + if ($categories) {
1479 + $cats.="\t\t\t\t".'<span class="event_categories">';
1480 +
1481 + foreach ($categories as $category) {
1482 + $cats.="\t\t\t\t\t".'<span ';
1483 + $classes = array('event-term', 'event_term_category');
1484 + $darkness = 0;
1485 + $color = $this->Taxonomies->get_taxonomy_color($category->term_id);
1486 + if ($color != '' && $color) {
1487 + $cats.=' style="background-color:#' . $color . '"';
1488 +
1489 + $darkness = $this->color_darkness($color);
1490 + if($darkness < 0.5){
1491 + array_push($classes, 'event-post-bg-dark');
1492 + }
1493 + else{
1494 + array_push($classes, 'event-post-bg-light');
1495 + }
1496 +
1497 + }
1498 + $cats.=' class="'.implode(' ', $classes).'">';
1499 + $cats .= $category->name . ' ';
1500 + $cats.='</span>';
1501 + }
1502 + $cats.='</span>';
954 1503 }
955 - $cats.='>';
956 - foreach ($categories as $category) {
957 - $cats .= $category->name . ' ';
958 - }
959 - $cats.='</span>';
960 1504 }
961 1505 return $cats;
962 1506 }
963 1507
@@ -962,11 +1506,14 @@
962 1506 }
963 1507
964 1508 /**
965 1509 * Generate, return or output date event datas
1510 + *
966 1511 * @param WP_Post object $post
967 1512 * @param string $class
1513 + *
968 1514 * @filter eventpost_get_single
1515 + *
969 1516 * @return string
970 1517 */
971 1518 public function get_single($post = null, $class = '', $context='') {
972 1519 if ($post == null) {
@@ -971,22 +1518,24 @@
971 1518 public function get_single($post = null, $class = '', $context='') {
972 1519 if ($post == null) {
973 1520 $post = $this->retreive();
974 1521 }
975 - $datas_date = $this->print_date($post, null, $context);
976 - $datas_cat = $this->print_categories($post, $context);
977 - $datas_loc = $this->print_location($post, $context);
978 - $classes = array(
979 - 'event_data',
980 - 'status-'.$post->status,
981 - 'location-type-'.$post->attendance_mode,
982 - $class
983 - );
984 - if ($datas_date != '' || $datas_loc != '') {
985 - $rgb = $this->hex2dec($post->color);
986 - return '<div class="' . implode(' ', $classes) . '" style="border-left-color:#' . $post->color . ';background:rgba(' . $rgb['R'] . ',' . $rgb['G'] . ',' . $rgb['B'] . ',0.1)" itemscope itemtype="http://microformats.org/profile/hcard">'
987 - . apply_filters('eventpost_get_single', $datas_date . $datas_cat . $datas_loc, $post)
988 - . '</div>';
1522 + if ($post != null){
1523 + $datas_date = $this->print_date($post, null, $context);
1524 + $datas_cat = $this->print_categories($post, $context);
1525 + $datas_loc = $this->print_location($post, $context);
1526 + $classes = array(
1527 + 'event_data',
1528 + 'status-'.strtolower(str_replace('Event', '', $post->status)),
1529 + 'location-type-'.strtolower(str_replace('EventAttendanceMode', '', $post->attendance_mode)),
1530 + $class
1531 + );
1532 + if ($datas_date != '' || $datas_loc != '') {
1533 + $rgb = $this->hex2dec($post->color);
1534 + return '<div class="' . implode(' ', $classes) . '" style="border-left-color:#' . $post->color . ';background:rgba(' . $rgb['R'] . ',' . $rgb['G'] . ',' . $rgb['B'] . ',0.1)" itemscope itemtype="http://microformats.org/profile/hcard">'
1535 + . apply_filters('eventpost_get_single', $datas_date . $datas_cat . $datas_loc, $post)
1536 + . '</div>';
1537 + }
989 1538 }
990 1539 return '';
991 1540 }
992 1541
@@ -991,10 +1540,12 @@
991 1540 }
992 1541
993 1542 /**
994 1543 * Displays dates of a gieven post
1544 + *
995 1545 * @param WP_Post object $post
996 1546 * @param string $class
1547 + *
997 1548 * @return string
998 1549 */
999 1550 public function get_singledate($post = null, $class = '', $context='') {
1000 1551 return '<div class="event_data event_date ' . $class . '" itemscope itemtype="http://microformats.org/profile/hcard">' . "\n\t\t".$this->print_date($post, null, $context) . "\n\t\t\t\t\t".'</div><!-- .event_date -->';
@@ -1001,10 +1552,12 @@
1001 1552 }
1002 1553
1003 1554 /**
1004 1555 * Displays coloured terms of a given post
1556 + *
1005 1557 * @param WP_Post object $post
1006 1558 * @param string $class
1559 + *
1007 1560 * @return string
1008 1561 */
1009 1562 public function get_singlecat($post = null, $class = '', $context='') {
1010 1563 return '<div class="event_data event_category ' . $class . '" itemscope itemtype="http://microformats.org/profile/hcard">' . "\n\t\t".$this->print_categories($post, $context) . "\n\t\t\t\t\t".'</div><!-- .event_category -->';
@@ -1011,10 +1564,12 @@
1011 1564 }
1012 1565
1013 1566 /**
1014 1567 * Displays location of a given post
1568 + *
1015 1569 * @param WP_Post object $post
1016 1570 * @param string $class
1571 + *
1017 1572 * @return string
1018 1573 */
1019 1574 public function get_singleloc($post = null, $class = '', $context='') {
1020 1575 return '<div class="event_data event_location ' . $class . '" itemscope itemtype="http://microformats.org/profile/hcard">' . "\n\t\t".$this->print_location($post, $context) . "\n\t\t\t\t\t".'</div><!-- .event_location -->';
@@ -1021,9 +1576,11 @@
1021 1576 }
1022 1577
1023 1578 /**
1024 1579 * Uses `the_content` filter to add event details before or after the content of the current post
1580 + *
1025 1581 * @param string $content
1582 + *
1026 1583 * @return string
1027 1584 */
1028 1585 public function display_single($content) {
1029 1586 if (is_page() || !is_single() || is_home() || !in_the_loop() || !is_main_query()){
@@ -1030,32 +1587,42 @@
1030 1587 return $content;
1031 1588 }
1032 1589
1033 1590 $post = $this->retreive();
1034 - $eventbar = apply_filters('eventpost_contentbar', $this->get_single($post, 'event_single', 'single'), $post);
1035 - if($this->settings['singlepos']=='before'){
1036 - $content=$eventbar.$content;
1591 + if($post != false){
1592 + // If the post is a product, don't display the event bar, use product tab instead
1593 + if($post->post_type=='product'){
1594 + return $content;
1595 + }
1596 +
1597 + $eventbar = apply_filters('eventpost_contentbar', $this->get_single($post, 'event_single', 'single'), $post);
1598 + if($this->settings['singlepos']=='before'){
1599 + $content=$eventbar.$content;
1600 + }
1601 + elseif($this->settings['singlepos']=='after'){
1602 + $content.=$eventbar;
1603 + }
1604 + $this->load_map_scripts();
1037 1605 }
1038 - elseif($this->settings['singlepos']=='after'){
1039 - $content.=$eventbar;
1040 - }
1041 - $this->load_map_scripts();
1042 1606 return $content;
1043 1607 }
1044 1608
1045 1609 /**
1046 1610 * Outputs events details (dates, geoloc, terms) of given post
1611 + *
1047 1612 * @param WP_Post object $post
1048 - * @echoes string
1613 + *
1049 1614 * @return void
1050 1615 */
1051 1616 public function print_single($post = null) {
1052 - echo $this->get_single($post);
1617 + echo wp_kses_post($this->get_single($post));
1053 1618 }
1054 1619
1055 1620 /**
1056 1621 * Alter the post title in order to add icons if needed
1622 + *
1057 1623 * @param string $title
1624 + *
1058 1625 * @return string
1059 1626 */
1060 1627 public function the_title($title, $post_id = null){
1061 1628 if(!$post_id || !in_the_loop() || !$this->settings['loopicons']){
@@ -1068,36 +1635,63 @@
1068 1635 2=>array('<span class="dashicons dashicons-calendar"></span>', '<span class="dashicons dashicons-location"></span>'),
1069 1636 );
1070 1637
1071 1638 $event = $this->retreive($post_id);
1072 - if(!empty($event->start)){
1073 - $title .= ' '.$icons_[$this->settings['loopicons']][0];
1639 + if ($event !== false){
1640 + if(!empty($event->start)){
1641 + $title .= ' '.$icons_[$this->settings['loopicons']][0];
1642 + }
1643 + if(!empty($event->lat) && !empty($event->long)){
1644 + $title .= ' '.$icons_[$this->settings['loopicons']][1];
1645 + }
1074 1646 }
1075 - if(!empty($event->lat) && !empty($event->long)){
1076 - $title .= ' '.$icons_[$this->settings['loopicons']][1];
1077 - }
1078 1647 return $title;
1079 1648 }
1080 1649
1081 1650
1651 + function get_price($event,$html=false){
1652 + $price = '';
1653 + $text_price = $price;
1654 + if($event->post_type == 'product'){
1655 + $product_id = $event->ID;
1656 + $product = wc_get_product($product_id);
1657 + $price = $product->get_price();
1658 + $currency = get_woocommerce_currency_symbol();
1659 + if($product->get_sale_price() != ""){
1660 + $old_price = $product->get_regular_price();
1661 + $text_price = '<span class="event_price"><del>'.$old_price . $currency . '</del> '.$price. $currency. '</span>';
1662 + } else {
1663 + $text_price = '<span class="event_price"> '.$price . $currency.'</span>';
1664 + }
1665 + }
1666 + if ($html == true) {
1667 + return $text_price;
1668 + } else {
1669 + return $price;
1670 + }
1671 + }
1672 +
1082 1673 /**
1083 1674 * Return an HTML list of events
1084 1675 *
1676 + * @param array $atts
1677 + * @param string $id
1678 + * @param string $context
1679 + *
1085 1680 * @filter eventpost_params($defaults, 'list_events')
1086 1681 * @filter eventpost_listevents
1087 1682 * @filter eventpost_item_scheme_entities
1088 1683 * @filter eventpost_item_scheme_values
1089 - *
1090 - * @param array $atts
1091 - * @param string $id
1092 - * @param string $context
1684 + *
1093 1685 * @return string
1094 1686 */
1095 1687 public function list_events($atts, $id = 'event_list', $context='') {
1096 -
1097 1688 $ep_settings = $this->settings;
1098 1689 $defaults = array(
1099 1690 'nb' => 0,
1691 + 'nb_desktop' => 0,
1692 + 'nb_tablet' => 0,
1693 + 'nb_mobile' => 0,
1100 1694 'type' => 'div',
1101 1695 'future' => true,
1102 1696 'past' => false,
1103 1697 'geo' => 0,
@@ -1125,45 +1719,95 @@
1125 1719 'excerpt' => '',
1126 1720 'orderby' => 'meta_value',
1127 1721 'order' => 'ASC',
1128 1722 'class' => '',
1723 + 'align' => '',
1129 1724 'className' => '',
1130 1725 'container_schema' => $this->list_shema['container'],
1131 1726 'item_schema' => $this->list_shema['item'],
1132 1727 'pages' => false,
1728 + 'paged' => '',
1729 + 'separate_years' => false,
1730 + 'separate_months' => false,
1133 1731 );
1134 1732 // Map UI options
1135 1733 foreach($this->map_interactions as $int_key=>$int_name){
1136 1734 $defaults[$int_key]=true;
1137 1735 }
1138 - $atts = shortcode_atts(apply_filters('eventpost_params', $defaults, 'list_events'), $atts);
1736 + $atts_old_nb = $defaults['nb'];
1737 + if($id == "event_timeline"){
1738 + $atts_old_nb = intval($atts['nb']);
1739 + $atts['nb'] = -1;
1740 + }
1139 1741
1742 + $atts = shortcode_atts(apply_filters('eventpost_params', $defaults, 'list_events', $context), $atts);
1743 +
1140 1744 extract($atts);
1141 1745 if (!is_array($events)) {
1142 1746 $events = $this->get_events($atts);
1143 1747 }
1748 +
1144 1749 $ret = '';
1145 1750 $this->list_id++;
1146 1751 if (sizeof($events) > 0) {
1147 1752 if (!empty($title)) {
1148 - $ret.= html_entity_decode($before_title) . $title . html_entity_decode($after_title);
1753 + $ret .= wp_kses_post($before_title . esc_html($title) . $after_title);
1149 1754 }
1150 1755
1151 - $child = ($type == 'ol' || $type == 'ul') ? 'li' : 'div';
1756 + $type = in_array($type, ['div', 'ul', 'ol']) ? $type : 'div';
1757 + $child = in_array($type, ['ul', 'ol']) ? 'li' : 'div';
1152 1758
1153 1759 $html = '';
1154 1760
1155 - if($id=='event_geolist'){
1156 - $this->load_map_scripts();
1157 - $html.=sprintf('<%1$s class="event_geolist_icon_loader"><p><span class="dashicons dashicons-location-alt"></span></p><p class="screen-reader-text">'.__('An events map', 'event-post').'</p></%1$s>', $type);
1158 - }
1761 + if($id=='event_geolist'){
1762 + $this->load_map_scripts();
1763 + $html.=sprintf('<%1$s class="event_geolist_icon_loader"><p><span class="dashicons dashicons-location-alt"></span></p><p class="screen-reader-text">'.__('An events map', 'event-post').'</p></%1$s>', $type);
1764 + }
1765 + $attributes = '';
1766 + $prev_arrow = "";
1767 + $next_arrow = "";
1768 + $item_child_style = "";
1769 + if($id == "event_timeline"){
1770 + $prev_arrow = '<div class="previous"><span class="screen-reader-text">'.__('« Previous Events', 'event-post')."</span></div>";
1771 + $next_arrow = '<div class="next"><span class="screen-reader-text">'.__('Next Events »', 'event-post')."</span></div>";
1772 + if($atts_old_nb != 0){
1773 + $item_child_style = 'width : '.((100/$atts_old_nb) - 2).'%;';
1774 + }
1775 + $attributes .= ' data-nb="'.$atts_old_nb.'"';
1776 + $attributes .= ' data-nb-desktop="'.intval($atts['nb_desktop'] ?? 0).'"';
1777 + $attributes .= ' data-nb-tablet="'.intval($atts['nb_tablet'] ?? 0).'"';
1778 + $attributes .= ' data-nb-mobile="'.intval($atts['nb_mobile'] ?? 0).'"';
1779 + $attributes .= ' data-filter="'.http_build_query($atts).'" ';
1780 + }
1159 1781
1782 + if($id === 'event_timeline'){
1783 + $previous_year = $atts['separate_years'] ? true : false;
1784 + $previous_month = $atts['separate_months'] ? true : false;
1785 + }
1786 +
1160 1787 foreach ($events as $event) {
1788 + if($id === 'event_timeline'){
1789 + if($previous_year && $previous_year !== date('Y', $event->time_start)){
1790 + $html.= '<div class="event-timeline-separator event-timeline-year"><span class="event-timeline-year-text">'.date_i18n('Y', $event->time_start).'</span></div>';
1791 + $previous_year = date('Y', $event->time_start);
1792 + }
1793 + if($previous_month && $previous_month !== date('Ym', $event->time_start)){
1794 + $html.= '<div class="event-timeline-separator event-timeline-month"><span class="event-timeline-month-text">'.date_i18n('F', $event->time_start).'</span>'.($previous_year ? '' : ' <span class="event-timeline-year-text">'.date_i18n('Y', $event->time_start).'</span>').'</div>';
1795 + $previous_month = date('Ym', $event->time_start);
1796 + }
1797 + }
1798 + $text_price = $this->get_price($event,true);
1161 1799 $class_item = array(
1162 1800 $this->is_future($event) ? 'event_future' : 'event_past',
1163 - 'status-'.$event->status,
1164 - 'location-type-'.$event->attendance_mode,
1801 + 'status-'.strtolower(str_replace('Event', '', $event->status)),
1802 + 'location-type-'.strtolower(str_replace('EventAttendanceMode', '', $event->attendance_mode)),
1165 1803 );
1804 + $taxonomies= get_taxonomies('','names');
1805 + $post_terms = [];
1806 + $terms = wp_get_post_terms($event->ID, $taxonomies);
1807 + foreach($terms as $term){
1808 + $class_item[] = $term->taxonomy.'-'.$term->slug;
1809 + }
1166 1810 if ($ep_settings['emptylink'] == 0 && empty($event->post_content)) {
1167 1811 $event->permalink = '#' . $id . $this->list_id;
1168 1812 }
1169 1813 elseif(empty($event->permalink)){
@@ -1176,27 +1820,31 @@
1176 1820 '%color%',
1177 1821 '%event_link%',
1178 1822 '%event_thumbnail%',
1179 1823 '%event_title%',
1824 + '%event_price%',
1180 1825 '%event_date%',
1181 1826 '%event_cat%',
1182 1827 '%event_location%',
1183 - '%event_excerpt%'
1828 + '%event_excerpt%',
1829 + '%style%',
1184 1830 )), apply_filters('eventpost_item_scheme_values', array(
1185 1831 $child,
1186 1832 implode(' ', $class_item),
1187 - $event->color,
1833 + $this->get_post_color($event->ID, $this->settings['default_color'],true),
1188 1834 $event->permalink,
1189 1835 $thumbnail == true ? '<span class="event_thumbnail_wrap">' . get_the_post_thumbnail($event->root_ID, !empty($thumbnail_size) ? $thumbnail_size : 'thumbnail', array('class' => 'attachment-thumbnail wp-post-image event_thumbnail')) . '</span>' : '',
1190 1836 $event->post_title,
1837 + $event->post_type == 'product' ? $text_price : '',
1191 1838 $this->get_singledate($event, '', $context),
1192 1839 $this->get_singlecat($event, '', $context),
1193 1840 $this->get_singleloc($event, '', $context),
1194 - $excerpt == true && $event->post_excerpt!='' ? '<span class="event_exerpt">'.$event->post_excerpt.'</span>' : '',
1841 + $excerpt == true && $event->description!='' ? '<span class="event_exerpt">'.$event->description.'</span>' : '',
1842 + $item_child_style,
1195 1843 ), $event), $item_schema
1196 1844 );
1845 +
1197 1846 }
1198 - $attributes = '';
1199 1847 if($id == 'event_geolist'){
1200 1848 if($height==''){
1201 1849 $height = '300px';
1202 1850 }
@@ -1202,14 +1850,24 @@
1202 1850 }
1203 1851 if($width==''){
1204 1852 $width = '100%';
1205 1853 }
1206 - $attributes = 'data-tile="'.$tile.'" data-width="'.$width.'" data-height="'.$height.'" data-zoom="'.$zoom.'" data-map_position="'.$map_position.'" data-latitude="'.$latitude.'" data-longitude="'.$longitude.'" data-pop_element_schema="'.$pop_element_schema.'" data-htmlPop_element_schema="'.esc_attr($htmlPop_element_schema).'" data-list="'.$list.'" data-disabled-interactions="';
1854 + $attributes .= ' data-tile="'.esc_attr($tile).'"
1855 + data-width="'.esc_attr($width).'"
1856 + data-height="'.esc_attr($height).'"
1857 + data-zoom="'.esc_attr($zoom).'"
1858 + data-map_position="'.esc_attr($map_position).'"
1859 + data-latitude="'.esc_attr($latitude).'"
1860 + data-longitude="'.esc_attr($longitude).'"
1861 + data-pop_element_schema="'.esc_attr($pop_element_schema).'"
1862 + data-htmlPop_element_schema="'.esc_attr($htmlPop_element_schema).'"
1863 + data-list="'.esc_attr($list).'"
1864 + data-disabled-interactions="';
1207 1865 // add data-position avec ma variables
1208 1866 foreach($this->map_interactions as $int_key=>$int_name){
1209 - $attributes.=$atts[$int_key]==false ? $int_key.', ' : '';
1867 + $attributes.=$atts[$int_key]==false ? esc_attr($int_key).', ' : '';
1210 1868 }
1211 - $attributes.='"';
1869 + $attributes.='" ';
1212 1870 }
1213 1871 $pagination = '';
1214 1872 if($pages && $this->pagination){
1215 1873 global $wp_rewrite;
@@ -1221,29 +1879,52 @@
1221 1879 'total' => $this->pagination['max_num_pages'],
1222 1880 )
1223 1881 );
1224 1882 }
1225 - $ret.=str_replace(
1226 - array(
1227 - '%type%',
1228 - '%id%',
1229 - '%class%',
1230 - '%listid%',
1231 - '%style%',
1232 - '%attributes%',
1233 - '%list%',
1234 - '%pagination%',
1235 - ), array(
1236 - $type,
1237 - $id,
1238 - $class.($className ? ' '.$className : '').($id == 'event_geolist' && $list ? ' has-list list-'.$list : ' no-list'),
1239 - $id . $this->list_id,
1240 - (!empty($width) ? 'width:' . $width . ';' : '') . (!empty($height) ? 'height:' . $height . ';' : '') . $style,
1241 - $attributes,
1242 - $html,
1243 - $pagination,
1244 - ), $container_schema
1245 - );
1883 +
1884 + if($context == 'events_only'){
1885 + $ret = $html;
1886 + }else{
1887 + $classes = [
1888 + $class,
1889 + $className,
1890 + 'className',
1891 + $id == 'event_geolist' && $list ? ' has-list list-'.esc_attr($list) : ' no-list',
1892 + ];
1893 + if(!empty($align)){
1894 + $classes[] = 'align'.esc_attr($align);
1895 + }
1896 + if($id === 'event_timeline' && ($previous_year || $previous_month)){
1897 + $classes[] = 'has-time-separators';
1898 + }
1899 + $ret.=str_replace(
1900 + array(
1901 + '%type%',
1902 + '%id%',
1903 + '%class%',
1904 + '%listid%',
1905 + '%style%',
1906 + '%attributes%',
1907 + '%list%',
1908 + '%pagination%',
1909 + '%prev_arrow%',
1910 + '%next_arrow%',
1911 + '%number%'
1912 + ), array(
1913 + $type,
1914 + $id,
1915 + esc_attr(implode(' ', $classes)),
1916 + $id . $this->list_id,
1917 + (!empty($width) ? 'width:' . esc_attr($width) . ';' : '') . (!empty($height) ? 'height:' . esc_attr($height) . ';' : '') . esc_attr($style),
1918 + $attributes,
1919 + $html,
1920 + $pagination,
1921 + $prev_arrow,
1922 + $next_arrow
1923 + ), $container_schema
1924 + );
1925 + }
1926 +
1246 1927 }
1247 1928 elseif(filter_input(INPUT_POST, 'action')=='bulk_do_shortcode'){
1248 1929 return '<div class="event_geolist_icon_loader"><p><span class="dashicons dashicons-calendar"></span></p><p class="screen-reader-text">'.__('An empty list of events', 'event-post').'</p></div>';
1249 1930 }
@@ -1249,17 +1930,35 @@
1249 1930 }
1250 1931 return apply_filters('eventpost_listevents', $ret, $id.$this->list_id, $atts, $events, $context);
1251 1932 }
1252 1933
1934 +
1253 1935 /**
1254 - * get_events
1936 + * Get events
1937 + *
1255 1938 * @param array $atts
1939 + *
1256 1940 * @filter eventpost_params
1257 1941 * @filter eventpost_get_items
1258 - * @return array of post_ids wich are events
1942 + *
1943 + * @return array of post_ids which are events
1259 1944 */
1260 1945 public function get_events($atts) {
1261 - $paged = ( get_query_var( 'page' ) ) ? absint( get_query_var( 'page' ) ) : 1;
1946 + if(isset($atts['future'])){
1947 + $atts['future'] = filter_var( $atts['future'], FILTER_VALIDATE_BOOLEAN);
1948 + }
1949 + if(isset($atts['past'])){
1950 + $atts['past'] = filter_var( $atts['past'], FILTER_VALIDATE_BOOLEAN);
1951 + }
1952 + if(isset($atts['geo'])){
1953 + $atts['geo'] = filter_var( $atts['geo'], FILTER_VALIDATE_BOOLEAN);
1954 + }
1955 + if(isset($atts['pages'])){
1956 + $atts['pages'] = filter_var( $atts['pages'], FILTER_VALIDATE_BOOLEAN);
1957 + }
1958 +
1959 +
1960 +
1262 1961 $requete = (shortcode_atts(apply_filters('eventpost_params', array(
1263 1962 'nb' => 5,
1264 1963 'future' => true,
1265 1964 'past' => false,
@@ -1271,11 +1970,14 @@
1271 1970 'orderbykey' => $this->META_START,
1272 1971 'order' => 'ASC',
1273 1972 'tax_name' => '',
1274 1973 'tax_term' => '',
1275 - 'paged' => $paged,
1974 + 'paged' => 1,
1276 1975 'post_type'=> $this->settings['posttypes']
1277 1976 ), 'get_events'), $atts));
1977 + if(!isset($requete['paged']) || $requete['paged'] == ""){
1978 + $requete['paged'] = ( get_query_var( 'page' ) ) ? absint( get_query_var( 'page' ) ) : 1;
1979 + }
1278 1980 extract($requete);
1279 1981 wp_reset_query();
1280 1982
1281 1983
@@ -1406,9 +2108,9 @@
1406 2108 }
1407 2109
1408 2110 $arg['meta_query'] = $meta_query;
1409 2111
1410 - $query_md5 = 'eventpost_' . md5(var_export($requete, true));
2112 + $query_md5 = 'eventpost_' . md5(wp_json_encode($requete, true));
1411 2113 // Check if cache is activated
1412 2114 if ($this->settings['cache'] == 1 && false !== ( $cached_events = get_transient($query_md5) )) {
1413 2115 return apply_filters('eventpost_get_items', is_array($cached_events) ? $cached_events : array(), $requete, $arg);
1414 2116 }
@@ -1423,9 +2125,11 @@
1423 2125 'max_num_pages' => $query->max_num_pages,
1424 2126 );
1425 2127 foreach ($events as $k => $post) {
1426 2128 $event = $this->retreive($post);
1427 - $events[$k] = $event;
2129 + if ($event != false){
2130 + $events[$k] = $event;
2131 + }
1428 2132 }
1429 2133 }
1430 2134 if ($this->settings['cache'] == 1){
1431 2135 set_transient($query_md5, $events, 5 * MINUTE_IN_SECONDS);
@@ -1435,10 +2139,11 @@
1435 2139
1436 2140 /**
1437 2141 * Checks if the given event is in the future or not
1438 2142 *
1439 - * @param object $event
1440 - * @param boolean $exact Future status has to be calculated against time or entire day
2143 + * @param object $event
2144 + * @param boolean $exact Future status has to be calculated against time or entire day
2145 + *
1441 2146 * @return boolean
1442 2147 */
1443 2148 function is_future($event, $exact=false){
1444 2149 $match = current_time('timestamp');
@@ -1451,10 +2156,11 @@
1451 2156
1452 2157 /**
1453 2158 * Checks if the given event is completed or not
1454 2159 *
1455 - * @param object $event
1456 - * @param boolean $exact Past status has to be calculated against time or entire day
2160 + * @param object $event
2161 + * @param boolean $exact Past status has to be calculated against time or entire day
2162 + *
1457 2163 * @return boolean
1458 2164 */
1459 2165 function is_past($event, $exact=false){
1460 2166 $match = current_time('timestamp');
@@ -1464,25 +2170,43 @@
1464 2170 }
1465 2171 return ($event->time_end < $match);
1466 2172 }
1467 2173
2174 + /**
2175 + * Checks if an event is online
2176 + *
2177 + * @param $event
2178 + *
2179 + * @return boolean
2180 + */
1468 2181 function is_online($event){
1469 2182 return (in_array($event->attendance_mode, array('MixedEventAttendanceMode', 'OnlineEventAttendanceMode')));
1470 2183 }
1471 2184
2185 + /**
2186 + * Checks if an event is offline
2187 + *
2188 + * @param $event
2189 + *
2190 + * @return boolean
2191 + */
1472 2192 function is_offline($event){
1473 2193 return (in_array($event->attendance_mode, array('MixedEventAttendanceMode', 'OfflineEventAttendanceMode')));
1474 2194 }
1475 2195
1476 -
1477 2196 /**
1478 - *
2197 + * Populates a WP_Post object with event datas
2198 + *
1479 2199 * @param object $event
2200 + *
1480 2201 * @return object
1481 2202 */
1482 2203 public function retreive($event = null) {
1483 2204 global $EventPost_cache;
1484 2205 $ob = get_post($event);
2206 + if(!$ob){
2207 + return false;
2208 + }
1485 2209 if(is_object($ob) && $ob->start){
1486 2210 return $ob;
1487 2211 }
1488 2212 if(is_object($ob) && isset($EventPost_cache[$ob->ID])){
@@ -1499,28 +2223,37 @@
1499 2223 $ob->root_ID = $ob->ID;
1500 2224 $ob->time_start = !empty($ob->start) ? strtotime($ob->start) : '';
1501 2225 $ob->time_end = !empty($ob->end) ? strtotime($ob->end) : '';
1502 2226 $ob->virtual_location = get_post_meta($ob->ID, $this->META_VIRTUAL_LOCATION, true);
2227 + $ob->virtual_location = esc_url($ob->virtual_location);
2228 + $ob->organization = get_post_meta($ob->ID, $this->META_ORGANIZATION, true);
2229 + $ob->offer = get_post_meta($ob->ID, $this->META_OFFER, true);
2230 + if(empty($ob->offer)){
2231 + $ob->offer = array(
2232 + 'url' => null,
2233 + 'price' => null,
2234 + 'currency' => null,
2235 + );
2236 + }
1503 2237 $ob->address = get_post_meta($ob->ID, $this->META_ADD, true);
1504 - $ob->lat = get_post_meta($ob->ID, $this->META_LAT, true);
1505 - $ob->long = get_post_meta($ob->ID, $this->META_LONG, true);
2238 + $ob->lat = $this->sanitize_coordinate(get_post_meta($ob->ID, $this->META_LAT, true));
2239 + $ob->long = $this->sanitize_coordinate(get_post_meta($ob->ID, $this->META_LONG, true));
1506 2240 $ob->attendance_mode = (null != $att_mod = get_post_meta($ob->ID, $this->META_ATTENDANCE_MODE, true)) ? $att_mod : array_keys($this->attendance_modes)[0];
1507 2241 $ob->status = (null != $status = get_post_meta($ob->ID, $this->META_STATUS, true)) ? $status : array_keys($this->statuses)[0];
1508 - $ob->color = get_post_meta($ob->ID, $this->META_COLOR, true);
1509 - $ob->categories = get_the_category($ob->ID);
2242 + $ob->color = $this->get_post_color($ob->ID);
2243 + $ob->icon = $this->get_post_icon($ob->ID);
2244 + $ob->Taxonomies = get_the_category($ob->ID);
1510 2245 $ob->permalink = get_permalink($ob->ID);
1511 2246 $ob->blog_id = get_current_blog_id();
1512 - if ($ob->color == ''){
1513 - $ob->color = '000000';
1514 - }
1515 -
2247 + $ob->description = $ob->post_excerpt ? $ob->post_excerpt : str_replace('&nbsp;', ' ', preg_replace("/\n+/", "\n", trim(wp_strip_all_tags(excerpt_remove_blocks($ob->post_content)))));
1516 2248 $EventPost_cache[$ob->ID] = apply_filters('eventpost_retreive', $ob);
1517 2249 return $EventPost_cache[$ob->ID];
1518 2250 }
1519 2251
1520 2252 /**
1521 - *
1522 - * @param mixte $_term
2253 + * Fetch terms of a post
2254 + *
2255 + * @param mixed $_term
1523 2256 * @param string $taxonomy
1524 2257 * @param string $post_type
1525 2258 */
1526 2259 public function retreive_term($_term=null, $taxonomy='category', $post_type='post') {
@@ -1564,12 +2297,12 @@
1564 2297 return $term;
1565 2298
1566 2299 }
1567 2300
1568 - /** ADMIN ISSUES * */
2301 + // ADMIN ISSUES
1569 2302
1570 2303 /**
1571 - * add custom boxes in posts edit page
2304 + * Add custom boxes in posts edit page
1572 2305 */
1573 2306 public function add_custom_box() {
1574 2307 foreach($this->settings['posttypes'] as $posttype){
1575 2308 add_meta_box(
@@ -1596,42 +2329,84 @@
1596 2329 );
1597 2330 do_action('eventpost_add_custom_box', $posttype);
1598 2331 }
1599 2332 }
2333 +
1600 2334 /**
1601 - * display the date custom box
2335 + * Displays the date custom box
1602 2336 */
1603 2337 public function inner_custom_box_date() {
2338 +
2339 +
2340 +
1604 2341 wp_nonce_field(plugin_basename(__FILE__), 'eventpost_nonce');
1605 2342 $post_id = get_the_ID();
1606 2343 $event = $this->retreive($post_id);
1607 - $start_date = $event->start;
1608 - $end_date = $event->end;
1609 - $eventcolor = $event->color;
2344 + if ($event != false){
2345 + $start_date = $event->start;
2346 + $end_date = $event->end;
2347 + $eventcolor = $event->color;
2348 + $eventicon = $event->icon;
1610 2349
1611 - $language = get_bloginfo('language');
1612 - if (strpos($language, '-') > -1) {
1613 - $language = strtolower(substr($language, 0, 2));
2350 + $language = get_bloginfo('language');
2351 + if (strpos($language, '-') > -1) {
2352 + $language = strtolower(substr($language, 0, 2));
2353 + }
2354 + $colors = $this->get_colors();
2355 + include (plugin_dir_path(__FILE__) . 'views/admin/custombox-date.php');
2356 + do_action ('eventpost_custom_box_date', $event);
1614 2357 }
1615 - $colors = $this->get_colors();
1616 - include (plugin_dir_path(__FILE__) . 'views/admin/custombox-date.php');
1617 - do_action ('eventpost_custom_box_date', $event);
1618 2358 }
2359 +
1619 2360 /**
1620 - * displays the location custom box
2361 + * Displays the location custom box
1621 2362 */
1622 2363 public function inner_custom_box_loc($post) {
1623 2364 $event = $this->retreive($post);
1624 - include (plugin_dir_path(__FILE__) . 'views/admin/custombox-location.php');
1625 - do_action ('eventpost_custom_box_loc', $event);
1626 - $this->load_map_scripts();
2365 + if ($event != false){
2366 + include (plugin_dir_path(__FILE__) . 'views/admin/custombox-location.php');
2367 + do_action ('eventpost_custom_box_loc', $event);
2368 + $this->load_map_scripts();
2369 + }
1627 2370 }
1628 2371
2372 + public function icon_color_fields($item_id, $meta_color,$value_color,$meta_icon,$value_icon ){
2373 + ?>
2374 + <div class="eventpost-misc-pub-section event-color-section">
2375 + <span class="screen-reader-text"><?php esc_html_e('Color:', 'event-post'); ?></span>
2376 +
2377 + <input class="color-field-post eventpost-colorpicker"
2378 + type="text"
2379 + name="<?php echo esc_attr($meta_color); ?>"
2380 + value="<?php echo esc_attr($value_color); ?>"
2381 + id="color-field<?php echo esc_attr($item_id); ?>"/>
2382 +
2383 + <select style="font-family : dashicons;" class="eventpost-iconpicker" name="<?php echo esc_attr($meta_icon); ?>">
2384 + <option value=""><?php esc_attr_e('None','event-post') ?></option>
2385 + <?php
2386 + foreach($this->DashIcons->icons as $class => $unicode){
2387 + ?>
2388 + <option value="<?php echo esc_attr($class) ?>" <?php selected($value_icon, $class, true); ?>>&#x<?php esc_attr_e($unicode) ?>; <?php echo esc_html($class) ?></option><?php // phpcs:ignore WordPress.WP.I18n ?>
2389 + <?php
2390 + }
2391 + ?>
2392 + </select>
2393 + <div class="custom-marker-container">
2394 + <p><?php esc_html_e('An image was found in your custom folder for this color', 'event-post')?> <span class="color-hex"></span> </p>
2395 + <img src="" class="image-marker">
2396 + </div>
2397 + </div>
2398 +
2399 +
2400 + <?php
2401 + }
2402 +
1629 2403 /**
1630 - *
1631 - * @param string $column_name
1632 - * @param boolean $bulk
1633 - */
2404 + * Quick edit
2405 + *
2406 + * @param string $column_name
2407 + * @param boolean $bulk
2408 + */
1634 2409 function quick_edit( $column_name, $post_type, $bulk=false) {
1635 2410
1636 2411 if ($bulk) {
1637 2412 static $eventpostprintNonceBulk = TRUE;
@@ -1649,17 +2424,17 @@
1649 2424 $fields = $this->quick_edit_fields;
1650 2425 }
1651 2426 wp_nonce_field(plugin_basename(__FILE__), 'eventpost_nonce');
1652 2427 if(isset($fields[$column_name])): ?>
1653 - <fieldset class="inline-edit-col-left inline-edit-<?php echo $column_name; ?>">
2428 + <fieldset class="inline-edit-col-left inline-edit-<?php echo esc_attr($column_name); ?>">
1654 2429 <div class="inline-edit-group">
1655 2430 <?php foreach ($fields[$column_name] as $fieldname=>$fieldlabel): ?>
1656 - <fieldset class="inline-edit-col inline-edit-<?php echo $fieldname; ?>">
1657 - <div class="inline-edit-col column-<?php echo $fieldname; ?>">
2431 + <fieldset class="inline-edit-col inline-edit-<?php echo esc_attr($fieldname); ?>">
2432 + <div class="inline-edit-col column-<?php echo esc_attr($fieldname); ?>">
1658 2433 <label class="inline-edit-group">
1659 - <span class="title"><?php echo $fieldlabel; ?></span>
2434 + <span class="title"><?php echo esc_html($fieldlabel); ?></span>
1660 2435 <span class="input-text-wrap">
1661 - <?php echo $this->inline_field($fieldname, $bulk); ?>
2436 + <?php echo wp_kses($this->inline_field($fieldname, $bulk), $this->kses_tags); ?>
1662 2437 </span>
1663 2438 </label>
1664 2439 </div>
1665 2440 </fieldset>
@@ -1669,135 +2444,195 @@
1669 2444 <?php endif;
1670 2445 }
1671 2446
1672 2447 /**
1673 - *
2448 + * Inline field in bulk edit
2449 + *
1674 2450 * @param type $fieldname
1675 - * @return type
2451 + *
2452 + * @return string
1676 2453 */
1677 2454 function inline_field($fieldname, $bulk){
1678 - return apply_filters('eventpost_inline_field', '<input name="'.$fieldname.'" class="eventpost-inline-'.$fieldname.'" value="" type="text">', $fieldname, $bulk);
2455 + return apply_filters('eventpost_inline_field', '<input name="'.esc_attr($fieldname).'" class="eventpost-inline-'.esc_attr($fieldname).'" value="" type="text">', $fieldname, $bulk);
1679 2456 }
1680 2457
1681 2458 function inline_field_color($html, $fieldname, $bulk){
1682 2459 if($fieldname==$this->META_COLOR){
1683 - $colors = $this->get_colors();
1684 2460 $html='';
1685 2461 if($bulk){
1686 - $html.= '<span class="eventpost-bulk-colorpicker-button link">'.__('No Change', 'event-post').'</span>';
2462 + $html.= '<span class="eventpost-bulk-colorpicker-button link">'.esc_html(__('No Change', 'event-post')).'</span>';
1687 2463 }
1688 - $html .= '<select name="'.$fieldname.'" class="eventpost-inline-colorpicker eventpost-inline-'.$fieldname.' '.($bulk?'is-bulk':'no-bulk').'" >';
2464 + $html .= '
2465 +
2466 + <input class="eventpost-inline-colorpicker eventpost-inline-'.esc_attr($fieldname).' '.($bulk?'is-bulk':'no-bulk').'" type="color" name="'.esc_attr($fieldname).'" >';
2467 + }
2468 + return $html;
2469 + }
2470 + function inline_field_icon($html, $fieldname, $bulk){
2471 + if($fieldname==$this->META_ICON){
1689 2472 if($bulk){
1690 - $html.='<option value="false">— '.__('No Change', 'event-post').' —</option>';
2473 + $html.= '<span class="eventpost-bulk-icon-button link">'.__('No Change', 'event-post').'</span>';
1691 2474 }
1692 - foreach ($colors as $color=>$image_path){
1693 - $html.='<option value="'.$color.'" data-path="'.$image_path.'">'.$color.'</option>';
2475 + $html = '<select class="eventpost-inline-colorpicker eventpost-inline-'.$fieldname.' '.($bulk?'is-bulk':'no-bulk').'"
2476 + type="text"
2477 + name="'.$fieldname.'"
2478 + style="font-family : dashicons">
2479 + <option value="">'.__("None", 'event-post').'</option>';
2480 + foreach($this->DashIcons->icons as $class => $unicode){
2481 + $html .= '<option value="'.$class.'">&#x'.$unicode.'; '.$class.'</option>';
1694 2482 }
1695 - $html.= '</select>';
2483 + $html .= '</select>';
2484 +
1696 2485 }
1697 2486 return $html;
1698 2487 }
1699 2488
2489 +
1700 2490 /**
1701 - *
2491 + * Bulk edit
2492 + *
1702 2493 * @param type $column_name
1703 2494 * @param type $post_type
1704 2495 */
1705 2496 function bulk_edit($column_name, $post_type){
1706 - $this->quick_edit($column_name, $post_type, true);
2497 + $this->quick_edit($column_name, $post_type, true);
1707 2498 }
1708 2499
1709 2500 /**
1710 - *
2501 + * Saves data from quick-edit via `wp_ajax_inline-save` action
2502 + *
2503 + * @return void
1711 2504 */
1712 2505 function inline_save(){
1713 - $post_id = filter_input(INPUT_POST, 'post_ID', FILTER_SANITIZE_NUMBER_INT);
2506 + $post_id = absint(filter_input(INPUT_POST, 'post_ID', FILTER_SANITIZE_NUMBER_INT));
1714 2507 $this->save_postdata($post_id);
1715 2508 }
1716 2509 /**
1717 2510 * When the post is saved, saves our custom data
2511 + *
1718 2512 * @param int $post_id
2513 + *
1719 2514 * @return void
1720 2515 */
1721 2516 public function save_postdata($post_id) {
1722 2517 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
1723 2518 return;
1724 - }
2519 + }
1725 2520
1726 - if (!wp_verify_nonce(filter_input(INPUT_POST, 'eventpost_nonce', FILTER_SANITIZE_STRING), plugin_basename(__FILE__))){
2521 + if (!wp_verify_nonce((string) filter_input(INPUT_POST, 'eventpost_nonce'), plugin_basename(__FILE__))){
1727 2522 return;
1728 - }
2523 + }
1729 2524
2525 + $post_id = absint($post_id);
2526 + if (!$post_id || !current_user_can('edit_post', $post_id)) {
2527 + return;
2528 + }
2529 +
1730 2530 // Clean color or no color
1731 - if (false !== $color = filter_input(INPUT_POST, $this->META_COLOR, FILTER_SANITIZE_STRING)) {
1732 - update_post_meta($post_id, $this->META_COLOR, $color);
2531 + if (false !== $color = filter_input(INPUT_POST, $this->META_COLOR)) {
2532 + update_post_meta($post_id, $this->META_COLOR, sanitize_text_field($color));
1733 2533 }
1734 - if (false !== $attendance_mode = filter_input(INPUT_POST, $this->META_ATTENDANCE_MODE, FILTER_SANITIZE_STRING)) {
1735 - update_post_meta($post_id, $this->META_ATTENDANCE_MODE, $attendance_mode);
2534 + // Clean color or no color
2535 + if (false !== $icon = filter_input(INPUT_POST, $this->META_ICON)) {
2536 + update_post_meta($post_id, $this->META_ICON, sanitize_text_field($icon));
1736 2537 }
1737 - if (false !== $status = filter_input(INPUT_POST, $this->META_STATUS, FILTER_SANITIZE_STRING)) {
1738 - update_post_meta($post_id, $this->META_STATUS, $status);
2538 + if (false !== $attendance_mode = filter_input(INPUT_POST, $this->META_ATTENDANCE_MODE)) {
2539 + update_post_meta($post_id, $this->META_ATTENDANCE_MODE, sanitize_text_field($attendance_mode));
1739 2540 }
1740 - if (false !== $virtual_location = filter_input(INPUT_POST, $this->META_VIRTUAL_LOCATION, FILTER_SANITIZE_URL)) {
1741 - update_post_meta($post_id, $this->META_VIRTUAL_LOCATION, $virtual_location);
2541 + if (false !== $status = filter_input(INPUT_POST, $this->META_STATUS)) {
2542 + update_post_meta($post_id, $this->META_STATUS, sanitize_text_field($status));
1742 2543 }
2544 + $virtual_location = filter_input(INPUT_POST, $this->META_VIRTUAL_LOCATION, FILTER_SANITIZE_URL);
2545 + if ($virtual_location !== null && $virtual_location !== false) {
2546 + update_post_meta($post_id, $this->META_VIRTUAL_LOCATION, sanitize_url($virtual_location));
2547 + }
2548 + if (false !== $organization = filter_input(INPUT_POST, $this->META_ORGANIZATION)) {
2549 + update_post_meta($post_id, $this->META_ORGANIZATION, sanitize_text_field($organization));
2550 + }
2551 + $offer_url = filter_input(INPUT_POST, "{$this->META_OFFER}_url", FILTER_SANITIZE_URL);
2552 + $offer_price = filter_input(INPUT_POST, "{$this->META_OFFER}_price");
2553 + $offer_currency = filter_input(INPUT_POST, "{$this->META_OFFER}_currency");
2554 + if ($offer_url || ($offer_price && $offer_currency) ) {
2555 + // Format floating
2556 + $offer_price = $offer_price ? str_replace(',', '.', $offer_price) : null;
2557 + update_post_meta($post_id, $this->META_OFFER, array(
2558 + 'url' => $offer_url ? sanitize_text_field($offer_url) : null,
2559 + 'price' => $offer_price ? (float) $offer_price : null,
2560 + 'currency' => $offer_currency ? sanitize_text_field($offer_currency) : null,
2561 + ));
2562 + }
2563 + else{
2564 + delete_post_meta($post_id, $this->META_OFFER);
2565 + }
1743 2566 // Clean date or no date
1744 - if ((false !== $start = filter_input(INPUT_POST, $this->META_START, FILTER_SANITIZE_STRING)) &&
1745 - (false !== $end = filter_input(INPUT_POST, $this->META_END, FILTER_SANITIZE_STRING)) &&
1746 - '' != $start &&
1747 - '' != $end) {
1748 - update_post_meta($post_id, $this->META_START, substr($start,0,16).':00');
1749 - update_post_meta($post_id, $this->META_END, substr($end,0,16).':00');
2567 + if ((false !== $start = filter_input(INPUT_POST, $this->META_START)) &&
2568 + (false !== $end = filter_input(INPUT_POST, $this->META_END)) &&
2569 + '' != $start &&
2570 + '' != $end) {
2571 + update_post_meta($post_id, $this->META_START, sanitize_text_field(substr($start,0,16).':00'));
2572 + update_post_meta($post_id, $this->META_END, sanitize_text_field(substr($end,0,16).':00'));
1750 2573 }
1751 - else {
1752 - delete_post_meta($post_id, $this->META_START);
1753 - delete_post_meta($post_id, $this->META_END);
1754 - }
2574 + else {
2575 + delete_post_meta($post_id, $this->META_START);
2576 + delete_post_meta($post_id, $this->META_END);
2577 + }
1755 2578
1756 - // Clean location or no location
1757 - if ((false !== $lat = filter_input(INPUT_POST, $this->META_LAT, FILTER_SANITIZE_STRING)) &&
1758 - (false !== $long = filter_input(INPUT_POST, $this->META_LONG, FILTER_SANITIZE_STRING)) &&
1759 - '' != $lat &&
1760 - '' != $long) {
1761 - update_post_meta($post_id, $this->META_ADD, filter_input(INPUT_POST, $this->META_ADD, FILTER_SANITIZE_STRING));
1762 - update_post_meta($post_id, $this->META_LAT, $lat);
1763 - update_post_meta($post_id, $this->META_LONG, $long);
1764 - }
1765 - else {
1766 - delete_post_meta($post_id, $this->META_ADD);
1767 - delete_post_meta($post_id, $this->META_LAT);
1768 - delete_post_meta($post_id, $this->META_LONG);
1769 - }
2579 + // Clean location or no location
2580 + if ((false !== $lat = filter_input(INPUT_POST, $this->META_LAT)) &&
2581 + (false !== $long = filter_input(INPUT_POST, $this->META_LONG)) &&
2582 + '' != $lat &&
2583 + '' != $long) {
2584 + update_post_meta($post_id, $this->META_ADD, sanitize_text_field(filter_input(INPUT_POST, $this->META_ADD)));
2585 + update_post_meta($post_id, $this->META_LAT, $this->sanitize_coordinate(sanitize_text_field($lat)));
2586 + update_post_meta($post_id, $this->META_LONG, $this->sanitize_coordinate(sanitize_text_field($long)));
2587 + }
2588 + else {
2589 + delete_post_meta($post_id, $this->META_ADD);
2590 + delete_post_meta($post_id, $this->META_LAT);
2591 + delete_post_meta($post_id, $this->META_LONG);
2592 + }
1770 2593
1771 2594 $post_ids = (!empty($_POST['post_ids']) ) ? $_POST['post_ids'] : array();
1772 2595 }
1773 2596
1774 - function save_bulkdatas() {
1775 - $current_post_type = isset($_GET['post_type']) ? $_GET['post_type'] : 'post';
2597 + /**
2598 + * Saves data from bulk-edit
2599 + * Uses bulk_edit_posts hook
2600 + *
2601 + * @see https://developer.wordpress.org/reference/hooks/bulk_edit_posts/
2602 + *
2603 + * @return void
2604 + */
2605 + function save_bulkdatas(array $post_ids, array $shared_post_data) {
2606 + if (!wp_verify_nonce(filter_input(INPUT_GET, 'eventpost_nonce'), plugin_basename(__FILE__))){
2607 + return;
2608 + }
2609 + $current_post_type = isset($shared_post_data['post_type']) ? $shared_post_data['post_type'] : 'post';
1776 2610 if (in_array($current_post_type, $this->settings['posttypes'])) {
1777 - $post_ids = (!empty($_POST['post_ids']) ) ? $_POST['post_ids'] : array();
1778 2611 if (!empty($post_ids) && is_array($post_ids)) {
1779 - foreach ($this->bulk_edit_fields as $sets) {
1780 - foreach ($sets as $fieldname => $fieldlabel) {
1781 - if ((false != $value = filter_input(INPUT_POST, $fieldname))) {
1782 - foreach ($post_ids as $post_id) {
1783 - update_post_meta($post_id, $fieldname, $value);
2612 + foreach ($post_ids as $post_id) {
2613 + if(! current_user_can( 'edit_post', $post_id )){
2614 + continue;
2615 + }
2616 + foreach ($this->bulk_edit_fields as $sets) {
2617 + foreach ($sets as $fieldname => $fieldlabel) {
2618 + if (isset($shared_post_data[$fieldname])) {
2619 + update_post_meta($post_id, $fieldname, $shared_post_data[$fieldname]);
1784 2620 }
1785 2621 }
1786 2622 }
1787 2623 }
1788 2624 }
1789 - wp_send_json(true);
1790 - exit;
1791 2625 }
1792 - wp_send_json(false);
1793 2626 }
1794 2627
1795 2628 /**
1796 - *
2629 + * Displays a date for calendar cell
2630 + *
1797 2631 * @param string $date
1798 2632 * @param string $cat
1799 2633 * @param boolean $display
2634 + *
1800 2635 * @return boolean
1801 2636 */
1802 2637 public function display_caldate($date, $cat = '', $display = false, $colored=true, $thumbnail='', $title='',$tax_name='' ,$tax_term='') {
1803 2638 $events = $this->get_events(array('nb' => -1, 'date' => $date, 'cat' => $cat, 'retreive' => true,'tax_name' => $tax_name ,'tax_term' => $tax_term));
@@ -1802,21 +2637,26 @@
1802 2637 public function display_caldate($date, $cat = '', $display = false, $colored=true, $thumbnail='', $title='',$tax_name='' ,$tax_term='') {
1803 2638 $events = $this->get_events(array('nb' => -1, 'date' => $date, 'cat' => $cat, 'retreive' => true,'tax_name' => $tax_name ,'tax_term' => $tax_term));
1804 2639 $nb = count($events);
1805 2640 $ret = "";
2641 + $price = "";
1806 2642 if(!$display && !$nb){
1807 2643 $ret = date('j', $date);
1808 2644 }
2645 + $price = '';
1809 2646 if($nb){
1810 2647 if ($display || $title) {
1811 2648 $ret='<ul>';
1812 2649 foreach ($events as $event) {
2650 + $price = $this->get_price($event, true);
1813 2651 if ($this->settings['emptylink'] == 0 && empty($event->post_content)) {
1814 2652 $event->guid = '#';
1815 2653 }
1816 2654 $ret.='<li>'
2655 + // Translators: %s is the event title
1817 2656 . '<a href="' . $event->permalink . '" title="'.esc_attr(sprintf(__('View event: %s', 'event-post'), $event->post_title)).'">'
1818 2657 . '<h4>' . $event->post_title . '</h4>'
2658 + . '<span class="event_price">' . $price . '</span>'
1819 2659 .$this->get_single($event)
1820 2660 . (!empty($thumbnail) ? '<span class="event_thumbnail_wrap">' . get_the_post_thumbnail($event->ID, $thumbnail) . '</span>' : '')
1821 2661 .'</a>'
1822 2662 . '</li>';
@@ -1831,8 +2671,9 @@
1831 2671 }
1832 2672 else {
1833 2673 $ret = '<button data-event="'. $tax_term .'" data-date="' . date('Y-m-d', $date).'"'
1834 2674 .' class="'.apply_filters( 'event_post_class_calendar_link', 'eventpost_cal_link' ).'"'.($colored?' style="background-color:#'.$events[0]->color.'"':'')
2675 + // Translators: %1$d is the number of events, %2$s is the date
1835 2676 .' title="'.esc_attr(sprintf(_n('View %1$d event at date %2$s', 'View %1$d events at date %2$s', $nb, 'event-post'), $nb, $this->human_date($date, $this->settings['dateformat']))).'"'
1836 2677 .'>'
1837 2678 . date('j', $date)
1838 2679 . '</button>';
@@ -1837,16 +2678,19 @@
1837 2678 . date('j', $date)
1838 2679 . '</button>';
1839 2680 }
1840 2681 }
1841 -
1842 - return apply_filters('eventpost_display_caldate', $ret, $events, $date, $cat ,$display ,$colored ,$thumbnail ,$title ,$tax_name ,$tax_term );
2682 + return apply_filters('eventpost_display_caldate', $ret, $events, $date, $cat ,$price, $display ,$colored ,$thumbnail ,$title ,$tax_name ,$tax_term );
1843 2683 }
1844 2684
1845 2685
1846 2686 /**
2687 + * Returns a calendar HTML
2688 + *
1847 2689 * @param array $atts
2690 + *
1848 2691 * @filter eventpost_params
2692 + *
1849 2693 * @return string
1850 2694 */
1851 2695 public function calendar($atts) {
1852 2696 extract(shortcode_atts(apply_filters('eventpost_params', array(
@@ -1895,14 +2739,18 @@
1895 2739 . '</caption>';
1896 2740 $ret.='<thead><tr><th colspan="7">';
1897 2741 if ($datepicker == 1) {
1898 2742 $ret.='<div class="eventpost-calendar-header">';
2743 + // Translators: %s is the year
1899 2744 $ret.='<span class="eventpost-cal-year"><button data-date="' . date('Y-n', $prev_year) . '" tabindex="0" title="'.sprintf(__('Switch to %s', 'event-post'), date('Y', $prev_year)).'" class="eventpost_cal_bt eventpost-cal-bt-prev">&laquo;</button><span class="eventpost-cal-header-text">';
1900 2745 $ret.=$annee;
2746 + // Translators: %s is the year
1901 2747 $ret.='</span><button data-date="' . date('Y-n', $next_year) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date('Y', $next_year)).'" class="eventpost_cal_bt eventpost-cal-bt-next">&raquo;</button></span>';
1902 - $ret.='<span class="eventpost-cal-month"><button data-date="' . date('Y-n', $prev_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $prev_month)).'" class="eventpost_cal_bt eventpost-cal-bt-prev">&laquo;</button><span class="eventpost-cal-header-text">';
2748 + // Translators: %s is the month name
2749 + $ret.='<span class="eventpost-cal-month"><button data-date="' . date('Y-n', $prev_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $prev_month)).'" class="eventpost_cal_bt eventpost-cal-bt-prev eventpost-cal-bt-prev-month">&laquo;</button><span class="eventpost-cal-header-text">';
1903 2750 $ret.=$this->NomDuMois[abs($mois)];
1904 - $ret.='</span><button data-date="' . date('Y-n', $next_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $next_month)).'" class="eventpost_cal_bt eventpost-cal-bt-next">&raquo;</button> </span>';
2751 + // Translators: %s is the month name
2752 + $ret.='</span><button data-date="' . date('Y-n', $next_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $next_month)).'" class="eventpost_cal_bt eventpost-cal-bt-next eventpost-cal-bt-next-month">&raquo;</button> </span>';
1905 2753 $ret.='<span class="eventpost-cal-today"><button data-date="' . date('Y-n') . '" class="eventpost_cal_bt">' . __('Today', 'event-post') . '</button></span>';
1906 2754 $ret.='</div>';
1907 2755 }
1908 2756 $ret.='</th></tr><tr class="event_post_cal_days">';
@@ -1942,10 +2790,15 @@
1942 2790 $ret.='</tbody></table>';
1943 2791 return $ret;
1944 2792 }
1945 2793
2794 + /**
2795 + * Echoes a list of event, should be called via AJAX
2796 + *
2797 + * @return void
2798 + */
1946 2799 public function ajaxlist(){
1947 - echo $this->list_events(array(
2800 + echo wp_kses($this->list_events(array(
1948 2801 'nb' => esc_attr(FILTER_INPUT(INPUT_POST, 'nb')),
1949 2802 'future' => esc_attr(FILTER_INPUT(INPUT_POST, 'future')),
1950 2803 'past' => esc_attr(FILTER_INPUT(INPUT_POST, 'past')),
1951 2804 'geo' => esc_attr(FILTER_INPUT(INPUT_POST, 'geo')),
@@ -1966,18 +2819,93 @@
1966 2819 'orderby' => esc_attr(FILTER_INPUT(INPUT_POST, 'orderby')),
1967 2820 'order' => esc_attr(FILTER_INPUT(INPUT_POST, 'order')),
1968 2821 'class' => esc_attr(FILTER_INPUT(INPUT_POST, 'class')),
1969 2822 'pages' => esc_attr(FILTER_INPUT(INPUT_POST, 'pages')),
1970 - ), esc_attr(FILTER_INPUT(INPUT_POST, 'list_type')));
2823 + ), esc_attr(FILTER_INPUT(INPUT_POST, 'list_type'))), $this->kses_tags);
1971 2824 exit;
1972 2825 }
1973 2826
1974 2827 /**
1975 - * echoes the content of the calendar in ajax context
2828 + * Echoes a list of event, should be called via AJAX
2829 + *
2830 + * @return void
1976 2831 */
2832 + public function ajaxTimeline(){
2833 + echo wp_kses($this->list_events(array(
2834 + 'nb' => esc_attr(FILTER_INPUT(INPUT_POST, 'nb')),
2835 + 'future' => esc_attr(FILTER_INPUT(INPUT_POST, 'future')),
2836 + 'past' => esc_attr(FILTER_INPUT(INPUT_POST, 'past')),
2837 + 'geo' => esc_attr(FILTER_INPUT(INPUT_POST, 'geo')),
2838 + 'width' => esc_attr(FILTER_INPUT(INPUT_POST, 'width')),
2839 + 'height' => esc_attr(FILTER_INPUT(INPUT_POST, 'height')),
2840 + 'zoom' => esc_attr(FILTER_INPUT(INPUT_POST, 'zoom')),
2841 + 'tile' => esc_attr(FILTER_INPUT(INPUT_POST, 'tile')),
2842 + 'title' => esc_attr(FILTER_INPUT(INPUT_POST, 'title')),
2843 + 'before_title' => esc_attr(FILTER_INPUT(INPUT_POST, 'before_title')),
2844 + 'after_title' => esc_attr(FILTER_INPUT(INPUT_POST, 'after_title')),
2845 + 'cat' => esc_attr(FILTER_INPUT(INPUT_POST, 'cat')),
2846 + 'tag' => esc_attr(FILTER_INPUT(INPUT_POST, 'tag')),
2847 + 'events' => esc_attr(FILTER_INPUT(INPUT_POST, 'events')),
2848 + 'style' => esc_attr(FILTER_INPUT(INPUT_POST, 'style')),
2849 + 'thumbnail' => esc_attr(FILTER_INPUT(INPUT_POST, 'thumbnail')),
2850 + 'thumbnail_size' => esc_attr(FILTER_INPUT(INPUT_POST, 'thumbnail_size')),
2851 + 'excerpt' => esc_attr(FILTER_INPUT(INPUT_POST, 'excerpt')),
2852 + 'orderby' => esc_attr(FILTER_INPUT(INPUT_POST, 'orderby')),
2853 + 'order' => esc_attr(FILTER_INPUT(INPUT_POST, 'order')),
2854 + 'class' => esc_attr(FILTER_INPUT(INPUT_POST, 'class')),
2855 + 'pages' => esc_attr(FILTER_INPUT(INPUT_POST, 'pages')),
2856 + ), esc_attr(FILTER_INPUT(INPUT_POST, 'list_type'))), $this->kses_tags);
2857 + exit;
2858 + }
2859 + /**
2860 + * Echoes next page of events, should be called via AJAX
2861 + *
2862 + * @return void
2863 + */
2864 + public function ajaxGetNextPage(){
2865 + $response = [
2866 + "success" => false,
2867 + "next_query" => false,
2868 + ];
2869 + if(isset($_POST['query'])){
2870 + parse_str($_POST['query'],$query);
2871 + foreach($query as $key => $value){
2872 + $query[$key] = esc_attr($value);
2873 + }
2874 + if(isset($_POST['paged'])){
2875 + $query["paged"] = esc_attr($_POST['paged']);
2876 + }else{
2877 + $response['message'] = __('Page number missing', 'event-post');
2878 + }
2879 + $query['container_schema'] = $this->timeline_shema['container'];
2880 + $query['item_schema'] = $this->timeline_shema['item'];
2881 + $html = $this->list_events($query,'event_timeline','events_only');
2882 + if($html == ""){
2883 + $response['message'] = __('No more to load', 'event-post');
2884 + }else{
2885 + $query["paged"] = $query["paged"] + 1;
2886 + $next_html = $this->list_events($query,'event_timeline','events_only');
2887 + $response = [
2888 + "success" => true,
2889 + "html" => $html,
2890 + "next_query" => $next_html == "" ? false : true,
2891 + ];
2892 + }
2893 + }else{
2894 + $response['message'] = __('Query missing', 'event-post');
2895 + }
2896 + wp_send_json($response);
2897 + exit;
2898 + }
2899 +
2900 + /**
2901 + * Echoes the content of the calendar in ajax context
2902 + *
2903 + * @return void
2904 + */
1977 2905 public function ajaxcal() {
1978 2906 $method = isset($_GET['action']) ? INPUT_GET : INPUT_POST;
1979 - echo $this->calendar(array(
2907 + echo wp_kses($this->calendar(array(
1980 2908 'date' => esc_attr(FILTER_INPUT($method, 'date')),
1981 2909 'cat' => esc_attr(FILTER_INPUT($method, 'cat')),
1982 2910 'mondayfirst' => esc_attr(FILTER_INPUT($method, 'mf')),
1983 2911 'datepicker' => esc_attr(FILTER_INPUT($method, 'dp')),
@@ -1985,17 +2913,17 @@
1985 2913 'display_title' => esc_attr(FILTER_INPUT($method, 'display_title')),
1986 2914 'thumbnail' => esc_attr(FILTER_INPUT($method, 'thumbnail')),
1987 2915 'tax_name' => esc_attr(FILTER_INPUT($method, 'tax_name')),
1988 2916 'tax_term' => esc_attr(FILTER_INPUT($method, 'tax_term')),
1989 - ));
2917 + )), $this->kses_tags);
1990 2918 exit();
1991 2919 }
1992 2920
1993 2921 /**
1994 - * echoes the date of the calendar in ajax context
2922 + * Echoes the date of the calendar in ajax context
1995 2923 */
1996 2924 public function ajaxdate() {
1997 - echo $this->display_caldate(
2925 + echo wp_kses($this->display_caldate(
1998 2926 strtotime(esc_attr(FILTER_INPUT(INPUT_GET, 'date'))),
1999 2927 esc_attr(FILTER_INPUT(INPUT_GET, 'cat')),
2000 2928 true,
2001 2929 esc_attr(FILTER_INPUT(INPUT_GET, 'color')),
@@ -2002,19 +2930,19 @@
2002 2930 esc_attr(FILTER_INPUT(INPUT_GET, 'thumbnail')),
2003 2931 esc_attr(FILTER_INPUT(INPUT_GET, 'display_title')),
2004 2932 esc_attr(FILTER_INPUT(INPUT_GET, 'tax_name')),
2005 2933 esc_attr(FILTER_INPUT(INPUT_GET, 'tax_term'))
2006 - );
2934 + ), $this->kses_tags);
2007 2935 exit();
2008 2936 }
2009 2937
2010 2938 /**
2011 - * echoes a date in ajax context
2939 + * Echoes a date in ajax context
2012 2940 */
2013 2941 public function HumanDate() {
2014 2942 if (isset($_REQUEST['date']) && !empty($_REQUEST['date'])) {
2015 2943 $date = strtotime($_REQUEST['date']);
2016 - echo $this->human_date($date, $this->settings['dateformat']).(date('H:i', $date)=='00:00' ? '' : ' '. date($this->settings['timeformat'], $date));
2944 + echo esc_html($this->human_date($date, $this->settings['dateformat']).(date('H:i', $date)=='00:00' ? '' : ' '. date($this->settings['timeformat'], $date)));
2017 2945 exit();
2018 2946 }
2019 2947 }
2020 2948
@@ -2021,8 +2949,9 @@
2021 2949 /**
2022 2950 * Displays a search form
2023 2951 *
2024 2952 * @param type $atts
2953 + *
2025 2954 * @return type
2026 2955 */
2027 2956 public function search($atts) {
2028 2957 $params = shortcode_atts(apply_filters('eventpost_params', array(
@@ -2093,8 +3022,54 @@
2093 3022 }
2094 3023 }
2095 3024
2096 3025 /**
3026 + * Geocodes an address using OpenStreetMap Nominatim API and cache the result in a transient for 30 days
3027 + *
3028 + * @param string $address
3029 + * @param boolean $single_result Whether to return only the first result or all results
3030 + *
3031 + * @return array|false|string The geocoding result(s) or false on failure
3032 + */
3033 + public function geocode(string $address, bool $single_result = false){
3034 + $transient_name = 'eventpost_osquery_' . $address;
3035 + $val = get_transient($transient_name);
3036 + if (false === $val || empty($val) || !is_string($val)) {
3037 + $language = get_bloginfo('language');
3038 + if (strpos($language, '-') > -1) {
3039 + $language = strtolower(substr($language, 0, 2));
3040 + }
3041 + $remote_val = wp_safe_remote_request('https://nominatim.openstreetmap.org/search?q=' . rawurlencode($address) . '&format=json&accept-language=' . $language, [
3042 + 'user-agent' => getenv('HTTP_USER_AGENT') ?? 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url'),
3043 + 'headers' => [
3044 + 'Referer' => get_bloginfo('url'),
3045 + ],
3046 + 'timeout' => 5,
3047 + ]);
3048 + $remote_body = wp_remote_retrieve_body($remote_val);
3049 + if(strstr($remote_body, '<html>')){
3050 + $val = [
3051 + [
3052 + 'lat' => '',
3053 + 'lon' => '',
3054 + 'display_name' => strip_tags($remote_body),
3055 + ]
3056 + ];
3057 + }
3058 + else{
3059 + $val = json_decode($remote_body);
3060 + if($val){
3061 + set_transient($transient_name, $val, 30 * DAY_IN_SECONDS);
3062 + }
3063 + }
3064 + }
3065 + if($single_result && is_array($val) && count($val) > 0){
3066 + $val = $val[0];
3067 + }
3068 + return $val;
3069 + }
3070 +
3071 + /**
2097 3072 * AJAX Get lat long from address
2098 3073 */
2099 3074 public function GetLatLong() {
2100 3075 if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
@@ -2100,31 +3075,22 @@
2100 3075 if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
2101 3076 // verifier le cache
2102 3077 $q = $_REQUEST['q'];
2103 3078 header('Content-Type: application/json');
2104 - $transient_name = 'eventpost_osquery_' . $q;
2105 - $val = get_transient($transient_name);
2106 - if (false === $val || empty($val) || !is_string($val)) {
2107 - $language = get_bloginfo('language');
2108 - if (strpos($language, '-') > -1) {
2109 - $language = strtolower(substr($language, 0, 2));
2110 - }
2111 - $remote_val = wp_safe_remote_request('http://nominatim.openstreetmap.org/search?q=' . urlencode($q) . '&format=json&accept-language=' . $language);
2112 - if(json_decode($remote_val['body'])){
2113 - $val = $remote_val['body'];
2114 - }
2115 - set_transient($transient_name, $val, 30 * DAY_IN_SECONDS);
2116 - }
2117 - echo $val;
3079 + $val = $this->geocode($q);
3080 + wp_send_json( $val );
2118 3081 exit();
2119 3082 }
2120 3083 }
2121 3084
2122 3085 /**
2123 - * alters columns
3086 + * Alters columns
3087 + *
2124 3088 * @param array $defaults
3089 + *
3090 + * @filter eventpost_columns_head
3091 + *
2125 3092 * @return array
2126 - * @filter eventpost_columns_head
2127 3093 */
2128 3094 public function columns_head($defaults) {
2129 3095 $defaults['event'] = __('Event', 'event-post');
2130 3096 $defaults['location'] = __('Location', 'event-post');
@@ -2131,34 +3097,40 @@
2131 3097 return apply_filters('eventpost_columns_head', $defaults);
2132 3098 }
2133 3099
2134 3100 /**
2135 - * echoes content of a row in a given column
3101 + * Echoes content of a row in a given column
3102 + *
2136 3103 * @param string $column_name
2137 3104 * @param int $post_id
3105 + *
2138 3106 * @action eventpost_columns_content
2139 3107 */
2140 3108 public function columns_content($column_name, $post_id) {
2141 3109 if ($column_name == 'location') {
2142 - $lat = get_post_meta($post_id, $this->META_LAT, true);
2143 - $lon = get_post_meta($post_id, $this->META_LONG, true);
3110 + $lat = $this->sanitize_coordinate(get_post_meta($post_id, $this->META_LAT, true));
3111 + $lon = $this->sanitize_coordinate(get_post_meta($post_id, $this->META_LONG, true));
2144 3112
2145 3113 if (!empty($lat) && !empty($lon)) {
2146 3114 add_thickbox();
2147 - $color = get_post_meta($post_id, $this->META_COLOR, true);
3115 + $color = $this->get_post_color($post_id, $this->settings['default_color'], true);
3116 + $icon = $this->get_post_icon($post_id, $this->settings['default_icon'], true);
2148 3117 if ($color == ''){
2149 3118 $color = '777777';
2150 - }
2151 - echo '<a href="https://www.openstreetmap.org/export/embed.html?bbox='.($lon-0.005).'%2C'.($lat-0.005).'%2C'.($lon+0.005).'%2C'.($lat+0.005).'&TB_iframe=true&width=600&height=550" class="thickbox" target="_blank">'
2152 - . '<i class="dashicons dashicons-location" style="color:#'.$color.';"></i>'
3119 + }
3120 + if ($icon == ''){
3121 + $icon = 'location';
3122 + }
3123 + echo wp_kses( '<a href="https://www.openstreetmap.org/export/embed.html?bbox='.($lon-0.005).'%2C'.($lat-0.005).'%2C'.($lon+0.005).'%2C'.($lat+0.005).'&TB_iframe=true&width=600&height=550" class="thickbox" target="_blank">'
3124 + . '<i class="dashicons dashicons-'.$icon.'" style="color:#'.$color.';"></i>'
2153 3125 . '<span class="screen-reader-text">'.__('View on a map', 'event-post').'</span>'
2154 3126 . get_post_meta($post_id, $this->META_ADD, true)
2155 - . '</a> ';
3127 + . '</a> ', $this->kses_tags);
2156 3128 }
2157 3129 $this->column_edit_hidden_fields($post_id, 'location');
2158 3130 }
2159 3131 if ($column_name == 'event') {
2160 - echo $this->print_date($post_id, false);
3132 + echo wp_kses($this->print_date($post_id, false), $this->kses_tags);
2161 3133 $this->column_edit_hidden_fields($post_id, 'event');
2162 3134 }
2163 3135 do_action('eventpost_columns_content', $column_name, $post_id);
2164 3136 }
@@ -2164,20 +3136,25 @@
2164 3136 }
2165 3137
2166 3138 function column_edit_hidden_fields($post_id, $set){
2167 3139 $event = $this->retreive($post_id);
2168 - echo '<div class="hidden">';
2169 - foreach($this->quick_edit_fields[$set] as $fieldname=>$fieldlabel){
2170 - echo'<span class="inline-edit-value '.$fieldname.'">'.esc_attr($event->$fieldname).'</span>';
3140 + $html = '<div class="hidden">';
3141 + if ($event != false){
3142 + foreach($this->quick_edit_fields[$set] as $fieldname=>$fieldlabel){
3143 + $html .= '<span class="inline-edit-value '.$fieldname.'">'.esc_attr($event->$fieldname).'</span>';
3144 + }
2171 3145 }
2172 - echo '</div>';
3146 + $html .= '</div>';
3147 + echo wp_kses($html, $this->kses_tags);
2173 3148 }
2174 3149
2175 - /** ADMIN PAGES **/
3150 + // ADMIN PAGES
2176 3151
2177 3152 /**
2178 - * adds items to the native "right now" dashboard widget
3153 + * Adds items to the native "right now" dashboard widget
3154 + *
2179 3155 * @param array $elements
3156 + *
2180 3157 * @return array
2181 3158 */
2182 3159 public function dashboard_right_now($elements){
2183 3160 $nb_date = count($this->get_events(array('future'=>1, 'past'=>1, 'nb'=>-1)));
@@ -2182,11 +3159,13 @@
2182 3159 public function dashboard_right_now($elements){
2183 3160 $nb_date = count($this->get_events(array('future'=>1, 'past'=>1, 'nb'=>-1)));
2184 3161 $nb_geo = count($this->get_events(array('future'=>1, 'past'=>1, 'geo'=>1, 'nb'=>-1)));
2185 3162 if($nb_date){
3163 + // Translators: %d is the number of events
2186 3164 array_push($elements, '<i class="dashicons dashicons-calendar"></i> <i href="edit.php?post_type=post">'.sprintf(__('%d Events','event-post'), $nb_date)."</i>");
2187 3165 }
2188 3166 if($nb_geo){
3167 + // Translators: %d is the number of geolocalized events
2189 3168 array_push($elements, '<i class="dashicons dashicons-location"></i> <i href="edit.php?post_type=post">'.sprintf(__('%d Geolocalized events','event-post'), $nb_geo)."</i>");
2190 3169 }
2191 3170 return $elements;
2192 3171 }
@@ -2191,19 +3170,21 @@
2191 3170 return $elements;
2192 3171 }
2193 3172
2194 3173 /*
2195 - * feed
3174 + * Feed
2196 3175 * generate ICS or VCS files from a category
2197 3176 */
2198 3177
2199 3178 /**
2200 - *
3179 + * Get a date formatted for ICS
3180 + *
2201 3181 * @param timestamp $timestamp
3182 + *
2202 3183 * @return string
2203 3184 */
2204 3185 public function ics_date($timestamp){
2205 - return date("Ymd",$timestamp).'T'.date("His",$timestamp);
3186 + return date("Ymd",$timestamp).'T'.date("His",$timestamp);
2206 3187 }
2207 3188
2208 3189 public function get_gmt_offset(){
2209 3190 $gmt_offset = get_option('gmt_offset ');
@@ -2217,16 +3198,34 @@
2217 3198 }
2218 3199 return $gmt_offset;
2219 3200 }
2220 3201
3202 + /**
3203 + * Outputs an ICS or VCS file for a given event
3204 + *
3205 + * @param int $event_id
3206 + * @param string $format
3207 + *
3208 + * @return void
3209 + */
2221 3210 private function generate_ics($event_id, $format){
2222 - $export_file = plugin_dir_path(__FILE__).'inc/export/'.$format.'.php';
2223 - if(is_numeric($event_id) && file_exists($export_file)){
2224 - $event = $this->retreive($event_id);
2225 - include $export_file;
2226 - exit;
3211 + $allowed_formats = array('ics', 'vcs');
3212 + $event_id = intval($event_id);
3213 + $format = sanitize_text_field($format);
3214 + if (in_array($format, $allowed_formats)) {
3215 + $export_file = plugin_dir_path(__FILE__) . 'inc/export/' . $format . '.php';
3216 + if (is_numeric($event_id) && file_exists($export_file)) {
3217 + $event = $this->retreive($event_id);
3218 + if($event->post_status != 'publish'){
3219 + wp_die(esc_html__('Event not found.', 'event-post'), 404);
3220 + }
3221 + include $export_file;
3222 + exit;
3223 + }
2227 3224 }
3225 + wp_die(esc_html__('Invalid request.', 'event-post'), 400);
2228 3226 }
3227 +
2229 3228
2230 3229 public function parse_request(){
2231 3230 global $wp;
2232 3231 if (preg_match('#^event-feed#i', $wp->request, $match)) {
@@ -2239,9 +3238,9 @@
2239 3238 }
2240 3239
2241 3240 public function export(){
2242 3241 if(false !== $event_id=\filter_input(INPUT_GET, 'event_id',FILTER_SANITIZE_NUMBER_INT)){
2243 - $format = \filter_input(INPUT_GET, 'format',FILTER_SANITIZE_STRING);
3242 + $format = \filter_input(INPUT_GET, 'format');
2244 3243 $this->generate_ics($event_id, $format);
2245 3244 }
2246 3245 }
2247 3246
@@ -2246,77 +3245,119 @@
2246 3245 }
2247 3246
2248 3247
2249 3248 /**
2250 - * outputs an ICS document
3249 + * Outputs an ICS document
3250 + *
3251 + * Filters can be applied to the criteria used to retrieve events in GET parameters:
3252 + * - cat : category slug
3253 + * - tag : tag slug
3254 + * - tax_name : custom taxonomy name
3255 + * - tax_term : custom taxonomy term slug
3256 + * - nb : number of events to retrieve (default 10)
3257 + * - future : retreive future events
3258 + * - past : retreive past events
3259 + *
3260 + * @return void
2251 3261 */
2252 3262 public function feed(){
2253 - if(false !== $cat=\filter_input(INPUT_GET, 'cat',FILTER_SANITIZE_STRING)){
2254 - $vtz = get_option('timezone_string');
2255 - $gmt = $this->get_gmt_offset();
2256 - date_default_timezone_set($vtz);
2257 - $separator = "\n";
3263 + $criteria = array(
3264 + 'nb'=>10,
3265 + );
3266 + if(false !== $cat=\filter_input(INPUT_GET, 'cat')){
3267 + $criteria['cat'] = sanitize_text_field($cat);
3268 + }
3269 + if(false !== $tag=\filter_input(INPUT_GET, 'tag')){
3270 + $criteria['tag'] = sanitize_text_field($tag);
3271 + }
3272 + if(false !== $tax_name=\filter_input(INPUT_GET, 'tax_name')){
3273 + $criteria['tax_name'] = sanitize_text_field($tax_name);
3274 + }
3275 + if(false !== $tax_term=\filter_input(INPUT_GET, 'tax_term')){
3276 + $criteria['tax_term'] = sanitize_text_field($tax_term);
3277 + }
3278 + if(false !== $nb=\filter_input(INPUT_GET, 'nb', FILTER_SANITIZE_NUMBER_INT)){
3279 + $criteria['nb'] = sanitize_text_field($nb);
3280 + }
3281 + if(false !== $future=\filter_input(INPUT_GET, 'future', FILTER_SANITIZE_NUMBER_INT)){
3282 + $criteria['future'] = sanitize_text_field($future);
3283 + }
3284 + if(false !== $past=\filter_input(INPUT_GET, 'past', FILTER_SANITIZE_NUMBER_INT)){
3285 + $criteria['past'] = sanitize_text_field($past);
3286 + }
3287 + $vtz = get_option('timezone_string');
3288 + $gmt = $this->get_gmt_offset();
3289 + date_default_timezone_set($vtz);
3290 + $separator = "\n";
2258 3291
2259 - header("content-type:text/calendar");
2260 - header("Pragma: public");
2261 - header("Expires: 0");
2262 - header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
2263 - header("Cache-Control: public");
2264 - header("Content-Disposition: attachment; filename=". str_replace('+','-',urlencode(get_option('blogname').'-'.$cat)).".ics;" );
3292 + header("content-type:text/calendar");
3293 + header("Pragma: public");
3294 + header("Expires: 0");
3295 + header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
3296 + header("Cache-Control: public");
3297 + header("Content-Disposition: attachment; filename=". str_replace('+','-',rawurlencode(get_option('blogname').'-'.$cat)).".ics;" );
2265 3298
2266 - $props = array();
3299 + $props = array();
2267 3300
2268 - // General
2269 - $props[] = 'BEGIN:VCALENDAR';
2270 - $props[] = 'PRODID://WordPress//Event-Post-V'. file_get_contents(('VERSION')).'//EN';
2271 - $props[] = 'VERSION:2.0';
3301 + // General
3302 + $props[] = 'BEGIN:VCALENDAR';
3303 + $props[] = 'PRODID://WordPress//Event-Post-V'.$this->version.'//EN';
3304 + $props[] = 'VERSION:2.0';
3305 + // Timezone
3306 + if(!empty($vtz)){
3307 + array_push($props,
3308 + 'BEGIN:VTIMEZONE',
3309 + 'TZID:'.$vtz,
3310 + 'BEGIN:DAYLIGHT',
3311 + 'TZOFFSETFROM:+0100',
3312 + 'TZOFFSETTO:'.($gmt).'00',
3313 + 'DTSTART:19700329T020000',
3314 + 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3',
3315 + 'END:DAYLIGHT',
3316 + 'BEGIN:STANDARD',
3317 + 'TZOFFSETFROM:'.($gmt).'00',
3318 + 'TZOFFSETTO:+0100',
3319 + 'TZNAME:CET',
3320 + 'DTSTART:19701025T030000',
3321 + 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10',
3322 + 'END:STANDARD',
3323 + 'END:VTIMEZONE'
3324 + );
3325 + }
2272 3326
2273 - // Timezone
2274 - if(!empty($vtz)){
2275 - array_push($props,
2276 - 'BEGIN:VTIMEZONE',
2277 - 'TZID:'.$vtz,
2278 - 'BEGIN:DAYLIGHT',
2279 - 'TZOFFSETFROM:+0100',
2280 - 'TZOFFSETTO:'.($gmt).'00',
2281 - 'DTSTART:19700329T020000',
2282 - 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3',
2283 - 'END:DAYLIGHT',
2284 - 'BEGIN:STANDARD',
2285 - 'TZOFFSETFROM:'.($gmt).'00',
2286 - 'TZOFFSETTO:+0100',
2287 - 'TZNAME:CET',
2288 - 'DTSTART:19701025T030000',
2289 - 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10',
2290 - 'END:STANDARD',
2291 - 'END:VTIMEZONE'
2292 - );
2293 - }
2294 -
2295 - // Events
2296 - $events=$this->get_events(array('cat'=>$cat,'nb'=>-1));
2297 - foreach ($events as $event) {
2298 - if($event->time_start && $event->time_end){
2299 - array_push($props,
2300 - 'BEGIN:VEVENT',
2301 - 'CREATED:'.$this->ics_date(strtotime($event->post_date)).'Z',
2302 - 'LAST-MODIFIED:'.$this->ics_date(strtotime($event->post_modified)).'Z',
2303 - 'SUMMARY:'.$event->post_title,
2304 - 'UID:'.md5(site_url()."_eventpost_".$event->ID),
2305 - 'LOCATION:'.str_replace(',','\,',$event->address),
2306 - 'DTSTAMP:'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
2307 - 'DTSTART'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
2308 - 'DTEND'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_end).(!empty($vtz)?'':'Z'),
2309 - 'DESCRIPTION:'.trim(chunk_split($event->post_excerpt."\\n\\n".$event->permalink, 60, "\n")),
2310 - 'END:VEVENT'
2311 - );
2312 - }
3327 + // Events
3328 + $events=$this->get_events($criteria);
3329 + foreach ($events as $event) {
3330 + if($event->time_start && $event->time_end){
3331 + $description = wordwrap(
3332 + str_replace(
3333 + ['\\', ';', ',', "\r", "\n"],
3334 + ['\\\\', '\;', '\,', '', '\n'],
3335 + wp_strip_all_tags($event->description . "\n\n" . $event->permalink)
3336 + ),
3337 + 70,
3338 + "\n ",
3339 + true
3340 + );
3341 + array_push($props,
3342 + 'BEGIN:VEVENT',
3343 + 'CREATED:'.$this->ics_date(strtotime($event->post_date)).'Z',
3344 + 'LAST-MODIFIED:'.$this->ics_date(strtotime($event->post_modified)).'Z',
3345 + 'SUMMARY:'.$event->post_title,
3346 + 'UID:'.md5(site_url()."_eventpost_".$event->ID),
3347 + 'LOCATION:'.str_replace(',','\,',$event->address),
3348 + 'DTSTAMP:'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
3349 + 'DTSTART'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
3350 + 'DTEND'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_end).(!empty($vtz)?'':'Z'),
3351 + 'DESCRIPTION:'.$description,
3352 + 'END:VEVENT'
3353 + );
2313 3354 }
3355 + }
2314 3356
2315 - // End
2316 - $props[] = 'END:VCALENDAR';
3357 + // End
3358 + $props[] = 'END:VCALENDAR';
2317 3359
2318 - echo implode($separator, $props);
2319 - exit;
2320 - }
3360 + echo esc_html(implode($separator, $props));
3361 + exit;
2321 3362 }
2322 3363 }