@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for the calendar page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.1
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_Avatar_Fallbacks extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Default avatar fallbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_fallbacks = array(
|
||||
'post_thumbnail',
|
||||
'content_img',
|
||||
'category_avatar',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get registered fallbacks.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_all() {
|
||||
return apply_filters( 'ai1ec_avatar_fallbacks', $this->_fallbacks );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new avatar fallbacks.
|
||||
*
|
||||
* @param array $fallbacks Fallbacks.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function set( array $fallbacks ) {
|
||||
$this->_fallbacks = $fallbacks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for the calendar page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_Page extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Memory_Utility Instance of memory to hold exact dates
|
||||
*/
|
||||
protected $_exact_dates = NULL;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param Ai1ec_Registry_Object $registry The registry object
|
||||
*/
|
||||
public function __construct( Ai1ec_Registry_Object $registry ) {
|
||||
parent::__construct( $registry );
|
||||
$this->_exact_dates = $registry->get( 'cache.memory' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content if the calendar page
|
||||
*
|
||||
* @param Ai1ec_Request_Parser $request Request object.
|
||||
* @param string $caller Method caller, expected one of
|
||||
* ['shortcode', 'render-command']
|
||||
* Defaults to 'render-command'.
|
||||
*
|
||||
* @return string Content.
|
||||
*/
|
||||
public function get_content(
|
||||
Ai1ec_Request_Parser $request,
|
||||
$caller = 'render-command'
|
||||
) {
|
||||
// Get args for the current view; required to generate HTML for views
|
||||
// dropdown list, categories, tags, subscribe buttons, and of course the
|
||||
// view itself.
|
||||
$view_args = $this->get_view_args_for_view( $request );
|
||||
|
||||
try {
|
||||
$action = $this->_registry->get( 'model.settings-view' )
|
||||
->get_configured( $view_args['action'] );
|
||||
} catch ( Ai1ec_Settings_Exception $exception ) {
|
||||
// short-circuit and return error message
|
||||
return '<div id="ai1ec-container"><div class="timely"><p>' .
|
||||
Ai1ec_I18n::__(
|
||||
'There was an error loading calendar. Please contact site administrator and inform him to configure calendar views.'
|
||||
) .
|
||||
'</p></div></div>';
|
||||
}
|
||||
$type = $request->get( 'request_type' );
|
||||
$is_json = $this->_registry->get( 'http.request' )->is_json_required(
|
||||
$view_args['request_format'], $action
|
||||
);
|
||||
|
||||
// Add view-specific args to the current view args.
|
||||
$exact_date = $this->get_exact_date( $request );
|
||||
try {
|
||||
$view_obj = $this->_registry->get(
|
||||
'view.calendar.view.' . $action,
|
||||
$request
|
||||
);
|
||||
} catch ( Ai1ec_Bootstrap_Exception $exc ) {
|
||||
$this->_registry->get( 'notification.admin' )->store(
|
||||
sprintf(
|
||||
Ai1ec_I18n::__( 'Calendar was unable to initialize %s view and has reverted to Agenda view. Please check if you have installed the latest versions of calendar add-ons.' ),
|
||||
ucfirst( $action )
|
||||
),
|
||||
'error',
|
||||
0,
|
||||
array( Ai1ec_Notification_Admin::RCPT_ADMIN ),
|
||||
true
|
||||
);
|
||||
// don't disable calendar - just switch to agenda which should
|
||||
// always exists
|
||||
$action = 'agenda';
|
||||
$view_obj = $this->_registry->get(
|
||||
'view.calendar.view.' . $action,
|
||||
$request
|
||||
);
|
||||
}
|
||||
$view_args = $view_obj->get_extra_arguments( $view_args, $exact_date );
|
||||
|
||||
// Get HTML for views dropdown list.
|
||||
$dropdown_args = $view_args;
|
||||
if (
|
||||
isset( $dropdown_args['time_limit'] ) &&
|
||||
false !== $exact_date
|
||||
) {
|
||||
$dropdown_args['exact_date'] = $exact_date;
|
||||
}
|
||||
$views_dropdown =
|
||||
$this->get_html_for_views_dropdown( $dropdown_args, $view_obj );
|
||||
// Add views dropdown markup to view args.
|
||||
$view_args['views_dropdown'] = $views_dropdown;
|
||||
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
if ( $settings->get( 'ai1ec_use_frontend_rendering' ) ) {
|
||||
$view_args['request_format'] = 'json';
|
||||
}
|
||||
|
||||
// Get HTML for subscribe buttons.
|
||||
$subscribe_buttons = $this->get_html_for_subscribe_buttons( $view_args );
|
||||
|
||||
// Get HTML for view itself.
|
||||
$view = $view_obj->get_content( $view_args );
|
||||
|
||||
$router = $this->_registry->get( 'routing.router' );
|
||||
$are_filters_set = $router->is_at_least_one_filter_set_in_request(
|
||||
$view_args
|
||||
);
|
||||
|
||||
if (
|
||||
$is_json &&
|
||||
( $view_args['no_navigation'] || $type !== 'html' )
|
||||
) {
|
||||
// send data both for json and jsonp as shortcodes are jsonp
|
||||
return array(
|
||||
'html' => $view,
|
||||
'views_dropdown' => $views_dropdown,
|
||||
'subscribe_buttons' => $subscribe_buttons,
|
||||
'are_filters_set' => $are_filters_set,
|
||||
'is_json' => $is_json,
|
||||
);
|
||||
|
||||
} else {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$empty = $loader->get_file( 'empty.twig', array(), false );
|
||||
// Get HTML for categories and for tags
|
||||
$taxonomy = $this->_registry->get( 'view.calendar.taxonomy' );
|
||||
$categories = $taxonomy->get_html_for_categories(
|
||||
$view_args
|
||||
);
|
||||
$tags = $taxonomy->get_html_for_tags(
|
||||
$view_args,
|
||||
true
|
||||
);
|
||||
|
||||
// option to show filters in the super widget
|
||||
// Define new arguments for overall calendar view
|
||||
$filter_args = array(
|
||||
'views_dropdown' => $views_dropdown,
|
||||
'categories' => $categories,
|
||||
'tags' => $tags,
|
||||
'contribution_buttons' => apply_filters(
|
||||
'ai1ec_contribution_buttons',
|
||||
'',
|
||||
$type,
|
||||
$caller
|
||||
),
|
||||
'additional_buttons' => apply_filters(
|
||||
'ai1ec_additional_buttons',
|
||||
'',
|
||||
$view_args
|
||||
),
|
||||
'show_dropdowns' => apply_filters(
|
||||
'ai1ec_show_dropdowns',
|
||||
true
|
||||
),
|
||||
'show_select2' => apply_filters(
|
||||
'ai1ec_show_select2',
|
||||
false
|
||||
),
|
||||
'span_for_select2' => apply_filters(
|
||||
'ai1ec_span_for_select2',
|
||||
''
|
||||
),
|
||||
'authors' => apply_filters(
|
||||
'ai1ec_authors',
|
||||
''
|
||||
),
|
||||
'save_view_btngroup' => apply_filters(
|
||||
'ai1ec_save_view_btngroup',
|
||||
$empty
|
||||
),
|
||||
'view_args' => $view_args,
|
||||
'request' => $request,
|
||||
);
|
||||
|
||||
$filter_menu = $loader->get_file(
|
||||
'filter-menu.twig',
|
||||
$filter_args,
|
||||
false
|
||||
)->get_content();
|
||||
// hide filters in the SW
|
||||
if ( 'true' !== $request->get( 'display_filters' ) && 'jsonp' === $type ) {
|
||||
$filter_menu = '';
|
||||
}
|
||||
|
||||
$calendar_args = array(
|
||||
'version' => AI1EC_VERSION,
|
||||
'filter_menu' => $filter_menu,
|
||||
'view' => $view,
|
||||
'subscribe_buttons' => $subscribe_buttons,
|
||||
'disable_standard_filter_menu' => apply_filters(
|
||||
'ai1ec_disable_standard_filter_menu',
|
||||
false
|
||||
),
|
||||
'inline_js_calendar' => apply_filters(
|
||||
'ai1ec_inline_js_calendar',
|
||||
''
|
||||
),
|
||||
'after_view' => apply_filters(
|
||||
'ai1ec_after_view',
|
||||
''
|
||||
),
|
||||
'ai1ec_above_calendar' => apply_filters(
|
||||
'ai1ec_above_calendar',
|
||||
''
|
||||
),
|
||||
);
|
||||
|
||||
if ( is_array( $calendar_args['view'] ) ) {
|
||||
$view_args['request_format'] = 'html';
|
||||
$calendar_args['view'] = $view_obj->get_content( $view_args );
|
||||
}
|
||||
$calendar = $loader->get_file( 'calendar.twig', $calendar_args, false );
|
||||
// if it's just html, only the calendar html must be returned.
|
||||
if ( 'html' === $type ) {
|
||||
return $calendar->get_content();
|
||||
}
|
||||
// send data both for json and jsonp as shortcodes are jsonp
|
||||
return array(
|
||||
'html' => $calendar->get_content(),
|
||||
'views_dropdown' => $views_dropdown,
|
||||
'subscribe_buttons' => $subscribe_buttons,
|
||||
'are_filters_set' => $are_filters_set,
|
||||
'is_json' => $is_json
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the HTML for the `subscribe' buttons.
|
||||
*
|
||||
* @param array $view_args Args to pass.
|
||||
*
|
||||
* @return string Rendered HTML to include in output.
|
||||
*/
|
||||
public function get_html_for_subscribe_buttons( array $view_args ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$turn_off_subscribe = $settings->get( 'turn_off_subscription_buttons' );
|
||||
if ( $turn_off_subscribe ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'url_args' => '',
|
||||
'is_filtered' => false,
|
||||
'export_url' => AI1EC_EXPORT_URL,
|
||||
'export_url_no_html' => AI1EC_EXPORT_URL . '&no_html=true',
|
||||
'text_filtered' => Ai1ec_I18n::__( 'Subscribe to filtered calendar' ),
|
||||
'text_subscribe' => Ai1ec_I18n::__( 'Subscribe' ),
|
||||
'text_get_calendar' => Ai1ec_I18n::__( 'Get a Timely Calendar' ),
|
||||
'show_get_calendar' => ! $settings->get( 'disable_get_calendar_button' ),
|
||||
'text' => $this->_registry
|
||||
->get( 'view.calendar.subscribe-button' )
|
||||
->get_labels(),
|
||||
'placement' => 'up',
|
||||
);
|
||||
if ( ! empty( $view_args['cat_ids'] ) ) {
|
||||
$args['url_args'] .= '&ai1ec_cat_ids=' .
|
||||
implode( ',', $view_args['cat_ids'] );
|
||||
$args['is_filtered'] = true;
|
||||
}
|
||||
if ( ! empty( $view_args['tag_ids'] ) ) {
|
||||
$args['url_args'] .= '&ai1ec_tag_ids=' .
|
||||
implode( ',', $view_args['tag_ids'] );
|
||||
$args['is_filtered'] = true;
|
||||
}
|
||||
if ( ! empty( $view_args['post_ids'] ) ) {
|
||||
$args['url_args'] .= '&ai1ec_post_ids=' .
|
||||
implode( ',', $view_args['post_ids'] );
|
||||
$args['is_filtered'] = true;
|
||||
}
|
||||
$args = apply_filters(
|
||||
'ai1ec_subscribe_buttons_arguments',
|
||||
$args,
|
||||
$view_args
|
||||
);
|
||||
$localization = $this->_registry->get( 'p28n.wpml' );
|
||||
if (
|
||||
NULL !== ( $use_lang = $localization->get_language() )
|
||||
) {
|
||||
$args['url_args'] .= '&lang=' . $use_lang;
|
||||
}
|
||||
$subscribe = $this->_registry->get( 'theme.loader' )
|
||||
->get_file( 'subscribe-buttons.twig', $args, false );
|
||||
return $subscribe->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function generates the html for the view dropdowns.
|
||||
*
|
||||
* @param array $view_args Args passed to view
|
||||
* @param Ai1ec_Calendar_View_Abstract $view View object
|
||||
*/
|
||||
protected function get_html_for_views_dropdown(
|
||||
array $view_args,
|
||||
Ai1ec_Calendar_View_Abstract $view
|
||||
) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$available_views = array();
|
||||
$enabled_views = (array)$settings->get( 'enabled_views', array() );
|
||||
$view_names = array();
|
||||
$mode = wp_is_mobile() ? '_mobile' : '';
|
||||
foreach ( $enabled_views as $key => $val ) {
|
||||
$view_names[$key] = translate_nooped_plural(
|
||||
$val['longname'],
|
||||
1
|
||||
);
|
||||
// Find out if view is enabled in requested mode (mobile or desktop). If
|
||||
// no mode-specific setting is available, fall back to desktop setting.
|
||||
$view_enabled = isset( $enabled_views[$key]['enabled' . $mode] ) ?
|
||||
$enabled_views[$key]['enabled' . $mode] :
|
||||
$enabled_views[$key]['enabled'];
|
||||
$values = array();
|
||||
$options = $view_args;
|
||||
if ( $view_enabled ) {
|
||||
if ( $view instanceof Ai1ec_Calendar_View_Agenda ) {
|
||||
if (
|
||||
isset( $options['exact_date'] ) &&
|
||||
! isset( $options['time_limit'] )
|
||||
) {
|
||||
$options['time_limit'] = $options['exact_date'];
|
||||
}
|
||||
unset( $options['exact_date'] );
|
||||
} else {
|
||||
unset( $options['time_limit'] );
|
||||
}
|
||||
unset( $options['month_offset'] );
|
||||
unset( $options['week_offset'] );
|
||||
unset( $options['oneday_offset'] );
|
||||
$options['action'] = $key;
|
||||
$values['desc'] = translate_nooped_plural(
|
||||
$val['longname'],
|
||||
1
|
||||
);
|
||||
if ( $settings->get( 'ai1ec_use_frontend_rendering' ) ) {
|
||||
$options['request_format'] = 'json';
|
||||
}
|
||||
$href = $this->_registry->get( 'html.element.href', $options );
|
||||
$values['href'] = $href->generate_href();
|
||||
$available_views[$key] = $values;
|
||||
}
|
||||
};
|
||||
$args = array(
|
||||
'view_names' => $view_names,
|
||||
'available_views' => $available_views,
|
||||
'current_view' => $view_args['action'],
|
||||
'data_type' => $view_args['data_type'],
|
||||
);
|
||||
|
||||
$views_dropdown = $this->_registry->get( 'theme.loader' )
|
||||
->get_file( 'views_dropdown.twig', $args, false );
|
||||
return $views_dropdown->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exact date from request if available, or else from settings.
|
||||
*
|
||||
* @param Ai1ec_Abstract_Query settings
|
||||
*
|
||||
* @return boolean|int
|
||||
*/
|
||||
private function get_exact_date( Ai1ec_Abstract_Query $request ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
|
||||
// Preprocess exact_date.
|
||||
// Check to see if a date has been specified.
|
||||
$exact_date = $request->get( 'exact_date' );
|
||||
$use_key = $exact_date;
|
||||
if ( null === ( $exact_date = $this->_exact_dates->get( $use_key ) ) ) {
|
||||
$exact_date = $use_key;
|
||||
// Let's check if we have a date
|
||||
if ( false !== $exact_date ) {
|
||||
// If it's not a timestamp
|
||||
if ( ! Ai1ec_Validation_Utility::is_valid_time_stamp( $exact_date ) ) {
|
||||
// Try to parse it
|
||||
$exact_date = $this->return_gmtime_from_exact_date( $exact_date );
|
||||
if ( false === $exact_date ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Last try, let's see if an exact date is set in settings.
|
||||
if ( false === $exact_date && $settings->get( 'exact_date' ) !== '' ) {
|
||||
$exact_date = $this->return_gmtime_from_exact_date(
|
||||
$settings->get( 'exact_date' )
|
||||
);
|
||||
}
|
||||
$this->_exact_dates->set( $use_key, $exact_date );
|
||||
}
|
||||
return $exact_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decomposes an 'exact_date' parameter into month, day, year components based
|
||||
* on date pattern defined in settings (assumed to be in local time zone),
|
||||
* then returns a timestamp in GMT.
|
||||
*
|
||||
* @param string $exact_date 'exact_date' parameter passed to a view
|
||||
* @return bool|int false if argument not provided or invalid,
|
||||
* else UNIX timestamp in GMT
|
||||
*/
|
||||
private function return_gmtime_from_exact_date( $exact_date ) {
|
||||
$input_format = $this->_registry->get( 'model.settings' )
|
||||
->get( 'input_date_format' );
|
||||
|
||||
$date = Ai1ec_Validation_Utility::format_as_iso(
|
||||
$exact_date,
|
||||
$input_format
|
||||
);
|
||||
if ( false === $date ) {
|
||||
$exact_date = false;
|
||||
} else {
|
||||
$exact_date = $this->_registry->get(
|
||||
'date.time',
|
||||
$date,
|
||||
'sys.default'
|
||||
)->format_to_gmt();
|
||||
if ( $exact_date < 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $exact_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct data attribute to use in views
|
||||
*
|
||||
* @param string $type
|
||||
*/
|
||||
private function return_data_type_for_request_type( $type ) {
|
||||
$data_type = 'data-type="json"';
|
||||
if ( $type === 'jsonp' ) {
|
||||
$data_type = 'data-type="jsonp"';
|
||||
}
|
||||
return $data_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parameters for the view from the request object
|
||||
*
|
||||
* @param Ai1ec_Abstract_Query $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_view_args_for_view( Ai1ec_Abstract_Query $request ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
// Define arguments for specific calendar sub-view (month, agenda, etc.)
|
||||
// Preprocess action.
|
||||
// Allow action w/ or w/o ai1ec_ prefix. Remove ai1ec_ if provided.
|
||||
$action = $request->get( 'action' );
|
||||
|
||||
if ( 0 === strncmp( $action, 'ai1ec_', 6 ) ) {
|
||||
$action = substr( $action, 6 );
|
||||
}
|
||||
$view_args = $request->get_dict(
|
||||
apply_filters(
|
||||
'ai1ec_view_args_for_view',
|
||||
array(
|
||||
'post_ids',
|
||||
'auth_ids',
|
||||
'cat_ids',
|
||||
'tag_ids',
|
||||
'events_limit',
|
||||
'instance_ids',
|
||||
)
|
||||
)
|
||||
);
|
||||
$type = $request->get( 'request_type' );
|
||||
if ( 'html' === $type ) {
|
||||
$add_defaults = array(
|
||||
'cat_ids' => 'categories',
|
||||
'tag_ids' => 'tags',
|
||||
);
|
||||
foreach ( $add_defaults as $query => $default ) {
|
||||
if ( empty( $view_args[$query] ) ) {
|
||||
$setting = $settings->get( 'default_tags_categories' );
|
||||
if ( isset( $setting[$default] ) ) {
|
||||
$view_args[$query] = $setting[$default];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$view_args['data_type'] = $this->return_data_type_for_request_type(
|
||||
$type
|
||||
);
|
||||
|
||||
$view_args['request_format'] = $request->get( 'request_format' );
|
||||
$exact_date = $this->get_exact_date( $request );
|
||||
|
||||
$view_args['no_navigation'] = $request->get( 'no_navigation' ) == true;
|
||||
|
||||
// Find out which view of the calendar page was requested, and render it
|
||||
// accordingly.
|
||||
$view_args['action'] = $action;
|
||||
|
||||
$view_args['request'] = $request;
|
||||
$view_args = apply_filters(
|
||||
'ai1ec_view_args_array',
|
||||
$view_args
|
||||
);
|
||||
if ( null === $exact_date ) {
|
||||
$href = $this->_registry->get( 'html.element.href', $view_args )
|
||||
->generate_href();
|
||||
return Ai1ec_Http_Response_Helper::redirect( $href, 307 );
|
||||
|
||||
}
|
||||
return $view_args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
/**
|
||||
* The class that handles rendering the shortcode.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Calendar_Shortcode extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Generate replacement content for [ai1ec] shortcode.
|
||||
*
|
||||
* @param array $atts Attributes provided on shortcode
|
||||
* @param string $content Tag internal content (shall be empty)
|
||||
* @param string $tag Used tag name (must be 'ai1ec' always)
|
||||
*
|
||||
* @staticvar $call_count Used to restrict to single calendar per page
|
||||
*
|
||||
* @return string Replacement for shortcode entry
|
||||
*/
|
||||
public function shortcode( $atts, $content = '', $tag = 'ai1ec' ) {
|
||||
$settings_view = $this->_registry->get( 'model.settings-view' );
|
||||
$view_names_list = array_keys( $settings_view->get_all() );
|
||||
$default_view = $settings_view->get_default();
|
||||
|
||||
$view_names = array();
|
||||
foreach ( $view_names_list as $view_name ) {
|
||||
$view_names[$view_name] = true;
|
||||
}
|
||||
|
||||
$view = $default_view;
|
||||
$_events_categories = $_events_tags = $post_ids = array();
|
||||
|
||||
if ( isset( $atts['view'] ) ) {
|
||||
if ( 'ly' === substr( $atts['view'], -2 ) ) {
|
||||
$atts['view'] = substr( $atts['view'], 0, -2 );
|
||||
}
|
||||
if ( ! isset( $view_names[$atts['view']] ) ) {
|
||||
return false;
|
||||
}
|
||||
$view = $atts['view'];
|
||||
}
|
||||
|
||||
$mappings = array(
|
||||
'cat_name' => 'events_categories',
|
||||
'cat_id' => 'events_categories',
|
||||
'tag_name' => 'events_tags',
|
||||
'tag_id' => 'events_tags',
|
||||
'post_id' => 'post_ids',
|
||||
'events_limit' => 'events_limit',
|
||||
);
|
||||
$matches = array();
|
||||
$custom_taxonomies = array();
|
||||
if ( ! empty( $atts ) ) {
|
||||
foreach ( $atts as $att => $value ) {
|
||||
if (
|
||||
! preg_match( '/([a-z0-9\_]+)_(id|name)/', $att, $matches ) ||
|
||||
isset( $mappings[$matches[1] . '_id'] )
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
${'_' . $matches[1] . '_ids'} = array();
|
||||
$custom_taxonomies[] = $matches[1];
|
||||
|
||||
if ( ! isset( $mappings[$matches[1] . '_id'] ) ) {
|
||||
$mappings[$matches[1] . '_id'] = $matches[1];
|
||||
}
|
||||
if ( ! isset( $mappings[$matches[1] . '_name'] ) ) {
|
||||
$mappings[$matches[1] . '_name'] = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $mappings as $att_name => $type ) {
|
||||
if ( ! isset( $atts[$att_name] ) ) {
|
||||
continue;
|
||||
}
|
||||
$raw_values = explode( ',', $atts[$att_name] );
|
||||
foreach ( $raw_values as $argument ) {
|
||||
if ( 'post_id' === $att_name ) {
|
||||
if ( ( $argument = (int)$argument ) > 0 ) {
|
||||
$post_ids[] = $argument;
|
||||
}
|
||||
} else {
|
||||
if ( ! is_numeric( $argument ) ) {
|
||||
$search_val = trim( $argument );
|
||||
$argument = false;
|
||||
foreach ( array( 'name', 'slug' ) as $field ) {
|
||||
$record = get_term_by(
|
||||
$field,
|
||||
$search_val,
|
||||
$type
|
||||
);
|
||||
if ( false !== $record ) {
|
||||
$argument = $record;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset( $search_val, $record, $field );
|
||||
if ( false === $argument ) {
|
||||
continue;
|
||||
}
|
||||
$argument = (int)$argument->term_id;
|
||||
} else {
|
||||
if ( ( $argument = (int)$argument ) <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
${'_' . $type}[] = $argument;
|
||||
}
|
||||
}
|
||||
}
|
||||
$query = array(
|
||||
'ai1ec_cat_ids' => implode( ',', $_events_categories ),
|
||||
'ai1ec_tag_ids' => implode( ',', $_events_tags ),
|
||||
'ai1ec_post_ids' => implode( ',', $post_ids ),
|
||||
'action' => $view,
|
||||
'request_type' => 'jsonp',
|
||||
'events_limit' => isset( $atts['events_limit'] )
|
||||
// definition above casts values as array, so we take first element,
|
||||
// as there won't be others
|
||||
? (int) $atts['events_limit']
|
||||
: null,
|
||||
);
|
||||
// this is the opposite of how the SuperWidget works.
|
||||
if ( ! isset( $atts['display_filters'] ) ) {
|
||||
$query['display_filters'] = 'true';
|
||||
} else {
|
||||
$query['display_filters'] = $atts['display_filters'];
|
||||
}
|
||||
|
||||
foreach ( $custom_taxonomies as $taxonomy ) {
|
||||
$query['ai1ec_' . $taxonomy . '_ids'] = implode( ',', ${'_' . $taxonomy} );
|
||||
}
|
||||
if ( isset( $atts['exact_date'] ) ) {
|
||||
$query['exact_date'] = $atts['exact_date'];
|
||||
}
|
||||
$request = $this->_registry->get(
|
||||
'http.request.parser',
|
||||
$query,
|
||||
$default_view
|
||||
);
|
||||
$request->parse();
|
||||
$page_content = $this->_registry->get( 'view.calendar.page' )
|
||||
->get_content( $request, 'shortcode' );
|
||||
$this->_registry->get( 'css.frontend' )
|
||||
->add_link_to_html_for_frontend();
|
||||
$this->_registry->get( 'controller.javascript' )
|
||||
->load_frontend_js( true );
|
||||
$page_content['html'] = preg_replace( '/\s+/', ' ', $page_content['html'] );
|
||||
return $page_content['html'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Generate translation entities for subscription buttons.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Calendar_SubscribeButton {
|
||||
|
||||
/**
|
||||
* Get a list of texts for subscribtion buttons.
|
||||
*
|
||||
* @return array Map of labels.
|
||||
*/
|
||||
public function get_labels() {
|
||||
return array(
|
||||
'label' => array(
|
||||
'timely' => Ai1ec_I18n::__( 'Add to Timely Calendar' ),
|
||||
'google' => Ai1ec_I18n::__( 'Add to Google' ),
|
||||
'outlook' => Ai1ec_I18n::__( 'Add to Outlook' ),
|
||||
'apple' => Ai1ec_I18n::__( 'Add to Apple Calendar' ),
|
||||
'plaintext' => Ai1ec_I18n::__( 'Add to other calendar' ),
|
||||
'xml' => Ai1ec_I18n::__( 'Export to XML' ),
|
||||
),
|
||||
'title' => array(
|
||||
'timely' => Ai1ec_I18n::__( 'Copy this URL for your own Timely calendar or click to add to your rich-text calendar' ),
|
||||
'google' => Ai1ec_I18n::__( 'Subscribe to this calendar in your Google Calendar' ),
|
||||
'outlook' => Ai1ec_I18n::__( 'Subscribe to this calendar in MS Outlook' ),
|
||||
'apple' => Ai1ec_I18n::__( 'Subscribe to this calendar in Apple Calendar/iCal' ),
|
||||
'plaintext' => Ai1ec_I18n::__( 'Subscribe to this calendar in another plain-text calendar' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The class that handles html generation for taxonomies.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Calendar_Taxonomy extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Returns a link to a calendar page without the given arguments; does not
|
||||
* otherwise disturb current page state.
|
||||
*
|
||||
* @param array $args Current arguments to the calendar
|
||||
* @param array $args_to_remove Names of arguments to remove from current args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_href_without_arguments(
|
||||
array $args,
|
||||
array $args_to_remove
|
||||
) {
|
||||
$args_to_remove = array_flip( $args_to_remove );
|
||||
$args = array_diff_key( $args, $args_to_remove );
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
return $href->generate_href();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the html for tags filter
|
||||
*
|
||||
* @param array $view_args
|
||||
* @return string
|
||||
*/
|
||||
public function get_html_for_tags( array $view_args ) {
|
||||
return $this->_get_html_for_taxonomy( $view_args, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the html for categories filter
|
||||
*
|
||||
* @param array $view_args
|
||||
* @return string
|
||||
*/
|
||||
public function get_html_for_categories( array $view_args ) {
|
||||
return $this->_get_html_for_taxonomy( $view_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the HTML for a taxonomy selector.
|
||||
*
|
||||
* @param array $view_args Arguments to the parent view
|
||||
* @param bool $tag whether it's tags or categories.
|
||||
*
|
||||
* @return string Markup for categories selector
|
||||
*/
|
||||
protected function _get_html_for_taxonomy( $view_args, $tag = false ) {
|
||||
$taxonomy_name = 'events_categories';
|
||||
$type = 'category';
|
||||
$type_for_filter = 'cat_ids';
|
||||
$type_for_view_args = 'categories';
|
||||
if ( true === $tag ) {
|
||||
$taxonomy_name = 'events_tags';
|
||||
$type = 'tag';
|
||||
$type_for_filter = 'tag_ids';
|
||||
$type_for_view_args = 'tags';
|
||||
}
|
||||
|
||||
|
||||
$terms = get_terms( $taxonomy_name, array( 'orderby' => 'name' ) );
|
||||
if( empty( $terms ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach( $terms as &$term ) {
|
||||
$href = $this->_registry->get( 'html.element.href', $view_args, $type );
|
||||
$href->set_term_id( $term->term_id );
|
||||
$term->href = $href->generate_href();
|
||||
if ( false === $tag ) {
|
||||
$taxonomy = $this->_registry->get( 'view.event.taxonomy' );
|
||||
$term->color = $taxonomy->get_category_color_square( $term->term_id );
|
||||
}
|
||||
}
|
||||
|
||||
$href_for_clearing_filter =
|
||||
$this->generate_href_without_arguments( $view_args, array( $type_for_filter ) );
|
||||
|
||||
$args = array(
|
||||
$type_for_view_args => $terms,
|
||||
'selected_' . $type_for_filter => $view_args[$type_for_filter],
|
||||
'data_type' => $view_args['data_type'],
|
||||
'clear_filter' => $href_for_clearing_filter,
|
||||
'text_clear_category_filter' => __( 'Clear category filter', AI1EC_PLUGIN_NAME ),
|
||||
'text_categories' => __( 'Categories', AI1EC_PLUGIN_NAME ),
|
||||
'text_clear_tag_filter' => __( 'Clear tag filter', AI1EC_PLUGIN_NAME ),
|
||||
'text_tags' => __( 'Tags', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
return $loader->get_file( $type_for_view_args . '.twig', $args, false )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The abstract class for a view.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
abstract class Ai1ec_Calendar_View_Abstract extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Request_Parser The request object
|
||||
*/
|
||||
protected $_request;
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Compatibility_Check Theme compatibility check object.
|
||||
*/
|
||||
protected $_compatibility;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param Ai1ec_Registry_Object $registry
|
||||
* @param Ai1ec_Request_Parser $request
|
||||
*/
|
||||
public function __construct( Ai1ec_Registry_Object $registry, Ai1ec_Request_Parser $request ) {
|
||||
parent::__construct( $registry );
|
||||
$this->_request = $request;
|
||||
$this->_compatibility = $registry->get( 'compatibility.check' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the machine name for the view
|
||||
*
|
||||
* @return string The machine name of the view.
|
||||
*/
|
||||
abstract public function get_name();
|
||||
|
||||
/**
|
||||
* Get extra arguments specific for the view
|
||||
*
|
||||
* @param array $view_args
|
||||
* @param int|bool $exact_date the exact date used to display the view.
|
||||
*
|
||||
* @return array The view arguments with the extra parameters added.
|
||||
*/
|
||||
public function get_extra_arguments( array $view_args, $exact_date ) {
|
||||
$offset = $this->get_name() . '_offset';
|
||||
$view_args[$offset] = $this->_request->get( $offset );
|
||||
if( false !== $exact_date ) {
|
||||
$view_args['exact_date'] = $exact_date;
|
||||
}
|
||||
return $view_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra arguments specific for the view's template
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return array The template arguments with the extra parameters added.
|
||||
*/
|
||||
public function get_extra_template_arguments( array $args ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$args['action_buttons'] = apply_filters(
|
||||
'ai1ec_add_action_buttons',
|
||||
$this->_action_buttons()
|
||||
);
|
||||
if (
|
||||
true === apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
) {
|
||||
$args['has_product_buy_button'] = true;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the view and return the content
|
||||
*
|
||||
* @param array $view_args
|
||||
*
|
||||
* @return string the html of the view
|
||||
*/
|
||||
abstract public function get_content( array $view_args );
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string HTML of action buttons
|
||||
*/
|
||||
protected function _action_buttons() {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$action_buttons = $loader->get_file(
|
||||
'buttons.twig',
|
||||
array(
|
||||
'action_buttons' => apply_filters(
|
||||
'ai1ec_action_buttons',
|
||||
''
|
||||
),
|
||||
'tickets_button' => true,
|
||||
'text_tickets' => __( 'Tickets', AI1EC_PLUGIN_NAME ),
|
||||
'has_buy_tickets_product' => apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
),
|
||||
false
|
||||
)->get_content();
|
||||
return $action_buttons;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $exact_date
|
||||
*/
|
||||
protected function _create_link_for_day_view( $exact_date ) {
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
array(
|
||||
'action' => 'oneday',
|
||||
'exact_date' => $exact_date,
|
||||
)
|
||||
);
|
||||
return $href->generate_href();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view html
|
||||
*
|
||||
* @param array $view_args
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function _get_view( array $view_args ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$view = $this->get_name();
|
||||
$file = $loader->get_file( $view . '.twig', $view_args, false );
|
||||
|
||||
return apply_filters(
|
||||
'ai1ec_get_' . $view . '_view',
|
||||
$file->get_content(),
|
||||
$view_args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies filters to view args for front end rendering
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
protected function _apply_filters_to_args( array $args ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$view = $this->get_name();
|
||||
return $loader->apply_filters_to_args( $args, $view . '.twig', false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare week specific event start/end timestamps.
|
||||
*
|
||||
* @param Ai1ec_Event $event Instance of event.
|
||||
*
|
||||
* @return array Start and end respectively in 0 and 1 positions.
|
||||
*/
|
||||
protected function _get_view_specific_timestamps( Ai1ec_Event $event ) {
|
||||
if ( $event->is_allday() ) {
|
||||
// reset to be day-contained with respect to current timezone
|
||||
$event_start = $this->_registry
|
||||
->get( 'date.time', $event->get( 'start' ), 'sys.default' )
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
$event_end = $this->_registry
|
||||
->get( 'date.time', $event->get( 'end' ), 'sys.default' )
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
} else {
|
||||
$event_start = $event->get( 'start' )->format();
|
||||
$event_end = $event->get( 'end' )->format();
|
||||
}
|
||||
return array( $event_start, $event_end );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update metadata for retrieved events.
|
||||
*
|
||||
* This speeds up further meta data requests.
|
||||
*
|
||||
* @param array $events List of events retrieved.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _update_meta( array $events ) {
|
||||
$post_ids = array();
|
||||
foreach ( $events as $event ) {
|
||||
$post_ids[] = (int)$event->get( 'post_id' );
|
||||
}
|
||||
update_meta_cache( 'post', $post_ids );
|
||||
$this->_registry->get( 'model.taxonomy' )
|
||||
->update_meta( $post_ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the navigation bar HTML.
|
||||
*
|
||||
* @param array $nav_args Args for the navigation bar template, including
|
||||
* 'no_navigation' which determines whether to show it
|
||||
* @return string
|
||||
*/
|
||||
protected function _get_navigation( array $nav_args ) {
|
||||
$navigation = '';
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$nav_args['contribution_buttons'] = apply_filters(
|
||||
'ai1ec_contribution_buttons',
|
||||
'',
|
||||
'html',
|
||||
'render-command'
|
||||
);
|
||||
if ( true !== $nav_args['no_navigation'] ) {
|
||||
$navigation = $loader->get_file(
|
||||
'navigation.twig',
|
||||
$nav_args,
|
||||
false
|
||||
)->get_content();
|
||||
}
|
||||
return $navigation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the get_*_pagination_links method for the current view type and
|
||||
* renders its result, returning the rendered pagination links.
|
||||
*
|
||||
* @param array $args Current request arguments
|
||||
* @param string $title Title to display in datepicker button
|
||||
* @return string
|
||||
*/
|
||||
protected function _get_pagination( array $args, $title ) {
|
||||
$method = 'get_' . $this->get_name() . '_pagination_links';
|
||||
$pagination_links = $this->$method( $args, $title );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$pagination_links = $loader->get_file(
|
||||
'pagination.twig',
|
||||
array(
|
||||
'links' => $pagination_links,
|
||||
'data_type' => $args['data_type'],
|
||||
),
|
||||
false
|
||||
)->get_content();
|
||||
return $pagination_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds runtime properties to the event.
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
*/
|
||||
protected function _add_runtime_properties( Ai1ec_Event $event ) {
|
||||
global $post;
|
||||
$original_post = $post;
|
||||
$post = $event->get( 'post' );
|
||||
$instance_permalink = get_permalink(
|
||||
$event->get( 'post_id' )
|
||||
);
|
||||
$instance_permalink = add_query_arg(
|
||||
'instance_id',
|
||||
$event->get( 'instance_id' ),
|
||||
$instance_permalink
|
||||
);
|
||||
$event->set_runtime( 'instance_permalink', $instance_permalink );
|
||||
|
||||
$event->set_runtime(
|
||||
'filtered_title',
|
||||
apply_filters(
|
||||
'the_title',
|
||||
$event->get( 'post' )->post_title,
|
||||
$event->get( 'post_id' ),
|
||||
true
|
||||
)
|
||||
);
|
||||
$calendar_state = $this->_registry->get( 'calendar.state' );
|
||||
$calendar_state->set_append_content( false );
|
||||
$event->set_runtime(
|
||||
'filtered_content',
|
||||
apply_filters(
|
||||
'ai1ec_the_content',
|
||||
apply_filters(
|
||||
'the_content',
|
||||
$event->get( 'post' )->post_content
|
||||
)
|
||||
)
|
||||
);
|
||||
$calendar_state->set_append_content( true );
|
||||
|
||||
$taxonomy = $this->_registry->get( 'view.event.taxonomy' );
|
||||
$ticket = $this->_registry->get( 'view.event.ticket' );
|
||||
$event->set_runtime(
|
||||
'color_style',
|
||||
$taxonomy->get_color_style( $event )
|
||||
);
|
||||
$event->set_runtime( 'category_colors', $taxonomy->get_category_colors( $event ) );
|
||||
$event->set_runtime( 'ticket_url_label', $ticket->get_tickets_url_label( $event, false ) );
|
||||
$event->set_runtime( 'edit_post_link', get_edit_post_link( $event->get( 'post_id' ) ) );
|
||||
$event_post = $this->_registry->get( 'view.event.post' );
|
||||
$event->set_runtime( 'post_excerpt', $event_post->trim_excerpt( $event ) );
|
||||
$color = $this->_registry->get( 'view.event.color' );
|
||||
$event->set_runtime( 'faded_color', $color->get_faded_color( $event ) );
|
||||
$event->set_runtime( 'rgba_color', $color->get_rgba_color( $event ) );
|
||||
$event->set_runtime(
|
||||
'short_start_time',
|
||||
$this->_registry->get( 'view.event.time' )
|
||||
->get_short_time( $event->get( 'start' ) )
|
||||
);
|
||||
$this->_add_view_specific_runtime_properties( $event );
|
||||
$post = $original_post;
|
||||
}
|
||||
|
||||
/**
|
||||
* If some views have specific runtime properties they must extend this method
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
*/
|
||||
protected function _add_view_specific_runtime_properties( Ai1ec_Event $event ) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,582 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for agenda view.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_View_Agenda extends Ai1ec_Calendar_View_Abstract {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_name()
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'agenda';
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_content()
|
||||
*/
|
||||
public function get_content( array $view_args ) {
|
||||
|
||||
$type = $this->get_name();
|
||||
$time = $this->_registry->get( 'date.system' );
|
||||
// Get localized time
|
||||
$timestamp = $time->current_time();
|
||||
|
||||
// Get events, then classify into date array
|
||||
$per_page_setting = $type . '_events_per_page';
|
||||
$search = $this->_registry->get( 'model.search' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$events_limit = is_numeric( $view_args['events_limit'] )
|
||||
? $view_args['events_limit']
|
||||
: $settings->get( $per_page_setting );
|
||||
$events_limit = apply_filters(
|
||||
'ai1ec_events_limit',
|
||||
$events_limit
|
||||
);
|
||||
$relative_to_reference = in_array( $this->get_name(), array( 'agenda', 'posterboard', 'stream' ) );
|
||||
if ( $relative_to_reference ) {
|
||||
$results = $search->get_events_relative_to_reference(
|
||||
$view_args['time_limit'],
|
||||
$events_limit,
|
||||
$view_args['page_offset'],
|
||||
apply_filters(
|
||||
'ai1ec_get_events_relative_to_filter',
|
||||
array(
|
||||
'post_ids' => $view_args['post_ids'],
|
||||
'auth_ids' => $view_args['auth_ids'],
|
||||
'cat_ids' => $view_args['cat_ids'],
|
||||
'tag_ids' => $view_args['tag_ids'],
|
||||
'instance_ids' => $view_args['instance_ids'],
|
||||
),
|
||||
$view_args
|
||||
),
|
||||
apply_filters(
|
||||
'ai1ec_show_unique_events',
|
||||
false
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$results = $search->get_events_relative_to(
|
||||
$timestamp,
|
||||
$events_limit,
|
||||
$view_args['page_offset'],
|
||||
apply_filters(
|
||||
'ai1ec_get_events_relative_to_filter',
|
||||
array(
|
||||
'post_ids' => $view_args['post_ids'],
|
||||
'auth_ids' => $view_args['auth_ids'],
|
||||
'cat_ids' => $view_args['cat_ids'],
|
||||
'tag_ids' => $view_args['tag_ids'],
|
||||
'instance_ids' => $view_args['instance_ids'],
|
||||
),
|
||||
$view_args
|
||||
),
|
||||
$view_args['time_limit'],
|
||||
apply_filters(
|
||||
'ai1ec_show_unique_events',
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
$this->_update_meta( $results['events'] );
|
||||
$dates = $this->get_agenda_like_date_array(
|
||||
$results['events'],
|
||||
$view_args['request']
|
||||
);
|
||||
|
||||
|
||||
// Generate title of view based on date range month & year.
|
||||
$range_start = $results['date_first'] &&
|
||||
false === $results['date_first']->is_empty() ?
|
||||
$results['date_first'] :
|
||||
$this->_registry->get( 'date.time', $timestamp );
|
||||
$range_end = $results['date_last'] &&
|
||||
false === $results['date_last']->is_empty() ?
|
||||
$results['date_last'] :
|
||||
$this->_registry->get( 'date.time', $timestamp );
|
||||
$range_start = $this->_registry->get( 'date.time', $range_start );
|
||||
$range_end = $this->_registry->get( 'date.time', $range_end );
|
||||
$start_year = $range_start->format_i18n( 'Y' );
|
||||
$end_year = $range_end->format_i18n( 'Y' );
|
||||
$start_month = $range_start->format_i18n( 'F' );
|
||||
$start_month_short = $range_start->format_i18n( 'M' );
|
||||
$end_month = $range_end->format_i18n( 'F' );
|
||||
$end_month_short = $range_end->format_i18n( 'M' );
|
||||
if ( $start_year === $end_year && $start_month === $end_month ) {
|
||||
$title = "$start_month $start_year";
|
||||
$title_short = "$start_month_short $start_year";
|
||||
} elseif ( $start_year === $end_year ) {
|
||||
$title = "$start_month – $end_month $end_year";
|
||||
$title_short = "$start_month_short – $end_month_short $end_year";
|
||||
} else {
|
||||
$title = "$start_month $start_year – $end_month $end_year";
|
||||
$title_short = "$start_month_short $start_year – $end_month_short $end_year";
|
||||
}
|
||||
|
||||
// Create navigation bar if requested.
|
||||
$navigation = '';
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$pagination_links = '';
|
||||
if ( ! $view_args['no_navigation'] ) {
|
||||
|
||||
if ( $relative_to_reference ) {
|
||||
$pagination_links = $this->_get_pagination_links(
|
||||
$view_args,
|
||||
$results['prev'],
|
||||
$results['next'],
|
||||
$results['date_first'],
|
||||
$results['date_last'],
|
||||
$title,
|
||||
$title_short,
|
||||
$view_args['page_offset'] + -1,
|
||||
$view_args['page_offset'] + 1
|
||||
);
|
||||
} else {
|
||||
$pagination_links = $this->_get_agenda_like_pagination_links(
|
||||
$view_args,
|
||||
$results['prev'],
|
||||
$results['next'],
|
||||
$results['date_first'],
|
||||
$results['date_last'],
|
||||
$title,
|
||||
$title_short,
|
||||
null === $view_args['time_limit'] ||
|
||||
0 === $view_args['time_limit'] ?
|
||||
$timestamp :
|
||||
$view_args['time_limit']
|
||||
);
|
||||
}
|
||||
|
||||
$pagination_links = $loader->get_file(
|
||||
'pagination.twig',
|
||||
array(
|
||||
'links' => $pagination_links,
|
||||
'data_type' => $view_args['data_type'],
|
||||
),
|
||||
false
|
||||
)->get_content();
|
||||
|
||||
// Get HTML for navigation bar.
|
||||
$nav_args = array(
|
||||
'no_navigation' => $view_args['no_navigation'],
|
||||
'pagination_links' => $pagination_links,
|
||||
'views_dropdown' => $view_args['views_dropdown'],
|
||||
'below_toolbar' => apply_filters(
|
||||
'ai1ec_below_toolbar',
|
||||
'',
|
||||
$type,
|
||||
$view_args
|
||||
),
|
||||
);
|
||||
// Add extra buttons to Agenda view's nav bar if events were returned.
|
||||
if ( $type === 'agenda' && $dates ) {
|
||||
$button_args = array(
|
||||
'text_collapse_all' => __( 'Collapse All', AI1EC_PLUGIN_NAME ),
|
||||
'text_expand_all' => __( 'Expand All', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
$nav_args['after_pagination'] = $loader
|
||||
->get_file( 'agenda-buttons.twig', $button_args, false )
|
||||
->get_content();
|
||||
}
|
||||
$navigation = $this->_get_navigation( $nav_args );
|
||||
}
|
||||
|
||||
$is_ticket_button_enabled = apply_filters( 'ai1ec_' . $type . '_ticket_button', false );
|
||||
$args = array(
|
||||
'title' => $title,
|
||||
'dates' => $dates,
|
||||
'type' => $type,
|
||||
'show_year_in_agenda_dates' => $settings->get( 'show_year_in_agenda_dates' ),
|
||||
'expanded' => $settings->get( 'agenda_events_expanded' ),
|
||||
'show_location_in_title' => $settings->get( 'show_location_in_title' ),
|
||||
'page_offset' => $view_args['page_offset'],
|
||||
'navigation' => $navigation,
|
||||
'pagination_links' => $pagination_links,
|
||||
'post_ids' => join( ',', $view_args['post_ids'] ),
|
||||
'data_type' => $view_args['data_type'],
|
||||
'is_ticket_button_enabled' => $is_ticket_button_enabled,
|
||||
'text_upcoming_events' => __( 'There are no upcoming events to display at this time.', AI1EC_PLUGIN_NAME ),
|
||||
'text_edit' => __( 'Edit', AI1EC_PLUGIN_NAME ),
|
||||
'text_read_more' => __( 'Read more', AI1EC_PLUGIN_NAME ),
|
||||
'text_categories' => __( 'Categories:', AI1EC_PLUGIN_NAME ),
|
||||
'text_tags' => __( 'Tags:', AI1EC_PLUGIN_NAME ),
|
||||
'text_venue_separator' => __( '@ %s', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
|
||||
// Allow child views to modify arguments passed to template.
|
||||
$args = $this->get_extra_template_arguments( $args );
|
||||
|
||||
return
|
||||
$this->_registry->get( 'http.request' )->is_json_required(
|
||||
$view_args['request_format'], $type
|
||||
)
|
||||
? $loader->apply_filters_to_args( $args, $type . '.twig', false )
|
||||
: $this->_get_view( $args );
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_extra_arguments()
|
||||
*/
|
||||
public function get_extra_arguments( array $view_args, $exact_date ) {
|
||||
$view_args += $this->_request->get_dict( array(
|
||||
'page_offset',
|
||||
'time_limit',
|
||||
) );
|
||||
if( false !== $exact_date ) {
|
||||
$view_args['time_limit'] = $exact_date;
|
||||
}
|
||||
return $view_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Breaks down the given ordered array of event objects into dates, and
|
||||
* outputs an ordered array of two-element associative arrays in the
|
||||
* following format:
|
||||
* key: localized UNIX timestamp of date
|
||||
* value:
|
||||
* ['events'] => two-element associatative array broken down thus:
|
||||
* ['allday'] => all-day events occurring on this day
|
||||
* ['notallday'] => all other events occurring on this day
|
||||
* ['today'] => whether or not this date is today
|
||||
*
|
||||
* @param array $events Event results
|
||||
* @param Ai1ec_Abstract_Query|null $query Current calendar page request, if
|
||||
* any (null for widget)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_agenda_like_date_array(
|
||||
$events,
|
||||
Ai1ec_Abstract_Query $query = null
|
||||
) {
|
||||
$dates = array();
|
||||
$time = $this->_registry->get( 'date.system' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->clear_the_content_filters();
|
||||
// Classify each event into a date/allday category
|
||||
foreach ( $events as $event ) {
|
||||
$start_time = $this->_registry
|
||||
->get(
|
||||
'date.time',
|
||||
$event->get( 'start' )->format( 'Y-m-d\T00:00:00' ),
|
||||
'sys.default'
|
||||
);
|
||||
$exact_date = $time->format_datetime_for_url(
|
||||
$start_time,
|
||||
$settings->get( 'input_date_format' )
|
||||
);
|
||||
$href_for_date = $this->_create_link_for_day_view( $exact_date );
|
||||
// timestamp is used to have correctly sorted array as UNIX
|
||||
// timestamp never goes in decreasing order for increasing dates.
|
||||
$timestamp = $start_time->format();
|
||||
// Ensure all-day & non all-day categories are created in correct
|
||||
// order: "allday" preceding "notallday".
|
||||
if ( ! isset( $dates[$timestamp]['events'] ) ) {
|
||||
$dates[$timestamp]['events'] = array(
|
||||
'allday' => array(),
|
||||
'notallday' => array(),
|
||||
);
|
||||
}
|
||||
$this->_add_runtime_properties( $event );
|
||||
// Add the event.
|
||||
$category = $event->is_allday()
|
||||
? 'allday'
|
||||
: 'notallday';
|
||||
$event_props = array();
|
||||
$event_props['post_id'] = $event->get( 'post_id' );
|
||||
$event_props['instance_id'] = $event->get( 'instance_id' );
|
||||
$event_props['venue'] = $event->get( 'venue' );
|
||||
$event_props['ticket_url'] = $event->get( 'ticket_url' );
|
||||
$event_props['filtered_title'] = $event->get_runtime( 'filtered_title' );
|
||||
$event_props['edit_post_link'] = $event->get_runtime( 'edit_post_link' );
|
||||
$event_props['content_img_url'] = $event->get_runtime( 'content_img_url' );
|
||||
$event_props['filtered_content'] = $event->get_runtime( 'filtered_content' );
|
||||
$event_props['ticket_url_label'] = $event->get_runtime( 'ticket_url_label' );
|
||||
$event_props['permalink'] = $event->get_runtime( 'instance_permalink' );
|
||||
$event_props['categories_html'] = $event->get_runtime( 'categories_html' );
|
||||
$event_props['category_bg_color'] = $event->get_runtime( 'category_bg_color' );
|
||||
$event_props['category_text_color'] = $event->get_runtime( 'category_text_color' );
|
||||
$event_props['tags_html'] = $event->get_runtime( 'tags_html' );
|
||||
$event_props['post_excerpt'] = $event->get_runtime( 'post_excerpt' );
|
||||
$event_props['short_start_time'] = $event->get_runtime( 'short_start_time' );
|
||||
$event_props['is_allday'] = $event->is_allday();
|
||||
$event_props['is_multiday'] = $event->is_multiday();
|
||||
$event_props['enddate_info'] = $event->getenddate_info();
|
||||
$event_props['timespan_short'] = $event->_registry->
|
||||
get( 'view.event.time' )->get_timespan_html( $event, 'short' );
|
||||
$event_props['avatar'] = $event->getavatar();
|
||||
$event_props['avatar_not_wrapped'] = $event->getavatar( false );
|
||||
$event_props['avatar_url'] = $this->_registry
|
||||
->get( 'view.event.avatar' )->get_event_avatar_url( $event );
|
||||
$event_props['category_divider_color'] = $event->get_runtime(
|
||||
'category_divider_color'
|
||||
);
|
||||
|
||||
$meta = $this->_registry->get( 'model.meta-post' );
|
||||
if ( ! $event_props['ticket_url'] ) {
|
||||
$timely_tickets = $meta->get(
|
||||
$event->get( 'post_id' ),
|
||||
'_ai1ec_timely_tickets_url',
|
||||
null
|
||||
);
|
||||
if ( $timely_tickets ) {
|
||||
$event_props['ticket_url'] = $timely_tickets;
|
||||
$event->set( 'ticket_url', $event_props['ticket_url'] );
|
||||
}
|
||||
}
|
||||
if (
|
||||
true === apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
) {
|
||||
$full_details = $meta->get(
|
||||
$event->get( 'post_id' ),
|
||||
'_ai1ec_ep_product_details',
|
||||
null
|
||||
);
|
||||
if (
|
||||
is_array( $full_details ) &&
|
||||
isset( $full_details['show_buy_button'] ) &&
|
||||
true === $full_details['show_buy_button']
|
||||
&& $event_props['ticket_url']
|
||||
) {
|
||||
// Tickets button is shown by default in this case.
|
||||
} else {
|
||||
// Otherwise not.
|
||||
$event_props['ticket_url'] = false;
|
||||
}
|
||||
$event->set( 'ticket_url', $event_props['ticket_url'] );
|
||||
}
|
||||
|
||||
$event_object = $event_props;
|
||||
if (
|
||||
$this->_compatibility->use_backward_compatibility()
|
||||
) {
|
||||
$event_object = $event;
|
||||
}
|
||||
|
||||
$months = apply_filters( 'ai1ec_i18n_months', array() );
|
||||
$weekdays = apply_filters( 'ai1ec_i18n_weekdays', array() );
|
||||
|
||||
$dates[$timestamp]['events'][$category][] = $event_object;
|
||||
$dates[$timestamp]['href'] = $href_for_date;
|
||||
$dates[$timestamp]['day'] = $this->_registry->
|
||||
get( 'date.time', $timestamp )->format_i18n( 'j' );
|
||||
|
||||
$w = $this->
|
||||
_registry->get( 'date.time', $timestamp )->format_i18n( 'D' );
|
||||
$dates[$timestamp]['weekday'] = array_key_exists( $w, $weekdays ) ? $weekdays[$w] : $w;
|
||||
|
||||
$m = $this->
|
||||
_registry->get( 'date.time', $timestamp )->format_i18n( 'M' );
|
||||
$dates[$timestamp]['month'] = array_key_exists( $m, $months ) ? $months[$m] : $m;
|
||||
|
||||
$this->_registry->
|
||||
get( 'date.time', $timestamp )->format_i18n( 'M' );
|
||||
|
||||
$dates[$timestamp]['full_month'] = $this->_registry->
|
||||
get( 'date.time', $timestamp )->format_i18n( 'F' );
|
||||
$dates[$timestamp]['full_weekday'] = $this->_registry->
|
||||
get( 'date.time', $timestamp )->format_i18n( 'l' );
|
||||
$dates[$timestamp]['year'] = $this->_registry->
|
||||
get( 'date.time', $timestamp )->format_i18n( 'Y' );
|
||||
}
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->restore_the_content_filters();
|
||||
// Flag today
|
||||
$today = $this->_registry->get( 'date.time', 'now', 'sys.default' )
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
if ( isset( $dates[$today] ) ) {
|
||||
$dates[$today]['today'] = true;
|
||||
}
|
||||
return $dates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associative array of two links for any agenda-like view of the
|
||||
* calendar:
|
||||
* previous page (if previous events exist),
|
||||
* next page (if next events exist).
|
||||
* Each element is an associative array containing the link's enabled status
|
||||
* ['enabled'], CSS class ['class'], text ['text'] and value to assign to
|
||||
* link's href ['href'].
|
||||
*
|
||||
* @param array $args Current request arguments
|
||||
*
|
||||
* @param bool $prev Whether there are more events before
|
||||
* the current page
|
||||
* @param bool $next Whether there are more events after
|
||||
* the current page
|
||||
* @param Ai1ec_Date_Time|null $date_first
|
||||
* @param Ai1ec_Date_Time|null $date_last
|
||||
* @param string $title Title to display in datepicker button
|
||||
* @param string $title_short Short month names.
|
||||
* @param int|null $default_time_limit The default time limit in the case of pagination ends.
|
||||
* @return array Array of links
|
||||
*/
|
||||
protected function _get_agenda_like_pagination_links(
|
||||
$args,
|
||||
$prev = false,
|
||||
$next = false,
|
||||
$date_first = null,
|
||||
$date_last = null,
|
||||
$title = '',
|
||||
$title_short = '',
|
||||
$default_time_limit = 0
|
||||
) {
|
||||
$links = array();
|
||||
|
||||
if (
|
||||
$this->_registry->get(
|
||||
'model.settings'
|
||||
)->get( 'ai1ec_use_frontend_rendering' )
|
||||
) {
|
||||
$args['request_format'] = 'json';
|
||||
}
|
||||
$args['page_offset'] = -1;
|
||||
if ( null === $date_first || $date_first->is_empty() ) {
|
||||
$args['time_limit'] = $default_time_limit;
|
||||
} else {
|
||||
$args['time_limit'] = $this->_registry
|
||||
->get( 'date.time', $date_first )->set_time(
|
||||
$date_first->format( 'H' ),
|
||||
$date_first->format( 'i' ),
|
||||
$date_first->format( 's' ) - 1
|
||||
)->format_to_gmt();
|
||||
}
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
$args
|
||||
);
|
||||
$links[] = array(
|
||||
'class' => 'ai1ec-prev-page',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-left"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
'enabled' => $prev,
|
||||
);
|
||||
|
||||
// Minical datepicker.
|
||||
$factory = $this->_registry->get( 'factory.html' );
|
||||
$links[] = $factory->create_datepicker_link(
|
||||
$args,
|
||||
$date_first->format_to_gmt(),
|
||||
$title,
|
||||
$title_short
|
||||
);
|
||||
|
||||
$args['page_offset'] = 1;
|
||||
if ( null === $date_last || $date_last->is_empty() ) {
|
||||
$args['time_limit'] = $default_time_limit;
|
||||
} else {
|
||||
$args['time_limit'] = $this->_registry
|
||||
->get( 'date.time', $date_last )->set_time(
|
||||
$date_last->format( 'H' ),
|
||||
$date_last->format( 'i' ),
|
||||
$date_last->format( 's' ) + 1
|
||||
)->format_to_gmt();
|
||||
}
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
$args
|
||||
);
|
||||
$links[] = array(
|
||||
'class' => 'ai1ec-next-page',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
'enabled' => $next,
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associative array of two links for any agenda-like view of the
|
||||
* calendar:
|
||||
* previous page (if previous events exist),
|
||||
* next page (if next events exist).
|
||||
* Each element is an associative array containing the link's enabled status
|
||||
* ['enabled'], CSS class ['class'], text ['text'] and value to assign to
|
||||
* link's href ['href'].
|
||||
*
|
||||
* @param array $args Current request arguments
|
||||
*
|
||||
* @param bool $prev Whether there are more events before
|
||||
* the current page
|
||||
* @param bool $next Whether there are more events after
|
||||
* the current page
|
||||
* @param Ai1ec_Date_Time|null $date_first
|
||||
* @param Ai1ec_Date_Time|null $date_last
|
||||
* @param string $title Title to display in datepicker button
|
||||
* @param string $title_short Short month names.
|
||||
* @param int|null $default_time_limit The default time limit in the case of pagination ends.
|
||||
* @return array Array of links
|
||||
*/
|
||||
protected function _get_pagination_links(
|
||||
$args,
|
||||
$prev = false,
|
||||
$next = false,
|
||||
$date_first = null,
|
||||
$date_last = null,
|
||||
$title = '',
|
||||
$title_short = '',
|
||||
$prev_offset = -1,
|
||||
$next_offset = 1) {
|
||||
|
||||
$links = array();
|
||||
|
||||
if ( $this->_registry->get( 'model.settings' )->get( 'ai1ec_use_frontend_rendering' ) ) {
|
||||
$args['request_format'] = 'json';
|
||||
}
|
||||
$args['page_offset'] = $prev_offset;
|
||||
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'class' => 'ai1ec-prev-page',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-left"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
'enabled' => $prev );
|
||||
|
||||
// Minical datepicker.
|
||||
$factory = $this->_registry->get( 'factory.html' );
|
||||
$links[] = $factory->create_datepicker_link( $args, $date_first->format_to_gmt(), $title, $title_short );
|
||||
|
||||
$args['page_offset'] = $next_offset;
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'class' => 'ai1ec-next-page',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
'enabled' => $next );
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::_add_view_specific_runtime_properties()
|
||||
*/
|
||||
protected function _add_view_specific_runtime_properties( Ai1ec_Event $event ) {
|
||||
$taxonomy = $this->_registry->get( 'view.event.taxonomy' );
|
||||
$avatar = $this->_registry->get( 'view.event.avatar' );
|
||||
$event->set_runtime(
|
||||
'categories_html',
|
||||
$taxonomy->get_categories_html( $event )
|
||||
);
|
||||
$event->set_runtime(
|
||||
'tags_html',
|
||||
$taxonomy->get_tags_html( $event )
|
||||
);
|
||||
$event->set_runtime(
|
||||
'content_img_url',
|
||||
$avatar->get_content_img_url( $event )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,573 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for month view.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_View_Month extends Ai1ec_Calendar_View_Abstract {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_name()
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'month';
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_content()
|
||||
*/
|
||||
public function get_content( array $view_args ) {
|
||||
$date_system = $this->_registry->get( 'date.system' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$defaults = array(
|
||||
'month_offset' => 0,
|
||||
'cat_ids' => array(),
|
||||
'auth_ids' => array(),
|
||||
'tag_ids' => array(),
|
||||
'post_ids' => array(),
|
||||
'instance_ids' => array(),
|
||||
'exact_date' => $date_system->current_time(),
|
||||
);
|
||||
$args = wp_parse_args( $view_args, $defaults );
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' );
|
||||
$local_date->set_date(
|
||||
$local_date->format( 'Y' ),
|
||||
$local_date->format( 'm' ) + $args['month_offset'],
|
||||
1
|
||||
)
|
||||
->set_time( 0, 0, 0 );
|
||||
|
||||
$days_events = $this->get_events_for_month(
|
||||
$local_date,
|
||||
apply_filters(
|
||||
'ai1ec_get_events_relative_to_filter',
|
||||
array(
|
||||
'cat_ids' => $args['cat_ids'],
|
||||
'tag_ids' => $args['tag_ids'],
|
||||
'post_ids' => $args['post_ids'],
|
||||
'auth_ids' => $args['auth_ids'],
|
||||
'instance_ids' => $args['instance_ids'],
|
||||
),
|
||||
$view_args,
|
||||
apply_filters(
|
||||
'ai1ec_show_unique_events',
|
||||
false
|
||||
)
|
||||
)
|
||||
);
|
||||
$cell_array = $this->get_month_cell_array(
|
||||
$local_date,
|
||||
$days_events
|
||||
);
|
||||
// Create pagination links.
|
||||
$title = $local_date->format_i18n( 'F Y' );
|
||||
$pagination_links = $this->_get_pagination( $args, $title );
|
||||
|
||||
$is_ticket_button_enabled = apply_filters(
|
||||
'ai1ec_month_ticket_button',
|
||||
false
|
||||
);
|
||||
|
||||
$view_args = array(
|
||||
'title' => $title,
|
||||
'type' => 'month',
|
||||
'weekdays' => $this->get_weekdays(),
|
||||
'cell_array' => $cell_array,
|
||||
'show_location_in_title' => $settings->get( 'show_location_in_title' ),
|
||||
'month_word_wrap' => $settings->get( 'month_word_wrap' ),
|
||||
'post_ids' => join( ',', $args['post_ids'] ),
|
||||
'data_type' => $args['data_type'],
|
||||
'is_ticket_button_enabled' => $is_ticket_button_enabled,
|
||||
'text_venue_separator' => __( '@ %s', AI1EC_PLUGIN_NAME ),
|
||||
'pagination_links' => $pagination_links,
|
||||
);
|
||||
|
||||
// Add navigation if requested.
|
||||
$view_args['navigation'] = $this->_get_navigation(
|
||||
array(
|
||||
'no_navigation' => $args['no_navigation'],
|
||||
'pagination_links' => $pagination_links,
|
||||
'views_dropdown' => $args['views_dropdown'],
|
||||
'below_toolbar' => apply_filters(
|
||||
'ai1ec_below_toolbar',
|
||||
'',
|
||||
$this->get_name(),
|
||||
$args
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$view_args = $this->get_extra_template_arguments( $view_args );
|
||||
|
||||
return
|
||||
$this->_registry->get( 'http.request' )->is_json_required(
|
||||
$args['request_format'], 'month'
|
||||
)
|
||||
? $this->_apply_filters_to_args( $view_args )
|
||||
: $this->_get_view( $view_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-associative array of four links for the month view of the
|
||||
* calendar:
|
||||
* previous year, previous month, next month, and next year.
|
||||
* Each element is an associative array containing the link's enabled status
|
||||
* ['enabled'], CSS class ['class'], text ['text'] and value to assign to
|
||||
* link's href ['href'].
|
||||
*
|
||||
* @param array $args Current request arguments
|
||||
* @param string $title Title to display in datepicker button
|
||||
*
|
||||
* @return array Array of links
|
||||
*/
|
||||
function get_month_pagination_links( $args, $title ) {
|
||||
$links = array();
|
||||
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' );
|
||||
$orig_date = $this->_registry->get( 'date.time', $local_date );
|
||||
$default_tz = $this->_registry->get( 'date.timezone' )->get_default_timezone();
|
||||
// =================
|
||||
// = Previous year =
|
||||
// =================
|
||||
// Align date to first of month, month offset applied, 1 year behind.
|
||||
$local_date
|
||||
->set_timezone( $default_tz )
|
||||
->set_date(
|
||||
$local_date->format( 'Y' ) -1,
|
||||
$local_date->format( 'm' ) + $args['month_offset'],
|
||||
1
|
||||
)
|
||||
->set_time( 0, 0, 0 );
|
||||
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-prev-year',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-angle-double-left"></i> ' .
|
||||
$local_date->format_i18n( 'Y' ),
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
// ==================
|
||||
// = Previous month =
|
||||
// ==================
|
||||
// Align date to first of month, month offset applied, 1 month behind.
|
||||
$local_date
|
||||
->set_date(
|
||||
$local_date->format( 'Y' ) + 1,
|
||||
$local_date->format( 'm' ) - 1,
|
||||
1
|
||||
);
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$months = apply_filters( 'ai1ec_i18n_months', array() );
|
||||
$m = $local_date->format_i18n( 'M' );
|
||||
$month_text = array_key_exists( $m, $months ) ? $months[$m] : $m;
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-prev-month',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-angle-left"></i> ' . $month_text,
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
// ======================
|
||||
// = Minical datepicker =
|
||||
// ======================
|
||||
// Align date to first of month, month offset applied.
|
||||
|
||||
$orig_date
|
||||
->set_timezone('UTC')
|
||||
->set_date(
|
||||
$orig_date->format( 'Y' ),
|
||||
$orig_date->format( 'm' ) + $args['month_offset'],
|
||||
1
|
||||
);
|
||||
$args['exact_date'] = $orig_date->format();
|
||||
$factory = $this->_registry->get( 'factory.html' );
|
||||
$links[] = $factory->create_datepicker_link(
|
||||
$args,
|
||||
$args['exact_date'],
|
||||
$title
|
||||
);
|
||||
|
||||
// ==============
|
||||
// = Next month =
|
||||
// ==============
|
||||
// Align date to first of month, month offset applied, 1 month ahead.
|
||||
$orig_date
|
||||
->set_timezone( $default_tz )
|
||||
->set_date(
|
||||
$orig_date->format( 'Y' ),
|
||||
$orig_date->format( 'm' ) + 1,
|
||||
1
|
||||
)
|
||||
->set_time( 0, 0, 0 );
|
||||
$args['exact_date'] = $orig_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$m = $orig_date->format_i18n( 'M' );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-next-month',
|
||||
'text' => ( array_key_exists( $m, $months ) ? $months[$m] : $m ) .
|
||||
' <i class="ai1ec-fa ai1ec-fa-angle-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
// =============
|
||||
// = Next year =
|
||||
// =============
|
||||
// Align date to first of month, month offset applied, 1 year ahead.
|
||||
$orig_date
|
||||
->set_date(
|
||||
$orig_date->format( 'Y' ) + 1,
|
||||
$orig_date->format( 'm' ) - 1,
|
||||
1
|
||||
);
|
||||
$args['exact_date'] = $orig_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-next-year',
|
||||
'text' => $orig_date->format_i18n( 'Y' ) .
|
||||
' <i class="ai1ec-fa ai1ec-fa-angle-double-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_weekdays function
|
||||
*
|
||||
* Returns a list of abbreviated weekday names starting on the configured
|
||||
* week start day setting.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_weekdays() {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
static $weekdays;
|
||||
|
||||
if ( ! isset( $weekdays ) ) {
|
||||
$time = $this->_registry->get(
|
||||
'date.time',
|
||||
'next Sunday',
|
||||
'sys.default'
|
||||
);
|
||||
$time->adjust_day( $settings->get( 'week_start_day' ) );
|
||||
|
||||
$weekdays = array();
|
||||
for( $i = 0; $i < 7; $i++ ) {
|
||||
$weekdays[] = $time->format_i18n( 'D' );
|
||||
$time->adjust_day( 1 );// Add a day
|
||||
}
|
||||
}
|
||||
return $weekdays;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::_add_view_specific_runtime_properties()
|
||||
*/
|
||||
protected function _add_view_specific_runtime_properties(
|
||||
Ai1ec_Event $event
|
||||
) {
|
||||
$end_day = $this->_registry->get( 'date.time', $event->get( 'end' ) )
|
||||
->adjust( -1, 'second' )
|
||||
->format_i18n( 'd' );
|
||||
$event->set_runtime( 'multiday_end_day', $end_day );
|
||||
$event->set_runtime(
|
||||
'start_day',
|
||||
$event->get( 'start' )->format( 'j' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_month_cell_array function
|
||||
*
|
||||
* Return an array of weeks, each containing an array of days, each
|
||||
* containing the date for the day ['date'] (if inside the month) and
|
||||
* the events ['events'] (if any) for the day, and a boolean ['today']
|
||||
* indicating whether that day is today.
|
||||
*
|
||||
* @param int $timestamp UNIX timestamp of the 1st day of the desired
|
||||
* month to display
|
||||
* @param array $days_events list of events for each day of the month in
|
||||
* the format returned by get_events_for_month()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function get_month_cell_array( Ai1ec_Date_Time $timestamp, $days_events ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$date_system = $this->_registry->get( 'date.system' );
|
||||
$today = $this->_registry->get( 'date.time' );// Used to flag today's cell
|
||||
|
||||
// Figure out index of first table cell
|
||||
$first_cell_index = $timestamp->format( 'w' );
|
||||
// Modify weekday based on start of week setting
|
||||
$first_cell_index = ( 7 + $first_cell_index - $settings->get( 'week_start_day' ) ) % 7;
|
||||
|
||||
// Get the last day of the month
|
||||
$last_day = $timestamp->format( 't' );
|
||||
$last_timestamp = $this->_registry->get( 'date.time', $timestamp );
|
||||
$last_timestamp->set_date(
|
||||
$timestamp->format( 'Y' ),
|
||||
$timestamp->format( 'm' ),
|
||||
$last_day
|
||||
)->set_time( 0, 0, 0 );
|
||||
// Figure out index of last table cell
|
||||
$last_cell_index = $last_timestamp->format( 'w' );
|
||||
// Modify weekday based on start of week setting
|
||||
$last_cell_index = ( 7 + $last_cell_index - $settings->get( 'week_start_day' ) ) % 7;
|
||||
|
||||
$weeks = array();
|
||||
$week = 0;
|
||||
$weeks[$week] = array();
|
||||
|
||||
// Insert any needed blank cells into first week
|
||||
for( $i = 0; $i < $first_cell_index; $i++ ) {
|
||||
$weeks[$week][] = array(
|
||||
'date' => null,
|
||||
'events' => array(),
|
||||
'date_link' => null
|
||||
);
|
||||
}
|
||||
|
||||
// Insert each month's day and associated events
|
||||
for( $i = 1; $i <= $last_day; $i++ ) {
|
||||
$day = $this->_registry->get( 'date.time' )
|
||||
->set_date(
|
||||
$timestamp->format( 'Y' ),
|
||||
$timestamp->format( 'm' ),
|
||||
$i
|
||||
)
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
$exact_date = $date_system->format_date_for_url(
|
||||
$day,
|
||||
$settings->get( 'input_date_format' )
|
||||
);
|
||||
$events = array();
|
||||
foreach ( $days_events[$i] as $evt ){
|
||||
$event_data = array(
|
||||
'filtered_title' => $evt->get_runtime( 'filtered_title' ),
|
||||
'post_excerpt' => $evt->get_runtime( 'post_excerpt' ),
|
||||
'color_style' => $evt->get_runtime( 'color_style' ),
|
||||
'category_colors' => $evt->get_runtime( 'category_colors' ),
|
||||
'permalink' => $evt->get_runtime( 'instance_permalink' ),
|
||||
'ticket_url_label' => $evt->get_runtime( 'ticket_url_label' ),
|
||||
'edit_post_link' => $evt->get_runtime( 'edit_post_link' ),
|
||||
'short_start_time' => $evt->get_runtime( 'short_start_time' ),
|
||||
'multiday_end_day' => $evt->get_runtime( 'multiday_end_day' ),
|
||||
'start_day' => $evt->get_runtime( 'start_day' ),
|
||||
'short_start_time' => $evt->get_runtime( 'short_start_time' ),
|
||||
'instance_id' => $evt->get( 'instance_id' ),
|
||||
'post_id' => $evt->get( 'post_id' ),
|
||||
'is_allday' => $evt->is_allday(),
|
||||
'is_multiday' => $evt->is_multiday(),
|
||||
'venue' => $evt->get( 'venue' ),
|
||||
'ticket_url' => $evt->get( 'ticket_url' ),
|
||||
'start_truncated' => $evt->get( 'start_truncated' ),
|
||||
'end_truncated' => $evt->get( 'end_truncated' ),
|
||||
'popup_timespan' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->timespan( $evt, 'short' ),
|
||||
'avatar_not_wrapped' => $evt->getavatar( false ),
|
||||
'avatar' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->avatar(
|
||||
$evt,
|
||||
array(
|
||||
'post_thumbnail',
|
||||
'content_img',
|
||||
'location_avatar',
|
||||
'category_avatar',
|
||||
),
|
||||
'',
|
||||
false ),
|
||||
);
|
||||
$meta = $this->_registry->get( 'model.meta-post' );
|
||||
if ( ! $event_data['ticket_url'] ) {
|
||||
$timely_tickets = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_timely_tickets_url',
|
||||
null
|
||||
);
|
||||
if ( $timely_tickets ) {
|
||||
$event_data['ticket_url'] = $timely_tickets;
|
||||
$evt->set( 'ticket_url', $event_data['ticket_url'] );
|
||||
}
|
||||
}
|
||||
if (
|
||||
true === apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
) {
|
||||
$full_details = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_ep_product_details',
|
||||
null
|
||||
);
|
||||
if (
|
||||
is_array( $full_details ) &&
|
||||
isset( $full_details['show_buy_button'] ) &&
|
||||
true === $full_details['show_buy_button']
|
||||
&& $event_data['ticket_url']
|
||||
) {
|
||||
// Tickets button is shown by default in this case.
|
||||
} else {
|
||||
// Otherwise not.
|
||||
$event_data['ticket_url'] = false;
|
||||
}
|
||||
$evt->set( 'ticket_url', $event_data['ticket_url'] );
|
||||
}
|
||||
|
||||
if (
|
||||
$this->_compatibility->use_backward_compatibility()
|
||||
) {
|
||||
$event_data = $evt;
|
||||
}
|
||||
$events[] = $event_data;
|
||||
}
|
||||
$weeks[$week][] = array(
|
||||
'date' => $i,
|
||||
'date_link' => $this->_create_link_for_day_view( $exact_date ),
|
||||
'today' =>
|
||||
$timestamp->format( 'Y' ) == $today->format( 'Y' ) &&
|
||||
$timestamp->format( 'm' ) == $today->format( 'm' ) &&
|
||||
$i == $today->format( 'j' ),
|
||||
'events' => $events,
|
||||
|
||||
);
|
||||
// If reached the end of the week, increment week
|
||||
if( count( $weeks[$week] ) == 7 )
|
||||
$week++;
|
||||
}
|
||||
|
||||
// Insert any needed blank cells into last week
|
||||
for( $i = $last_cell_index + 1; $i < 7; $i++ ) {
|
||||
$weeks[$week][] = array( 'date' => null, 'events' => array() );
|
||||
}
|
||||
|
||||
return $weeks;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_events_for_month function
|
||||
*
|
||||
* Return an array of all dates for the given month as an associative
|
||||
* array, with each element's value being another array of event objects
|
||||
* representing the events occuring on that date.
|
||||
*
|
||||
* @param int $time the UNIX timestamp of a date within the desired month
|
||||
* @param array $filter Array of filters for the events returned:
|
||||
* ['cat_ids'] => non-associatative array of category IDs
|
||||
* ['tag_ids'] => non-associatative array of tag IDs
|
||||
* ['post_ids'] => non-associatative array of post IDs
|
||||
* ['auth_ids'] => non-associatative array of author IDs
|
||||
*
|
||||
* @return array array of arrays as per function's description
|
||||
*/
|
||||
protected function get_events_for_month(
|
||||
Ai1ec_Date_Time $time,
|
||||
$filter = array()
|
||||
) {
|
||||
$last_day = $time->format( 't' );
|
||||
|
||||
$day_entry = array(
|
||||
'multi' => array(),
|
||||
'allday' => array(),
|
||||
'other' => array(),
|
||||
);
|
||||
$days_events = array_fill(
|
||||
1,
|
||||
$last_day,
|
||||
$day_entry
|
||||
);
|
||||
unset( $day_entry );
|
||||
$start_time = $this->_registry->get( 'date.time', $time );
|
||||
$start_time->set_date(
|
||||
$time->format( 'Y' ),
|
||||
$time->format( 'm' ),
|
||||
1
|
||||
)->set_time( 0, 0, 0 );
|
||||
$end_time = $this->_registry->get( 'date.time', $start_time );
|
||||
|
||||
$end_time->adjust_month( 1 );
|
||||
|
||||
$search = $this->_registry->get( 'model.search' );
|
||||
$month_events = $search->get_events_between(
|
||||
$start_time,
|
||||
$end_time,
|
||||
$filter,
|
||||
true
|
||||
);
|
||||
$start_time = $start_time->format();
|
||||
$end_time = $end_time->format();
|
||||
$this->_update_meta( $month_events );
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->clear_the_content_filters();
|
||||
foreach ( $month_events as $event ) {
|
||||
$event_start = $event->get( 'start' )->format();
|
||||
$event_end = $event->get( 'end' )->format();
|
||||
|
||||
/**
|
||||
* REASONING: we assume, that event spans multiple periods, one of
|
||||
* which happens to be current (month). Thus we mark, that current
|
||||
* event starts at the very first day of current month and further
|
||||
* we will mark it as having truncated beginning (unless it is not
|
||||
* overlapping period boundaries).
|
||||
* Although, if event starts after the first second of this period
|
||||
* it's start day will be decoded as time 'j' format (`int`-casted
|
||||
* to increase map access time), of it's actual start time.
|
||||
*/
|
||||
$day = 1;
|
||||
if ( $event_start > $start_time ) {
|
||||
$day = (int)$event->get( 'start' )->format( 'j' );
|
||||
}
|
||||
|
||||
// Set multiday properties. TODO: Should these be made event object
|
||||
// properties? They probably shouldn't be saved to the DB, so I'm
|
||||
// not sure. Just creating properties dynamically for now.
|
||||
if ( $event_start < $start_time ) {
|
||||
$event->set( 'start_truncated', true );
|
||||
}
|
||||
if ( $event_end >= $end_time ) {
|
||||
$event->set( 'end_truncated', true );
|
||||
}
|
||||
|
||||
// Categorize event.
|
||||
$priority = 'other';
|
||||
if ( $event->is_allday() ) {
|
||||
$priority = 'allday';
|
||||
} elseif ( $event->is_multiday() ) {
|
||||
$priority = 'multi';
|
||||
}
|
||||
$this->_add_runtime_properties( $event );
|
||||
$days_events[$day][$priority][] = $event;
|
||||
}
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->restore_the_content_filters();
|
||||
for ( $day = 1; $day <= $last_day; $day++ ) {
|
||||
$days_events[$day] = array_merge(
|
||||
$days_events[$day]['multi'],
|
||||
$days_events[$day]['allday'],
|
||||
$days_events[$day]['other']
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters(
|
||||
'ai1ec_get_events_for_month',
|
||||
$days_events,
|
||||
$time,
|
||||
$filter
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for day view.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_View_Oneday extends Ai1ec_Calendar_View_Abstract {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_name()
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'oneday';
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_content()
|
||||
*/
|
||||
public function get_content( array $view_args ) {
|
||||
$date_system = $this->_registry->get( 'date.system' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$defaults = array(
|
||||
'oneday_offset' => 0,
|
||||
'cat_ids' => array(),
|
||||
'tag_ids' => array(),
|
||||
'auth_ids' => array(),
|
||||
'post_ids' => array(),
|
||||
'instance_ids' => array(),
|
||||
'exact_date' => $date_system->current_time(),
|
||||
);
|
||||
$args = wp_parse_args( $view_args, $defaults );
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' )
|
||||
->adjust_day( 0 + $args['oneday_offset'] )
|
||||
->set_time( 0, 0, 0 );
|
||||
|
||||
$cell_array = $this->get_oneday_cell_array(
|
||||
$local_date,
|
||||
apply_filters(
|
||||
'ai1ec_get_events_relative_to_filter',
|
||||
array(
|
||||
'cat_ids' => $args['cat_ids'],
|
||||
'tag_ids' => $args['tag_ids'],
|
||||
'post_ids' => $args['post_ids'],
|
||||
'auth_ids' => $args['auth_ids'],
|
||||
'instance_ids' => $args['instance_ids'],
|
||||
),
|
||||
$view_args,
|
||||
apply_filters(
|
||||
'ai1ec_show_unique_events',
|
||||
false
|
||||
)
|
||||
)
|
||||
);
|
||||
// Create pagination links.
|
||||
$title = $local_date->format_i18n(
|
||||
$this->_registry->get( 'model.option' )
|
||||
->get( 'date_format', 'l, M j, Y' )
|
||||
);
|
||||
$pagination_links = $this->_get_pagination( $args, $title );
|
||||
|
||||
// Calculate today marker's position.
|
||||
$midnight = $this->_registry->get( 'date.time', 'now', 'sys.default' )
|
||||
->set_time( 0, 0, 0 );
|
||||
$now = $this->_registry->get( 'date.time', 'now', 'sys.default' );
|
||||
$now_text = $this->_registry->get( 'view.event.time' )
|
||||
->get_short_time( $now );
|
||||
$now = (int) ( $now->diff_sec( $midnight ) / 60 );
|
||||
|
||||
$is_ticket_button_enabled = apply_filters( 'ai1ec_oneday_ticket_button', false );
|
||||
$show_reveal_button = apply_filters( 'ai1ec_oneday_reveal_button', false );
|
||||
|
||||
$time_format = $this->_registry->get( 'model.option' )
|
||||
->get( 'time_format', Ai1ec_I18n::__( 'g a' ) );
|
||||
|
||||
$hours = array();
|
||||
$today = $this->_registry->get( 'date.time', 'now', 'sys.default' );
|
||||
for ( $hour = 0; $hour < 24; $hour++ ) {
|
||||
$hours[] = $today
|
||||
->set_time( $hour, 0, 0 )
|
||||
->format_i18n( $time_format );
|
||||
}
|
||||
|
||||
$view_args = array(
|
||||
'title' => $title,
|
||||
'type' => 'oneday',
|
||||
'cell_array' => $cell_array,
|
||||
'show_location_in_title' => $settings->get( 'show_location_in_title' ),
|
||||
'now_top' => $now,
|
||||
'now_text' => $now_text,
|
||||
'time_format' => $time_format,
|
||||
'done_allday_label' => false,// legacy
|
||||
'done_grid' => false,// legacy
|
||||
'data_type' => $args['data_type'],
|
||||
'is_ticket_button_enabled' => $is_ticket_button_enabled,
|
||||
'show_reveal_button' => $show_reveal_button,
|
||||
'text_full_day' => __( 'Reveal full day', AI1EC_PLUGIN_NAME ),
|
||||
'text_all_day' => __( 'All-day', AI1EC_PLUGIN_NAME ),
|
||||
'text_now_label' => __( 'Now:', AI1EC_PLUGIN_NAME ),
|
||||
'text_venue_separator' => __( '@ %s', AI1EC_PLUGIN_NAME ),
|
||||
'hours' => $hours,
|
||||
'indent_multiplier' => 16,
|
||||
'indent_offset' => 54,
|
||||
'pagination_links' => $pagination_links,
|
||||
);
|
||||
|
||||
$view_args = $this->get_extra_template_arguments( $view_args );
|
||||
|
||||
// Add navigation if requested.
|
||||
$view_args['navigation'] = $this->_get_navigation(
|
||||
array(
|
||||
'no_navigation' => $args['no_navigation'],
|
||||
'pagination_links' => $pagination_links,
|
||||
'views_dropdown' => $args['views_dropdown'],
|
||||
'below_toolbar' => apply_filters(
|
||||
'ai1ec_below_toolbar',
|
||||
'',
|
||||
$this->get_name(),
|
||||
$args
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
return
|
||||
$this->_registry->get( 'http.request' )->is_json_required(
|
||||
$args['request_format'], 'oneday'
|
||||
)
|
||||
? $this->_apply_filters_to_args( $view_args )
|
||||
: $this->_get_view( $view_args );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce an array of three links for the day view of the calendar.
|
||||
*
|
||||
* Each element is an associative array containing the link's enabled status
|
||||
* ['enabled'], CSS class ['class'], text ['text'] and value to assign to
|
||||
* link's href ['href'].
|
||||
*
|
||||
* @param array $args Current request arguments.
|
||||
* @param string $title Title to display in datepicker button
|
||||
*
|
||||
* @return array Array of links.
|
||||
*/
|
||||
function get_oneday_pagination_links( $args, $title ) {
|
||||
$links = array();
|
||||
$orig_date = $args['exact_date'];
|
||||
|
||||
// ================
|
||||
// = Previous day =
|
||||
// ================
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' )
|
||||
->adjust_day( $args['oneday_offset'] - 1 )
|
||||
->set_time( 0, 0, 0 );
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-prev-day',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-left"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
// ======================
|
||||
// = Minical datepicker =
|
||||
// ======================
|
||||
$args['exact_date'] = $orig_date;
|
||||
$factory = $this->_registry->get( 'factory.html' );
|
||||
$links[] = $factory->create_datepicker_link(
|
||||
$args,
|
||||
$args['exact_date'],
|
||||
$title
|
||||
);
|
||||
|
||||
// ============
|
||||
// = Next day =
|
||||
// ============
|
||||
$local_date->adjust_day( +2 ); // above was (-1), (+2) is to counteract
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class' => 'ai1ec-next-day',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_oneday_cell_array function
|
||||
*
|
||||
* Return an associative array of weekdays, indexed by the day's date,
|
||||
* starting the day given by $timestamp, each element an associative array
|
||||
* containing three elements:
|
||||
* ['today'] => whether the day is today
|
||||
* ['allday'] => non-associative ordered array of events that are all-day
|
||||
* ['notallday'] => non-associative ordered array of non-all-day events to
|
||||
* display for that day, each element another associative
|
||||
* array like so:
|
||||
* ['top'] => how many minutes offset from the start of the day
|
||||
* ['height'] => how many minutes this event spans
|
||||
* ['indent'] => how much to indent this event to accommodate multiple
|
||||
* events occurring at the same time (0, 1, 2, etc., to
|
||||
* be multiplied by whatever desired px/em amount)
|
||||
* ['event'] => event data object
|
||||
*
|
||||
* @param int $timestamp the UNIX timestamp of the first day of the week
|
||||
* @param array $filter Array of filters for the events returned:
|
||||
* ['cat_ids'] => non-associatative array of category IDs
|
||||
* ['tag_ids'] => non-associatative array of tag IDs
|
||||
* ['post_ids'] => non-associatative array of post IDs
|
||||
* ['auth_ids'] => non-associatative array of author IDs
|
||||
* ['instance_ids'] => non-associatative array of event instance IDs
|
||||
*
|
||||
* @return array array of arrays as per function description
|
||||
*/
|
||||
function get_oneday_cell_array(
|
||||
Ai1ec_Date_Time $start_time,
|
||||
array $filter = array(),
|
||||
$legacy = false
|
||||
) {
|
||||
$search = $this->_registry->get( 'model.search' );
|
||||
|
||||
$loc_start_time = $this->_registry
|
||||
->get( 'date.time', $start_time, 'sys.default' )
|
||||
->set_time( 0, 0, 0 );
|
||||
$loc_end_time = $this->_registry
|
||||
->get( 'date.time', $start_time, 'sys.default' )
|
||||
->adjust_day( +1 )
|
||||
->set_time( 0, 0, 0 );
|
||||
|
||||
$day_events = $search->get_events_for_day( $loc_start_time, $filter );
|
||||
$this->_update_meta( $day_events );
|
||||
// Split up events on a per-day basis
|
||||
$all_events = array();
|
||||
|
||||
$day_start_ts = $loc_start_time->format();
|
||||
$day_end_ts = $loc_end_time->format();
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->clear_the_content_filters();
|
||||
foreach ( $day_events as $evt ) {
|
||||
list( $evt_start, $evt_end ) = $this->
|
||||
_get_view_specific_timestamps( $evt );
|
||||
|
||||
// If event falls on this day, make a copy.
|
||||
if ( $evt_end > $day_start_ts && $evt_start < $day_end_ts ) {
|
||||
$_evt = clone $evt;
|
||||
if ( $evt_start < $day_start_ts ) {
|
||||
// If event starts before this day, adjust copy's start time
|
||||
$_evt->set( 'start', $day_start_ts );
|
||||
$_evt->set( 'start_truncated', true );
|
||||
}
|
||||
if ( $evt_end > $day_end_ts ) {
|
||||
// If event ends after this day, adjust copy's end time
|
||||
$_evt->set( 'end', $day_end_ts );
|
||||
$_evt->set( 'end_truncated', true );
|
||||
}
|
||||
|
||||
// Store reference to original, unmodified event, required by view.
|
||||
$_evt->set( '_orig', $evt );
|
||||
$this->_add_runtime_properties( $_evt );
|
||||
// Place copy of event in appropriate category
|
||||
if ( $_evt->is_allday() ) {
|
||||
$all_events[$day_start_ts]['allday'][] = $_evt;
|
||||
} else {
|
||||
$all_events[$day_start_ts]['notallday'][] = $_evt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->restore_the_content_filters();
|
||||
|
||||
// This will store the returned array
|
||||
$days = array();
|
||||
|
||||
// Initialize empty arrays for this day if no events to minimize warnings
|
||||
if ( ! isset( $all_events[$day_start_ts]['allday'] ) ) {
|
||||
$all_events[$day_start_ts]['allday'] = array();
|
||||
}
|
||||
if ( ! isset( $all_events[$day_start_ts]['notallday'] ) ) {
|
||||
$all_events[$day_start_ts]['notallday'] = array();
|
||||
}
|
||||
|
||||
$today_ymd = $this->_registry->get(
|
||||
'date.time',
|
||||
$this->_registry->get( 'date.system' )->current_time()
|
||||
)->format( 'Y-m-d' );
|
||||
|
||||
$evt_stack = array( 0 ); // Stack to keep track of indentation
|
||||
|
||||
foreach ( $all_events[$day_start_ts] as $event_type => &$events ) {
|
||||
foreach ( $events as &$evt ) {
|
||||
$event = array(
|
||||
'filtered_title' => $evt->get_runtime( 'filtered_title' ),
|
||||
'post_excerpt' => $evt->get_runtime( 'post_excerpt' ),
|
||||
'color_style' => $evt->get_runtime( 'color_style' ),
|
||||
'category_colors' => $evt->get_runtime( 'category_colors' ),
|
||||
'permalink' => $evt->get_runtime( 'instance_permalink' ),
|
||||
'ticket_url_label' => $evt->get_runtime( 'ticket_url_label' ),
|
||||
'edit_post_link' => $evt->get_runtime( 'edit_post_link' ),
|
||||
'faded_color' => $evt->get_runtime( 'faded_color' ),
|
||||
'rgba_color' => $evt->get_runtime( 'rgba_color' ),
|
||||
'short_start_time' => $evt->get_runtime( 'short_start_time' ),
|
||||
'instance_id' => $evt->get( 'instance_id' ),
|
||||
'post_id' => $evt->get( 'post_id' ),
|
||||
'is_multiday' => $evt->get( 'is_multiday' ),
|
||||
'venue' => $evt->get( 'venue' ),
|
||||
'ticket_url' => $evt->get( 'ticket_url' ),
|
||||
'start_truncated' => $evt->get( 'start_truncated' ),
|
||||
'end_truncated' => $evt->get( 'end_truncated' ),
|
||||
'popup_timespan' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->timespan( $evt, 'short' ),
|
||||
'avatar_not_wrapped' => $evt->getavatar( false ),
|
||||
'avatar' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->avatar(
|
||||
$evt,
|
||||
array(
|
||||
'post_thumbnail',
|
||||
'content_img',
|
||||
'location_avatar',
|
||||
'category_avatar',
|
||||
),
|
||||
'',
|
||||
false ),
|
||||
);
|
||||
$meta = $this->_registry->get( 'model.meta-post' );
|
||||
if ( ! $event['ticket_url'] ) {
|
||||
$timely_tickets = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_timely_tickets_url',
|
||||
null
|
||||
);
|
||||
if ( $timely_tickets ) {
|
||||
$event['ticket_url'] = $timely_tickets;
|
||||
$evt->set( 'ticket_url', $event['ticket_url'] );
|
||||
}
|
||||
}
|
||||
if (
|
||||
true === apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
) {
|
||||
$full_details = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_ep_product_details',
|
||||
null
|
||||
);
|
||||
if (
|
||||
is_array( $full_details ) &&
|
||||
isset( $full_details['show_buy_button'] ) &&
|
||||
true === $full_details['show_buy_button']
|
||||
&& $event['ticket_url']
|
||||
) {
|
||||
// Tickets button is shown by default in this case.
|
||||
} else {
|
||||
// Otherwise not.
|
||||
$event['ticket_url'] = false;
|
||||
}
|
||||
$evt->set( 'ticket_url', $event['ticket_url'] );
|
||||
}
|
||||
|
||||
if (
|
||||
$this->_compatibility->use_backward_compatibility()
|
||||
) {
|
||||
$event = $evt;
|
||||
}
|
||||
if ( 'notallday' === $event_type) {
|
||||
// Calculate top and bottom edges of current event
|
||||
$top = (int)(
|
||||
$evt->get( 'start' )->diff_sec( $loc_start_time ) / 60
|
||||
);
|
||||
$bottom = min(
|
||||
$top + ( $evt->get_duration() / 60 ),
|
||||
1440
|
||||
);
|
||||
// While there's more than one event in the stack and this event's
|
||||
// top position is beyond the last event's bottom, pop the stack
|
||||
while ( count( $evt_stack ) > 1 && $top >= end( $evt_stack ) ) {
|
||||
array_pop( $evt_stack );
|
||||
}
|
||||
// Indentation is number of stacked events minus 1
|
||||
$indent = count( $evt_stack ) - 1;
|
||||
// Push this event onto the top of the stack
|
||||
array_push( $evt_stack, $bottom );
|
||||
$evt = array(
|
||||
'top' => $top,
|
||||
'height' => $bottom - $top,
|
||||
'indent' => $indent,
|
||||
'event' => $event,
|
||||
);
|
||||
} else {
|
||||
$evt = $event;
|
||||
}
|
||||
}
|
||||
}
|
||||
$days[$day_start_ts] = array(
|
||||
'today' => 0 === strcmp(
|
||||
$today_ymd,
|
||||
$start_time->format( 'Y-m-d' )
|
||||
),
|
||||
'allday' => $all_events[$day_start_ts]['allday'],
|
||||
'notallday' => $all_events[$day_start_ts]['notallday'],
|
||||
'day' => $this->_registry->
|
||||
get( 'date.time', $day_start_ts )->format_i18n( 'j' ),
|
||||
'weekday' => $this->_registry->
|
||||
get( 'date.time', $day_start_ts )->format_i18n( 'D' ),
|
||||
);
|
||||
|
||||
return apply_filters(
|
||||
'ai1ec_get_oneday_cell_array',
|
||||
$days,
|
||||
$start_time->format(),
|
||||
$filter
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::_add_view_specific_runtime_properties()
|
||||
*/
|
||||
protected function _add_view_specific_runtime_properties( Ai1ec_Event $event ) {
|
||||
$event->set_runtime(
|
||||
'multiday',
|
||||
$event->get( '_orig' )->is_multiday()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The concrete class for day view.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_Calendar_View_Week extends Ai1ec_Calendar_View_Abstract {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_name()
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'week';
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_content()
|
||||
*/
|
||||
public function get_content( array $view_args ) {
|
||||
$date_system = $this->_registry->get( 'date.system' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$defaults = array(
|
||||
'week_offset' => 0,
|
||||
'cat_ids' => array(),
|
||||
'tag_ids' => array(),
|
||||
'auth_ids' => array(),
|
||||
'post_ids' => array(),
|
||||
'instance_ids' => array(),
|
||||
'exact_date' => $date_system->current_time(),
|
||||
);
|
||||
$args = wp_parse_args( $view_args, $defaults );
|
||||
|
||||
// Localize requested date and get components.
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' );
|
||||
$start_day_offset = $this->get_week_start_day_offset( $local_date->format( 'w' ) );
|
||||
// get the first day of week
|
||||
$local_date->adjust_day( 0 + $start_day_offset + ( $args['week_offset'] * 7 ) )
|
||||
->set_time( 0, 0, 0 );
|
||||
|
||||
$cell_array = $this->get_week_cell_array(
|
||||
$local_date,
|
||||
apply_filters(
|
||||
'ai1ec_get_events_relative_to_filter',
|
||||
array(
|
||||
'cat_ids' => $args['cat_ids'],
|
||||
'tag_ids' => $args['tag_ids'],
|
||||
'post_ids' => $args['post_ids'],
|
||||
'auth_ids' => $args['auth_ids'],
|
||||
'instance_ids' => $args['instance_ids'],
|
||||
),
|
||||
$view_args,
|
||||
apply_filters(
|
||||
'ai1ec_show_unique_events',
|
||||
false
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Create pagination links. (Translators: '%s' = week's start date.)
|
||||
$title = sprintf(
|
||||
__( 'Week of %s', AI1EC_PLUGIN_NAME ),
|
||||
$local_date->format_i18n( 'F j' )
|
||||
);
|
||||
$pagination_links = $this->_get_pagination( $args, $title );
|
||||
|
||||
$time_format = $this->_registry->get( 'model.option' )
|
||||
->get( 'time_format', Ai1ec_I18n::__( 'g a' ) );
|
||||
|
||||
// Calculate today marker's position.
|
||||
$now = $this->_registry->get( 'date.time', 'now', 'sys.default' );
|
||||
$now_text = $now->format_i18n( 'M j h:i a' );
|
||||
$now = $now->format( 'G' ) * 60 + $now->format( 'i' );
|
||||
// Find out if the current week view contains "now" and thus should display
|
||||
// the "now" marker.
|
||||
$show_now = false;
|
||||
foreach ( $cell_array as $day ) {
|
||||
if ( $day['today'] ) {
|
||||
$show_now = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$is_ticket_button_enabled = apply_filters( 'ai1ec_week_ticket_button', false );
|
||||
$show_reveal_button = apply_filters( 'ai1ec_week_reveal_button', false );
|
||||
|
||||
$hours = array();
|
||||
$today = $this->_registry->get( 'date.time', 'now', 'sys.default' );
|
||||
for ( $hour = 0; $hour < 24; $hour++ ) {
|
||||
$hours[] = $today
|
||||
->set_time( $hour, 0, 0 )
|
||||
->format_i18n( $time_format );
|
||||
}
|
||||
|
||||
$view_args = array(
|
||||
'title' => $title,
|
||||
'type' => 'week',
|
||||
'cell_array' => $cell_array,
|
||||
'show_location_in_title' => $settings->get( 'show_location_in_title' ),
|
||||
'now_top' => $now,
|
||||
'now_text' => $now_text,
|
||||
'show_now' => $show_now,
|
||||
'post_ids' => join( ',', $args['post_ids'] ),
|
||||
'time_format' => $time_format,
|
||||
'done_allday_label' => false,
|
||||
'done_grid' => false,
|
||||
'data_type' => $args['data_type'],
|
||||
'is_ticket_button_enabled' => $is_ticket_button_enabled,
|
||||
'show_reveal_button' => $show_reveal_button,
|
||||
'text_full_day' => __( 'Reveal full day', AI1EC_PLUGIN_NAME ),
|
||||
'text_all_day' => __( 'All-day', AI1EC_PLUGIN_NAME ),
|
||||
'text_now_label' => __( 'Now:', AI1EC_PLUGIN_NAME ),
|
||||
'text_venue_separator' => __( '@ %s', AI1EC_PLUGIN_NAME ),
|
||||
'hours' => $hours,
|
||||
'indent_multiplier' => 8,
|
||||
'indent_offset' => 0,
|
||||
'pagination_links' => $pagination_links,
|
||||
);
|
||||
|
||||
// Add navigation if requested.
|
||||
$view_args['navigation'] = $this->_get_navigation(
|
||||
array(
|
||||
'no_navigation' => $args['no_navigation'],
|
||||
'pagination_links' => $pagination_links,
|
||||
'views_dropdown' => $args['views_dropdown'],
|
||||
'below_toolbar' => apply_filters(
|
||||
'ai1ec_below_toolbar',
|
||||
'',
|
||||
$this->get_name(),
|
||||
$args
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$view_args = $this->get_extra_template_arguments( $view_args );
|
||||
|
||||
return
|
||||
$this->_registry->get( 'http.request' )->is_json_required(
|
||||
$args['request_format'], 'week'
|
||||
)
|
||||
? $this->_apply_filters_to_args( $view_args )
|
||||
: $this->_get_view( $view_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-associative array of two links for the week view of the
|
||||
* calendar:
|
||||
* previous week, and next week.
|
||||
* Each element is an associative array containing the link's enabled status
|
||||
* ['enabled'], CSS class ['class'], text ['text'] and value to assign to
|
||||
* link's href ['href'].
|
||||
*
|
||||
* @param array $args Current request arguments
|
||||
* @param string $title Title to display in datepicker button
|
||||
*
|
||||
* @return array Array of links
|
||||
*/
|
||||
protected function get_week_pagination_links( $args, $title ) {
|
||||
$links = array();
|
||||
|
||||
$orig_date = $args['exact_date'];
|
||||
|
||||
$negative_offset = $args['week_offset'] * 7 - 7;
|
||||
$positive_offset = $args['week_offset'] * 7 + 7;
|
||||
// =================
|
||||
// = Previous week =
|
||||
// =================
|
||||
$local_date = $this->_registry
|
||||
->get( 'date.time', $args['exact_date'], 'sys.default' )
|
||||
->adjust_day( $negative_offset )
|
||||
->set_time( 0, 0, 0 );
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-prev-week',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-left"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
// ======================
|
||||
// = Minical datepicker =
|
||||
// ======================
|
||||
$args['exact_date'] = $orig_date;
|
||||
$factory = $this->_registry->get( 'factory.html' );
|
||||
$links[] = $factory->create_datepicker_link(
|
||||
$args,
|
||||
$args['exact_date'],
|
||||
$title
|
||||
);
|
||||
|
||||
// =============
|
||||
// = Next week =
|
||||
// =============
|
||||
$local_date->adjust_day( $positive_offset * 2 ); // above was (-1), (+2) is to counteract
|
||||
$args['exact_date'] = $local_date->format();
|
||||
$href = $this->_registry->get( 'html.element.href', $args );
|
||||
$links[] = array(
|
||||
'enabled' => true,
|
||||
'class'=> 'ai1ec-next-week',
|
||||
'text' => '<i class="ai1ec-fa ai1ec-fa-chevron-right"></i>',
|
||||
'href' => $href->generate_href(),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_week_cell_array function
|
||||
*
|
||||
* Return an associative array of weekdays, indexed by the day's date,
|
||||
* starting the day given by $timestamp, each element an associative array
|
||||
* containing three elements:
|
||||
* ['today'] => whether the day is today
|
||||
* ['allday'] => non-associative ordered array of events that are all-day
|
||||
* ['notallday'] => non-associative ordered array of non-all-day events to
|
||||
* display for that day, each element another associative
|
||||
* array like so:
|
||||
* ['top'] => how many minutes offset from the start of the day
|
||||
* ['height'] => how many minutes this event spans
|
||||
* ['indent'] => how much to indent this event to accommodate multiple
|
||||
* events occurring at the same time (0, 1, 2, etc., to
|
||||
* be multiplied by whatever desired px/em amount)
|
||||
* ['event'] => event data object
|
||||
*
|
||||
* @param int $start_of_week the UNIX timestamp of the first day of the week
|
||||
* @param array $filter Array of filters for the events returned:
|
||||
* ['cat_ids'] => non-associatative array of category IDs
|
||||
* ['tag_ids'] => non-associatative array of tag IDs
|
||||
* ['post_ids'] => non-associatative array of post IDs
|
||||
* ['auth_ids'] => non-associatative array of author IDs
|
||||
*
|
||||
* @return array array of arrays as per function description
|
||||
*/
|
||||
protected function get_week_cell_array( Ai1ec_Date_Time $start_of_week, $filter = array() ) {
|
||||
$search = $this->_registry->get( 'model.search' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$date_system = $this->_registry->get( 'date.system' );
|
||||
$end_of_week = $this->_registry->get( 'date.time', $start_of_week );
|
||||
$end_of_week->adjust_day( 7 );
|
||||
// Do one SQL query to find all events for the week, including spanning
|
||||
$week_events = $search->get_events_between(
|
||||
$start_of_week,
|
||||
$end_of_week,
|
||||
$filter,
|
||||
true
|
||||
);
|
||||
$this->_update_meta( $week_events );
|
||||
// Split up events on a per-day basis
|
||||
$all_events = array();
|
||||
$this->_days_cache = $this->_registry->get( 'cache.memory' );
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->clear_the_content_filters();
|
||||
foreach ( $week_events as $evt ) {
|
||||
list( $evt_start, $evt_end ) = $this->
|
||||
_get_view_specific_timestamps( $evt );
|
||||
|
||||
// Iterate through each day of the week and generate new event object
|
||||
// based on this one for each day that it spans
|
||||
for (
|
||||
$day = $start_of_week->format( 'j' ),
|
||||
$last_week_day_index = $start_of_week->format( 'j' ) + 7;
|
||||
$day < $last_week_day_index;
|
||||
$day++
|
||||
) {
|
||||
list( $day_start, $day_end ) = $this->
|
||||
_get_wkday_start_end( $day, $start_of_week );
|
||||
|
||||
if ( $evt_end < $day_start ) {
|
||||
break; // save cycles
|
||||
}
|
||||
|
||||
// If event falls on this day, make a copy.
|
||||
if ( $evt_end > $day_start && $evt_start < $day_end ) {
|
||||
$_evt = clone $evt;
|
||||
if ( $evt_start < $day_start ) {
|
||||
// If event starts before this day, adjust copy's start time
|
||||
$_evt->set( 'start', $day_start );
|
||||
$_evt->set( 'start_truncated', true );
|
||||
}
|
||||
if ( $evt_end > $day_end ) {
|
||||
// If event ends after this day, adjust copy's end time
|
||||
$_evt->set( 'end', $day_end );
|
||||
$_evt->set( 'end_truncated', true );
|
||||
}
|
||||
|
||||
// Store reference to original, unmodified event, required by view.
|
||||
$_evt->set( '_orig', $evt );
|
||||
$this->_add_runtime_properties( $_evt );
|
||||
|
||||
// Place copy of event in appropriate category
|
||||
if ( $_evt->is_allday() ) {
|
||||
$all_events[$day_start]['allday'][] = $_evt;
|
||||
} else {
|
||||
$all_events[$day_start]['notallday'][] = $_evt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_registry->get( 'controller.content-filter' )
|
||||
->restore_the_content_filters();
|
||||
// This will store the returned array
|
||||
$days = array();
|
||||
$now = $this->_registry->get(
|
||||
'date.time',
|
||||
'now',
|
||||
$start_of_week->get_timezone()
|
||||
);
|
||||
// =========================================
|
||||
// = Iterate through each date of the week =
|
||||
// =========================================
|
||||
for (
|
||||
$day = $start_of_week->format( 'j' ),
|
||||
$last_week_day_index = $start_of_week->format( 'j' ) + 7;
|
||||
$day < $last_week_day_index;
|
||||
$day++
|
||||
) {
|
||||
list( $day_date, , $day_date_ob ) = $this->
|
||||
_get_wkday_start_end( $day, $start_of_week );
|
||||
|
||||
$exact_date = $date_system->format_datetime_for_url(
|
||||
$day_date_ob,
|
||||
$settings->get( 'input_date_format' )
|
||||
);
|
||||
$href_for_date = $this->_create_link_for_day_view( $exact_date );
|
||||
|
||||
// Initialize empty arrays for this day if no events to minimize warnings
|
||||
if ( ! isset( $all_events[$day_date]['allday'] ) ) {
|
||||
$all_events[$day_date]['allday'] = array();
|
||||
}
|
||||
if ( ! isset( $all_events[$day_date]['notallday'] ) ) {
|
||||
$all_events[$day_date]['notallday'] = array();
|
||||
}
|
||||
|
||||
$evt_stack = array( 0 ); // Stack to keep track of indentation
|
||||
|
||||
foreach ( $all_events[$day_date] as $event_type => &$events ) {
|
||||
foreach ( $events as &$evt ) {
|
||||
$event = array(
|
||||
'filtered_title' => $evt->get_runtime( 'filtered_title' ),
|
||||
'post_excerpt' => $evt->get_runtime( 'post_excerpt' ),
|
||||
'color_style' => $evt->get_runtime( 'color_style' ),
|
||||
'category_colors' => $evt->get_runtime( 'category_colors' ),
|
||||
'permalink' => $evt->get_runtime( 'instance_permalink' ),
|
||||
'ticket_url_label' => $evt->get_runtime( 'ticket_url_label' ),
|
||||
'edit_post_link' => $evt->get_runtime( 'edit_post_link' ),
|
||||
'faded_color' => $evt->get_runtime( 'faded_color' ),
|
||||
'rgba_color' => $evt->get_runtime( 'rgba_color' ),
|
||||
'short_start_time' => $evt->get_runtime( 'short_start_time' ),
|
||||
'instance_id' => $evt->get( 'instance_id' ),
|
||||
'post_id' => $evt->get( 'post_id' ),
|
||||
'is_multiday' => $evt->get( 'is_multiday' ),
|
||||
'venue' => $evt->get( 'venue' ),
|
||||
'ticket_url' => $evt->get( 'ticket_url' ),
|
||||
'start_truncated' => $evt->get( 'start_truncated' ),
|
||||
'end_truncated' => $evt->get( 'end_truncated' ),
|
||||
'popup_timespan' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->timespan( $evt, 'short' ),
|
||||
'avatar_not_wrapped' => $evt->getavatar( false ),
|
||||
'avatar' => $this->_registry
|
||||
->get( 'twig.ai1ec-extension')->avatar(
|
||||
$evt,
|
||||
array(
|
||||
'post_thumbnail',
|
||||
'content_img',
|
||||
'location_avatar',
|
||||
'category_avatar',
|
||||
),
|
||||
'',
|
||||
false ),
|
||||
);
|
||||
$meta = $this->_registry->get( 'model.meta-post' );
|
||||
if ( ! $event['ticket_url'] ) {
|
||||
$timely_tickets = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_timely_tickets_url',
|
||||
null
|
||||
);
|
||||
if ( $timely_tickets ) {
|
||||
$event['ticket_url'] = $timely_tickets;
|
||||
$evt->set( 'ticket_url', $event['ticket_url'] );
|
||||
}
|
||||
}
|
||||
if (
|
||||
true === apply_filters(
|
||||
'ai1ec_buy_button_product',
|
||||
false
|
||||
)
|
||||
) {
|
||||
$full_details = $meta->get(
|
||||
$evt->get( 'post_id' ),
|
||||
'_ai1ec_ep_product_details',
|
||||
null
|
||||
);
|
||||
if (
|
||||
is_array( $full_details ) &&
|
||||
isset( $full_details['show_buy_button'] ) &&
|
||||
true === $full_details['show_buy_button']
|
||||
&& $event['ticket_url']
|
||||
) {
|
||||
// Tickets button is shown by default in this case.
|
||||
} else {
|
||||
// Otherwise not.
|
||||
$event['ticket_url'] = false;
|
||||
}
|
||||
$evt->set( 'ticket_url', $event['ticket_url'] );
|
||||
}
|
||||
|
||||
if (
|
||||
$this->_compatibility->use_backward_compatibility()
|
||||
) {
|
||||
$event = $evt;
|
||||
}
|
||||
if ( 'notallday' === $event_type) {
|
||||
$start = $evt->get( 'start' );
|
||||
// Calculate top and bottom edges of current event
|
||||
$top = $start->format( 'G' ) * 60 + $start->format( 'i' );
|
||||
$bottom = min( $top + $evt->get_duration() / 60, 1440 );
|
||||
// While there's more than one event in the stack and this event's top
|
||||
// position is beyond the last event's bottom, pop the stack
|
||||
while ( count( $evt_stack ) > 1 && $top >= end( $evt_stack ) ) {
|
||||
array_pop( $evt_stack );
|
||||
}
|
||||
// Indentation is number of stacked events minus 1
|
||||
$indent = count( $evt_stack ) - 1;
|
||||
// Push this event onto the top of the stack
|
||||
array_push( $evt_stack, $bottom );
|
||||
$evt = array(
|
||||
'top' => $top,
|
||||
'height' => $bottom - $top,
|
||||
'indent' => $indent,
|
||||
'event' => $event,
|
||||
);
|
||||
} else {
|
||||
$evt = $event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$days[$day_date] = array(
|
||||
'today' =>
|
||||
$day_date_ob->format( 'Y' ) == $now->format( 'Y' ) &&
|
||||
$day_date_ob->format( 'm' ) == $now->format( 'm' ) &&
|
||||
$day_date_ob->format( 'j' ) == $now->format( 'j' ),
|
||||
'allday' => $all_events[$day_date]['allday'],
|
||||
'notallday' => $all_events[$day_date]['notallday'],
|
||||
'href' => $href_for_date,
|
||||
'day' => $this->_registry->
|
||||
get( 'date.time', $day_date )->format_i18n( 'j' ),
|
||||
'weekday' => $this->_registry->
|
||||
get( 'date.time', $day_date )->format_i18n( 'D' ),
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters( 'ai1ec_get_week_cell_array', $days, $start_of_week, $filter );
|
||||
}
|
||||
|
||||
/**
|
||||
* get_week_start_day_offset function
|
||||
*
|
||||
* Returns the day offset of the first day of the week given a weekday in
|
||||
* question.
|
||||
*
|
||||
* @param int $wday The weekday to get information about
|
||||
* @return int A value between -6 and 0 indicating the week start
|
||||
* day relative to the given weekday.
|
||||
*/
|
||||
protected function get_week_start_day_offset( $wday ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
return - ( 7 - ( $settings->get( 'week_start_day' ) - $wday ) ) % 7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get start/end timestamps for a given weekday and week start identifier.
|
||||
*
|
||||
* @param int $day Week day number.
|
||||
* @param Ai1ec_Date_Time $week_start Date/Time information for week start.
|
||||
*
|
||||
* @return array List of start and and timestamps, 0-indexed array.
|
||||
*/
|
||||
protected function _get_wkday_start_end(
|
||||
$day,
|
||||
Ai1ec_Date_Time $week_start
|
||||
) {
|
||||
$entry = null;
|
||||
$day = (int)$day;
|
||||
if ( null === ( $entry = $this->_days_cache->get( $day ) ) ) {
|
||||
$day_start = $this->_registry
|
||||
->get( 'date.time', $week_start )
|
||||
->set_date(
|
||||
$week_start->format( 'Y' ),
|
||||
$week_start->format( 'm' ),
|
||||
$day
|
||||
)
|
||||
->set_time( 0, 0, 0 );
|
||||
$day_end = $this->_registry->get( 'date.time', $day_start );
|
||||
$day_end->adjust_day( 1 );
|
||||
$entry = array(
|
||||
$day_start->format(),
|
||||
$day_end->format(),
|
||||
$day_start
|
||||
);
|
||||
unset( $day_end ); // discard and free memory
|
||||
$this->_days_cache->set( $day, $entry );
|
||||
}
|
||||
return $entry;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Calendar Widget class
|
||||
*
|
||||
* A widget that displays the next X upcoming events (similar to Agenda view).
|
||||
*/
|
||||
class Ai1ec_View_Admin_Widget extends Ai1ec_Embeddable {
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_css_loaded = false;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_id() {
|
||||
return 'ai1ec_agenda_widget';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the widget class.
|
||||
*/
|
||||
public static function register_widget() {
|
||||
register_widget( 'Ai1ec_View_Admin_Widget' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for widget.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
parent::__construct(
|
||||
$this->get_id(),
|
||||
__( 'Upcoming Events', AI1EC_PLUGIN_NAME ),
|
||||
array(
|
||||
'description' => __( 'All-in-One Event Calendar: Lists upcoming events in Agenda view', AI1EC_PLUGIN_NAME ),
|
||||
'class' => 'ai1ec-agenda-widget',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::register_javascript_widget()
|
||||
*/
|
||||
public function register_javascript_widget( $id_base ) {
|
||||
$this->_registry->get( 'controller.javascript-widget' )
|
||||
->add_widget( $id_base, 'view.calendar.widget' );
|
||||
}
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::get_defaults()
|
||||
*/
|
||||
public function get_defaults() {
|
||||
return array(
|
||||
'title' => __( 'Upcoming Events', AI1EC_PLUGIN_NAME ),
|
||||
'events_seek_type' => 'events',
|
||||
'events_per_page' => 10,
|
||||
'days_per_page' => 10,
|
||||
'show_subscribe_buttons' => true,
|
||||
'show_calendar_button' => true,
|
||||
'hide_on_calendar_page' => true,
|
||||
'limit_by_cat' => false,
|
||||
'limit_by_tag' => false,
|
||||
'cat_ids' => array(),
|
||||
'tag_ids' => array(),
|
||||
'link_for_days' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::get_configurable_for_widget_creation()
|
||||
*/
|
||||
public function get_configurable_for_widget_creation() {
|
||||
$defaults = $this->get_js_widget_configurable_defaults();
|
||||
return array(
|
||||
'events_seek_type' => array(
|
||||
'renderer' => array(
|
||||
'class' => 'select',
|
||||
'label' => __(
|
||||
'Choose how to limit the upcoming events',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'options' => array(
|
||||
array(
|
||||
'text' => __(
|
||||
'Events',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'value' => 'events'
|
||||
),
|
||||
array(
|
||||
'text' => __(
|
||||
'Days',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'value' => 'days'
|
||||
),
|
||||
),
|
||||
),
|
||||
'value' => $defaults['events_seek_type']
|
||||
),
|
||||
'events_per_page' => array(
|
||||
'renderer' => array(
|
||||
'class' => 'input',
|
||||
'label' => Ai1ec_I18n::__( 'Number of events to show' ),
|
||||
'type' => 'append',
|
||||
'append' => 'events',
|
||||
),
|
||||
'value' => $defaults['events_per_page'],
|
||||
),
|
||||
'days_per_page' => array(
|
||||
'renderer' => array(
|
||||
'class' => 'input',
|
||||
'label' => Ai1ec_I18n::__( 'Number of days to show' ),
|
||||
'type' => 'append',
|
||||
'append' => 'days',
|
||||
),
|
||||
'value' => $defaults['days_per_page'],
|
||||
),
|
||||
'upcoming_widgets_default_tags_categories' => array(
|
||||
'renderer' => array(
|
||||
'class' => 'tags-categories',
|
||||
'label' => __(
|
||||
'Show events filtered for the following tags/categories',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'help' => __(
|
||||
'To clear, hold ⌘/<abbr class="initialism">CTRL</abbr> and click selection.',
|
||||
AI1EC_PLUGIN_NAME
|
||||
)
|
||||
),
|
||||
'value' => array(
|
||||
'categories' => array(),
|
||||
'tags' => array(),
|
||||
),
|
||||
),
|
||||
'show_subscribe_buttons' => array(
|
||||
'renderer' => array(
|
||||
'class' => 'checkbox',
|
||||
'label' => Ai1ec_I18n::__( 'Show the subscribe button in the widget' ),
|
||||
),
|
||||
'value' => $defaults['show_subscribe_buttons'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Calendar_View_Abstract::get_name()
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'Upcoming Events';
|
||||
}
|
||||
|
||||
/**
|
||||
* The icon class associated with the widget.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon() {
|
||||
return 'ai1ec-fa ai1ec-fa-clock-o';
|
||||
}
|
||||
|
||||
/**
|
||||
* Form function.
|
||||
*
|
||||
* Renders the widget's configuration form for the Manage Widgets page.
|
||||
*
|
||||
* @param array $instance The data array for the widget instance being configured.
|
||||
* @return void
|
||||
*/
|
||||
public function form( $instance ) {
|
||||
$default = $this->get_defaults();
|
||||
$instance = wp_parse_args( (array) $instance, $default );
|
||||
|
||||
// Get available cats, tags, events to allow user to limit widget to certain categories
|
||||
$events_categories = get_terms( 'events_categories', array( 'orderby' => 'name', "hide_empty" => false ) );
|
||||
$events_tags = get_terms( 'events_tags', array( 'orderby' => 'name', "hide_empty" => false ) );
|
||||
|
||||
// Generate unique IDs and NAMEs of all needed form fields
|
||||
$fields = array(
|
||||
'title' => array('value' => $instance['title']),
|
||||
'events_seek_type' => array('value' => $instance['events_seek_type']),
|
||||
'events_per_page' => array('value' => $instance['events_per_page']),
|
||||
'days_per_page' => array('value' => $instance['days_per_page']),
|
||||
'show_subscribe_buttons' => array('value' => $instance['show_subscribe_buttons']),
|
||||
'show_calendar_button' => array('value' => $instance['show_calendar_button']),
|
||||
'hide_on_calendar_page' => array('value' => $instance['hide_on_calendar_page']),
|
||||
'limit_by_cat' => array('value' => $instance['limit_by_cat']),
|
||||
'limit_by_tag' => array('value' => $instance['limit_by_tag']),
|
||||
'cat_ids' => array(
|
||||
'value' => (array)$instance['cat_ids'],
|
||||
'options' => $events_categories
|
||||
),
|
||||
'tag_ids' => array(
|
||||
'value' => (array)$instance['tag_ids'],
|
||||
'options' => $events_tags
|
||||
),
|
||||
);
|
||||
foreach ( $fields as $field => $data ) {
|
||||
$fields[$field]['id'] = $this->get_field_id( $field );
|
||||
$fields[$field]['name'] = $this->get_field_name( $field );
|
||||
$fields[$field]['value'] = $data['value'];
|
||||
if ( isset($data['options']) ) {
|
||||
$fields[$field]['options'] = $data['options'];
|
||||
}
|
||||
}
|
||||
|
||||
// Display theme
|
||||
$this->_registry->get( 'theme.loader' )->get_file(
|
||||
'agenda-widget-form.php',
|
||||
$fields,
|
||||
true
|
||||
)->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update function.
|
||||
*
|
||||
* Called when a user submits the widget configuration form.
|
||||
* The data should be validated and returned.
|
||||
*
|
||||
* @param array $new_instance The new data that was submitted.
|
||||
* @param array $old_instance The widget's old data.
|
||||
* @return array The new data to save for this widget instance.
|
||||
*/
|
||||
public function update( $new_instance, $old_instance ) {
|
||||
// Save existing data as a base to modify with new data
|
||||
$instance = $old_instance;
|
||||
$instance['title'] = strip_tags( $new_instance['title'] );
|
||||
$instance['events_per_page'] = Ai1ec_Primitive_Int::index(
|
||||
$new_instance['events_per_page'],
|
||||
1,
|
||||
1
|
||||
);
|
||||
$instance['days_per_page'] = Ai1ec_Primitive_Int::index(
|
||||
$new_instance['days_per_page'],
|
||||
1,
|
||||
1
|
||||
);
|
||||
$instance['events_seek_type'] = $this->_valid_seek_type(
|
||||
$new_instance['events_seek_type']
|
||||
);
|
||||
$instance['show_subscribe_buttons'] = isset( $new_instance['show_subscribe_buttons'] ) ? true : false;
|
||||
$instance['show_calendar_button'] = isset( $new_instance['show_calendar_button'] ) ? true : false;
|
||||
$instance['hide_on_calendar_page'] = isset( $new_instance['hide_on_calendar_page'] ) ? true : false;
|
||||
|
||||
// For limits, set the limit to False if no IDs were selected, or set the respective IDs to empty if "limit by" was unchecked
|
||||
$instance['limit_by_cat'] = false;
|
||||
$instance['cat_ids'] = array();
|
||||
if ( isset( $new_instance['cat_ids'] ) && $new_instance['cat_ids'] != false ) {
|
||||
$instance['limit_by_cat'] = true;
|
||||
}
|
||||
if ( isset( $new_instance['limit_by_cat'] ) && $new_instance['limit_by_cat'] != false ) {
|
||||
$instance['limit_by_cat'] = true;
|
||||
}
|
||||
if ( isset( $new_instance['cat_ids'] ) && $instance['limit_by_cat'] === true ) {
|
||||
$instance['cat_ids'] = $new_instance['cat_ids'];
|
||||
}
|
||||
|
||||
$instance['limit_by_tag'] = false;
|
||||
$instance['tag_ids'] = array();
|
||||
if ( isset( $new_instance['tag_ids'] ) && $new_instance['tag_ids'] != false ) {
|
||||
$instance['limit_by_tag'] = true;
|
||||
}
|
||||
if ( isset( $new_instance['limit_by_tag'] ) && $new_instance['limit_by_tag'] != false ) {
|
||||
$instance['limit_by_tag'] = true;
|
||||
}
|
||||
if ( isset( $new_instance['tag_ids'] ) && $instance['limit_by_tag'] === true ) {
|
||||
$instance['tag_ids'] = $new_instance['tag_ids'];
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::add_js()
|
||||
*/
|
||||
public function add_js() {
|
||||
$this->_registry->get( 'controller.javascript' )->add_link_to_render_js(
|
||||
Ai1ec_Javascript_Controller::LOAD_ONLY_FRONTEND_SCRIPTS,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::get_content()
|
||||
*/
|
||||
public function get_content( array $args_for_widget, $remote = false ) {
|
||||
$agenda = $this->_registry->get(
|
||||
'view.calendar.view.agenda',
|
||||
$this->_registry->get( 'http.request.parser' )
|
||||
);
|
||||
$time = $this->_registry->get( 'date.time' );
|
||||
$search = $this->_registry->get( 'model.search' );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$html = $this->_registry->get( 'factory.html' );
|
||||
|
||||
$is_calendar_page = is_page( $settings->get( 'calendar_page_id' ) );
|
||||
if ( $args_for_widget['hide_on_calendar_page'] &&
|
||||
$is_calendar_page ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add params to the subscribe_url for filtering by Limits (category, tag)
|
||||
$subscribe_filter = '';
|
||||
if ( ! is_array( $args_for_widget['cat_ids'] ) ) {
|
||||
$args_for_widget['cat_ids'] = explode( ',', $args_for_widget['cat_ids'] );
|
||||
}
|
||||
|
||||
if ( ! is_array( $args_for_widget['tag_ids'] ) ) {
|
||||
$args_for_widget['tag_ids'] = explode( ',', $args_for_widget['tag_ids'] );
|
||||
}
|
||||
$subscribe_filter .= $args_for_widget['cat_ids'] ? '&ai1ec_cat_ids=' . join( ',', $args_for_widget['cat_ids'] ) : '';
|
||||
$subscribe_filter .= $args_for_widget['tag_ids'] ? '&ai1ec_tag_ids=' . join( ',', $args_for_widget['tag_ids'] ) : '';
|
||||
|
||||
// Get localized time
|
||||
$timestamp = $time->format_to_gmt();
|
||||
|
||||
// Set $limit to the specified category/tag
|
||||
$limit = array(
|
||||
'cat_ids' => $args_for_widget['cat_ids'],
|
||||
'tag_ids' => $args_for_widget['tag_ids'],
|
||||
);
|
||||
$limit = apply_filters( 'ai1ec_add_filters_upcoming_widget', $limit );
|
||||
|
||||
// Get events, then classify into date array
|
||||
// JB: apply seek check here
|
||||
$seek_days = ( 'days' === $args_for_widget['events_seek_type'] );
|
||||
$seek_count = $args_for_widget['events_per_page'];
|
||||
$last_day = false;
|
||||
if ( $seek_days ) {
|
||||
$seek_count = $args_for_widget['days_per_page'] * 5;
|
||||
$last_day = strtotime(
|
||||
'+' . $args_for_widget['days_per_page'] . ' days'
|
||||
);
|
||||
}
|
||||
|
||||
$event_results = $search->get_events_relative_to(
|
||||
$timestamp,
|
||||
$seek_count,
|
||||
0,
|
||||
$limit
|
||||
);
|
||||
if ( $seek_days ) {
|
||||
foreach ( $event_results['events'] as $ek => $event ) {
|
||||
if ( $event->get( 'start' )->format() >= $last_day ) {
|
||||
unset( $event_results['events'][$ek] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dates = $agenda->get_agenda_like_date_array( $event_results['events'] );
|
||||
|
||||
|
||||
$args_for_widget['dates'] = $dates;
|
||||
// load CSS just once for all widgets.
|
||||
// Do not load it on the calendar page as it's already loaded.
|
||||
if ( false === $this->_css_loaded && ! $is_calendar_page ) {
|
||||
if ( true === $remote ) {
|
||||
$args_for_widget['css'] = $this->_registry->get( 'css.frontend' )->get_compiled_css();
|
||||
}
|
||||
$this->_css_loaded = true;
|
||||
}
|
||||
$args_for_widget['show_location_in_title'] = $settings->get( 'show_location_in_title' );
|
||||
$args_for_widget['show_year_in_agenda_dates'] = $settings->get( 'show_year_in_agenda_dates' );
|
||||
$args_for_widget['calendar_url'] = $html->create_href_helper_instance( $limit )->generate_href();
|
||||
$args_for_widget['subscribe_url'] = AI1EC_EXPORT_URL . $subscribe_filter;
|
||||
$args_for_widget['subscribe_url_no_html'] = AI1EC_EXPORT_URL . '&no_html=true' . $subscribe_filter;
|
||||
$args_for_widget['text_upcoming_events'] = __( 'There are no upcoming events.', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['text_all_day'] = __( 'all-day', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['text_view_calendar'] = __( 'View Calendar', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['text_edit'] = __( 'Edit', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['text_venue_separator'] = __( '@ %s', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['text_subscribe_label'] = __( 'Add', AI1EC_PLUGIN_NAME );
|
||||
$args_for_widget['subscribe_buttons_text'] = $this->_registry
|
||||
->get( 'view.calendar.subscribe-button' )
|
||||
->get_labels();
|
||||
// Display theme
|
||||
return $this->_registry->get( 'theme.loader' )->get_file(
|
||||
'agenda-widget.twig',
|
||||
$args_for_widget
|
||||
)->get_content();
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::get_js_widget_configurable_defaults()
|
||||
*/
|
||||
public function get_js_widget_configurable_defaults() {
|
||||
$def = $this->get_defaults();
|
||||
unset( $def['title'] );
|
||||
unset( $def['link_for_days'] );
|
||||
return $def;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::javascript_widget()
|
||||
*/
|
||||
public function javascript_widget( $args ) {
|
||||
$args['show_calendar_button'] = false;
|
||||
$args['link_for_days'] = false;
|
||||
return parent::javascript_widget( $args );
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_Embeddable::check_requirements()
|
||||
*/
|
||||
public function check_requirements() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* _valid_seek_type method.
|
||||
*
|
||||
* Return valid seek type for given user input (selection).
|
||||
*
|
||||
* @param string $value User selection for seek type
|
||||
* @return string Seek type to use
|
||||
*/
|
||||
protected function _valid_seek_type( $value ) {
|
||||
static $list = array( 'events', 'days' );
|
||||
if ( ! in_array( $value, $list ) ) {
|
||||
return (string)reset( $list );
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user