'Start Date',
'END-DATE-ASC' => 'End Date',
'ALPHABETA' => 'Alphabetical (by event title)',
);
public static $arr_views = array(
'default' => 'List',
'tile' => 'Tile',
'month' => 'Month',
);
private static $_total_event = 0;
public static function init() {
// handle the shortcode to display in the frontend
add_shortcode( AC_SHORTCODE_KEY, array(__CLASS__, 'handle_shortcode'));
// Register an action for ajax
add_action( 'wp_ajax_nopriv_ac_get_feed', array(__CLASS__,'ac_get_feed' ));
add_action('wp_ajax_ac_get_feed', array(__CLASS__, 'ac_get_feed'));
if (isset($_GET['event_id']) && $_GET['event_id']) {
add_action('wp_head', array(__CLASS__, 'add_meta_tags_fb'));
}
}
public static function handle_shortcode($atts) {
// Set the current url of the page or post, using for the ajax request when we handle the link for event
if (!session_id()) {
session_start();
}
/* Only show javascripts on page have shortcode */
Artsopolis_Calendar::setPageShortcode(true);
// Only get the base url in the parent page
if (! isset($_GET['event_id']) && ! isset($_GET['category'])) {
$_SESSION['artsopolis_calendar_current_url'] = get_site_url(). $_SERVER["REQUEST_URI"];
}
extract(shortcode_atts(array(
'hour' => isset($atts['hour']) && $atts['hour'] ? $atts['hour'] : OVERRIDE_TIME_XML_FILE,
'fid' => isset($atts['fid']) && $atts['fid'] ? $atts['fid'] : '',
), $atts));
self::init_data( $fid );
// Get options from the settings
$ac_options = get_option( self::$option_key, false );
if ( $ac_options === false ) {
echo 'The plugin option is not exist. Please try to check you config again';
exit;
}
extract($ac_options, EXTR_PREFIX_ALL, 'ac');
self::$feed_url = $ac_options['feed_url'];
// Get the category array for filter
$category_data = self::_process_category_opt( isset( $ac_category ) ? $ac_category : '' );
if (isset($_GET['event_id']) && $_GET['event_id']) {
$xml = @simplexml_load_file(self::$xml_file_path);
$event_id = $_GET['event_id'];
$event = $xml->xpath("event[eventID=$event_id]");
$html_events = self::get_detail_event($event);
} else {
if (self::check_can_override_xml_file($hour)) {
Artsopolis_Calendar_API::save_xml_data();
}
// Filter by category when click on the tags
if (isset($_GET['category']) && $_GET['category']) {
$categories = $_GET['category'];
}
// Get the list events and some value for the template
$arr_filter = array(
'page' => 1,
'category' => isset( $category_data['categories'] ) ? $category_data['categories'] : array(),
'first_tab' => true, // Filter all events has date end less than 2037-01-01 for second tab
);
// Featured only
if ( isset($ac_options['featured_only']) && $ac_options['featured_only'] ) {
$arr_filter['featured_events'] = get_option( AC_FEATURED_EVENTS. self::get_geed_id( $fid ) );
}
$events = self::get_list_events_data($arr_filter);
// Validate ongoing data
$ongoingFilter = $arr_filter;
$ongoingFilter['first_tab'] = false;
$ongoingFilter['force_ongoing'] = true;
$ongoingData = self::get_list_events_data($ongoingFilter);
$total_event = self::$feed_url ? count($events) : 0;
$page_size = FRONT_END_PAGE_SIZE;
if (!session_id()) {
session_start();
}
$html_events = self::get_html_list_events($events, array(
'page' => 1,
'view' => isset($_GET['view']) ? $_GET['view'] : ''
), isset( $category_data['keys'] ) ? $category_data['keys'] : '' );
$xml = @simplexml_load_file(self::$xml_file_path);
}
if ($xml == false || ! $ac_options['feed_valid']) {
echo 'The feed url is invalid. Please try to check it again';
exit;
}
// Get list location
$locations_xml = $xml->xpath('event/venueCity');
$_locations = array();
if (! empty($locations_xml)) {
foreach ($locations_xml as $location) {
if ($l = (string) $location) {
$_locations[rtrim($l)] = $l;
}
}
}
$locations = array_values($_locations);
asort($locations);
// Get spotlight events
$spotlight_events = Artsopolis_Calendar_Shortcode::get_spotlight_events(self::$fid);
// Render html and return
ob_start();
include dirname(__FILE__). '/frontend-template.php';
$html = ob_get_contents();
ob_end_clean();
return $html;
}
public static function add_meta_tags_fb() {
$event_id = $_GET['event_id'];
$fid = isset( $_GET['fid'] ) ? $_GET['fid'] : '';
$xml = @simplexml_load_file( self::get_xml_fullpath( $fid ) );
if (! $xml) {
return false;
}
$event = $xml->xpath("event[eventID=$event_id]");
if (! empty($event)) {
$event = self::get_cdata_xml($event[0]);
if ( !empty($event) && acIsExpiredTime($event->eventDateEnd,$event->event_dates_times) ) return false;
} else {
return false;
}
$desc = preg_replace("/<.*?>/", "", $event->eventDescription);
$url = get_site_url(). $_SERVER["REQUEST_URI"];
echo '
'
. ''
. ''
. '';
}
public static function _process_category_opt($ac_category) {
if (empty($ac_category)) {
return array();
}
$categories = array();
$cat_keys = array ();
foreach ($ac_category as $key => $cats) {
if (!empty($cats['name'])) {
$categories[] = $key. '[+]'. ( isset( $cats['name'] ) ? $cats['name'] : '' );
$cat_keys[] = $key;
}
if (isset($cats['subs']) && $cats['subs']) {
foreach ($cats['subs'] as $key => $val) {
$categories[] = $key. '[+]'. $val;
$cat_keys[] = $key;
}
}
}
return array('categories' => $categories, 'keys' => $cat_keys);
}
/**
* Get the detail event
* @param $event
* @return html
* @internal param int $event_id
* @author vulh
*
*/
public static function get_detail_event($event) {
$ac_options = get_option( self::$option_key );
if (! $ac_options['category']) {
return 'Please select at least a category to display events Click here';
}
$event = ! empty($event) ? self::get_cdata_xml($event[0]) : '';
// Thienld : custom logic to check expired event
if ( !empty($event) && acIsExpiredTime($event->eventDateEnd,$event->event_dates_times) ) return "";
ob_start();
include dirname(__FILE__) . '/detail-event-template.php';
$html = ob_get_contents();
ob_end_clean();
return $html;
}
public static function get_list_events_data($arr_filter) {
$page_size = FRONT_END_PAGE_SIZE;
if ( ! file_exists( self::$xml_file_path ) || ! file_get_contents( self::$xml_file_path ) ) {
return array();
}
$xml = @simplexml_load_file( self::$xml_file_path );
if (!$xml) return array();
// if ( isset( $arr_filter['first_tab'] ) && !$arr_filter['first_tab'] ) {
// $arr_filter['date_end_ongoing'] = '01-01-2037';
// }
$xpath_query = self::_get_xpath_query($arr_filter);
$events = $xml->xpath($xpath_query);
// Get options from the settings
$_arr_key = explode( '_', self::$option_key );
$fid = $_arr_key ? $_arr_key[count( $_arr_key ) - 1] : '';
$ac_options = get_option( self::$option_key );
$settings_display_order = isset($ac_options['settings_display_order']) ? $ac_options['settings_display_order']: 'START-DATE-ASC';
$events = self::_sort_events($events, $settings_display_order);
if (empty($ac_options['category'])) {
return array();
}
return $events;
}
private static function _sort_events (&$events , $settings_display_order) {
switch($settings_display_order) {
case 'START-DATE-ASC':
usort($events, 'ac_sort_by_start_upcomming_time');
break;
case 'END-DATE-ASC':
usort($events, 'ac_sort_by_end_date');
break;
case 'ALPHABETA':
usort($events, 'ac_sort_by_alpha');
break;
case 'PRICE-HIGHT':
usort($events, 'ac_sort_by_price_hight');
break;
case 'PRICE-SLOW':
usort($events, 'ac_sort_by_price_slow');
}
return $events;
}
public static function sort_tags(&$tags) {
usort($tags, 'ac_admin_sub_sort_by_alpha');
return $tags;
}
/**
* Do xpath query
* @param $arr_filter
* @return string
*/
private static function _get_xpath_query($arr_filter) {
$key_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$key_lowercase = 'abcdefghijklmnopqrstuvwxyz';
$arr_condition = array();
// Generate featured query
if (isset($arr_filter['featured_events']) ) {
if (!$arr_filter['featured_events']) {
return false;
}
$featuredQuery = array();
foreach ($arr_filter['featured_events'] as $event_id) {
$featuredQuery[] = 'contains(eventID, "'.$event_id.'")';
}
$arr_condition[] = ' ('. implode(' or ', $featuredQuery). ') ' ;
}
$fromDate = ! empty($arr_filter['from_date']) ? $arr_filter['from_date'] : '';
$toDate = ! empty($arr_filter['to_date']) ? $arr_filter['to_date'] : '';
$from = str_replace(DELIMITER_DATE, '', $fromDate);
$to = str_replace(DELIMITER_DATE, '', $toDate);
// Change the operator to OR if we select the this weedken
if ( isset( $arr_filter['this_weedken'] ) && intval($arr_filter['this_weedken']) == 1 ) {
$arr_condition[] = " (eventDatesTimes/datetime/date_filter = $from or eventDatesTimes/datetime/date_filter = $to )";
} else {
if ($from && $to) {
$arr_condition[] = " eventDatesTimes/datetime/date_filter[. >= $from and $to >= . ] ";
}
else if ($from) {
$arr_condition[] = " eventDatesTimes/datetime/date_filter[. >= $from ] ";
}
else if ($to) {
$arr_condition[] = " eventDatesTimes/datetime/date_filter[ $to >= . ] ";
}
}
/**
* Do not care about the ongoing filter because
* we will hide the tab menu in the month view
*/
if (!isset($arr_filter['view']) || $arr_filter['view'] != 'month') {
if ( isset( $arr_filter['first_tab'] ) && $arr_filter['first_tab'] ) {
$arr_condition[] = " (translate(normalize-space(ongoing), ' ', '') != 'Y' and translate(normalize-space(ongoing), ' ', '') != 'y') ";
} else {
// Only filter event in the front end. So we make it avoid filter in
// featured events
if ( (is_admin() && $_REQUEST['page'] !== 'artsopolis-calendar-featured-events') || !empty($arr_filter['force_ongoing']) ) {
$arr_condition[] = " (translate(normalize-space(ongoing), ' ', '') = 'Y' or translate(normalize-space(ongoing), ' ', '') = 'y') ";
}
}
}
if (! empty($arr_filter['location'])) {
$arr_condition[] = 'venueCity="'.$arr_filter['location'].'"';
}
if (!empty($arr_filter['keyword'])) {
$keyword = strtolower($arr_filter['keyword']);
$arr_condition[] = ' (contains(translate(eventName, "'.$key_uppercase.'", "'.$key_lowercase.'"), "'.$keyword.'")'
. ' or contains(translate(orgName, "'.$key_uppercase.'", "'.$key_lowercase.'"), "'.$keyword.'")'
. ' or contains(translate(venueName, "'.$key_uppercase.'", "'.$key_lowercase.'"), "'.$keyword.'")'
. ' or contains(translate(venueCity, "'.$key_uppercase.'", "'.$key_lowercase.'"), "'.$keyword.'") ) ';
}
$category_list_where = '';
// If don't have any category param in the filter,
// get the list categories selected in the backend
$op = get_option( self::$option_key );
if (empty($arr_filter['category']) && ! empty($op['category'])) {
$cat_data = self::_process_category_opt($op['category']);
$arr_filter['category'] = $cat_data['categories'];
}
if (! empty($arr_filter['category'])) {
if (is_array($arr_filter['category'])) {
$arr_categories_list = array();
foreach ($arr_filter['category'] as $category) {
$cat_arr = explode('[+]', $category);
$cat_id = isset($cat_arr[0]) ? $cat_arr[0] : '';
$cat_name = isset($cat_arr[1]) ? $cat_arr[1] : '';
$arr_categories_list[] = ' ( contains(categories, "'.$cat_id.'") and contains(tags, "'.$cat_name.'") ) ';
}
$arr_condition[] = '('. implode(' or ', $arr_categories_list) . ')';
} else {
$cat_arr = explode('[+]', $arr_filter['category']);
if (isset($cat_arr[0])) {
$arr_condition[] = '(contains(categories, "'.$cat_arr[0].'")) ';
}
if (isset($cat_arr[1])) {
$arr_condition[] = '(contains(tags, "'.$cat_arr[1].'")) ';
}
}
}
$xpath_query = 'event';
if (!empty($arr_condition)) {
$xpath_query .= '[' . implode(" and ", $arr_condition) . ']';
}
return $xpath_query;
}
/**
* Render HTML
* @param $events
* @param $arr_filter
* @param array $selected_category
* @return string
*/
public static function get_html_list_events($events, $arr_filter, $selected_category = array()) {
$ac_options = get_option( self::$option_key );
if (! $ac_options['feed_url']) {
$total_event = 0;
$events = array();
return '';
}
$page_size = FRONT_END_PAGE_SIZE;
$total_event = count($events);
Artsopolis_Calendar_Shortcode::$_total_event = $total_event;
$events = array_splice($events, ($arr_filter['page'] - 1) * $page_size, $page_size);
ob_start();
// Default view from admin config
if (empty($_GET['view'])) {
$view = isset($ac_options['settings_default_view']) ? $ac_options['settings_default_view'] : '';
}
else {
$view = isset($arr_filter['view']) ? $arr_filter['view'] : '';
}
switch ($view) {
case 'tile' :
include dirname(__FILE__) . '/view/list/includes/tile.php';
break;
case 'month' :
if (empty($arr_filter['from_date'])) {
$arr_filter['from_date'] = self::firstDayOfCurrentMonth();
}
if (empty($arr_filter['to_date'])) {
$arr_filter['to_date'] = self::lastDayOfCurrentMonth();
}
include dirname(__FILE__) . '/view/list/includes/month.php';
break;
default :
include dirname(__FILE__) . '/list-events-template.php';
break;
}
$html = ob_get_contents();
ob_end_clean();
return $html;
}
/* Define callback ajax function */
public static function ac_get_feed() {
// The $_REQUEST contains all the data sent via ajax
if (isset($_REQUEST['page'])) {
$page = isset( $_REQUEST['page'] ) ? $_REQUEST['page'] : 1;
$from_date = isset( $_REQUEST['from_date'] ) ? $_REQUEST['from_date'] : '';
$to_date = isset( $_REQUEST['to_date'] ) ? $_REQUEST['to_date'] : '';
$location = isset( $_REQUEST['location'] ) ? stripslashes($_REQUEST['location']) : '';
$repagination = isset( $_REQUEST['repagination'] ) ? $_REQUEST['repagination'] : '';
$keyword = isset( $_REQUEST['keyword'] ) ? stripslashes($_REQUEST['keyword']) : '';
$this_weekend = isset( $_REQUEST['this_weekend'] ) ? $_REQUEST['this_weekend'] : '';
$category = isset( $_REQUEST['category'] ) ? $_REQUEST['category'] : '';
$first_tab = isset( $_REQUEST['first_tab'] ) && $_REQUEST['first_tab'] == 'true';
$fid = isset( $_REQUEST['fid'] ) && $_REQUEST['fid'] ? $_REQUEST['fid'] : '';
$outputType = isset( $_REQUEST['output_type'] ) && $_REQUEST['output_type'] ? $_REQUEST['output_type'] : '';
self::init_data($fid);
$arr_filter = array(
'page' => $page,
'from_date' => $from_date,
'to_date' => $to_date,
'location' => $location,
'repagination' => $repagination,
'keyword' => $keyword,
'this_weedken' => $this_weekend ,
'category' => $category,
'first_tab' => $first_tab,
'view' => isset( $_REQUEST['view'] ) && $_REQUEST['view'] ? $_REQUEST['view'] : '',
);
$ac_options = get_option( self::$option_key );
if ( isset($ac_options['featured_only']) && $ac_options['featured_only'] ) {
$featuredEvents = get_option( AC_FEATURED_EVENTS. self::get_geed_id( $fid ) );
$arr_filter['featured_events'] = $featuredEvents;
}
// Get the category array for filter
$category_data = self::_process_category_opt( isset( $ac_options['category'] ) ? $ac_options['category'] : '' );
switch ($outputType) {
case 'json':
$output = self::month_view_formatting($arr_filter);
break;
case 'html':
default:
$arr_events = self::get_list_events_data($arr_filter);
$output = self::get_html_list_events($arr_events, $arr_filter, isset( $category_data['keys'] ) ? $category_data['keys'] : '' );
break;
}
echo json_encode( array(
'html' => $output,
'total' => Artsopolis_Calendar_Shortcode::$_total_event,
'page_size' => FRONT_END_PAGE_SIZE,
) );
}
// Always exit function when you call by the ajax
exit();
}
/**
* Month view formatting
* @author vulh
* @param $arr_filter
* @return array
* @internal param $events
*/
public static function month_view_formatting($arr_filter)
{
$output = array();
if (empty($arr_filter['from_date'])) {
$arr_filter['from_date'] = self::firstDayOfCurrentMonth();
}
if (empty($arr_filter['to_date'])) {
$arr_filter['to_date'] = self::lastDayOfCurrentMonth();
}
$startNumberOfTheFirstCell = date('w', strtotime($arr_filter['from_date']));
$endNumberOfTheFirstCell = 6 - date('w', strtotime($arr_filter['to_date']));
$start = date('Y-m-d', strtotime($arr_filter['from_date'] . "-$startNumberOfTheFirstCell days"));
$end = date('Y-m-d', strtotime($arr_filter['to_date'] . "+$endNumberOfTheFirstCell days"));
$days = ((strtotime($end) - strtotime($start)) / (24*3600)) + 1;
$ac_options = get_option( self::$option_key, false );
$date = $start;
for ($i = 0; $i < $days; $i++) {
$arr_filter['from_date'] = $arr_filter['to_date'] = $date;
$events = self::get_list_events_data($arr_filter);
if ($events) {
foreach($events as $event) {
$formatted = self::get_cdata_xml($event);
if ( !empty($formatted) && acIsExpiredTime($formatted->eventDateEnd,$formatted->event_dates_times) ) continue;
$formatted->viewLink = self::get_link($ac_options, $formatted);
$formatted->viewTargetLink = self::get_target($ac_options);
$output[$date][] = $formatted;
}
}
$date = date('Y-m-d', strtotime($date . "+1 days"));
}
if ($output) {
foreach($output as $date => &$items) {
usort($items, 'ac_sort_ongoing');
}
}
return $output;
}
/**
* Get link of an event
* @param $ac_options
* @param $event
* @return string
*/
public static function get_link($ac_options, $event)
{
if (! $ac_options['details_link_to']) {
$link = $event->link;
} else {
// Custom url follow the permalink structure
$url_ext_sign = ! get_option('permalink_structure') ? '&' : '?';
$parent_link = get_site_url().'/'. $ac_options['calendar_slug'];
$link = $parent_link. $url_ext_sign .'event_id='. $event->eventID. ( self::$fid ? '&fid='. self::$fid : '' );
}
return $link;
}
/**
* Get target link of an event
* @param $ac_options
* @return string
*/
public static function get_target($ac_options)
{
return ! $ac_options['details_link_to'] ? 'target="_blank"' : '';
}
/**
* Get first date of current month
* @return string
*/
public static function firstDayOfCurrentMonth() {
$query_date = date('Y-m-d');
$date = new DateTime($query_date);
$date->modify('first day of this month');
return $date->format('Y-m-d');
}
/**
* Get last date of current month
* @return string
*/
public static function lastDayOfCurrentMonth() {
$query_date = date('Y-m-d');
$date = new DateTime($query_date);
$date->modify('last day of this month');
return $date->format('Y-m-d');
}
public static function get_event_url($url) {
if (( ! strpos($url, '.gif')
&& ! strpos($url, '.png')
&& ! strpos($url, '.jpg')
&& ! strpos($url, '.jpeg')
)
|| strpos($url, 'missing_org') || ! $url) {
return plugins_url('/artsopolis-calendar/img/calendar-icon.png');
}
// Remove this logic for the new WP version
// if (strpos($url, '_medium')) {
// $event_img = str_replace('_medium', '_category', $url);
// } else {
// $ext = substr($url, -4);
// $ext = (strpos($ext, '.') === null ? '.':'').$ext;
// $event_img = str_replace($ext, '', $url). '_category'. $ext;
// }
return $url;
}
public static function get_featured_events( $fid = '' ) {
$selected_events = get_option( AC_FEATURED_EVENTS. self::get_geed_id( $fid ) );
if ( empty($selected_events) ) {
return array();
}
$xml = @simplexml_load_file( self::get_xml_fullpath($fid) );
if ( ! $xml ) {
return array();
}
$query = array();
foreach ($selected_events as $event_id) {
$query[] = 'contains(eventID, "'.$event_id.'")';
}
$query = implode(' or ', $query) ;
$events = $xml->xpath('event['.$query.']');
return $events;
}
public static function get_spotlight_events( $fid = '' ) {
$spotlight_events = get_option( AC_SPOTLIGHT_EVENTS. self::get_geed_id( $fid ) );
if ( empty($spotlight_events) ) {
return array();
}
$xml = @simplexml_load_file( self::get_xml_fullpath($fid) );
if ( ! $xml ) {
return array();
}
$query = array();
foreach ($spotlight_events as $event_id) {
$query[] = 'contains(eventID, "'.$event_id.'")';
}
$query = implode(' or ', $query) ;
$events = $xml->xpath('event['.$query.']');
return $events;
}
}
}
Artsopolis_Calendar_Shortcode::init();