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 +228 -97 5.10.1 → 6.1.2 View file →
@@ -2,9 +2,9 @@
2 2 /**
3 3 * Plugin Name: Event Post
4 4 * Plugin URI: https://event-post.com?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard&mtm_source=plugin-uri
5 5 * Description: Add calendar and/or geolocation metadata on any posts.
6 - * Version: 5.10.1
6 + * Version: 6.1.2
7 7 * Author: N.O.U.S. Open Useful and Simple
8 8 * Contributors: bastho, sabrinaleroy, unecologeek, agencenous
9 9 * Author URI: https://apps.avecnous.eu/?mtm_campaign=wp-plugin&mtm_kwd=event-post&mtm_medium=dashboard&mtm_source=author
10 10 * License: GPLv2
@@ -13,8 +13,11 @@
13 13 * Tags: Post,posts,event,date,geolocalization,gps,widget,map,openstreetmap,EELV,calendar,agenda,blocks
14 14 *
15 15 * @package event-post
16 16 */
17 +
18 +if ( ! defined( 'ABSPATH' ) ) exit;
19 +
17 20 global $EventPost;
18 21 $EventPost = new EventPost();
19 22
20 23 $EventPost_cache=array();
@@ -40,12 +43,15 @@
40 43 */
41 44 class EventPost {
42 45 /**
43 46 * The current version
44 - *
45 - * @var array
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
46 52 */
47 - public $version = '5.9.2';
53 + public $version = '6.1.2';
48 54
49 55 // --------------------------------------------------------------------------------
50 56 // Post metas
51 57
@@ -916,8 +922,10 @@
916 922 'use_current_location'=>__('Use my current location','event-post'),
917 923 'start_drag'=>__('Click to<br>drag the map<br>and change location','event-post'),
918 924 'empty_address'=>__('Be kind to fill a non empty address:)', 'event-post'),
919 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'),
920 928 'stop_drag'=>_x('Done','Stop allowing to drag the map', 'event-post'),
921 929 'datepickeri18n'=>array(
922 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
923 931 'order'=>__( '%1$s %2$s, %3$s @ %4$s:%5$s', 'event-post'),
@@ -1516,10 +1524,10 @@
1516 1524 $datas_cat = $this->print_categories($post, $context);
1517 1525 $datas_loc = $this->print_location($post, $context);
1518 1526 $classes = array(
1519 1527 'event_data',
1520 - 'status-'.$post->status,
1521 - 'location-type-'.$post->attendance_mode,
1528 + 'status-'.strtolower(str_replace('Event', '', $post->status)),
1529 + 'location-type-'.strtolower(str_replace('EventAttendanceMode', '', $post->attendance_mode)),
1522 1530 $class
1523 1531 );
1524 1532 if ($datas_date != '' || $datas_loc != '') {
1525 1533 $rgb = $this->hex2dec($post->color);
@@ -1605,9 +1613,9 @@
1605 1613 *
1606 1614 * @return void
1607 1615 */
1608 1616 public function print_single($post = null) {
1609 - echo $this->get_single($post);
1617 + echo wp_kses_post($this->get_single($post));
1610 1618 }
1611 1619
1612 1620 /**
1613 1621 * Alter the post title in order to add icons if needed
@@ -1679,8 +1687,11 @@
1679 1687 public function list_events($atts, $id = 'event_list', $context='') {
1680 1688 $ep_settings = $this->settings;
1681 1689 $defaults = array(
1682 1690 'nb' => 0,
1691 + 'nb_desktop' => 0,
1692 + 'nb_tablet' => 0,
1693 + 'nb_mobile' => 0,
1683 1694 'type' => 'div',
1684 1695 'future' => true,
1685 1696 'past' => false,
1686 1697 'geo' => 0,
@@ -1708,13 +1719,16 @@
1708 1719 'excerpt' => '',
1709 1720 'orderby' => 'meta_value',
1710 1721 'order' => 'ASC',
1711 1722 'class' => '',
1723 + 'align' => '',
1712 1724 'className' => '',
1713 1725 'container_schema' => $this->list_shema['container'],
1714 1726 'item_schema' => $this->list_shema['item'],
1715 1727 'pages' => false,
1716 1728 'paged' => '',
1729 + 'separate_years' => false,
1730 + 'separate_months' => false,
1717 1731 );
1718 1732 // Map UI options
1719 1733 foreach($this->map_interactions as $int_key=>$int_name){
1720 1734 $defaults[$int_key]=true;
@@ -1720,13 +1734,13 @@
1720 1734 $defaults[$int_key]=true;
1721 1735 }
1722 1736 $atts_old_nb = $defaults['nb'];
1723 1737 if($id == "event_timeline"){
1724 - $atts_old_nb = $atts['nb'];
1725 - $atts['nb'] = 0;
1738 + $atts_old_nb = intval($atts['nb']);
1739 + $atts['nb'] = -1;
1726 1740 }
1727 1741
1728 - $atts = shortcode_atts(apply_filters('eventpost_params', $defaults, 'list_events'), $atts);
1742 + $atts = shortcode_atts(apply_filters('eventpost_params', $defaults, 'list_events', $context), $atts);
1729 1743
1730 1744 extract($atts);
1731 1745 if (!is_array($events)) {
1732 1746 $events = $this->get_events($atts);
@@ -1735,12 +1749,13 @@
1735 1749 $ret = '';
1736 1750 $this->list_id++;
1737 1751 if (sizeof($events) > 0) {
1738 1752 if (!empty($title)) {
1739 - $ret .= esc_html($before_title) . esc_html($title) . esc_html($after_title);
1753 + $ret .= wp_kses_post($before_title . esc_html($title) . $after_title);
1740 1754 }
1741 1755
1742 - $child = ($type == 'ol' || $type == 'ul') ? 'li' : 'div';
1756 + $type = in_array($type, ['div', 'ul', 'ol']) ? $type : 'div';
1757 + $child = in_array($type, ['ul', 'ol']) ? 'li' : 'div';
1743 1758
1744 1759 $html = '';
1745 1760
1746 1761 if($id=='event_geolist'){
@@ -1756,23 +1771,42 @@
1756 1771 $next_arrow = '<div class="next"><span class="screen-reader-text">'.__('Next Events »', 'event-post')."</span></div>";
1757 1772 if($atts_old_nb != 0){
1758 1773 $item_child_style = 'width : '.((100/$atts_old_nb) - 2).'%;';
1759 1774 }
1760 - $attributes .= ' data-nb="'.$atts_old_nb.'" data-filter="'.http_build_query($atts).'" ';
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).'" ';
1761 1780 }
1762 1781
1782 + if($id === 'event_timeline'){
1783 + $previous_year = $atts['separate_years'] ? true : false;
1784 + $previous_month = $atts['separate_months'] ? true : false;
1785 + }
1786 +
1763 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 + }
1764 1798 $text_price = $this->get_price($event,true);
1765 1799 $class_item = array(
1766 1800 $this->is_future($event) ? 'event_future' : 'event_past',
1767 - 'status-'.$event->status,
1768 - 'location-type-'.$event->attendance_mode,
1801 + 'status-'.strtolower(str_replace('Event', '', $event->status)),
1802 + 'location-type-'.strtolower(str_replace('EventAttendanceMode', '', $event->attendance_mode)),
1769 1803 );
1770 1804 $taxonomies= get_taxonomies('','names');
1771 1805 $post_terms = [];
1772 1806 $terms = wp_get_post_terms($event->ID, $taxonomies);
1773 1807 foreach($terms as $term){
1774 - $class_item[] = $term->taxonomy.'-'.$term->name;
1808 + $class_item[] = $term->taxonomy.'-'.$term->slug;
1775 1809 }
1776 1810 if ($ep_settings['emptylink'] == 0 && empty($event->post_content)) {
1777 1811 $event->permalink = '#' . $id . $this->list_id;
1778 1812 }
@@ -1849,8 +1883,20 @@
1849 1883
1850 1884 if($context == 'events_only'){
1851 1885 $ret = $html;
1852 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 + }
1853 1899 $ret.=str_replace(
1854 1900 array(
1855 1901 '%type%',
1856 1902 '%id%',
@@ -1865,9 +1911,9 @@
1865 1911 '%number%'
1866 1912 ), array(
1867 1913 $type,
1868 1914 $id,
1869 - $class.($className ? ' '.esc_attr($className) : '').($id == 'event_geolist' && $list ? ' has-list list-'.esc_attr($list) : ' no-list'),
1915 + esc_attr(implode(' ', $classes)),
1870 1916 $id . $this->list_id,
1871 1917 (!empty($width) ? 'width:' . esc_attr($width) . ';' : '') . (!empty($height) ? 'height:' . esc_attr($height) . ';' : '') . esc_attr($style),
1872 1918 $attributes,
1873 1919 $html,
@@ -2338,9 +2384,9 @@
2338 2384 <option value=""><?php esc_attr_e('None','event-post') ?></option>
2339 2385 <?php
2340 2386 foreach($this->DashIcons->icons as $class => $unicode){
2341 2387 ?>
2342 - <option value="<?php echo esc_attr($class) ?>" <?php selected($value_icon, $class, true); ?>>&#x<?php esc_attr_e($unicode) ?>; <?php echo esc_html($class) ?></option>
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 ?>
2343 2389 <?php
2344 2390 }
2345 2391 ?>
2346 2392 </select>
@@ -2386,9 +2432,9 @@
2386 2432 <div class="inline-edit-col column-<?php echo esc_attr($fieldname); ?>">
2387 2433 <label class="inline-edit-group">
2388 2434 <span class="title"><?php echo esc_html($fieldlabel); ?></span>
2389 2435 <span class="input-text-wrap">
2390 - <?php echo $this->inline_field($fieldname, $bulk); ?>
2436 + <?php echo wp_kses($this->inline_field($fieldname, $bulk), $this->kses_tags); ?>
2391 2437 </span>
2392 2438 </label>
2393 2439 </div>
2394 2440 </fieldset>
@@ -2456,9 +2502,9 @@
2456 2502 *
2457 2503 * @return void
2458 2504 */
2459 2505 function inline_save(){
2460 - $post_id = filter_input(INPUT_POST, 'post_ID', FILTER_SANITIZE_NUMBER_INT);
2506 + $post_id = absint(filter_input(INPUT_POST, 'post_ID', FILTER_SANITIZE_NUMBER_INT));
2461 2507 $this->save_postdata($post_id);
2462 2508 }
2463 2509 /**
2464 2510 * When the post is saved, saves our custom data
@@ -2471,12 +2517,17 @@
2471 2517 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
2472 2518 return;
2473 2519 }
2474 2520
2475 - if (!wp_verify_nonce(filter_input(INPUT_POST, 'eventpost_nonce'), plugin_basename(__FILE__))){
2521 + if (!wp_verify_nonce((string) filter_input(INPUT_POST, 'eventpost_nonce'), plugin_basename(__FILE__))){
2476 2522 return;
2477 2523 }
2478 2524
2525 + $post_id = absint($post_id);
2526 + if (!$post_id || !current_user_can('edit_post', $post_id)) {
2527 + return;
2528 + }
2529 +
2479 2530 // Clean color or no color
2480 2531 if (false !== $color = filter_input(INPUT_POST, $this->META_COLOR)) {
2481 2532 update_post_meta($post_id, $this->META_COLOR, sanitize_text_field($color));
2482 2533 }
@@ -2694,12 +2745,12 @@
2694 2745 $ret.=$annee;
2695 2746 // Translators: %s is the year
2696 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>';
2697 2748 // Translators: %s is the month name
2698 - $ret.='<span class="eventpost-cal-month"><button data-date="' . date('Y-n', $prev_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $prev_month)).'" class="eventpost_cal_bt eventpost-cal-bt-prev">&laquo;</button><span class="eventpost-cal-header-text">';
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">';
2699 2750 $ret.=$this->NomDuMois[abs($mois)];
2700 2751 // Translators: %s is the month name
2701 - $ret.='</span><button data-date="' . date('Y-n', $next_month) . '" title="'.sprintf(__('Switch to %s', 'event-post'), date_i18n('F Y', $next_month)).'" class="eventpost_cal_bt eventpost-cal-bt-next">&raquo;</button> </span>';
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>';
2702 2753 $ret.='<span class="eventpost-cal-today"><button data-date="' . date('Y-n') . '" class="eventpost_cal_bt">' . __('Today', 'event-post') . '</button></span>';
2703 2754 $ret.='</div>';
2704 2755 }
2705 2756 $ret.='</th></tr><tr class="event_post_cal_days">';
@@ -2971,8 +3022,54 @@
2971 3022 }
2972 3023 }
2973 3024
2974 3025 /**
3026 + * Geocodes an address using OpenStreetMap Nominatim API and cache the result in a transient for 30 days
3027 + *
3028 + * @param string $address
3029 + * @param boolean $single_result Whether to return only the first result or all results
3030 + *
3031 + * @return array|false|string The geocoding result(s) or false on failure
3032 + */
3033 + public function geocode(string $address, bool $single_result = false){
3034 + $transient_name = 'eventpost_osquery_' . $address;
3035 + $val = get_transient($transient_name);
3036 + if (false === $val || empty($val) || !is_string($val)) {
3037 + $language = get_bloginfo('language');
3038 + if (strpos($language, '-') > -1) {
3039 + $language = strtolower(substr($language, 0, 2));
3040 + }
3041 + $remote_val = wp_safe_remote_request('https://nominatim.openstreetmap.org/search?q=' . rawurlencode($address) . '&format=json&accept-language=' . $language, [
3042 + 'user-agent' => getenv('HTTP_USER_AGENT') ?? 'WordPress/' . get_bloginfo('version') . '; ' . get_bloginfo('url'),
3043 + 'headers' => [
3044 + 'Referer' => get_bloginfo('url'),
3045 + ],
3046 + 'timeout' => 5,
3047 + ]);
3048 + $remote_body = wp_remote_retrieve_body($remote_val);
3049 + if(strstr($remote_body, '<html>')){
3050 + $val = [
3051 + [
3052 + 'lat' => '',
3053 + 'lon' => '',
3054 + 'display_name' => strip_tags($remote_body),
3055 + ]
3056 + ];
3057 + }
3058 + else{
3059 + $val = json_decode($remote_body);
3060 + if($val){
3061 + set_transient($transient_name, $val, 30 * DAY_IN_SECONDS);
3062 + }
3063 + }
3064 + }
3065 + if($single_result && is_array($val) && count($val) > 0){
3066 + $val = $val[0];
3067 + }
3068 + return $val;
3069 + }
3070 +
3071 + /**
2975 3072 * AJAX Get lat long from address
2976 3073 */
2977 3074 public function GetLatLong() {
2978 3075 if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
@@ -2978,22 +3075,10 @@
2978 3075 if (isset($_REQUEST['q']) && !empty($_REQUEST['q'])) {
2979 3076 // verifier le cache
2980 3077 $q = $_REQUEST['q'];
2981 3078 header('Content-Type: application/json');
2982 - $transient_name = 'eventpost_osquery_' . $q;
2983 - $val = get_transient($transient_name);
2984 - if (false === $val || empty($val) || !is_string($val)) {
2985 - $language = get_bloginfo('language');
2986 - if (strpos($language, '-') > -1) {
2987 - $language = strtolower(substr($language, 0, 2));
2988 - }
2989 - $remote_val = wp_safe_remote_request('http://nominatim.openstreetmap.org/search?q=' . rawurlencode($q) . '&format=json&accept-language=' . $language);
2990 - if(json_decode($remote_val['body'])){
2991 - $val = $remote_val['body'];
2992 - }
2993 - set_transient($transient_name, $val, 30 * DAY_IN_SECONDS);
2994 - }
2995 - wp_send_json( json_decode($val) );
3079 + $val = $this->geocode($q);
3080 + wp_send_json( $val );
2996 3081 exit();
2997 3082 }
2998 3083 }
2999 3084
@@ -3129,13 +3214,16 @@
3129 3214 if (in_array($format, $allowed_formats)) {
3130 3215 $export_file = plugin_dir_path(__FILE__) . 'inc/export/' . $format . '.php';
3131 3216 if (is_numeric($event_id) && file_exists($export_file)) {
3132 3217 $event = $this->retreive($event_id);
3218 + if($event->post_status != 'publish'){
3219 + wp_die(esc_html__('Event not found.', 'event-post'), 404);
3220 + }
3133 3221 include $export_file;
3134 3222 exit;
3135 3223 }
3136 3224 }
3137 - wp_die(__('Invalid request.', 'event-post'));
3225 + wp_die(esc_html__('Invalid request.', 'event-post'), 400);
3138 3226 }
3139 3227
3140 3228
3141 3229 public function parse_request(){
@@ -3158,75 +3246,118 @@
3158 3246
3159 3247
3160 3248 /**
3161 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
3162 3261 */
3163 3262 public function feed(){
3263 + $criteria = array(
3264 + 'nb'=>10,
3265 + );
3164 3266 if(false !== $cat=\filter_input(INPUT_GET, 'cat')){
3165 - $vtz = get_option('timezone_string');
3166 - $gmt = $this->get_gmt_offset();
3167 - date_default_timezone_set($vtz);
3168 - $separator = "\n";
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";
3169 3291
3170 - header("content-type:text/calendar");
3171 - header("Pragma: public");
3172 - header("Expires: 0");
3173 - header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
3174 - header("Cache-Control: public");
3175 - header("Content-Disposition: attachment; filename=". str_replace('+','-',rawurlencode(get_option('blogname').'-'.$cat)).".ics;" );
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;" );
3176 3298
3177 - $props = array();
3299 + $props = array();
3178 3300
3179 - // General
3180 - $props[] = 'BEGIN:VCALENDAR';
3181 - $props[] = 'PRODID://WordPress//Event-Post-V'.$this->version.'//EN';
3182 - $props[] = 'VERSION:2.0';
3183 - // Timezone
3184 - if(!empty($vtz)){
3185 - array_push($props,
3186 - 'BEGIN:VTIMEZONE',
3187 - 'TZID:'.$vtz,
3188 - 'BEGIN:DAYLIGHT',
3189 - 'TZOFFSETFROM:+0100',
3190 - 'TZOFFSETTO:'.($gmt).'00',
3191 - 'DTSTART:19700329T020000',
3192 - 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3',
3193 - 'END:DAYLIGHT',
3194 - 'BEGIN:STANDARD',
3195 - 'TZOFFSETFROM:'.($gmt).'00',
3196 - 'TZOFFSETTO:+0100',
3197 - 'TZNAME:CET',
3198 - 'DTSTART:19701025T030000',
3199 - 'RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10',
3200 - 'END:STANDARD',
3201 - 'END:VTIMEZONE'
3202 - );
3203 - }
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 + }
3204 3326
3205 - // Events
3206 - $events=$this->get_events(array('cat'=>$cat,'nb'=>-1));
3207 - foreach ($events as $event) {
3208 - if($event->time_start && $event->time_end){
3209 - array_push($props,
3210 - 'BEGIN:VEVENT',
3211 - 'CREATED:'.$this->ics_date(strtotime($event->post_date)).'Z',
3212 - 'LAST-MODIFIED:'.$this->ics_date(strtotime($event->post_modified)).'Z',
3213 - 'SUMMARY:'.$event->post_title,
3214 - 'UID:'.md5(site_url()."_eventpost_".$event->ID),
3215 - 'LOCATION:'.str_replace(',','\,',$event->address),
3216 - 'DTSTAMP:'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
3217 - 'DTSTART'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_start).(!empty($vtz)?'':'Z'),
3218 - 'DTEND'.(!empty($vtz)?';TZID='.$vtz:'').':'.$this->ics_date($event->time_end).(!empty($vtz)?'':'Z'),
3219 - 'DESCRIPTION:'.trim(chunk_split($event->description."\\n\\n".$event->permalink, 60, "\n ")),
3220 - 'END:VEVENT'
3221 - );
3222 - }
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 + );
3223 3354 }
3355 + }
3224 3356
3225 - // End
3226 - $props[] = 'END:VCALENDAR';
3357 + // End
3358 + $props[] = 'END:VCALENDAR';
3227 3359
3228 - echo esc_html(implode($separator, $props));
3229 - exit;
3230 - }
3360 + echo esc_html(implode($separator, $props));
3361 + exit;
3231 3362 }
3232 3363 }