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