| @@ -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.3 | |
| 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">»</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">«</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">«</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">»</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">»</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 | } |