PluginProbe
Event Post / 5.10.0
Event Post v5.10.0
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 5.6.1 All 46 releases
event-post / eventpost.php

eventpost.php in Event Post 5.10.0, at eventpost.php

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