Files
wordpress-preseed/wp-content/plugins/all-in-one-event-calendar/app/view/calendar/view/week.php
Adrian Nöthlich 290736650a Add upstream plugins
Signed-off-by: Adrian Nöthlich <git@promasu.tech>
2019-10-25 22:42:20 +02:00

514 lines
22 KiB
PHP

<?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;
}
}