2 Revīzijas 8866d45134 ... 9bd4669155

Autors SHA1 Ziņojums Datums
  elwin 9bd4669155 * Added hamburger menu for mobile/narrow view 7 gadi atpakaļ
  elwin 55cd029240 * Changed event calendars 7 gadi atpakaļ

+ 12 - 0
wp-content/plugins/event-organiser/.gitignore

@@ -0,0 +1,12 @@
+*~
+.project
+.settings
+.buildpath
+.metadata
+apigen
+documentation
+dist
+vendor
+tests
+node_modules
+/composer.phar

+ 174 - 0
wp-content/plugins/event-organiser/classes/class-eo-agenda-widget.php

@@ -0,0 +1,174 @@
+<?php
+/**
+ * Class used to create the event calendar widget
+ */
+class EO_Events_Agenda_Widget extends WP_Widget {
+
+	var $w_arg = array();
+
+	static $agendas = array();
+
+	function __construct() {
+		$widget_ops = array( 'classname' => 'widget_events', 'description' => __( 'Displays a list of events, grouped by date', 'eventorganiser' ) );
+		$this->w_arg = array(
+			'title'         => '',
+			'mode'          => 'day',
+			'group_format'  => 'l, jS F',
+			'item_format'   => get_option( 'time_format' ),
+			'add_to_google' => 1,
+		);
+		parent::__construct( 'EO_Events_Agenda_Widget', __( 'Events Agenda','eventorganiser' ), $widget_ops );
+	}
+
+	/**
+	 * Registers the widget with the WordPress Widget API.
+	 *
+	 * @return void.
+	 */
+	public static function register() {
+		register_widget( __CLASS__ );
+	}
+
+	function form( $instance ) {
+		$instance = wp_parse_args( (array) $instance, $this->w_arg );
+		?>
+		<p>
+		<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title', 'eventorganiser' ); ?>: </label>
+		<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] );?>" />
+		</p>
+	
+		<p>
+		<label for="<?php echo $this->get_field_id( 'mode' ); ?>"><?php _e( 'Group by', 'eventorganiser' ); ?>: </label>
+		<select id="<?php echo $this->get_field_id( 'mode' ); ?>" name="<?php echo $this->get_field_name( 'mode' ); ?>" >
+			<option value="day" <?php selected( $instance['mode'], '' ); ?>><?php _e( 'Day','eventorganiser' ); ?> </option>
+			<option value="week" <?php selected( $instance['mode'], 'week' ); ?>><?php _e( 'Week', 'eventorganiser' ); ?> </option>
+			<option value="month" <?php selected( $instance['mode'], 'month' ); ?>><?php _e( 'Month', 'eventorganiser' ); ?> </option>
+		</select>
+		</p>
+	
+		<p>
+		<label for="<?php echo $this->get_field_id( 'group_format' ); ?>"><?php _e( 'Group date format', 'eventorganiser' ); ?>: </label>
+		<input id="<?php echo $this->get_field_id( 'group_format' ); ?>" name="<?php echo $this->get_field_name( 'group_format' ); ?>" type="text" value="<?php echo esc_attr( $instance['group_format'] );?>" />
+		</p>
+	
+		<p>
+		<label for="<?php echo $this->get_field_id( 'item_format' ); ?>"><?php _e( 'Event date/time format', 'eventorganiser' ); ?>: </label>
+		<input id="<?php echo $this->get_field_id( 'item_format' ); ?>" name="<?php echo $this->get_field_name( 'item_format' ); ?>" type="text" value="<?php echo esc_attr( $instance['item_format'] );?>" />
+		</p>
+	
+		<p>
+		<label for="<?php echo $this->get_field_id( 'add_to_google' ); ?>"><?php _e( 'Include \'Add To Google\' link','eventorganiser' ); ?>: </label>
+		<input id="<?php echo $this->get_field_id( 'add_to_google' ); ?>" name="<?php echo $this->get_field_name( 'add_to_google' ); ?>" type="checkbox" value="1" <?php checked( $instance['add_to_google'], 1 );?> />
+		</p>
+		<?php
+	}
+
+	function update( $new_instance, $old_instance ) {
+		$validated = array();
+		delete_transient( 'eo_widget_agenda' );
+		$validated['title']         = sanitize_text_field( $new_instance['title'] );
+		$validated['mode']          = sanitize_text_field( $new_instance['mode'] );
+		$validated['group_format']  = sanitize_text_field( $new_instance['group_format'] );
+		$validated['item_format']   = sanitize_text_field( $new_instance['item_format'] );
+		$validated['add_to_google'] = intval( $new_instance['add_to_google'] );
+		return $validated;
+	}
+
+	function widget( $args, $instance ) {
+
+		wp_enqueue_script( 'eo_front' );
+		eo_enqueue_style( 'eo_front' );
+
+		add_action( 'wp_footer', array( __CLASS__, 'add_options_to_script' ) );
+
+		self::$agendas[$args['widget_id']] = array(
+			'id'            => esc_attr( $args['widget_id'] ),
+			'number'        => $this->number,
+			'mode'          => isset( $instance['mode'] ) ? $instance['mode'] : 'day',
+			'add_to_google' => $instance['add_to_google'],
+			'group_format'  => eo_php_to_moment( $instance['group_format'] ),
+			'item_format'   => eo_php_to_moment( $instance['item_format'] ),
+		);
+
+		//Echo widget
+		echo $args['before_widget'];
+
+		$widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
+
+		if ( $widget_title ) {
+			echo $args['before_title'] . esc_html( $widget_title ) . $args['after_title'];
+		}
+
+		printf( '<div data-eo-agenda-widget-id="%1$s" id="%1$s_container" class="eo-agenda-widget"></div>', esc_attr( $args['widget_id'] ) );
+
+		echo $args['after_widget'];
+	}
+
+	static function print_main_template() {
+		?>
+		<script type="text/template" id="eo-tmpl-agenda-widget">
+		<div class='eo-agenda-widget-nav'>
+			<span class="eo-agenda-widget-nav-prev"><</span>
+			<span class="eo-agenda-widget-nav-next">></span>
+		</div>
+		<ul class='dates'></ul>
+		</script>
+		<?php
+	}
+
+	static function print_group_template() {
+		?>
+	  	<script type="text/template" id="eo-tmpl-agenda-widget-group">
+		<li class="date">
+			{{{ group.start.format(this.param.group_format) }}}
+			<ul class="a-date"></ul>
+		</li>
+		</script>
+	  	<?php
+	}
+
+	static function print_item_template() {
+		?>
+		<script type="text/template" id="eo-tmpl-agenda-widget-item">
+		<li class="event">
+			<# if( !this.param.add_to_google ){ #>
+				<a class='eo-agenda-event-permalink' href='{{{ event.link }}}'>
+			<# } #>
+			<span class="cat" style="background:{{{ event.color }}}"></span>
+			<span><strong>
+				<# if( event.all_day ){ #>
+					<?php esc_html_e( 'All day', 'eventorganiser' ); ?>
+				<# }else{ #>
+					{{{ event.start.format(this.param.item_format) }}}
+				<# } #>
+			</strong></span>
+			{{{ event.title }}}		
+			<# if( this.param.add_to_google ){ #>		
+				<div class="meta" style="display:none;">
+					<span>
+						<a href="{{{ event.link }}}"><?php esc_html_e( 'View', 'eventorganiser' ); ?></a>
+					</span>
+					<span> &nbsp; </span>
+					<span>
+						<a href="{{{ event.google_link }}}" target="_blank"><?php esc_html_e( 'Add To Google Calendar', 'eventorganiser' ); ?></a>
+					</span>
+				</div>
+			<# } #>
+			<# if( !this.param.add_to_google ){ #>
+				</a>
+			<# } #>
+		</li>
+		</script>
+	 	<?php
+	}
+
+	static function add_options_to_script() {
+		if ( ! empty( self::$agendas ) ) {
+			wp_localize_script( 'eo_front', 'eo_widget_agenda', self::$agendas );
+			self::print_main_template();
+			self::print_group_template();
+			self::print_item_template();
+		}
+	}
+}
+add_action( 'widgets_init', array( 'EO_Events_Agenda_Widget', 'register' ) );

+ 407 - 0
wp-content/plugins/event-organiser/classes/class-eo-calendar-widget.php

@@ -0,0 +1,407 @@
+<?php
+/**
+ * Class used to create the event calendar widget
+ */
+class EO_Calendar_Widget extends WP_Widget {
+
+	/*
+	 * Array of default settings
+	 */
+	public static $w_arg = array(
+		'title'          => '',
+		'showpastevents' => 1,
+		'event-category' => '',
+		'event-venue'    => '',
+		'show-long'      => false,
+		'link-to-single' => false,
+	);
+
+	static $widget_cal = array();
+
+	function __construct() {
+		$widget_ops = array(
+			'classname'   => 'widget_calendar eo_widget_calendar',
+			'description' => __( 'Displays a calendar of your events','eventorganiser' ),
+		);
+		parent::__construct( 'EO_Calendar_Widget', __( 'Events Calendar', 'eventorganiser' ), $widget_ops );
+	}
+
+	/**
+	 * Registers the widget with the WordPress Widget API.
+	 *
+	 * @return void.
+	 */
+	public static function register() {
+		register_widget( __CLASS__ );
+	}
+
+	function form( $instance ) {
+
+		$instance = wp_parse_args( (array) $instance, self::$w_arg );
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				<input type="text" id="%1$s" name="%3$s" value="%4$s">
+			</p>',
+			esc_attr( $this->get_field_id( 'title' ) ),
+			esc_html__( 'Title', 'eventorganiser' ),
+			esc_attr( $this->get_field_name( 'title' ) ),
+			esc_attr( $instance['title'] )
+		);
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				<input type="checkbox" id="%1$s" name="%3$s" value="1" %4$s>
+			</p>',
+			esc_attr( $this->get_field_id( 'showpastevents' ) ),
+			esc_html__( 'Include past events', 'eventorganiser' ),
+			esc_attr( $this->get_field_name( 'showpastevents' ) ),
+			checked( $instance['showpastevents'], 1, false )
+		);
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				<input type="checkbox" id="%1$s" name="%3$s" value="1" %4$s>
+			</p>',
+			esc_attr( $this->get_field_id( 'show-long' ) ),
+			esc_html__( 'Show long events', 'eventorganiser' ),
+			esc_attr( $this->get_field_name( 'show-long' ) ),
+			checked( $instance['show-long'], 1, false )
+		);
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				<input type="checkbox" id="%1$s" name="%3$s" value="1" %4$s>
+			</p>',
+			esc_attr( $this->get_field_id( 'link-to-single' ) ),
+			esc_html__( 'Link directly to event for days with only one event', 'eventorganiser' ),
+			esc_attr( $this->get_field_name( 'link-to-single' ) ),
+			checked( $instance['link-to-single'], 1, false )
+		);
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				<input type="text" id="%1$s" name="%3$s" value="%4$s" class="widefat">
+				<em> %5$s </em>
+			</p>',
+			esc_attr( $this->get_field_id( 'event-category' ) ),
+			esc_html__( 'Event categories', 'eventorganiser' ),
+			esc_attr( $this->get_field_name( 'event-category' ) ),
+			esc_attr( $instance['event-category'] ),
+			esc_html__( 'List category slug(s), seperate by comma. Leave blank for all', 'eventorganiser' )
+		);
+
+		printf(
+			'<p>
+				<label for="%1$s"> %2$s: </label>
+				%3$s
+			</p>',
+			esc_attr( $this->get_field_id( 'event-venue' ) ),
+			esc_html__( 'Event venue', 'eventorganiser' ),
+			eo_taxonomy_dropdown( array(
+				'taxonomy'        => 'event-venue',
+				'echo'            => 0,
+				'show_option_all' => esc_html__( 'All Venues','eventorganiser' ),
+				'id'              => $this->get_field_id( 'event-venue' ),
+				'selected'        => $instance['event-venue'],
+				'name'            => $this->get_field_name( 'event-venue' ),
+				'hide_empty'      => false,
+			) )
+		);
+
+	}
+
+
+	function update( $new_instance, $old_instance ) {
+
+		$validated = array(
+			'title'          => sanitize_text_field( $new_instance['title'] ),
+			'event-category' => sanitize_text_field( $new_instance['event-category'] ),
+			'event-venue'    => sanitize_text_field( $new_instance['event-venue'] ),
+			'showpastevents' => ! empty( $new_instance['showpastevents'] ) ? 1:  0,
+			'show-long'      => ! empty( $new_instance['show-long'] ) ? 1:  0,
+			'link-to-single' => ! empty( $new_instance['link-to-single'] ) ? 1:  0,
+		);
+
+		delete_transient( 'eo_widget_calendar' );
+
+		return $validated;
+	}
+
+	function widget( $args, $instance ) {
+
+		wp_enqueue_script( 'eo_front' );
+
+		//Set the month to display (DateTime must be 1st of that month)
+		$tz   = eo_get_blog_timezone();
+		$date = get_query_var( 'ondate' ) ?  str_replace( '/', '-', get_query_var( 'ondate' ) ) : 'now';
+		try {
+			$month = new DateTime( $date, $tz );
+		} catch ( Exception $e ) {
+			$month = new DateTime( 'now', $tz );
+		}
+		$month = date_create( $month->format( 'Y-m-1' ), $tz );
+
+		/* Set up the event query */
+		$calendar = array(
+			'showpastevents' => ( empty( $instance['showpastevents'] ) ? 0 : 1 ),
+			'show-long'      => ( empty( $instance['show-long'] ) ? 0 : 1 ),
+			'link-to-single' => ( empty( $instance['link-to-single'] ) ? 0 : 1 ),
+			'event-venue'    => ( ! empty( $instance['event-venue'] ) ? $instance['event-venue'] : 0 ),
+			'event-category' => ( ! empty( $instance['event-category'] ) ? $instance['event-category'] : 0 ),
+		);
+		$title = ! empty( $instance['title'] ) ? $instance['title'] : false;
+
+		add_action( 'wp_footer', array( __CLASS__, 'add_options_to_script' ) );
+
+		$id = esc_attr( $args['widget_id'] );
+		self::$widget_cal[$id] = $calendar;
+
+		//Echo widget
+		echo $args['before_widget'];
+
+		$widget_title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
+
+		if ( $widget_title ) {
+			echo $args['before_title'] . esc_html( $widget_title ) . $args['after_title'];
+		}
+
+		echo "<div id='{$id}_content' class='eo-widget-cal-wrap' data-eo-widget-cal-id='{$id}' >";
+			echo $this->generate_output( $month, $calendar );
+		echo '</div>';
+
+		echo $args['after_widget'];
+	}
+
+	static function add_options_to_script() {
+		wp_enqueue_script( 'eo_front' );
+		eo_enqueue_style( 'eo_front' );
+		if ( ! empty( self::$widget_cal ) ) {
+			wp_localize_script( 'eo_front', 'eo_widget_cal', self::$widget_cal );
+		}
+	}
+
+	/**
+	* Generates widget / shortcode calendar html
+	*
+	* @param $month - DateTime object for first day of the month (in blog timezone)
+	*/
+	static function generate_output( $month, $args = array() ) {
+
+		//Translations
+		global $wp_locale;
+
+		$today = new DateTime( 'now', eo_get_blog_timezone() );
+
+		//Ensure a different cache key for those who can and cannot see private blogs
+		$args['_priv'] = current_user_can( 'read_private_events' ) ? '_priv' : false;
+
+		$key = $month->format( 'YM' ) . serialize( $args ) . get_locale() . $today->format( 'Y-m-d' );
+		$calendar = get_transient( 'eo_widget_calendar' );
+		if ( ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && $calendar && is_array( $calendar ) && isset( $calendar[$key] ) ) {
+			return $calendar[$key];
+		}
+
+		//Parse defaults
+		$args = array_merge( array(
+			'show-long'      => false,
+			'link-to-single' => false,
+			'event-venue'    => false,
+			'event-category' => false,
+		), $args );
+
+		//Month details
+		$first_day_of_month = intval( $month->format( 'N' ) ); //0=sun,...,6=sat
+		$days_in_month      = intval( $month->format( 't' ) ); // 28-31
+
+		$last_month = clone $month;
+		$next_month = clone $month;
+		$last_month->modify( 'last month' );
+		$next_month->modify( 'next month' );
+
+		//Retrieve the start day of the week from the options.
+		$start_day = intval( get_option( 'start_of_week' ) );//0=sun,...,6=sat
+
+		//How many blank cells before inserting dates
+		$offset = ( $first_day_of_month - $start_day + 7 ) % 7;
+
+		//Number of weeks to show in Calendar
+		$totalweeks = ceil( ( $offset + $days_in_month ) / 7 );
+
+		//Get events for this month
+		$start = $month->format( 'Y-m-d' );
+		$end   = $month->format( 'Y-m-t' );
+
+		//Query events
+		$required = array(
+			'numberposts' => -1,
+			'showrepeats' => 1,
+			'post_status' => array( 'publish', 'private' ),
+			'perm'        => 'readable',
+		);
+
+		if ( $args['show-long'] ) {
+			$args['event_start_before'] = $end;
+			$args['event_end_after']    = $start;
+		} else {
+			$args['event_start_before'] = $end;
+			$args['event_start_after']  = $start;
+		}
+		$events = eo_get_events( array_merge( $args, $required ) );
+
+		//Populate events array
+		$calendar_events = array();
+		foreach ( $events as $event ) :
+
+			if ( $args['show-long'] ) {
+				$start   = eo_get_the_start( DATETIMEOBJ, $event->ID, $event->occurrence_id );
+				$end     = eo_get_the_end( DATETIMEOBJ, $event->ID, $event->occurrence_id );
+				$pointer = clone $start;
+
+				while ( $pointer->format( 'Ymd' ) <= $end->format( 'Ymd' ) ) {
+					$date = eo_format_datetime( $pointer, 'Y-m-d' );
+					$calendar_events[ $date ][] = $event;
+					$pointer->modify( '+1 day' );
+				}
+			} else {
+				$date = eo_get_the_start( 'Y-m-d', $event->ID, $event->occurrence_id );
+				$calendar_events[$date][] = $event;
+			}
+
+		endforeach;
+
+		$before = "<table id='wp-calendar'>";
+
+		$title = sprintf( '<caption> %s </caption>', esc_html( eo_format_datetime( $month, 'F Y' ) ) );
+
+		$head = '<thead><tr>';
+		for ( $d = 0; $d <= 6; $d++ ) :
+			$day = $wp_locale->get_weekday( ( $d + $start_day ) % 7 );
+			$day_abbrev = $wp_locale->get_weekday_initial( $day );
+			$head .= sprintf( "<th title='%s' scope='col'>%s</th>", esc_attr( $day ), esc_html( $day_abbrev ) );
+		endfor;
+		$head .= '</tr></thead>';
+
+		$foot = sprintf(
+			"<tfoot><tr>
+				<td id='eo-widget-prev-month' colspan='3'><a title='%s' href='%s'>&laquo; %s</a></td>
+				<td class='pad'>&nbsp;</td>
+				<td id='eo-widget-next-month' colspan='3'><a title='%s' href='%s'> %s &raquo; </a></td>
+			</tr></tfoot>",
+			esc_html__( 'Previous month', 'eventorganiser' ),
+			esc_url( add_query_arg( 'eo_month', $last_month->format( 'Y-m' ), home_url() ) ),
+			esc_html( eo_format_datetime( $last_month, 'M' ) ),
+			esc_html__( 'Next month', 'eventorganiser' ),
+			esc_url( add_query_arg( 'eo_month', $next_month->format( 'Y-m' ), home_url() ) ),
+			esc_html( eo_format_datetime( $next_month, 'M' ) )
+		);
+
+		$body = '<tbody>';
+		$current_date = clone $month;
+
+		//Foreach week in calendar
+		for ( $w = 0; $w <= $totalweeks - 1; $w++ ) :
+			$body .= '<tr>';
+
+			//For each cell in this week
+			for ( $cell = ( $w * 7 ) + 1; $cell <= ($w + 1) * 7;  $cell++ ) :
+
+				$formated_date = $current_date->format( 'Y-m-d' );
+				$data = "data-eo-wc-date='{$formated_date}'";
+
+				if ( $cell <= $offset ) {
+					$body .= '<td class="pad eo-before-month" colspan="1">&nbsp;</td>';
+				} elseif ( $cell - $offset > $days_in_month ) {
+					$body .= '<td class="pad eo-after-month" colspan="1">&nbsp;</td>';
+
+				} else {
+					$class = array();
+
+					if ( $formated_date < $today->format( 'Y-m-d' ) ) {
+						$class[] = 'eo-past-date';
+					} elseif ( $formated_date == $today->format( 'Y-m-d' ) ) {
+						$class[] = 'today';
+					} else {
+						$class[] = 'eo-future-date';
+					}
+
+					//Does the date have any events
+					if ( isset( $calendar_events[$formated_date] ) ) {
+						$class[] = 'event';
+						$events = $calendar_events[$formated_date];
+
+						if ( $events && 1 == count( $events ) && $args['link-to-single'] ) {
+							$only_event = $events[0];
+							$link = get_permalink( $only_event->ID );
+						} else {
+							$link = eo_get_event_archive_link(
+								$current_date->format( 'Y' ),
+								$current_date->format( 'm' ),
+								$current_date->format( 'd' )
+							);
+							$query_args = array_filter( array(
+								'event-venue'    => $args['event-venue'],
+								'event-category' => $args['event-category'],
+							) );
+							$link = add_query_arg( $query_args, $link );
+						}
+						$link = esc_url( $link );
+
+						/**
+						 * Filters the the link of a date on the events widget calendar
+						 *
+						 * @package widgets
+						 * @param string $link The link
+						 * @param datetime $current_date The date being filtered
+						 * @param array $events Array of events starting on this day
+						*/
+						$link = apply_filters( 'eventorganiser_widget_calendar_date_link', $link, $current_date, $events );
+						foreach ( $events as $event ) {
+							$class = array_merge( $class, eo_get_event_classes( $event->ID, $event->occurrence_id ) );
+						}
+
+						$class   = array_unique( array_filter( $class ) );
+						$classes = implode( ' ', $class );
+						$titles  = implode( '&#13;&#10;', array_map( 'get_the_title', $events ) );
+
+						$body .= sprintf(
+							"<td $data class='%s'> <a title='%s' href='%s'> %s </a></td>",
+							esc_attr( $classes ),
+							esc_attr( $titles ),
+							$link,
+							$cell - $offset
+						);
+					} else {
+						$classes = implode( ' ',$class );
+						$body .= sprintf( "<td $data class='%s'> %s </td>", esc_attr( $classes ), $cell - $offset );
+					}
+
+					//Proceed to next day
+					$current_date->modify( '+1 day' );
+				}
+
+		 	endfor;//Endfor each day in week
+
+		 	$body .= '</tr>';
+
+		endfor; //End for each week
+
+		$body .= '</tbody>';
+		$after = '</table>';
+
+		if ( ! $calendar || ! is_array( $calendar ) ) {
+			$calendar = array();
+		}
+
+		$calendar[$key] = $before . $title . $head . $body . $foot . $after;
+
+		set_transient( 'eo_widget_calendar', $calendar, DAY_IN_SECONDS );
+		return $calendar[$key];
+	}
+}
+add_action( 'widgets_init', array( 'EO_Calendar_Widget', 'register' ) );

+ 343 - 0
wp-content/plugins/event-organiser/classes/class-eo-event-list-widget.php

@@ -0,0 +1,343 @@
+<?php
+/**
+ * Class used to create the event list widget
+ */
+class EO_Event_List_Widget extends WP_Widget {
+
+	/*
+	 * Array of default settings
+	 */
+	public static $w_arg;
+
+	function __construct() {
+		$widget_ops = array( 'classname' => 'EO_Event_List_Widget', 'description' => __( 'Displays a list of events', 'eventorganiser' ) );
+		parent::__construct( 'EO_Event_List_Widget', __( 'Events','eventorganiser' ), $widget_ops );
+	}
+
+	/**
+	 * Registers the widget with the WordPress Widget API.
+	 *
+	 * @return void.
+	 */
+	public static function register() {
+		register_widget( __CLASS__ );
+
+		//When adding new variables, remember to exclude non-query related ones
+		//from being pass to eventorganiser_list_events().
+		self::$w_arg = array(
+			'title'           => __( 'Events', 'eventorganiser' ),
+			'numberposts'     => 5,
+			'event-category'  => '',
+			'venue'           => '',
+			'orderby'         => 'eventstart',
+			'scope'           => 'future',
+			'group_events_by' => '',
+			'order'           => 'ASC',
+			'template'        => '',
+			'no_events'       => __( 'No Events', 'eventorganiser' ),
+		);
+
+	}
+
+	function get_event_intervals() {
+
+		$intervals = array(
+			'future' => array(
+				'label' => __( 'Future events', 'eventorganiser' ),
+				'query'	=> array(
+					'event_start_after' => 'now',
+				),
+			),
+			'all' => array(
+				'label' => __( 'All events', 'eventorganiser' ),
+				'query'	=> array(
+					'showpastevents' => 'all',
+				),
+			),
+			'running' => array(
+				'label' => __( 'Running events', 'eventorganiser' ),
+				'query'	=> array(
+					'event_start_before' => 'now',
+					'event_end_after'    => 'now',
+				),
+			),
+			'past' => array(
+				'label' => __( 'Past events', 'eventorganiser' ),
+				'query'	=> array(
+					'event_end_before' => 'now',
+				),
+			),
+			'future-running' => array(
+				'label' => __( 'Future & running events', 'eventorganiser' ),
+				'query'	=> array(
+					'event_end_after' => 'now',
+				),
+			),
+			'today' => array(
+				'label' => __( 'Events on today', 'eventorganiser' ),
+				'query'	=> array(
+					'event_start_before' => 'now',
+					'event_end_after'    => 'now',
+				),
+			),
+
+		);
+
+		$intervals = apply_filters( 'eventorganiser_query_scope', $intervals );
+
+		return $intervals;
+
+	}
+
+	function form( $instance ) {
+
+		if ( ! isset( $instance['scope'] ) && isset( $instance['showpastevents'] ) ) {
+			$exclude_running = eventorganiser_get_option( 'runningisnotpast',0 );
+			$instance['scope'] = $instance['showpastevents'] ? 'all' : ( $exclude_running ? 'future' : 'future-running' );
+		}
+		$instance = wp_parse_args( (array) $instance, self::$w_arg );
+
+		?>
+		<p>
+			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title', 'eventorganiser' ); ?>: </label>
+			<input type="text" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo esc_attr( $instance['title'] ); ?>" />
+		</p>
+			<p>
+				<label for="<?php echo $this->get_field_id( 'numberposts' ); ?>"><?php _e( 'Number of events', 'eventorganiser' );?>:   </label>
+	  		<input id="<?php echo $this->get_field_id( 'numberposts' ); ?>" name="<?php echo $this->get_field_name( 'numberposts' ); ?>" type="number" size="3" value="<?php echo intval( $instance['numberposts'] );?>" />
+		</p>
+			<p>
+				<label for="<?php echo $this->get_field_id( 'event-category' ); ?>"><?php _e( 'Event categories', 'eventorganiser' ); ?>:   </label>
+	  		<input  id="<?php echo $this->get_field_id( 'event-category' ); ?>" class="widefat" name="<?php echo $this->get_field_name( 'event-category' ); ?>" type="text" value="<?php echo esc_attr( $instance['event-category'] );?>" />
+				<em><?php _e( 'List category slug(s), seperate by comma. Leave blank for all', 'eventorganiser' ); ?></em>
+		</p>
+		<?php
+		if ( taxonomy_exists( 'event-venue' ) ) { ?>
+				<p>
+	  			<label for="<?php echo $this->get_field_id( 'venue' ); ?>"><?php _e( 'Venue:', 'eventorganiser' ); ?></label>
+				<?php $venues = get_terms( 'event-venue', array( 'hide_empty' => false ) );?>
+				<select id="<?php echo $this->get_field_id( 'venue' ); ?>" name="<?php echo $this->get_field_name( 'venue' ); ?>" type="text">
+					<option value="" <?php selected( $instance['venue'], '' ); ?>><?php _e( 'All Venues', 'eventorganiser' ); ?> </option>
+					<?php foreach ( $venues as $venue ) { ?>
+						<option <?php selected( $instance['venue'], $venue->slug );?> value="<?php echo esc_attr( $venue->slug );?>"><?php echo esc_html( $venue->name ); ?></option>
+					<?php } ?>
+				</select>
+			</p>
+		<?php } ?>
+		<p>
+				<label for="<?php echo $this->get_field_id( 'scope' ); ?>"><?php _e( 'Show:', 'eventorganiser' ); ?></label>
+			<select id="<?php echo $this->get_field_id( 'scope' ); ?>" name="<?php echo $this->get_field_name( 'scope' ); ?>" >
+				<?php
+				foreach ( $this->get_event_intervals() as $scope_id => $scope ) {
+					printf(
+						'<option value="%s" %s>%s</option>',
+						$scope_id,
+						selected( $instance['scope'], $scope_id, false ),
+						$scope['label']
+					);
+				}
+				?>
+			</select>
+		</p>
+		      
+		<p>
+				<label for="<?php echo $this->get_field_id( 'orderby' ); ?>"><?php _e( 'Order by', 'eventorganiser' ); ?></label>
+			<select id="<?php echo $this->get_field_id( 'orderby' ); ?>" name="<?php echo $this->get_field_name( 'orderby' ); ?>">
+				<option value="eventstart" <?php selected( $instance['orderby'], 'eventstart' ); ?>><?php _e( 'Start date', 'eventorganiser' ); ?></option>
+				<option value="title" <?php selected( $instance['orderby'], 'title' );?>><?php _e( 'Title', 'eventorganiser' ); ?></option>
+				<option value="date" <?php selected( $instance['orderby'], 'date' );?>><?php _e( 'Publish date', 'eventorganiser' ); ?></option>
+			</select>
+			<select id="<?php echo $this->get_field_id( 'order' ); ?>" name="<?php echo $this->get_field_name( 'order' ); ?>" >
+				<option value="asc" <?php selected( $instance['order'], 'asc' ); ?>><?php _e( 'ASC', 'eventorganiser' ); ?> </option>
+				<option value="desc" <?php selected( $instance['order'], 'desc' );?>><?php _e( 'DESC', 'eventorganiser' ); ?> </option>
+			</select>
+		</p>
+
+		<p>
+			<label for="<?php echo $this->get_field_id( 'group_events_by' ); ?>"><?php _e( 'Group occurrences', 'eventorganiser' ); ?></label>
+			<input type="checkbox" id="<?php echo $this->get_field_id( 'group_events_by' ); ?>" value="series" name="<?php echo $this->get_field_name( 'group_events_by' ); ?>" <?php checked( $instance['group_events_by'],'series' );?> />
+		</p>
+		
+		<p>
+			<label for="<?php echo $this->get_field_id( 'template' ); ?>">
+			<?php
+				_e( 'Template (leave blank for default)', 'eventorganiser' );
+				echo eventorganiser_inline_help(
+					__( 'Event list widget placeholders', 'eventorganiser' ),
+					sprintf(
+						__( 'You can use specified tags as placeholders for event information which you want to appear in the widget. <a href="%s" target="_blank"> Find out more</a>.', 'eventorganiser' ),
+						'http://docs.wp-event-organiser.com/widgets/events-list'
+					)
+				);
+			?>
+			</label>
+			<input id="<?php echo esc_attr( $this->get_field_id( 'template' ) ); ?>" class="widefat" name="<?php echo esc_attr( $this->get_field_name( 'template' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['template'] );?>" />
+			</p>
+	
+			<p>
+			<label for="<?php echo $this->get_field_id( 'no_events' ); ?>"><?php _e( "'No events' message", 'eventorganiser' ); ?>  </label>
+	  		<input  id="<?php echo $this->get_field_id( 'no_events' ); ?>" class="widefat" name="<?php echo $this->get_field_name( 'no_events' ); ?>" type="text" value="<?php echo esc_attr( $instance['no_events'] );?>" />
+			</p>
+		<?php
+	}
+
+	function update( $new_inst, $old_inst ) {
+
+		$intervals = array_keys( $this->get_event_intervals() );
+
+		$validated = array(
+			'title'           => sanitize_text_field( $new_inst['title'] ),
+			'numberposts'     => intval( $new_inst['numberposts'] ),
+			'venue'           => sanitize_text_field( $new_inst['venue'] ),
+			'scope'           => isset( $new_inst['scope'] ) && in_array( $new_inst['scope'], $intervals ) ? $new_inst['scope'] : 'future',
+			'order'           => ( 'asc' == $new_inst['order'] ? 'asc' : 'desc' ),
+			'orderby'         => in_array( $new_inst['orderby'],  array( 'title', 'eventstart', 'date' ) ) ? $new_inst['orderby'] : 'eventstart',
+			'group_events_by' => ( isset( $new_inst['group_events_by'] ) && ( 'series' == $new_inst['group_events_by'] ) ) ? 'series' : '',
+			'template'        => $new_inst['template'],
+			'no_events'       => $new_inst['no_events'],
+		);
+
+		$event_cats = array_map( 'sanitize_text_field', explode( ',', $new_inst['event-category'] ) );
+		$validated['event-category'] = implode( ',', $event_cats );
+
+		return $validated;
+	}
+
+	function widget( $args, $instance ) {
+		$instance = array_merge( array(
+			'no_events' => '',
+			'template'  => '',
+			'title'     => '',
+			'scope'     => 'future',
+		), $instance );
+
+		//Backwards compatability with show past events option
+		if ( ! isset( $instance['scope'] ) && isset( $instance['showpastevents'] ) ) {
+			$exclude_running = eventorganiser_get_option( 'runningisnotpast',0 );
+			$instance['scope'] = $instance['showpastevents'] ? 'all' : ( $exclude_running ? 'future' : 'future-running' );
+		}
+		unset( $instance['showpastevents'] );
+
+		$template  = $instance['template'];
+		$no_events = $instance['no_events'];
+
+		echo $args['before_widget'];
+
+		$widget_title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
+
+		if ( $widget_title ) {
+			echo $args['before_title'] . esc_html( $widget_title ) . $args['after_title'];
+		}
+
+		$scope     = $instance['scope'];
+		$intervals = $this->get_event_intervals();
+		$instance  = array_merge( $instance, (array) $intervals[$scope]['query'] );
+
+		//Ensure $query doesn't contain any non-query related values
+		//@see https://github.com/stephenharris/Event-Organiser/issues/314
+		$non_query = array( 'title', 'scope', 'no_events', 'template' );
+		$query = array_diff_key( $instance, array_flip( $non_query ) );
+		eventorganiser_list_events( $query, array(
+			'type'      => 'widget',
+			'class'     => 'eo-events eo-events-widget',
+			'template'  => $template,
+			'no_events' => $no_events,
+		) );
+
+		echo $args['after_widget'];
+	}
+}
+
+/**
+ * @access private
+ * @ignore
+ */
+function eventorganiser_list_events( $query, $args = array(), $echo = 1 ) {
+
+	$args = array_merge(array(
+		'id'        => '',
+		'class'     => 'eo-event-list',
+		'type'      => 'shortcode',
+		'no_events' => '',
+	),$args);
+
+	/* Pass these defaults - backwards compat with using eo_get_events()*/
+	$query = wp_parse_args($query, array(
+		'posts_per_page'   => -1,
+		'post_type'        => 'event',
+		'suppress_filters' => false,
+		'orderby'          => 'eventstart',
+		'order'            => 'ASC',
+		'showrepeats'      => 1,
+		'group_events_by'  => '',
+		'showpastevents'   => true,
+		'no_found_rows'    => true,
+	));
+
+	//Make sure false and 'False' etc actually get parsed as 0/false (input from shortcodes, for instance, can be varied).
+	//This maybe moved to the shortcode handler if this function is made public.
+	if ( 'false' === strtolower( $query['showpastevents'] ) ) {
+		$query['showpastevents'] = 0;
+	}
+
+	if ( ! empty( $query['numberposts'] ) ) {
+		$query['posts_per_page'] = (int) $query['numberposts'];
+	}
+
+	$template = isset( $args['template'] ) ? $args['template'] :'';
+
+	global $eo_event_loop,$eo_event_loop_args;
+	$eo_event_loop_args = $args;
+	$eo_event_loop = new WP_Query( $query );
+
+	/**
+	 * @ignore
+	 * Try to find template - backwards compat. Don't use this filter. Will be removed!
+	 */
+	$template_file = apply_filters( 'eventorganiser_event_list_loop', false );
+	$template_file = locate_template( $template_file );
+	if ( $template_file || empty( $template ) ) {
+		ob_start();
+		if ( empty( $template_file ) ) {
+			$template_file = eo_locate_template( array( $eo_event_loop_args['type'] . '-event-list.php', 'event-list.php' ), true, false );
+		} else {
+			require( $template_file );
+		}
+
+		$html = ob_get_contents();
+		ob_end_clean();
+
+	} else {
+		//Using the 'placeholder' template
+		$no_events = isset( $args['no_events'] ) ? $args['no_events'] : '';
+
+		$id        = ( ! empty( $args['id'] ) ? 'id="' . esc_attr( $args['id'] ) . '"' : '' );
+		$container = '<ul ' . $id . ' class="%2$s">%1$s</ul>';
+
+		$html = '';
+		if ( $eo_event_loop->have_posts() ) {
+			while ( $eo_event_loop->have_posts() ) {
+				$eo_event_loop->the_post();
+				$event_classes = eo_get_event_classes();
+				$html .= sprintf(
+					'<li class="%2$s">%1$s</li>',
+					EventOrganiser_Shortcodes::read_template( $template ),
+					esc_attr( implode( ' ', $event_classes ) )
+				);
+			}
+		} elseif ( $no_events ) {
+			$html .= sprintf( '<li class="%2$s">%1$s</li>', $no_events, 'eo-no-events' );
+		}
+
+		$html = sprintf( $container, $html, esc_attr( $args['class'] ) );
+	}
+
+	wp_reset_postdata();
+
+	if ( $echo ) {
+		echo $html;
+	}
+
+	return $html;
+}
+add_action( 'widgets_init', array( 'EO_Event_List_Widget', 'register' ) );

+ 225 - 0
wp-content/plugins/event-organiser/classes/class-eo-venue-list-table.php

@@ -0,0 +1,225 @@
+<?php
+
+/*
+ *The WP_List_Table class isn't automatically available to plugins, so we need
+ * to check if it's available and load it if necessary.
+ */
+if ( ! class_exists( 'WP_List_Table' ) ) {
+	require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
+}
+
+/**
+ * Class used for displaying venue table
+ */
+class EO_Venue_List_Table extends WP_List_Table {
+
+	/**
+	 * Constructor. Set some default configs.
+	 */
+	function __construct() {
+		//Set parent defaults
+		parent::__construct( array(
+			'singular'  => 'venue',//singular name of the listed records
+			'plural'    => 'venues',//plural name of the listed records
+		));
+	}
+
+	/*
+	 * For more detailed insight into how columns are handled, take a look at
+     * WP_List_Table::single_row_columns()
+	 *
+     * @param array $item A singular item (one full row's worth of data)
+     * @param array $column_name The name/slug of the column to be processed
+     * @return string Text or HTML to be placed inside the column <td>
+     */
+	function column_default( $item, $column_name ) {
+		$term_id = (int) $item->term_id;
+		$address = eo_get_venue_address( $term_id );
+
+		switch ( $column_name ) {
+
+			case 'venue_slug':
+				return esc_html( $item->slug );
+
+			case 'posts':
+				return intval( $item->count );
+
+			default:
+				$key = str_replace( 'venue_', '', $column_name );
+
+				if ( 'venue_' . $key == $column_name && isset( $address[$key] ) ) {
+					return esc_html( $address[$key] );
+				}
+				//TODO Hook for extra columns?
+		}
+	}
+
+
+	/**
+	 * @see WP_List_Table::::single_row_columns()
+	 * @param array $item A singular item (one full row's worth of data)
+	 * @return string Text to be placed inside the column <td>
+	 */
+	function column_name( $item ) {
+		$term_id = (int) $item->term_id;
+
+		$name       = $item->name;
+		$delete_url = add_query_arg( 'action', 'delete', get_edit_term_link( $term_id, 'event-venue', 'event' ) );
+
+		//Inline row actions
+		$actions = array(
+			'edit' => sprintf(
+				'<a href="%s" aria-label="%s">%s</a>',
+				esc_url( get_edit_term_link( $term_id, 'event-venue', 'event' ) ),
+				/* translators: %s: venue name */
+				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;', 'event-organiser' ), $name ) ),
+				esc_html__( 'Edit', 'eventorganiser' )
+			),
+			'delete' => sprintf(
+				'<a href="%s" aria-label="%s">%s</a>',
+				esc_url( wp_nonce_url( $delete_url, 'eventorganiser_delete_venue_' . $item->slug ) ),
+				/* translators: %s: venue name */
+				esc_attr( sprintf( __( 'Delete &#8220;%s&#8221;', 'event-organiser' ), $name ) ),
+				esc_html__( 'Delete', 'eventorganiser' )
+			),
+			'view' => sprintf(
+				'<a href="%s" aria-label="%s">%s</a>',
+				esc_url( eo_get_venue_link( $term_id ) ),
+				/* translators: %s: venue name */
+				esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'event-organiser' ), $name ) ),
+				esc_html__( 'View', 'eventorganiser' )
+			),
+		);
+
+		return sprintf(
+			'<a href="%1$s" class="row-title">%2$s</a>%3$s',
+			esc_url( get_edit_term_link( $term_id, 'event-venue', 'event' ) ),
+			esc_html( $name ),
+			$this->row_actions( $actions )
+		);
+	}
+
+	/**
+	 * Checkbox column for Bulk Actions.
+	 *
+	 * @see WP_List_Table::::single_row_columns()
+	 * @param array $item A singular item (one full row's worth of data)
+	 * @return string Text to be placed inside the column <td> (movie title only)
+	 */
+	function column_cb( $item ) {
+		return sprintf(
+			'<input type="checkbox" name="%1$s[]" value="%2$s" />',
+			/*$1%s*/ 'event-venue',
+			/*$2%s*/ esc_attr( $item->slug )
+		);
+	}
+
+	/**
+	 * Set columns sortable
+	 *
+	 * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
+	 */
+	function get_sortable_columns() {
+		$sortable_columns = array(
+			'name'		     => array( 'name', true ),//true means its sorted by default
+			'venue_address'  => array( 'address', false ),
+			'venue_city'	 => array( 'city', false ),
+			'venue_state'	 => array( 'state', false ),
+			'venue_postcode' => array( 'postcode', false ),
+			'venue_country'	 => array( 'country', false ),
+			'venue_slug'	 => array( 'slug', false ),
+			'posts'		     => array( 'count', false ),
+		);
+		return $sortable_columns;
+	}
+
+	/**
+	 * Set bulk actions
+	 *
+	 * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
+	 */
+	function get_bulk_actions() {
+		$actions = array(
+			'delete' => esc_html__( 'Delete', 'eventorganiser' ),
+		);
+		return $actions;
+	}
+
+
+	/**
+	 * Echos the row, after assigning it an ID based ont eh venue being shown. Assign appropriate class to alternate rows.
+	 */
+	function single_row( $item ) {
+		static $row_class = '';
+		$row_class = ( '' == $row_class ? 'alternate' : '' );
+		echo sprintf( '<tr class="%s" id="venue-%d">', $row_class, $item->term_id );
+		echo $this->single_row_columns( $item );
+		echo '</tr>';
+	}
+
+	function get_columns() {
+		return get_column_headers( 'event_page_venues' );
+	}
+
+	/**
+	 *
+	 * @return bool
+	 */
+	public function ajax_user_can() {
+		return current_user_can( 'manage_venues' );
+	}
+
+	/**
+	 * Prepare venues for display
+	 *
+	 * @uses $this->_column_headers
+	 * @uses $this->items
+	 * @uses $this->get_columns()
+	 * @uses $this->get_sortable_columns()
+	 * @uses $this->get_pagenum()
+	 * @uses $this->set_pagination_args()
+	 */
+	function prepare_items() {
+
+		//Retrieve page number for pagination
+		$current_page = (int) $this->get_pagenum();
+
+		//First, lets decide how many records per page to show
+		$screen   = get_current_screen();
+		$per_page = $this->get_items_per_page( 'edit_event_venue_per_page' );
+
+		//Get the columns, the hidden columns an sortable columns
+		$columns  = $this->get_columns();
+		$hidden   = get_hidden_columns( 'event_page_venues' );
+		$sortable = $this->get_sortable_columns();
+		$this->_column_headers = array( $columns, $hidden, $sortable );
+		$taxonomy = 'event-venue';
+
+		$request = array_merge( $_GET, $_POST );
+		$search  = ( ! empty( $request['s'] ) ? trim( stripslashes( $request['s'] ) ) : '' );
+		$orderby = ( ! empty( $request['orderby'] )  ? trim( stripslashes( $request['orderby'] ) ) : '' );
+		$order   = ( ! empty( $request['order'] )  ? trim( stripslashes( $request['order'] ) ) : '' );
+
+		//Display result
+		$this->items = get_terms( 'event-venue', array(
+			'hide_empty' => false,
+			'search'     => $search,
+			'offset'     => ( $current_page - 1 ) * $per_page,
+			'number'     => $per_page,
+		 	'orderby'    => $orderby,
+			'order'      => $order,
+			'eo_update_venue_cache' => true,
+		));
+
+		$this->set_pagination_args( array(
+			'total_items' => wp_count_terms( 'event-venue', compact( 'search', 'orderby' ) ),
+			'per_page'    => $per_page,
+		) );
+
+	}
+
+	function no_items() {
+		$tax = get_taxonomy( 'event-venue' );
+		echo esc_html( $tax->labels->not_found );
+	}
+}

+ 135 - 0
wp-content/plugins/event-organiser/classes/class-eo-widget-categories.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * Event categories widget class
+ *
+ * @since 1.8
+ */
+class EO_Widget_Categories extends WP_Widget {
+
+	function __construct() {
+		$widget_ops = array( 'classname' => 'eo__event_categories', 'description' => __( 'A list or dropdown of event categories', 'eventorganiser' ) );
+		parent::__construct( 'eo-event-categories', __( 'Event Categories', 'eventorganiser' ), $widget_ops );
+	}
+
+	/**
+	 * Registers the widget with the WordPress Widget API.
+	 *
+	 * @return void.
+	 */
+	public static function register() {
+		register_widget( __CLASS__ );
+	}
+
+	function widget( $args, $instance ) {
+
+		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Categories', 'eventorganiser' ) : $instance['title'], $instance, $this->id_base );
+		$h = ! empty( $instance['hierarchical'] ) ? '1' : '0';
+		$d = ! empty( $instance['dropdown'] ) ? '1' : '0';
+
+		echo $args['before_widget'];
+		if ( $title ) {
+			echo $args['before_title'] . $title . $args['after_title'];
+		}
+
+		//Select current category by default
+		if ( is_tax( 'event-category' ) ) {
+			$term = get_term( get_queried_object_id() , 'event-category' );
+			$selected = ( $term && ! is_wp_error( $term ) ? $term->slug : false );
+		} else {
+			$selected = false;
+		}
+
+		$cat_args = array(
+			'orderby'      => 'name',
+			'hierarchical' => $h,
+			'taxonomy'     => 'event-category',
+			'id'           => 'eo-event-cat',
+			'selected'     => $selected,
+		);
+
+		if ( $d ) {
+			$cat_args['walker'] = new EO_Walker_TaxonomyDropdown();
+			$cat_args['value_field'] = 'slug';
+			$cat_args['show_option_none'] = __( 'Select Category', 'eventorganiser' );
+			/**
+			 * Filters the settings for the event category dropdown.
+			 *
+			 * The filtered array is passed to `wp_dropdown_categories()`. See
+			 * the [WordPress codex](https://codex.wordpress.org/Function_Reference/wp_dropdown_categories Codex)
+			 * for details on its arguments.
+			 *
+			 * @package widgets
+			 * @link https://codex.wordpress.org/Function_Reference/wp_dropdown_categories Codex for `wp_dropdown_categories()`
+			 * @param array $cat_args Settings for the event category dropdown.
+			 */
+			$cat_args = apply_filters( 'eventorganiser_widget_event_categories_dropdown_args', $cat_args );
+			wp_dropdown_categories( $cat_args );
+			?>
+
+<script type='text/javascript'>
+/* <![CDATA[ */
+	var event_dropdown = document.getElementById("eo-event-cat");
+	function eventorganiserDropdownChange() {
+		if ( event_dropdown.options[event_dropdown.selectedIndex].value != -1 ) {
+			location.href = "<?php echo home_url() . '/?event-category=';?>"+event_dropdown.options[event_dropdown.selectedIndex].value;
+		}
+	}
+	event_dropdown.onchange = eventorganiserDropdownChange;
+/* ]]> */
+</script>
+
+<?php
+		} else {
+?>
+		<ul>
+<?php
+		$cat_args['title_li'] = '';
+		/**
+		 * Filters the arguments for the event category list.
+		 *
+		 * The filtered array is passed to `wp_list_categories()`. See
+		 * the [WordPress codex](https://codex.wordpress.org/Function_Reference/wp_list_categories Codex)
+		 * for details on its arguments.
+		 *
+		 * @package widgets
+		 * @link https://codex.wordpress.org/Function_Reference/wp_list_categories Codex for `wp_list_categories()`
+		 * @param array $cat_args Settings for the event category list.
+		 */
+		$cat_args = apply_filters( 'eventorganiser_widget_event_categories_args', $cat_args );
+		wp_list_categories( $cat_args );
+?>
+		</ul>
+<?php
+		}
+
+		echo $args['after_widget'];
+	}
+
+	function update( $new_instance, $old_instance ) {
+		$instance = array(
+			'title'        => strip_tags( $new_instance['title'] ),
+			'hierarchical' => ! empty( $new_instance['hierarchical'] ) ? 1 : 0,
+			'dropdown'     => ! empty( $new_instance['dropdown'] ) ? 1 : 0,
+		);
+		return $instance;
+	}
+
+	function form( $instance ) {
+		//Defaults
+		$instance     = wp_parse_args( (array) $instance, array( 'title' => '' ) );
+		$title        = esc_attr( $instance['title'] );
+		$hierarchical = isset( $instance['hierarchical'] ) ? (bool) $instance['hierarchical'] : false;
+		$dropdown     = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false;
+?>
+		<p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'eventorganiser' ); ?></label>
+		<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo $title; ?>" /></p>
+
+		<p><input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'dropdown' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'dropdown' ) ); ?>"<?php checked( $dropdown ); ?> />
+		<label for="<?php echo esc_attr( $this->get_field_id( 'dropdown' ) ); ?>"><?php esc_html_e( 'Display as dropdown', 'eventorganiser' ); ?></label><br />
+
+		<input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'hierarchical' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'hierarchical' ) ); ?>"<?php checked( $hierarchical ); ?> />
+		<label for="<?php echo esc_attr( $this->get_field_id( 'hierarchical' ) ); ?>"><?php esc_html_e( 'Show hierarchy', 'eventorganiser' ); ?></label></p>
+<?php
+	}
+}
+add_action( 'widgets_init', array( 'EO_Widget_Categories', 'register' ) );

+ 133 - 0
wp-content/plugins/event-organiser/classes/class-eo-widget-venues.php

@@ -0,0 +1,133 @@
+<?php
+/**
+ * Event venues widget class
+ *
+ * @since 1.8
+ * @ignore
+ */
+class EO_Widget_Venues extends WP_Widget {
+
+	function __construct() {
+		$widget_ops = array( 'classname' => 'eo__event_venues', 'description' => __( 'A list or dropdown of event venues', 'eventorganiser' ) );
+		parent::__construct( 'eo-event-venues', __( 'Event Venues', 'eventorganiser' ), $widget_ops );
+	}
+
+	/**
+	 * Registers the widget with the WordPress Widget API.
+	 *
+	 * @return void.
+	 */
+	public static function register() {
+		$supports = eventorganiser_get_option( 'supports' );
+		if ( in_array( 'event-venue', $supports ) ) {
+			register_widget( __CLASS__ );
+		}
+	}
+
+	function widget( $args, $instance ) {
+
+		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Venues', 'eventorganiser' ) : $instance['title'], $instance, $this->id_base );
+		$d     = ! empty( $instance['dropdown'] ) ? '1' : '0';
+
+		echo $args['before_widget'];
+		if ( $title ) {
+			echo $args['before_title'] . $title . $args['after_title']; }
+
+		//Select current category by default
+		if ( is_tax( 'event-venue' ) ) {
+			$term = get_term( get_queried_object_id() , 'event-venue' );
+			$selected = ( $term && ! is_wp_error( $term ) ? $term->slug : false );
+		} else {
+			$selected = false;
+		}
+
+		$cat_args = array(
+			'orderby'      => 'name',
+			'hierarchical' => false,
+			'taxonomy'     => 'event-venue',
+			'id'           => 'eo-event-venue',
+			'selected'     => $selected,
+		);
+
+		if ( $d ) {
+			$cat_args['walker'] = new EO_Walker_TaxonomyDropdown();
+			$cat_args['value_field'] = 'slug';
+			$cat_args['show_option_none'] = __( 'Select Venue', 'eventorganiser' );
+			/**
+			 * Filters the settings for the event venue list drppdown.
+			 *
+			 * The filtered array is passed to `wp_dropdown_categories()`. See
+			 * the [WordPress codex](https://codex.wordpress.org/Function_Reference/wp_dropdown_categories Codex)
+			 * for details on its arguments.
+			 *
+			 * @package widgets
+			 * @link https://codex.wordpress.org/Function_Reference/wp_dropdown_categories Codex for `wp_dropdown_categories()`
+			 * @param array $cat_args Settings for the event venue dropdown.
+			 */
+			$cat_args = apply_filters( 'eventorganiser_widget_event_venues_dropdown_args', $cat_args );
+			wp_dropdown_categories( $cat_args );
+			?>
+
+<script type='text/javascript'>
+/* <![CDATA[ */
+	var event_venue_dropdown = document.getElementById("eo-event-venue");
+	function eventorganiserVenueDropdownChange() {
+		console.log( event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value);
+		if ( event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value != -1 ) {
+			location.href = "<?php echo home_url() . '/?event-venue=';?>"+event_venue_dropdown.options[event_venue_dropdown.selectedIndex].value;
+		}
+	}
+	event_venue_dropdown.onchange = eventorganiserVenueDropdownChange;
+/* ]]> */
+</script>
+
+<?php
+		} else {
+?>
+		<ul>
+<?php
+		$cat_args['title_li'] = '';
+		/**
+		 * Filters the arguments for the event venue list.
+		 *
+		 * The filtered array is passed to `wp_list_categories()`. See
+		 * the [WordPress codex](https://codex.wordpress.org/Function_Reference/wp_list_categories Codex)
+		 * for details on its arguments.
+		 *
+		 * @package widgets
+		 * @link https://codex.wordpress.org/Function_Reference/wp_list_categories Codex for `wp_list_categories()`
+		 * @param array $cat_args Settings for the event venue list.
+		 */
+		$cat_args = apply_filters( 'eventorganiser_widget_event_venues_args', $cat_args );
+		wp_list_categories( $cat_args );
+?>
+		</ul>
+<?php
+		}
+
+		echo $args['after_widget'];
+	}
+
+	function update( $new_instance, $old_instance ) {
+		$instance = $old_instance;
+		$instance['title'] = strip_tags( $new_instance['title'] );
+		$instance['dropdown'] = ! empty( $new_instance['dropdown'] ) ? 1 : 0;
+
+		return $instance;
+	}
+
+	function form( $instance ) {
+		//Defaults
+		$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
+		$title    = esc_attr( $instance['title'] );
+		$dropdown = isset( $instance['dropdown'] ) ? (bool) $instance['dropdown'] : false;
+?>
+		<p><label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_attr_e( 'Title:', 'eventorganiser' ); ?></label>
+		<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo $title; ?>" /></p>
+
+		<p><input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'dropdown' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'dropdown' ) ); ?>"<?php checked( $dropdown ); ?> />
+		<label for="<?php echo esc_attr( $this->get_field_id( 'dropdown' ) ); ?>"><?php esc_attr_e( 'Display as dropdown', 'eventorganiser' ); ?></label><br />
+<?php
+	}
+}
+add_action( 'widgets_init', array( 'EO_Widget_Venues', 'register' ) );

+ 72 - 0
wp-content/plugins/event-organiser/classes/class-eventorganiser-admin-page.php

@@ -0,0 +1,72 @@
+<?php
+/**
+ * @ignore
+ */
+class EventOrganiser_Admin_Page {
+
+	var $hook;
+	var $title;
+	var $menu;
+	var $permissions;
+	var $slug;
+	var $page;
+
+	function __construct() {
+		add_action( 'init', array( $this, 'set_constants' ) );
+		add_action( 'init', array( $this, 'hooks_init' ) );
+	}
+
+	function hooks_init() {
+		add_action( 'admin_menu', array( $this, 'add_page' ) );
+	}
+
+	function set_constants() {
+	}
+
+	function add_page() {
+		$this->page = add_submenu_page( $this->hook,$this->title, $this->menu, $this->permissions,$this->slug,  array( $this, 'render_page' ),10 );
+		add_action( 'load-' . $this->page,  array( $this, 'page_actions' ),9 );
+		add_action( 'admin_print_scripts-' . $this->page,  array( $this, 'page_styles' ),10 );
+		add_action( 'admin_print_styles-' . $this->page,  array( $this, 'page_scripts' ),10 );
+		add_action( 'admin_footer-' . $this->page, array( $this, 'footer_scripts' ) );
+	}
+	function footer_scripts() {
+	}
+
+	function page_scripts() {
+	}
+	/*
+	* Actions to be taken prior to page loading. This is after headers have been set.
+        * @uses load-$hook
+	*/
+	function page_actions() {
+	}
+
+	function page_styles() {
+	}
+
+	function current_action() {
+
+		$request = array_merge( $_GET, $_POST );
+
+		if ( isset( $request['action'] ) && -1 != $request['action'] ) {
+			return $request['action'];
+		}
+
+		if ( isset( $request['action2'] ) && -1 != $request['action2'] ) {
+			return $request['action2'];
+		}
+
+		return false;
+	}
+
+	function init() {
+	}
+
+	function render_page() {
+		$this->init();
+		$this->display();
+	}
+	function display() {
+	}
+}

+ 587 - 0
wp-content/plugins/event-organiser/classes/class-eventorganiser-shortcodes.php

@@ -0,0 +1,587 @@
+<?php
+/**
+ * Class used to create the event calendar shortcode
+ *
+ * @uses EO_Calendar Widget class to generate calendar html
+ * @ignore
+ */
+class EventOrganiser_Shortcodes {
+	static $add_script;
+	static $calendars =array();
+	static $widget_calendars =array();
+	static $map = array();
+	static $event;
+ 
+	static function init() {
+		add_shortcode('eo_calendar', array(__CLASS__, 'handle_calendar_shortcode'));
+		add_shortcode('eo_fullcalendar', array( __CLASS__, 'handle_fullcalendar_shortcode'));
+		add_shortcode('eo_venue_map', array(__CLASS__, 'handle_venuemap_shortcode'));
+		add_shortcode('eo_events', array(__CLASS__, 'handle_eventlist_shortcode'));
+		add_shortcode('eo_subscribe', array(__CLASS__, 'handle_subscription_shortcode'));
+		add_action('wp_footer', array(__CLASS__, 'print_script'));
+	}
+ 
+	static function handle_calendar_shortcode($atts=array()) {
+
+		/* Shortcodes don't accept hyphens, so convert taxonomy names */
+		$taxs = array('category','tag','venue');
+		foreach ($taxs as $tax){
+			if(isset($atts['event_'.$tax])){
+				$atts['event-'.$tax]=	$atts['event_'.$tax];
+				unset($atts['event_'.$tax]);
+			}
+		}
+
+		if( isset( $atts['show_long'] ) ){
+			$atts['show-long'] = $atts['show_long'];
+			unset( $atts['show_long'] ); 			
+		}
+		
+		if( isset( $atts['link_to_single'] ) ){
+			$atts['link-to-single'] = $atts['link_to_single'];
+			unset( $atts['link_to_single'] ); 			
+		}
+
+		/* Parse defaults */
+		$atts = wp_parse_args($atts,array(
+			'showpastevents' => 1,
+			'show-long'      => 0,
+			'link-to-single' => 0,
+		));
+	
+		self::$add_script = true;
+
+		$id     = count(self::$widget_calendars);
+		$cal_id = 'eo_shortcode_calendar_'.$id;
+		self::$widget_calendars[$cal_id] = $atts;
+
+		$tz = eo_get_blog_timezone();
+		$date =  isset($_GET['eo_month']) ? $_GET['eo_month'].'-01' : 'now';
+		$month = new DateTime($date,$tz);
+		$month = date_create($month->format('Y-m-1'),$tz);
+		
+		$html = '<div class="widget_calendar eo-calendar eo-calendar-shortcode eo_widget_calendar" id="'.$cal_id.'">';
+		
+		$html .= '<div id="'.$cal_id.'_content" class="eo-widget-cal-wrap" data-eo-widget-cal-id="'.$cal_id.'">';
+		$html .= EO_Calendar_Widget::generate_output( $month, $atts );
+		$html .='</div>';
+		
+		$html .= '</div>';
+
+		return $html;
+	}
+
+	static function handle_subscription_shortcode( $atts, $content = null ) {
+		$atts = shortcode_atts( array(
+			'title' => 'Subscribe to calendar',
+			'type' => 'google',
+			'class' => '',
+			'id' => '',
+			'style' => '',
+			'category' => false,
+			'venue' => false,
+		), $atts, 'eo_subscribe' );
+
+		if ( $atts['category'] ) {
+			$url = eo_get_event_category_feed( $atts['category'] );
+
+		} elseif ( $atts['venue'] ) {
+			$url = eo_get_event_venue_feed( $atts['venue'] );
+
+		} else {
+			$url = eo_get_events_feed();
+		}
+
+		$class = $atts['class'] ? 'class="' . esc_attr( $atts['class'] ) . '"' : false;
+		$title = $atts['title'] ? 'title="' . esc_attr( $atts['title'] ) . '"' : false;
+		$style = $atts['style'] ? 'style="' . esc_attr( $atts['style'] ) . '"' : false;
+		$id    = $atts['id']    ? 'id="' . esc_attr( $atts['id'] ) . '"' : false;
+
+		if ( strtolower( $atts['type'] ) == 'webcal' ) {
+			$url = preg_replace( '/^http(s?):/i', 'webcal:', $url );
+		} elseif ( strtolower( $atts['type'] ) == 'ical' ) {
+			//Do nothing
+		} else {
+			//Google doesn't support https:// protocols for the cid value
+			//@see https://github.com/stephenharris/Event-Organiser/issues/328
+			//@link  http://stackoverflow.com/a/21218052/932391
+			$url = preg_replace( '/^https:/i', 'http:', $url );
+			$url = add_query_arg( 'cid', urlencode( $url ), 'https://www.google.com/calendar/render' );
+		}
+
+		$html = '<a href="'.$url.'" target="_blank" '.$class.' '.$title.' '.$id.' '.$style.'>'.$content.'</a>';
+		return $html;
+	}
+
+	static function handle_fullcalendar_shortcode( $atts = array() ) {
+
+		global $wp_locale;
+
+		/* Handle Boolean attributes - this will be passed as strings, we want them as boolean */
+		$bool_atts = array(
+			'tooltip' => 'true', 'weekends' => 'true', 'alldayslot' => 'true', 'users_events' => 'false',
+			'theme' => 'false', 'isrtl' => $wp_locale->is_rtl() ? 'true' : 'false', 'responsive' => 'true',
+			'compact' => false,
+		);
+
+		$atts = wp_parse_args( $atts, $bool_atts );
+
+		foreach( $bool_atts as $att => $value ){
+			$atts[$att] = ( strtolower( $atts[$att] ) == 'true' ? true : false );
+		}
+		
+		//Backwards compatability, key used to be true/false. Now can be bottom/top
+		if( isset( $atts['key'] ) ){
+			if( 'true' == strtolower( $atts['key'] ) ){
+				$atts['key'] = 'bottom';
+			}elseif( !in_array( strtolower( $atts['key'] ), array( 'bottom', 'top' ) ) ){
+				$atts['key'] = false;
+			}
+		}
+
+		if( isset($atts['venue']) && !isset( $atts['event_venue'] ) ){
+			$atts['event_venue'] = $atts['venue'];
+			unset( $atts['venue'] );
+		}
+		if( isset($atts['category']) && !isset( $atts['event_category'] ) ){
+			$atts['event_category'] = $atts['category'];
+			unset( $atts['category'] );
+		}
+		
+		$date_attributes = array( 
+			'timeformat', 'axisformat', 'titleformatday', 'titleformatweek', 'titleformatmonth',
+			'columnformatmonth', 'columnformatweek', 'columnformatday',
+		);
+		
+		foreach( $date_attributes as $attribute ){
+			if( isset( $atts[$attribute] ) ){
+				$atts[$attribute] = self::_cleanup_format( $atts[$attribute] );
+			}
+		}
+
+		$taxonomies = get_object_taxonomies( 'event' );
+		foreach( $taxonomies as $tax ){
+			//Shortcode attributes can't contain hyphens
+			$shortcode_attr = str_replace( '-', '_', $tax );
+			if( isset( $atts[$shortcode_attr] ) ){
+				$atts[$tax] = $atts[$shortcode_attr];
+				unset( $atts[$shortcode_attr] ); 
+			}
+		}
+		
+		if( isset( $atts['showdays'] ) ){
+			$atts['showdays'] = explode( ',', $atts['showdays'] );
+		}
+				
+		return eo_get_event_fullcalendar( $atts );
+	}
+	
+	/**
+	 * Prior to 3.0.0, formats could accept operators to deal with ranges.
+	 * Specifically {...} switches to formatting the 2nd date and ((...)) only displays 
+	 * the enclosed format if the current date is different from the alternate date in 
+	 * the same regards.E.g.  M j(( Y)){ '—'(( M)) j Y} produces the following dates: 
+	 * Dec 30 2013 — Jan 5 2014, Jan 6 — 12 2014
+	 * 
+	 * This was removed in 3.0.0, fullCalendar.js will now automatically split the date where
+	 * appropriate. This function removes {...} and all enclosed content and replaces ((...))
+	 * by the content contained within to help prevent an users upgrading from the old version.
+	 * 
+	 * @ignore
+	 */
+	static function _cleanup_format( $format ){
+		$format = preg_replace( '/({.*})/', '', $format );
+		$format = preg_replace_callback( '/\(\((.*)\)\)/', array( __CLASS__ ,'_replace_open_bracket' ), $format );			
+		return $format;
+	}
+	
+	static function _replace_open_bracket( $matches ){
+		return $matches[1];
+	}
+
+	static function handle_venuemap_shortcode($atts) {
+		global $post;
+
+		if( !empty( $atts['event_venue'] ) ){
+			$atts['venue'] = $atts['event_venue'];
+		}
+
+		//If venue is not set get from the venue being quiered or the post being viewed
+		if( empty($atts['venue']) ){
+			if( eo_is_venue() ){
+				$atts['venue'] = esc_attr( get_query_var( 'term' ) );
+			}else{
+				$atts['venue'] = eo_get_venue_slug( get_the_ID() );
+			}
+		}
+
+		$venue_slugs = explode( ',', $atts['venue'] );
+
+		$args = shortcode_atts( array(
+			'zoom' => 15, 'zoomcontrol' => 'true', 'minzoom' => 0, 'maxzoom' => null,
+			'scrollwheel' => 'true', 'rotatecontrol' => 'true', 'pancontrol' => 'true',
+			'overviewmapcontrol' => 'true', 'streetviewcontrol' => 'true',
+			'maptypecontrol' => 'true', 'draggable' => 'true', 'maptypeid' => 'ROADMAP',
+			'width' => '100%','height' => '200px','class' => '', 'tooltip' => 'false',
+			), $atts );
+
+		//Cast options as boolean:
+		$bool_options = array( 
+			'tooltip', 'scrollwheel', 'zoomcontrol', 'rotatecontrol', 'pancontrol',
+			'overviewmapcontrol', 'streetviewcontrol', 'draggable', 'maptypecontrol',
+		);
+		foreach( $bool_options as $option  ){
+			$args[$option] = ( $args[$option] == 'false' ? false : true );
+		}
+
+		return eo_get_venue_map( $venue_slugs, $args );
+	}
+
+
+
+	static function handle_eventlist_shortcode($atts=array(),$content=null) {
+		$taxs = array('category','tag','venue');
+		foreach ($taxs as $tax){
+			if(isset($atts['event_'.$tax])){
+				$atts['event-'.$tax]=	$atts['event_'.$tax];
+				unset($atts['event_'.$tax]);
+			}
+		}
+
+		if((isset($atts['venue']) &&$atts['venue']=='%this%') ||( isset($atts['event-venue']) && $atts['event-venue']=='%this%' )){
+			if( eo_get_venue_slug() ){
+				$atts['event-venue']=  eo_get_venue_slug();
+			}else{
+				unset($atts['venue']);
+				unset($atts['event-venue']);
+			}
+		}
+		
+		if( isset( $atts['users_events'] ) && strtolower( $atts['users_events'] ) == 'true' ){
+			$atts['bookee_id'] = get_current_user_id();
+		}
+
+		$args = array(
+			'class'=>'eo-events eo-events-shortcode',
+			'template'=>$content,
+			'no_events'=> isset( $atts['no_events'] ) ? $atts['no_events'] : '',
+			'type'=>'shortcode',
+		);
+		
+
+		return eventorganiser_list_events( $atts,$args, 0);
+	}
+
+
+	static function read_template($template){
+		$patterns = array(
+			'/%(event_title)%/',
+			'/%(start)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(end)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(end)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(end)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(end)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(schedule_start)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(schedule_last)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(schedule_end)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(event_range)({(?P<date>[^{}]*)})?({(?P<time>[^{}]*)})?%/',
+			'/%(event_venue)%/',
+			'/%(event_venue_url)%/',
+			'/%(event_cats)%/',
+			'/%(event_tags)%/',
+			'/%(event_venue_address)%/',
+			'/%(event_venue_postcode)%/',
+			'/%(event_venue_city)%/',
+			'/%(event_venue_country)%/',
+			'/%(event_venue_state)%/',
+			'/%(event_venue_city)%/',
+			'/%(event_organiser)%/',
+			'/%(event_thumbnail)(?:{([^{}]+)})?(?:{([^{}]+)})?%/',
+			'/%(event_url)%/',
+			'/%(event_custom_field){([^{}]+)}%/',
+			'/%(event_venue_map)({[^{}]+})?%/',
+			'/%(event_excerpt)(?:{(\d+)})?%/',
+			'/%(cat_color)%/',
+			'/%(event_title_attr)%/',
+			'/%(event_duration){([^{}]+)}%/',
+			'/%(event_content)%/',
+		);
+		$template = preg_replace_callback($patterns, array(__CLASS__,'parse_template'), $template);
+		return $template;
+	}
+	
+	static function parse_template($matches){
+		global $post;
+		$replacement='';
+
+		switch($matches[1]):
+			case 'event_title':
+				$replacement = get_the_title();
+				break;
+
+			case 'start':
+			case 'end':
+			case 'schedule_start':
+			case 'schedule_last':
+			case 'schedule_end':
+				$defaults = array(
+					'date' => get_option('date_format'),
+					'time' => get_option('time_format'),
+				);
+				$formats = array_merge( $defaults, $matches );
+				$format = eo_get_event_datetime_format( get_the_ID(), $formats['date'], $formats['time'] );
+
+				switch( $matches[1] ):
+					case 'start':
+						$replacement = eo_get_the_start( $format );
+					break;
+					case 'end':
+						$replacement = eo_get_the_end( $format );
+					break;
+					case 'schedule_start':
+						$replacement = eo_get_schedule_start( $format );
+					break;
+					case 'schedule_last':
+					case 'schedule_end':
+						$replacement = eo_get_schedule_end( $format );
+					break;
+				endswitch;
+				break;
+
+			case 'event_duration':
+				$start = eo_get_the_start( DATETIMEOBJ );
+				$end   = clone eo_get_the_end( DATETIMEOBJ );
+				if ( eo_is_all_day() ) {
+					$end->modify( '+1 minute' );
+				}
+				if ( function_exists( 'date_diff' ) ) {
+					$duration = date_diff( $start, $end );
+					$replacement = $duration->format( $matches[2] );
+				} else {
+					$replacement = eo_date_interval( $start,$end, $matches[2] );
+				}
+				break;
+
+			case 'event_range':
+				$defaults = array(
+					'date' => get_option('date_format'),
+					'time' => get_option('time_format'),
+				);
+				$formats = array_merge( $defaults, $matches );
+				$replacement = eo_format_event_occurrence( get_the_ID(), eo_get_the_occurrence_id(), $formats['date'], $formats['time'] );
+				break;
+
+				$start = eo_get_the_start( DATETIMEOBJ );
+				$end   = clone eo_get_the_end( DATETIMEOBJ );
+				if ( eo_is_all_day() ) {
+					$end->modify( '+1 minute' );
+				}
+				if ( function_exists( 'date_diff' ) ) {
+					$duration = date_diff( $start, $end );
+					$replacement = $duration->format( $matches[2] );
+				} else {
+					$replacement = eo_date_interval( $start,$end, $matches[2] );
+				}
+				break;
+
+			case 'event_organiser':
+				$event = get_post();
+				$event_organiser = get_user_by( 'id', (int) $event->post_author );
+				$replacement = $event_organiser->display_name;
+				break;
+			case 'event_tags':
+				$replacement = get_the_term_list( get_the_ID(), 'event-tag', '', ', ','');
+				break;
+
+			case 'event_cats':
+				$replacement = get_the_term_list( get_the_ID(), 'event-category', '', ', ','');
+				break;
+
+			case 'event_venue':
+				$replacement =eo_get_venue_name();
+				break;
+
+			case 'event_venue_map':
+				if(eo_get_venue()){
+					$class = (isset($matches[2]) ? self::eo_clean_input($matches[2]) : '');
+					$class = (!empty($class) ?  'class='.$class : '');
+					$replacement =  eo_get_venue_map( eo_get_venue(), compact('class') );
+				}
+				break;
+
+			case 'event_venue_url':
+				$venue_link =eo_get_venue_link();
+				$replacement = ( !is_wp_error($venue_link) ? $venue_link : '');
+				break;
+			case 'event_venue_address':
+				$address = eo_get_venue_address();
+				$replacement =$address['address'];
+				break;
+			case 'event_venue_postcode':
+				$address = eo_get_venue_address();
+				$replacement =$address['postcode'];
+				break;
+			case 'event_venue_city':
+				$address = eo_get_venue_address();
+				$replacement =$address['city'];
+				break;
+			case 'event_venue_country':
+				$address = eo_get_venue_address();
+				$replacement =$address['country'];
+				break;
+			case 'event_venue_state':
+                                $address = eo_get_venue_address();
+                                $replacement =$address['state'];
+                                break;
+			case 'event_venue_city':
+                                $address = eo_get_venue_address();
+                                $replacement =$address['city'];
+                                break;
+			case 'event_thumbnail':
+				$size = (isset($matches[2]) ? self::eo_clean_input($matches[2]) : '');
+				$size = (!empty($size) ?  $size : 'thumbnail');
+				$attr = (isset($matches[3]) ? self::eo_clean_input($matches[3]) : '');
+
+				//Decode HTML entities as shortcode encodes them
+				$attr = html_entity_decode($attr);
+				$replacement = get_the_post_thumbnail(get_the_ID(),$size, $attr);
+				break;
+			case 'event_url':
+				$replacement = eo_get_permalink();
+				break;
+			case 'event_custom_field':
+				$field = $matches[2];
+				$meta = get_post_meta(get_the_ID(), $field);
+				$replacement =  implode($meta);
+				break;
+			case 'event_excerpt':
+				$length = ( isset( $matches[2] ) ? intval( $matches[2] ) : 55 );
+				//Using get_the_excerpt adds a link....
+				if ( post_password_required( $post ) ) {
+					$output = __( 'There is no excerpt because this is a protected post.', 'eventorganiser' );
+				} else {
+					$output = $post->post_excerpt;
+				}
+				$replacement = eventorganiser_trim_excerpt( $output, $length );
+				break;
+			case 'event_content':
+				$replacement = get_the_content();
+				break;
+			case 'cat_color':
+				$replacement =  eo_get_event_color();
+				break;
+			case 'event_title_attr':
+				$replacement = get_the_title();
+				break;
+
+		endswitch;
+		return $replacement;
+	}
+
+	static function eo_clean_input($input){
+		$input = trim($input,"{}"); //remove { }
+		$input = str_replace(array("'",'"',"&#8221;","&#8216;", "&#8217;"),'',$input); //remove quotations
+		return $input;
+	}
+
+	static function print_script() {
+
+		if ( ! self::$add_script ) {
+			return;
+		}
+
+		$load_users = $load_venues = $load_categories = $load_tags = false;
+
+		if ( self::$calendars ) {
+			foreach( self::$calendars as $calendar ) {
+				if ( self::calendarHeadersContainCaseInsensitive( 'organiser', $calendar ) ) {
+					$load_users = true;
+				}
+				if ( self::calendarHeadersContainCaseInsensitive( 'venue', $calendar ) ) {
+					$load_venues = true;
+				}
+				if ( self::calendarHeadersContainCaseInsensitive( 'category', $calendar ) ) {
+					$load_categories = true;
+				}
+				if ( self::calendarHeadersContainCaseInsensitive( 'tag', $calendar ) ) {
+					$load_tags = true;
+				}
+			}
+		}
+
+		$fullcal = ( empty( self::$calendars ) ? array() : array(
+			'firstDay' => intval( get_option( 'start_of_week' ) ),
+		));
+
+		if ( $load_venues ) {
+			$fullcal['venues'] = get_terms( 'event-venue', array( 'hide_empty' => 0 ) );
+		}
+
+		if ( $load_categories ) {
+			$fullcal['categories'] = get_terms( 'event-category', array( 'hide_empty' => 0 ) );
+		}
+
+		if ( $load_tags ) {
+			$fullcal['tags'] = get_terms( 'event-tag', array( 'hide_empty' => 1 ) );
+		}
+
+		if ( $load_users ) {
+			$fullcal['users'] = wp_list_pluck( get_users(), 'display_name', 'ID' );
+		}
+
+		eo_localize_script( 'eo_front', array(
+			'ajaxurl'          => admin_url( 'admin-ajax.php' ),
+			'calendars'        => self::$calendars,
+			'widget_calendars' => self::$widget_calendars,
+			'fullcal'          => $fullcal,
+			'map'              => self::$map,
+		));
+
+		if ( ! empty( self::$calendars ) || ! empty( self::$map ) || ! empty( self::$widget_calendars ) ) {
+
+			wp_enqueue_script( 'eo_qtip2' );
+			wp_enqueue_script( 'eo_front' );
+
+			eo_enqueue_style( 'eo_front' );
+			eo_enqueue_style( 'eo_calendar-style' );
+
+		}
+
+		if ( ! empty( self::$map ) ) {
+			wp_enqueue_script( 'eo_GoogleMap' );
+		}
+	}
+
+	private static function calendarHeadersContainCaseInsensitive( $key, $calendar ) {
+		foreach( array( 'headerleft', 'headerright', 'headercenter' ) as $header ) {
+			$headers = array_map( 'strtolower',  preg_split( "/(,|\s)/", $calendar[$header] ) );
+			if ( in_array( strtolower( $key ), $headers ) ) {
+				return true;
+			}
+		}
+		return false;
+  }
+}
+
+EventOrganiser_Shortcodes::init();
+
+/**
+ * @ignore
+ */
+function eventorganiser_category_key($args=array(),$id=1){
+		$args['taxonomy'] ='event-category';
+
+		$html ='<div class="eo-fullcalendar-key" id="eo_fullcalendar_key'.$id.'">';
+		$terms = get_terms( 'event-category', $args );
+		$html.= "<ul class='eo_fullcalendar_key'>";
+		foreach ($terms as $term):
+			$slug = esc_attr($term->slug);
+			$color = esc_attr($term->color);
+			$class = "class='eo_fullcalendar_key_cat eo_fullcalendar_key_cat_{$slug}'";
+			$html.= "<li {$class}><span class='eo_fullcalendar_key_colour' style='background:{$color}'>&nbsp;</span>".esc_attr($term->name)."</li>";			
+		endforeach;
+		$html.='</ul></div>';
+
+		return $html;
+	}
+?>

+ 0 - 0
wp-content/plugins/event-organiser/css/eventorganiser-admin-style-rtl.css


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels