@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The abstract class for a admin page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
abstract class Ai1ec_View_Admin_Abstract extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_page_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_page_suffix;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_api_registration;
|
||||
|
||||
/**
|
||||
* Standard constructor
|
||||
*
|
||||
* @param Ai1ec_Registry_Object $registry
|
||||
*/
|
||||
public function __construct( Ai1ec_Registry_Object $registry ) {
|
||||
parent::__construct( $registry );
|
||||
$exploded_class = explode( '_', get_class( $this ) );
|
||||
$this->_page_suffix = strtolower( end( $exploded_class ) );
|
||||
$this->_api_registration = $this->_registry->get( 'model.api.api-registration' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url of the page
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_url() {
|
||||
return add_query_arg(
|
||||
array(
|
||||
'post_type' => AI1EC_POST_TYPE,
|
||||
'page' => AI1EC_PLUGIN_NAME . '-' . $this->_page_suffix,
|
||||
),
|
||||
ai1ec_admin_url( 'edit.php' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the page to the correct menu.
|
||||
*/
|
||||
abstract public function add_page();
|
||||
|
||||
/**
|
||||
* Adds the page to the correct menu.
|
||||
*/
|
||||
abstract public function add_meta_box();
|
||||
|
||||
/**
|
||||
* Display the page html
|
||||
*/
|
||||
abstract public function display_page();
|
||||
|
||||
/**
|
||||
* Handle post, likely to be deprecated to use commands.
|
||||
*/
|
||||
abstract public function handle_post();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,576 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Event create/update form backend view layer.
|
||||
*
|
||||
* Manage creation of boxes (containers) for our control elements
|
||||
* and instantiating, as well as updating them.
|
||||
*
|
||||
* @author Time.ly Network, Inc.
|
||||
* @since 2.0
|
||||
* @package Ai1EC
|
||||
* @subpackage Ai1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Add_New_Event extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Create hook to display event meta box when creating or editing an event.
|
||||
*
|
||||
* @wp_hook add_meta_boxes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function event_meta_box_container() {
|
||||
add_meta_box(
|
||||
AI1EC_POST_TYPE,
|
||||
Ai1ec_I18n::__( 'Event Details' ),
|
||||
array( $this, 'meta_box_view' ),
|
||||
AI1EC_POST_TYPE,
|
||||
'normal',
|
||||
'high'
|
||||
);
|
||||
|
||||
add_meta_box(
|
||||
AI1EC_POST_TYPE . '_features',
|
||||
Ai1ec_I18n::__( 'Empower your calendar, build your community' ),
|
||||
array( $this, 'features_info' ),
|
||||
AI1EC_POST_TYPE,
|
||||
'side',
|
||||
'low'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Event Details meta box to the Add/Edit Event screen in the dashboard.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function features_info( $post ) {
|
||||
$message = __(
|
||||
'<ul class="ai1ec-features-list"><li><a href="https://time.ly/hub" target="_blank">Pull events from other calendars</a></li><li><a href="https://time.ly/hub" target="_blank">Pull events from Facebook</a></li><li><a href="https://time.ly/hub" target="_blank">Add a Newsletter</a></li><li><a href="https://time.ly/hub" target="_blank">Get public event submissions</a></li><li><a href="https://time.ly/hub" target="_blank">Charge people to post events</a></li><li><a href="https://time.ly/hub" target="_blank">Add social sharing</a></li><li><a href="https://time.ly/hub" target="_blank">And more</a></li></ul>',
|
||||
AI1EC_PLUGIN_NAME
|
||||
);
|
||||
|
||||
echo $message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add Event Details meta box to the Add/Edit Event screen in the dashboard.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function meta_box_view( $post ) {
|
||||
|
||||
$theme_loader = $this->_registry->get( 'theme.loader' );
|
||||
$empty_event = $this->_registry->get( 'model.event' );
|
||||
|
||||
// ==================
|
||||
// = Default values =
|
||||
// ==================
|
||||
// ATTENTION - When adding new fields to the event remember that you must
|
||||
// also set up the duplicate-controller.
|
||||
// TODO: Fix this duplication.
|
||||
$all_day_event = '';
|
||||
$instant_event = '';
|
||||
$start = $this->_registry->get( 'date.time' );
|
||||
$end = $this->_registry->get( 'date.time', '+1 hour' );
|
||||
$timezone_name = null;
|
||||
$timezones_list = $this->_registry->get( 'date.timezone' )->get_timezones( true );
|
||||
$show_map = false;
|
||||
$google_map = '';
|
||||
$venue = '';
|
||||
$country = '';
|
||||
$address = '';
|
||||
$city = '';
|
||||
$province = '';
|
||||
$postal_code = '';
|
||||
$contact_name = '';
|
||||
$contact_phone = '';
|
||||
$contact_email = '';
|
||||
$contact_url = '';
|
||||
$cost = '';
|
||||
$is_free = '';
|
||||
$cost_type = 'free';
|
||||
$rrule = '';
|
||||
$rrule_text = '';
|
||||
$repeating_event = false;
|
||||
$exrule = '';
|
||||
$exrule_text = '';
|
||||
$exclude_event = false;
|
||||
$exdate = '';
|
||||
$show_coordinates = false;
|
||||
$longitude = '';
|
||||
$latitude = '';
|
||||
$coordinates = '';
|
||||
$ticket_url = '';
|
||||
|
||||
$instance_id = false;
|
||||
if ( isset( $_REQUEST['instance'] ) ) {
|
||||
$instance_id = absint( $_REQUEST['instance'] );
|
||||
}
|
||||
if ( $instance_id ) {
|
||||
add_filter(
|
||||
'print_scripts_array',
|
||||
array( $this, 'disable_autosave' )
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// on some php version, nested try catch blocks fail and the exception would never be caught.
|
||||
// this is why we use this approach.
|
||||
$excpt = null;
|
||||
$event = null;
|
||||
try {
|
||||
$event = $this->_registry->get(
|
||||
'model.event',
|
||||
get_the_ID(),
|
||||
$instance_id
|
||||
);
|
||||
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
||||
$ai1ec_localization_helper = $this->_registry
|
||||
->get( 'p28n.wpml' );
|
||||
$translatable_id = $ai1ec_localization_helper
|
||||
->get_translatable_id();
|
||||
if ( false !== $translatable_id ) {
|
||||
$event = $this->_registry->get(
|
||||
'model.event',
|
||||
$translatable_id,
|
||||
$instance_id
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( null !== $excpt ) {
|
||||
throw $excpt;
|
||||
}
|
||||
|
||||
// Existing event was found. Initialize form values with values from
|
||||
// event object.
|
||||
$all_day_event = $event->is_allday() ? 'checked' : '';
|
||||
$instant_event = $event->is_instant() ? 'checked' : '';
|
||||
|
||||
$start = $event->get( 'start' );
|
||||
$end = $event->get( 'end' );
|
||||
$timezone_name = $event->get( 'timezone_name' );
|
||||
|
||||
$multi_day = $event->is_multiday();
|
||||
|
||||
$show_map = $event->get( 'show_map' );
|
||||
$google_map = $show_map ? 'checked="checked"' : '';
|
||||
|
||||
$show_coordinates = $event->get( 'show_coordinates' );
|
||||
$coordinates = $show_coordinates ? 'checked="checked"' : '';
|
||||
$longitude = (float)$event->get( 'longitude', 0 );
|
||||
$latitude = (float)$event->get( 'latitude', 0 );
|
||||
// There is a known bug in Wordpress (https://core.trac.wordpress.org/ticket/15158) that saves 0 to the DB instead of null.
|
||||
// We handle a special case here to avoid having the fields with a value of 0 when the user never inputted any coordinates
|
||||
if ( ! $show_coordinates ) {
|
||||
$longitude = '';
|
||||
$latitude = '';
|
||||
}
|
||||
|
||||
$venue = $event->get( 'venue' );
|
||||
$country = $event->get( 'country' );
|
||||
$address = $event->get( 'address' );
|
||||
$city = $event->get( 'city' );
|
||||
$province = $event->get( 'province' );
|
||||
$postal_code = $event->get( 'postal_code' );
|
||||
$contact_name = $event->get( 'contact_name' );
|
||||
$contact_phone = $event->get( 'contact_phone' );
|
||||
$contact_email = $event->get( 'contact_email' );
|
||||
$contact_url = $event->get( 'contact_url' );
|
||||
$cost = $event->get( 'cost' );
|
||||
$ticket_url = $event->get( 'ticket_url' );
|
||||
$rrule = $event->get( 'recurrence_rules' );
|
||||
$exrule = $event->get( 'exception_rules' );
|
||||
$exdate = $event->get( 'exception_dates' );
|
||||
$repeating_event = ! empty( $rrule );
|
||||
$exclude_event = ! empty( $exrule );
|
||||
|
||||
$is_free = '';
|
||||
$free = $event->is_free();
|
||||
if ( ! empty( $free ) ) {
|
||||
$is_free = 'checked="checked" ';
|
||||
$cost = '';
|
||||
}
|
||||
|
||||
if ( $repeating_event ) {
|
||||
$rrule_text = ucfirst(
|
||||
$this->_registry->get( 'recurrence.rule' )
|
||||
->rrule_to_text( $rrule )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $exclude_event ) {
|
||||
$exrule_text = ucfirst(
|
||||
$this->_registry->get( 'recurrence.rule' )
|
||||
->rrule_to_text( $exrule )
|
||||
);
|
||||
}
|
||||
} catch ( Ai1ec_Event_Not_Found_Exception $excpt ) {
|
||||
// Event does not exist.
|
||||
// Leave form fields undefined (= zero-length strings)
|
||||
$event = null;
|
||||
}
|
||||
|
||||
// Time zone; display if set.
|
||||
$timezone = '';
|
||||
$timezone_string = null;
|
||||
$date_timezone = $this->_registry->get( 'date.timezone' );
|
||||
|
||||
if (
|
||||
! empty( $timezone_name ) &&
|
||||
$local_name = $date_timezone->get_name( $timezone_name )
|
||||
) {
|
||||
$timezone_string = $local_name;
|
||||
}
|
||||
if ( null === $timezone_string ) {
|
||||
$timezone_string = $date_timezone->get_default_timezone();
|
||||
}
|
||||
|
||||
if ( $timezone_string ) {
|
||||
$timezone = $this->_registry->get( 'date.system' )
|
||||
->get_gmt_offset_expr( $timezone_string );
|
||||
}
|
||||
|
||||
if ( empty( $timezone_name ) ) {
|
||||
/**
|
||||
* Actual Olsen timezone name is used when value is to be directly
|
||||
* exposed to user in some mean. It's possible to use named const.
|
||||
* `'sys.default'` only when passing value to date.time library.
|
||||
*/
|
||||
$timezone_name = $date_timezone->get_default_timezone();
|
||||
}
|
||||
|
||||
// This will store each of the accordion tabs' markup, and passed as an
|
||||
// argument to the final view.
|
||||
$boxes = array();
|
||||
$parent_event_id = null;
|
||||
if ( $event ) {
|
||||
$parent_event_id = $this->_registry->get( 'model.event.parent' )
|
||||
->event_parent( $event->get( 'post_id' ) );
|
||||
}
|
||||
// ===============================
|
||||
// = Display event time and date =
|
||||
// ===============================
|
||||
$args = array(
|
||||
'all_day_event' => $all_day_event,
|
||||
'instant_event' => $instant_event,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'repeating_event' => $repeating_event,
|
||||
'rrule' => $rrule,
|
||||
'rrule_text' => $rrule_text,
|
||||
'exclude_event' => $exclude_event,
|
||||
'exrule' => $exrule,
|
||||
'exrule_text' => $exrule_text,
|
||||
'timezone' => $timezone,
|
||||
'timezone_string' => $timezone_string,
|
||||
'timezone_name' => $timezone_name,
|
||||
'exdate' => $exdate,
|
||||
'parent_event_id' => $parent_event_id,
|
||||
'instance_id' => $instance_id,
|
||||
'timezones_list' => $timezones_list,
|
||||
);
|
||||
|
||||
$boxes[] = $theme_loader
|
||||
->get_file( 'box_time_and_date.php', $args, true )
|
||||
->get_content();
|
||||
|
||||
// =================================================
|
||||
// = Display event location details and Google map =
|
||||
// =================================================
|
||||
$args = array(
|
||||
'select_venue' => apply_filters( 'ai1ec_admin_pre_venue_html', '' ),
|
||||
'save_venue' => apply_filters( 'ai1ec_admin_post_venue_html', '' ),
|
||||
'venue' => $venue,
|
||||
'country' => $country,
|
||||
'address' => $address,
|
||||
'city' => $city,
|
||||
'province' => $province,
|
||||
'postal_code' => $postal_code,
|
||||
'google_map' => $google_map,
|
||||
'show_map' => $show_map,
|
||||
'show_coordinates' => $show_coordinates,
|
||||
'longitude' => $longitude,
|
||||
'latitude' => $latitude,
|
||||
'coordinates' => $coordinates,
|
||||
);
|
||||
$boxes[] = $theme_loader
|
||||
->get_file( 'box_event_location.php', $args, true )
|
||||
->get_content();
|
||||
|
||||
// ===================================
|
||||
// = Display event ticketing options =
|
||||
// ===================================
|
||||
if ( $event ) {
|
||||
$cost_type = get_post_meta(
|
||||
$event->get( 'post_id' ),
|
||||
'_ai1ec_cost_type',
|
||||
true
|
||||
);
|
||||
if ( ! $cost_type ) {
|
||||
if ( $ticket_url || $cost ) {
|
||||
$cost_type = 'external';
|
||||
} else {
|
||||
$cost_type = 'free';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
$api_reg = $this->_registry->get( 'model.api.api-registration' );
|
||||
$ticketing = $api_reg->is_signed() && $api_reg->is_ticket_available() && $api_reg->is_ticket_enabled();
|
||||
$message = $api->get_sign_message();
|
||||
$ticket_error = null;
|
||||
$ticket_event_imported = false;
|
||||
$tickets = array( null );
|
||||
$tax_options = null;
|
||||
|
||||
if ( ! $api_reg->is_ticket_available() ) {
|
||||
$message = __(
|
||||
'Ticketing is currently not available for this website. Please, try again later.',
|
||||
AI1EC_PLUGIN_NAME
|
||||
);
|
||||
} else if ( ! $api_reg->is_ticket_enabled() ) {
|
||||
$message = __(
|
||||
'Timely Ticketing saves time & money. Create ticketing/registration right here and now. You do not pay any ticketing fees (other than regular PayPal transaction costs). Create as many ticketing/registration as you\'d like.<br /><br />Ticketing feature is not enabled for this website. Please sign up for Ticketing plan <a href="https://time.ly/tickets-existing-users/" target="_blank">here</a>.',
|
||||
AI1EC_PLUGIN_NAME
|
||||
);
|
||||
}
|
||||
|
||||
if ( $event ) {
|
||||
$is_ticket_event = ! is_null( $api->get_api_event_id( $event->get( 'post_id' ) ) );
|
||||
$ticket_event_account = $api->get_api_event_account( $event->get( 'post_id' ) );
|
||||
$ticket_event_imported = $api->is_ticket_event_imported( $event->get( 'post_id' ) );
|
||||
if ( $ticketing || $ticket_event_imported ) {
|
||||
if ( 'tickets' === $cost_type ) {
|
||||
if ( $ticket_event_imported ) {
|
||||
$response = json_decode( $api->get_ticket_types( $event->get( 'post_id' ) ) );
|
||||
if ( isset( $response->data ) && 0 < count( $response->data ) ) {
|
||||
$tickets = array_merge( $tickets, $response->data );
|
||||
}
|
||||
if ( isset( $response->error ) ) {
|
||||
$ticket_error = $response->error;
|
||||
}
|
||||
} else {
|
||||
$response = $api->get_event( $event->get( 'post_id' ) );
|
||||
if ( isset( $response->data ) && 0 < count( $response->data ) ) {
|
||||
$tickets = array_merge( $tickets, $response->data->ticket_types );
|
||||
$tax_options = $response->data->tax_options;
|
||||
}
|
||||
if ( isset( $response->error ) ) {
|
||||
$ticket_error = $response->error;
|
||||
}
|
||||
}
|
||||
}
|
||||
$uid = $event->get_uid();
|
||||
} else {
|
||||
$uid = $empty_event->get_uid();
|
||||
}
|
||||
$uid = $event->get_uid();
|
||||
} else {
|
||||
$is_ticket_event = false;
|
||||
$ticket_event_account = '';
|
||||
$uid = $empty_event->get_uid();
|
||||
}
|
||||
|
||||
if ( $ticketing ) {
|
||||
if ( $event ) {
|
||||
$ticket_currency = $api->get_api_event_currency( $event->get( 'post_id' ) );
|
||||
if ( $api->is_ticket_event_from_another_account( $event->get( 'post_id' ) ) ) {
|
||||
$ticket_error = sprintf(
|
||||
__( 'This Event was created using a different account %s. Changes are not allowed.', AI1EC_PLUGIN_NAME ),
|
||||
$api->get_api_event_account( $event->get( 'post_id' ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
if ( ! isset( $ticket_currency ) || is_null( $ticket_currency ) ) {
|
||||
//for new ticket events get the currency from the payments settings
|
||||
$payments_settings = $api->get_payment_settings();
|
||||
if ( null !== $payments_settings ) {
|
||||
$ticket_currency = $payments_settings['currency'];
|
||||
} else {
|
||||
$ticket_currency = 'USD';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ticket_currency = '';
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'cost' => $cost,
|
||||
'cost_type' => $cost_type,
|
||||
'ticket_url' => $ticket_url,
|
||||
'event' => $empty_event,
|
||||
'uid' => $uid,
|
||||
'tickets' => $tickets,
|
||||
'ticketing' => $ticketing,
|
||||
'valid_payout_details' => $api->has_payment_settings(),
|
||||
'tickets_message' => $message,
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
'tickets_loading_error' => $ticket_error,
|
||||
'ticket_event_imported' => $ticket_event_imported,
|
||||
'is_free' => $is_free,
|
||||
'ticket_currency' => $ticket_currency,
|
||||
'is_ticket_event' => $is_ticket_event,
|
||||
'ticket_event_account' => $ticket_event_account,
|
||||
'tax_options' => $tax_options
|
||||
);
|
||||
|
||||
$boxes[] = $theme_loader
|
||||
->get_file( 'box_event_cost.php', $args, true )
|
||||
->get_content();
|
||||
|
||||
|
||||
|
||||
// =========================================
|
||||
// = Display organizer contact information =
|
||||
// =========================================
|
||||
$submitter_html = null;
|
||||
if ( $event ) {
|
||||
$submitter_info = $event->get_submitter_info();
|
||||
if ( null !== $submitter_info ) {
|
||||
if ( 1 === $submitter_info['is_organizer'] ) {
|
||||
$submitter_html = Ai1ec_I18n::__( '<span class="ai1ec-info-text">The event was submitted by this Organizer.</span>' );
|
||||
} else if ( isset( $submitter_info['email'] ) ||
|
||||
isset( $submitter_info['name'] ) ) {
|
||||
$submitted_by = '';
|
||||
if ( false === ai1ec_is_blank ( $submitter_info['name'] ) ) {
|
||||
$submitted_by = sprintf( '<strong>%s</strong>', htmlspecialchars( $submitter_info['name'] ) );
|
||||
}
|
||||
if ( false === ai1ec_is_blank( $submitter_info['email'] ) ) {
|
||||
if ( '' !== $submitted_by ) {
|
||||
$submitted_by .= Ai1ec_I18n::__( ', email: ' );
|
||||
}
|
||||
$submitted_by .= sprintf( '<a href="mailto:%s" target="_top">%s</a>', $submitter_info['email'], $submitter_info['email'] ) ;
|
||||
}
|
||||
$submitter_html = sprintf( Ai1ec_I18n::__( '<span class="ai1ec-info-text">The event was submitted by %s.</span>' ),
|
||||
$submitted_by
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$args = array(
|
||||
'contact_name' => $contact_name,
|
||||
'contact_phone' => $contact_phone,
|
||||
'contact_email' => $contact_email,
|
||||
'contact_url' => $contact_url,
|
||||
'event' => $empty_event,
|
||||
'submitter_html' => $submitter_html
|
||||
);
|
||||
$boxes[] = $theme_loader
|
||||
->get_file( 'box_event_contact.php', $args, true )
|
||||
->get_content();
|
||||
|
||||
// ==========================
|
||||
// = Parent/Child relations =
|
||||
// ==========================
|
||||
if ( $event ) {
|
||||
$parent = $this->_registry->get( 'model.event.parent' )
|
||||
->get_parent_event( $event->get( 'post_id' ) );
|
||||
if ( $parent ) {
|
||||
try {
|
||||
$parent = $this->_registry->get( 'model.event', $parent );
|
||||
} catch ( Ai1ec_Event_Not_Found_Exception $exception ) { // ignore
|
||||
$parent = null;
|
||||
}
|
||||
}
|
||||
if ( $parent ) {
|
||||
$children = $this->_registry->get( 'model.event.parent' )
|
||||
->get_child_event_objects( $event->get( 'post_id' ) );
|
||||
$args = compact( 'parent', 'children' );
|
||||
$args['registry'] = $this->_registry;
|
||||
|
||||
$boxes[] = $theme_loader->get_file(
|
||||
'box_event_children.php',
|
||||
$args,
|
||||
true
|
||||
)->get_content();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$boxes = apply_filters( 'ai1ec_add_new_event_boxes', $boxes, $event );
|
||||
// Display the final view of the meta box.
|
||||
$args = array(
|
||||
'boxes' => $boxes,
|
||||
);
|
||||
|
||||
if ( $this->_is_post_event( $post ) ) {
|
||||
// ======================
|
||||
// = Display Box Review =
|
||||
// ======================
|
||||
$review = $this->_registry->get( 'model.review' );
|
||||
$review_content = $review->get_content( $theme_loader );
|
||||
|
||||
if ( false === ai1ec_is_blank( $review_content ) ) {
|
||||
$args['review_box'] = $review_content;
|
||||
}
|
||||
}
|
||||
|
||||
echo $theme_loader
|
||||
->get_file( 'add_new_event_meta_box.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Banner Image meta box to the Add/Edit Event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function banner_meta_box_view( $post ) {
|
||||
$banner_image_meta = get_post_meta( $post->ID, 'ai1ec_banner_image' );
|
||||
$theme_loader = $this->_registry->get( 'theme.loader' );
|
||||
$args = array(
|
||||
'src' => $banner_image_meta && $banner_image_meta[0]
|
||||
? $banner_image_meta[0] : false,
|
||||
'set_text' => Ai1ec_I18n::__( 'Set banner image' ),
|
||||
'remove_text' => Ai1ec_I18n::__( 'Remove banner image' ),
|
||||
|
||||
);
|
||||
echo $theme_loader
|
||||
->get_file( 'banner-image.twig', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_autosave method
|
||||
*
|
||||
* Callback to disable autosave script
|
||||
*
|
||||
* @param array $input List of scripts registered
|
||||
*
|
||||
* @return array Modified scripts list
|
||||
*/
|
||||
public function disable_autosave( array $input ) {
|
||||
wp_deregister_script( 'autosave' );
|
||||
$autosave_key = array_search( 'autosave', $input );
|
||||
if ( false === $autosave_key || ! is_scalar( $autosave_key ) ) {
|
||||
unset( $input[$autosave_key] );
|
||||
}
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders Bootstrap inline alert.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function event_inline_alert( $post ) {
|
||||
if ( $this->_is_post_event( $post ) ) {
|
||||
$theme_loader = $this->_registry->get( 'theme.loader' );
|
||||
echo $theme_loader->get_file( 'box_inline_warning.php', null, true )
|
||||
->get_content();
|
||||
}
|
||||
}
|
||||
|
||||
private function _is_post_event( $post ) {
|
||||
return isset( $post->post_type ) && AI1EC_POST_TYPE === $post->post_type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Calendar Add-ons page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.1
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Add_Ons extends Ai1ec_View_Admin_Abstract {
|
||||
/**
|
||||
* Adds page to the menu.
|
||||
*
|
||||
* @wp_hook admin_menu
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_page() {
|
||||
// =======================
|
||||
// = Calendar Add Ons Page =
|
||||
// =======================
|
||||
add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
Ai1ec_I18n::__( 'Add-ons' ),
|
||||
Ai1ec_I18n::__( 'Add-ons' ),
|
||||
'manage_ai1ec_feeds',
|
||||
AI1EC_PLUGIN_NAME . '-add-ons',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Display Add Ons list page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_page() {
|
||||
wp_enqueue_style(
|
||||
'ai1ec_addons.css',
|
||||
AI1EC_ADMIN_THEME_CSS_URL . 'addons.css',
|
||||
array(),
|
||||
AI1EC_VERSION
|
||||
);
|
||||
$content = get_site_transient( 'ai1ec_timely_addons' );
|
||||
$is_error = false;
|
||||
if (
|
||||
false === $content ||
|
||||
(
|
||||
defined( 'AI1EC_DEBUG' ) &&
|
||||
AI1EC_DEBUG
|
||||
)
|
||||
) {
|
||||
$is_error = true;
|
||||
$feed = wp_remote_get( AI1EC_TIMELY_ADDONS_URI );
|
||||
if ( ! is_wp_error( $feed ) ) {
|
||||
$content = json_decode( wp_remote_retrieve_body( $feed ) );
|
||||
if ( null !== $content ) {
|
||||
set_site_transient( 'ai1ec_timely_addons', $content, 3600 );
|
||||
$is_error = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_registry->get( 'theme.loader' )->get_file(
|
||||
'add-ons-list/page.twig',
|
||||
array(
|
||||
'labels' => array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Add-ons for All In One Event Calendar'
|
||||
),
|
||||
'button_title' => Ai1ec_I18n::__(
|
||||
'Browse All Add-ons'
|
||||
),
|
||||
'paragraph_content' => Ai1ec_I18n::__(
|
||||
'These add-ons extend the functionality of the All-in-One Event Calendar.'
|
||||
),
|
||||
'error' => Ai1ec_I18n::__(
|
||||
'There was an error retrieving the extensions list from the server. Please try again later.'
|
||||
),
|
||||
),
|
||||
'content' => $content,
|
||||
'is_error' => $is_error,
|
||||
),
|
||||
true
|
||||
)->render();
|
||||
}
|
||||
|
||||
public function add_meta_box() {
|
||||
}
|
||||
|
||||
public function display_meta_box( $object, $box ) {
|
||||
}
|
||||
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
class Ai1ec_View_Admin_All_Events extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* change_columns function
|
||||
*
|
||||
* Adds Event date/time column to our custom post type
|
||||
* and renames Date column to Post Date
|
||||
*
|
||||
* @param array $columns Existing columns
|
||||
*
|
||||
* @return array Updated columns array
|
||||
*/
|
||||
public function change_columns( array $columns = array() ) {
|
||||
$columns['author'] = __( 'Author', AI1EC_PLUGIN_NAME );
|
||||
$columns['date'] = __( 'Post Date', AI1EC_PLUGIN_NAME );
|
||||
$columns['ai1ec_event_date'] = __( 'Event date/time', AI1EC_PLUGIN_NAME );
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
if ( $api->is_signed() ) {
|
||||
$columns['tickets'] = __( 'Ticket Types', AI1EC_PLUGIN_NAME );
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* orderby function
|
||||
*
|
||||
* Orders events by event date
|
||||
*
|
||||
* @param string $orderby Orderby sql
|
||||
* @param object $wp_query
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function orderby( $orderby, $wp_query ) {
|
||||
|
||||
$db = $this->_registry->get( 'dbi.dbi' );
|
||||
$aco = $this->_registry->get( 'acl.aco' );
|
||||
|
||||
if( true === $aco->is_all_events_page() ) {
|
||||
$wp_query->query = wp_parse_args( $wp_query->query );
|
||||
$table_name = $db->get_table_name( 'ai1ec_events' );
|
||||
$posts = $db->get_table_name( 'posts' );
|
||||
if( isset( $wp_query->query['orderby'] ) && 'ai1ec_event_date' === @$wp_query->query['orderby'] ) {
|
||||
$orderby = "(SELECT start FROM {$table_name} WHERE post_id = {$posts}.ID) " . $wp_query->get('order');
|
||||
} else if( empty( $wp_query->query['orderby'] ) || $wp_query->query['orderby'] === 'menu_order title' ) {
|
||||
$orderby = "(SELECT start FROM {$table_name} WHERE post_id = {$posts}.ID) " . 'desc';
|
||||
}
|
||||
}
|
||||
return $orderby;
|
||||
}
|
||||
|
||||
/**
|
||||
* custom_columns function
|
||||
*
|
||||
* Adds content for custom columns
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function custom_columns( $column, $post_id ) {
|
||||
if ( 'ai1ec_event_date' === $column ) {
|
||||
try {
|
||||
$event = $this->_registry->get( 'model.event', $post_id );
|
||||
$time = $this->_registry->get( 'view.event.time' );
|
||||
echo $time->get_timespan_html( $event );
|
||||
} catch ( Exception $e ) {
|
||||
// event wasn't found, output empty string
|
||||
echo '';
|
||||
}
|
||||
} else if ( 'tickets' === $column ) {
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
if ( $api->is_ticket_event_imported( $post_id ) ) {
|
||||
echo '';
|
||||
} else {
|
||||
try {
|
||||
$event = $this->_registry->get( 'model.event', $post_id );
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
$api_event_id = $api->get_api_event_id( $post_id );
|
||||
if ( $api_event_id ) {
|
||||
echo '<a href="#" class="ai1ec-has-tickets" data-post-id="'
|
||||
. $post_id . '">'
|
||||
. __( 'Ticketing Details', AI1EC_PLUGIN_NAME ) . '</a>';
|
||||
}
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
// event wasn't found, output empty string
|
||||
echo '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sortable_columns function
|
||||
*
|
||||
* Enable sorting of columns
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function sortable_columns( $columns ) {
|
||||
$columns['ai1ec_event_date'] = 'ai1ec_event_date';
|
||||
$columns['author'] = 'author';
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* taxonomy_filter_restrict_manage_posts function
|
||||
*
|
||||
* Adds filter dropdowns for event categories and event tags.
|
||||
* Adds filter dropdowns for event authors.
|
||||
*
|
||||
* @uses wp_dropdown_users To create a dropdown with current user selected.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function taxonomy_filter_restrict_manage_posts() {
|
||||
global $typenow;
|
||||
|
||||
// =============================================
|
||||
// = add the dropdowns only on the events page =
|
||||
// =============================================
|
||||
if( $typenow === AI1EC_POST_TYPE ) {
|
||||
$filters = get_object_taxonomies( $typenow );
|
||||
foreach( $filters as $tax_slug ) {
|
||||
$tax_obj = get_taxonomy( $tax_slug );
|
||||
wp_dropdown_categories( array(
|
||||
'show_option_all' => __( 'Show All ', AI1EC_PLUGIN_NAME ) . $tax_obj->label,
|
||||
'taxonomy' => $tax_slug,
|
||||
'name' => $tax_obj->name,
|
||||
'orderby' => 'name',
|
||||
'selected' => isset( $_GET[$tax_slug] ) ? $_GET[$tax_slug] : '',
|
||||
'hierarchical' => $tax_obj->hierarchical,
|
||||
'show_count' => true,
|
||||
'hide_if_empty' => true,
|
||||
'value_field' => 'slug',
|
||||
));
|
||||
}
|
||||
$args = array(
|
||||
'name' => 'author',
|
||||
'show_option_all' => __( 'Show All Authors', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
if ( isset( $_GET['user'] ) ) {
|
||||
$args['selected'] = (int)$_GET['user'];
|
||||
}
|
||||
wp_dropdown_users($args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* taxonomy_filter_post_type_request function
|
||||
*
|
||||
* Adds filtering of events list by event tags and event categories
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function taxonomy_filter_post_type_request( $query ) {
|
||||
global $pagenow, $typenow;
|
||||
if( 'edit.php' === $pagenow ) {
|
||||
$filters = get_object_taxonomies( $typenow );
|
||||
foreach( $filters as $tax_slug ) {
|
||||
$var = &$query->query_vars[$tax_slug];
|
||||
if( isset( $var ) ) {
|
||||
$term = null;
|
||||
|
||||
if( is_numeric( $var ) ) {
|
||||
$term = get_term_by( 'id', $var, $tax_slug );
|
||||
} else {
|
||||
$term = get_term_by( 'slug', $var, $tax_slug );
|
||||
}
|
||||
|
||||
if( isset( $term->slug ) ) {
|
||||
$var = $term->slug;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ===========================
|
||||
// = Order by Event date ASC =
|
||||
// ===========================
|
||||
if( 'ai1ec_event' === $typenow ) {
|
||||
if ( ! array_key_exists( 'orderby', $query->query_vars ) ) {
|
||||
$query->query_vars['orderby'] = 'ai1ec_event_date';
|
||||
$query->query_vars['order'] = 'desc';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS and templates files needed for ticketing.
|
||||
*/
|
||||
public function add_ticketing_styling() {
|
||||
// Add CSS
|
||||
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
||||
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
||||
);
|
||||
$this->_registry->get( 'css.admin' )->process_enqueue(
|
||||
array(
|
||||
array( 'style', 'ticketing.css', ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ticket details by Event id.
|
||||
*/
|
||||
public function show_ticket_details() {
|
||||
$post_id = $_POST['ai1ec_event_id'];
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
if ( $api->is_ticket_event_from_another_account( $post_id ) ) {
|
||||
$tickets = json_encode(
|
||||
array( 'data' => array(), 'error' =>
|
||||
sprintf(
|
||||
__( 'This Event was created using a different account %s. Changes are not allowed.', AI1EC_PLUGIN_NAME ),
|
||||
$api->get_api_event_account( $post_id )
|
||||
)
|
||||
) );
|
||||
} else {
|
||||
$tickets = $api->get_ticket_types( $post_id );
|
||||
}
|
||||
echo $tickets;
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attendees list.
|
||||
*/
|
||||
public function show_attendees() {
|
||||
$post_id = $_POST['ai1ec_event_id'];
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
$tickets = $api->get_tickets( $post_id );
|
||||
echo $tickets;
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* count_future_events function
|
||||
*
|
||||
* @return Count future events
|
||||
**/
|
||||
public function count_future_events( $user_id = null ) {
|
||||
if ( is_admin() ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$current_time = $this->_registry->get( 'date.time' );
|
||||
$current_time->set_timezone( $settings->get( 'timezone_string' ) );
|
||||
$current_time = $current_time->format_to_gmt();
|
||||
$user_id = get_current_user_id();
|
||||
$where = get_posts_by_author_sql( AI1EC_POST_TYPE, true, $user_id );
|
||||
$db = $this->_registry->get( 'dbi.dbi' );
|
||||
$posts = $db->get_table_name( 'posts' );
|
||||
$table_name = $db->get_table_name( 'ai1ec_events' );
|
||||
$sql = "SELECT COUNT(*) FROM $table_name INNER JOIN $posts on $table_name.post_id = {$posts}.ID"
|
||||
. " $where AND $table_name.start > $current_time"; //future event
|
||||
return $db->get_var( $sql );
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Calendar Feeds page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Calendar_Feeds extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/**
|
||||
* Adds page to the menu.
|
||||
*
|
||||
* @wp_hook admin_menu
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_page() {
|
||||
// =======================
|
||||
// = Calendar Feeds Page =
|
||||
// =======================
|
||||
$calendar_feeds = add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
Ai1ec_I18n::__( 'Import Feeds' ),
|
||||
Ai1ec_I18n::__( 'Import Feeds' ),
|
||||
'manage_ai1ec_feeds',
|
||||
AI1EC_PLUGIN_NAME . '-feeds',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
$this->_registry->get( 'model.settings' )
|
||||
->set( 'feeds_page', $calendar_feeds );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds metabox to the page.
|
||||
*
|
||||
* @wp_hook admin_init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_meta_box() {
|
||||
// Add the 'ICS Import Settings' meta box.
|
||||
add_meta_box(
|
||||
'ai1ec-feeds',
|
||||
Ai1ec_I18n::_x( 'Feed Subscriptions', 'meta box' ),
|
||||
array( $this, 'display_meta_box' ),
|
||||
$this->_registry->get( 'model.settings' )->get( 'feeds_page' ),
|
||||
'left',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display this plugin's feeds page in the admin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_page() {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$args = array(
|
||||
'title' => __(
|
||||
'All-in-One Event Calendar: Import Feeds',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'settings_page' => $settings->get( 'feeds_page' ),
|
||||
'calendar_settings' => false,
|
||||
);
|
||||
$file = $loader->get_file( 'feeds_settings.php', $args, true );
|
||||
wp_enqueue_style(
|
||||
'ai1ec_samples.css',
|
||||
AI1EC_ADMIN_THEME_CSS_URL . 'samples.css',
|
||||
array(),
|
||||
AI1EC_VERSION
|
||||
);
|
||||
$file->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the contents of the Calendar Feeds meta box.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_meta_box( $object, $box ) {
|
||||
// register the calendar feeds page.
|
||||
$calendar_feeds = $this->_registry->get( 'controller.calendar-feeds' );
|
||||
$feeds = array();
|
||||
|
||||
array_push( $feeds, $this->_registry->get( 'calendar-feed.import' ) );
|
||||
// Check for user subscription - Discover events
|
||||
if ($this->_api_registration->has_subscription_active( 'discover-events' ) ) {
|
||||
array_push( $feeds, $this->_registry->get( 'calendar-feed.suggested' ) );
|
||||
}
|
||||
|
||||
// Add ICS
|
||||
array_push( $feeds, $this->_registry->get( 'calendar-feed.ics' ) );
|
||||
|
||||
$feeds = apply_filters( 'ai1ec_calendar_feeds', $feeds );
|
||||
foreach ( $feeds as $feed ) {
|
||||
$calendar_feeds->add_plugin( $feed );
|
||||
}
|
||||
$calendar_feeds->handle_feeds_page_post();
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file(
|
||||
'box_feeds.php',
|
||||
array( 'calendar_feeds' => $calendar_feeds ),
|
||||
true
|
||||
);
|
||||
$file->render();
|
||||
}
|
||||
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Event category admin view snippets renderer.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Admin
|
||||
*/
|
||||
class Ai1ec_View_Admin_EventCategory extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Inserts Color element at index 2 of columns array
|
||||
*
|
||||
* @param array $columns Array with event_category columns
|
||||
*
|
||||
* @return array Array with event_category columns where Color is inserted
|
||||
* at index 2
|
||||
*/
|
||||
public function manage_event_categories_columns( $columns ) {
|
||||
wp_enqueue_media();
|
||||
$this->_registry->get( 'css.admin' )
|
||||
->process_enqueue( array(
|
||||
array( 'style', 'bootstrap.min.css' )
|
||||
) );
|
||||
return array_splice( $columns, 0, 3 ) + // get only first element
|
||||
// insert at index 2
|
||||
array( 'cat_color' => __( 'Color', AI1EC_PLUGIN_NAME ) ) +
|
||||
// insert at index 3
|
||||
array( 'cat_image' => __( 'Image', AI1EC_PLUGIN_NAME ) ) +
|
||||
// insert rest of elements at the back
|
||||
array_splice( $columns, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color or image of the event category.
|
||||
*
|
||||
* That will be displayed on event category lists page in the backend.
|
||||
*
|
||||
* @param $not_set
|
||||
* @param $column_name
|
||||
* @param $term_id
|
||||
* @internal param array $columns Array with event_category columns
|
||||
*
|
||||
* @return array Array with event_category columns where Color is inserted
|
||||
* at index 2
|
||||
*/
|
||||
public function manage_events_categories_custom_column(
|
||||
$not_set,
|
||||
$column_name,
|
||||
$term_id
|
||||
) {
|
||||
switch ( $column_name ) {
|
||||
case 'cat_color':
|
||||
return $this->_registry->get( 'view.event.taxonomy' )
|
||||
->get_category_color_square( $term_id );
|
||||
case 'cat_image':
|
||||
return $this->_registry->get( 'view.event.taxonomy' )
|
||||
->get_category_image_square( $term_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to process event categories creation
|
||||
*
|
||||
* @param $term_id
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function created_events_categories( $term_id ) {
|
||||
$this->edited_events_categories( $term_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback method, triggered when `event_categories' are being edited.
|
||||
*
|
||||
* @param int $term_id ID of term (category) being edited.
|
||||
*
|
||||
* @return void Method does not return.
|
||||
*/
|
||||
public function edited_events_categories( $term_id ) {
|
||||
if ( isset( $_POST['_inline_edit'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tag_color_value = '';
|
||||
if ( ! empty( $_POST['tag-color-value'] ) ) {
|
||||
$tag_color_value = (string)$_POST['tag-color-value'];
|
||||
}
|
||||
$tag_image_value = '';
|
||||
if ( ! empty( $_POST['ai1ec_category_image_url'] ) ) {
|
||||
$tag_image_value = (string)$_POST['ai1ec_category_image_url'];
|
||||
}
|
||||
if ( isset( $_POST['ai1ec_category_image_url_remove'] ) ) {
|
||||
$tag_image_value = null;
|
||||
}
|
||||
|
||||
$db = $this->_registry->get( 'dbi.dbi' );
|
||||
$table_name = $db->get_table_name( 'ai1ec_event_category_meta' );
|
||||
$term = $db->get_row( $db->prepare(
|
||||
'SELECT term_id FROM ' . $table_name .
|
||||
' WHERE term_id = %d',
|
||||
$term_id
|
||||
) );
|
||||
|
||||
if ( null === $term ) { // term does not exist, create it
|
||||
$db->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'term_id' => $term_id,
|
||||
'term_color' => $tag_color_value,
|
||||
'term_image' => $tag_image_value,
|
||||
),
|
||||
array(
|
||||
'%d',
|
||||
'%s',
|
||||
'%s',
|
||||
)
|
||||
);
|
||||
} else { // term exist, update it
|
||||
$db->update(
|
||||
$table_name,
|
||||
array(
|
||||
'term_color' => $tag_color_value,
|
||||
'term_image' => $tag_image_value
|
||||
),
|
||||
array( 'term_id' => $term_id ),
|
||||
array( '%s', '%s' ),
|
||||
array( '%d' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function show_color( $term = null ) {
|
||||
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$color = '';
|
||||
if ( null !== $term ) {
|
||||
$color = $taxonomy->get_category_color( $term->term_id );
|
||||
}
|
||||
|
||||
$style = '';
|
||||
$clr = '';
|
||||
|
||||
if ( $color ) {
|
||||
$style = 'style="background-color: ' . $color . '"';
|
||||
$clr = $color;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'style' => $style,
|
||||
'color' => $clr,
|
||||
'label' => Ai1ec_I18n::__( 'Category Color' ),
|
||||
'description' => Ai1ec_I18n::__(
|
||||
'Events in this category will be identified by this color'
|
||||
),
|
||||
'edit' => true,
|
||||
);
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$loader->get_file(
|
||||
'setting/categories-color-picker.twig',
|
||||
$args,
|
||||
true
|
||||
)->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit category form
|
||||
*
|
||||
* @param $term
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function events_categories_edit_form_fields( $term ) {
|
||||
$this->show_color( $term );
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$image = $taxonomy->get_category_image( $term->term_id );
|
||||
|
||||
$style = 'style="display:none"';
|
||||
|
||||
if ( null !== $image ) {
|
||||
$style = '';
|
||||
}
|
||||
|
||||
// Category image
|
||||
$args = array(
|
||||
'image_src' => $image,
|
||||
'image_style' => $style,
|
||||
'section_name' => __( 'Category Image', AI1EC_PLUGIN_NAME ),
|
||||
'label' => __( 'Add Image', AI1EC_PLUGIN_NAME ),
|
||||
'remove_label' => __( 'Remove Image', AI1EC_PLUGIN_NAME ),
|
||||
'description' => __(
|
||||
'Assign an optional image to the category. Recommended size: square, minimum 400×400 pixels.',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'edit' => true,
|
||||
);
|
||||
|
||||
$loader->get_file(
|
||||
'setting/categories-image.twig',
|
||||
$args,
|
||||
true
|
||||
)->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add category form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function events_categories_add_form_fields() {
|
||||
|
||||
$this->show_color();
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
// Category image
|
||||
$args = array(
|
||||
'image_src' => '',
|
||||
'image_style' => 'style="display:none"',
|
||||
'section_name' => __( 'Category Image', AI1EC_PLUGIN_NAME ),
|
||||
'label' => __( 'Add Image', AI1EC_PLUGIN_NAME),
|
||||
'description' => __( 'Assign an optional image to the category. Recommended size: square, minimum 400×400 pixels.', AI1EC_PLUGIN_NAME ),
|
||||
'edit' => false,
|
||||
);
|
||||
|
||||
$file = $loader->get_file(
|
||||
'setting/categories-image.twig',
|
||||
$args,
|
||||
true
|
||||
);
|
||||
|
||||
$file->render();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,670 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The get repeat box snippet.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Admin_Get_repeat_Box extends Ai1ec_Base {
|
||||
/**
|
||||
* get_repeat_box function
|
||||
*
|
||||
* @return string
|
||||
**/
|
||||
public function get_repeat_box() {
|
||||
$time_system = $this->_registry->get( 'date.system' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$repeat = (int) $_REQUEST["repeat"];
|
||||
$repeat = $repeat == 1 ? 1 : 0;
|
||||
$post_id = (int) $_REQUEST["post_id"];
|
||||
$count = 100;
|
||||
$end = 0;
|
||||
$until = $time_system->current_time( true );
|
||||
|
||||
// try getting the event
|
||||
try {
|
||||
$event = $this->_registry->get( 'model.event', $post_id );
|
||||
$rule = '';
|
||||
|
||||
if ( $repeat ) {
|
||||
$rule = $event->get( 'recurrence_rules' )
|
||||
? $event->get( 'recurrence_rules' )
|
||||
: '';
|
||||
} else {
|
||||
$rule = $event->get( 'exception_rules' ) ?
|
||||
$event->get( 'exception_rules' )
|
||||
: '';
|
||||
}
|
||||
|
||||
$rule = $this->_registry->get( 'recurrence.rule' )->filter_rule( $rule );
|
||||
|
||||
$rc = new SG_iCal_Recurrence(
|
||||
new SG_iCal_Line( 'RRULE:' . $rule )
|
||||
);
|
||||
|
||||
if ( $until = $rc->getUntil() ) {
|
||||
$until = ( is_numeric( $until ) )
|
||||
? $until
|
||||
: strtotime( $until );
|
||||
$end = 2;
|
||||
} elseif ( $count = $rc->getCount() ) {
|
||||
$count = ( is_numeric( $count ) ) ? $count : 100;
|
||||
$end = 1;
|
||||
}
|
||||
} catch( Ai1ec_Event_Not_Found_Exception $e ) {
|
||||
$rule = '';
|
||||
$rc = new SG_iCal_Recurrence(
|
||||
new SG_iCal_Line( 'RRULE:' )
|
||||
);
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'row_daily' => $this->row_daily(
|
||||
false,
|
||||
$rc->getInterval() ? $rc->getInterval() : 1
|
||||
),
|
||||
'row_weekly' => $this->row_weekly(
|
||||
false,
|
||||
$rc->getInterval() ? $rc->getInterval() : 1,
|
||||
is_array( $rc->getByDay() ) ? $rc->getByDay() : array()
|
||||
),
|
||||
'row_monthly' => $this->row_monthly(
|
||||
false,
|
||||
$rc->getInterval() ? $rc->getInterval() : 1,
|
||||
! $this->_is_monthday_empty( $rc ),
|
||||
$rc->getByMonthDay() ? $rc->getByMonthDay() : array(),
|
||||
$rc->getByDay() ? $rc->getByDay() : array()
|
||||
),
|
||||
'row_yearly' => $this->row_yearly(
|
||||
false,
|
||||
$rc->getInterval() ? $rc->getInterval() : 1,
|
||||
is_array( $rc->getByMonth() ) ? $rc->getByMonth() : array()
|
||||
),
|
||||
'row_custom' => $this->row_custom(
|
||||
false,
|
||||
$this->get_date_array_from_rule( $rule )
|
||||
),
|
||||
'count' => $this->create_count_input(
|
||||
'ai1ec_count',
|
||||
$count
|
||||
) . Ai1ec_I18n::__( 'times' ),
|
||||
'end' => $this->create_end_dropdown( $end ),
|
||||
'until' => $until,
|
||||
'repeat' => $repeat,
|
||||
'ending_type' => $end,
|
||||
'selected_tab' => $rc->getFreq()
|
||||
? strtolower( $rc->getFreq() )
|
||||
: 'custom',
|
||||
);
|
||||
$output = array(
|
||||
'error' => false,
|
||||
'message' => $loader->get_file(
|
||||
'box_repeat.php',
|
||||
$args,
|
||||
true
|
||||
)->get_content(),
|
||||
'repeat' => $repeat,
|
||||
);
|
||||
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
||||
$json_strategy->render( array( 'data' => $output ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* get_weekday_by_id function
|
||||
*
|
||||
* Returns weekday name in English
|
||||
*
|
||||
* @param int $day_id Day ID
|
||||
*
|
||||
* @return string
|
||||
**/
|
||||
public function get_weekday_by_id( $day_id, $by_value = false ) {
|
||||
// do not translate this !!!
|
||||
$week_days = array(
|
||||
0 => 'SU',
|
||||
1 => 'MO',
|
||||
2 => 'TU',
|
||||
3 => 'WE',
|
||||
4 => 'TH',
|
||||
5 => 'FR',
|
||||
6 => 'SA',
|
||||
);
|
||||
|
||||
if ( $by_value ) {
|
||||
while ( $_name = current( $week_days ) ) {
|
||||
if ( $_name == $day_id ) {
|
||||
return key( $week_days );
|
||||
}
|
||||
next( $week_days );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return $week_days[$day_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* convert_rrule_to_text method
|
||||
*
|
||||
* Convert a `recurrence rule' to text to display it on screen
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
public function convert_rrule_to_text() {
|
||||
$error = false;
|
||||
$message = '';
|
||||
// check to see if RRULE is set
|
||||
if ( isset( $_REQUEST['rrule'] ) ) {
|
||||
// check to see if rrule is empty
|
||||
if ( empty( $_REQUEST['rrule'] ) ) {
|
||||
$error = true;
|
||||
$message = Ai1ec_I18n::__(
|
||||
'Recurrence rule cannot be empty.'
|
||||
);
|
||||
} else {
|
||||
//list( $rule, $value ) = explode( '=', $_REQUEST['rrule'], 2 );
|
||||
//if ( in_array( array(), $rule ) ) {
|
||||
// $message = $this->_registry->get( 'recurrence.date' );
|
||||
//
|
||||
//} else {
|
||||
$rrule = $this->_registry->get( 'recurrence.rule' );
|
||||
// convert rrule to text
|
||||
$message = ucfirst(
|
||||
$rrule->rrule_to_text( $_REQUEST['rrule'] )
|
||||
);
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
$error = true;
|
||||
$message = Ai1ec_I18n::__(
|
||||
'Recurrence rule was not provided.'
|
||||
);
|
||||
}
|
||||
$output = array(
|
||||
'error' => $error,
|
||||
'message' => get_magic_quotes_gpc()
|
||||
? stripslashes( $message )
|
||||
: $message,
|
||||
);
|
||||
|
||||
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
||||
$json_strategy->render( array( 'data' => $output ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* create_end_dropdown function
|
||||
*
|
||||
* Outputs the dropdown list for the recurrence end option.
|
||||
*
|
||||
* @param int $selected The index of the selected option, if any
|
||||
* @return void
|
||||
**/
|
||||
protected function create_end_dropdown( $selected = NULL ) {
|
||||
ob_start();
|
||||
|
||||
$options = array(
|
||||
0 => Ai1ec_I18n::__( 'Never' ),
|
||||
1 => Ai1ec_I18n::__( 'After' ),
|
||||
2 => Ai1ec_I18n::__( 'On date' ),
|
||||
);
|
||||
|
||||
?>
|
||||
<select name="ai1ec_end" id="ai1ec_end">
|
||||
<?php foreach( $options as $key => $val ): ?>
|
||||
<option value="<?php echo $key ?>"
|
||||
<?php if( $key === $selected ) echo 'selected="selected"' ?>>
|
||||
<?php echo $val ?>
|
||||
</option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
<?php
|
||||
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* row_daily function
|
||||
*
|
||||
* Returns daily selector
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function row_daily( $visible = false, $selected = 1 ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$args = array(
|
||||
'visible' => $visible,
|
||||
'count' => $this->create_count_input(
|
||||
'ai1ec_daily_count',
|
||||
$selected,
|
||||
365
|
||||
) . Ai1ec_I18n::__( 'day(s)' ),
|
||||
);
|
||||
return $loader->get_file( 'row_daily.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* row_custom function
|
||||
*
|
||||
* Returns custom dates selector
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function row_custom( $visible = false, $dates = array() ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$args = array(
|
||||
'visible' => $visible,
|
||||
'selected_dates' => implode( ',', $dates )
|
||||
);
|
||||
return $loader->get_file( 'row_custom.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns "End after X times" input
|
||||
*
|
||||
* @param Integer|NULL $count Initial value of range input
|
||||
*
|
||||
* @return String Repeat dropdown
|
||||
*/
|
||||
protected function create_count_input( $name, $count = 100, $max = 365 ) {
|
||||
ob_start();
|
||||
|
||||
if ( ! $count ) {
|
||||
$count = 100;
|
||||
}
|
||||
?>
|
||||
<input type="range" name="<?php echo $name ?>" id="<?php echo $name ?>"
|
||||
min="1" max="<?php echo $max ?>"
|
||||
<?php if ( $count ) echo 'value="' . $count . '"' ?> />
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* row_weekly function
|
||||
*
|
||||
* Returns weekly selector
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function row_weekly(
|
||||
$visible = false,
|
||||
$count = 1,
|
||||
array $selected = array()
|
||||
) {
|
||||
global $wp_locale;
|
||||
$start_of_week = $this->_registry->get( 'model.option' )
|
||||
->get( 'start_of_week', 1 );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$options = array();
|
||||
// get days from start_of_week until the last day
|
||||
for ( $i = $start_of_week; $i <= 6; ++$i ) {
|
||||
$options[$this->get_weekday_by_id( $i )] = $wp_locale
|
||||
->weekday_initial[$wp_locale->weekday[$i]];
|
||||
}
|
||||
|
||||
// get days from 0 until start_of_week
|
||||
if ( $start_of_week > 0 ) {
|
||||
for ( $i = 0; $i < $start_of_week; $i++ ) {
|
||||
$options[$this->get_weekday_by_id( $i )] = $wp_locale
|
||||
->weekday_initial[$wp_locale->weekday[$i]];
|
||||
}
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'visible' => $visible,
|
||||
'count' => $this->create_count_input(
|
||||
'ai1ec_weekly_count',
|
||||
$count,
|
||||
52
|
||||
) . Ai1ec_I18n::__( 'week(s)' ),
|
||||
'week_days' => $this->create_list_element(
|
||||
'ai1ec_weekly_date_select',
|
||||
$options,
|
||||
$selected
|
||||
)
|
||||
);
|
||||
return $loader->get_file( 'row_weekly.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a grid of weekday, day, or month selection buttons.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function create_list_element(
|
||||
$name,
|
||||
array $options = array(),
|
||||
array $selected = array()
|
||||
) {
|
||||
ob_start();
|
||||
?>
|
||||
<div class="ai1ec-btn-group-grid" id="<?php echo $name; ?>">
|
||||
<?php foreach ( $options as $key => $val ) : ?>
|
||||
<div class="ai1ec-pull-left">
|
||||
<a class="ai1ec-btn ai1ec-btn-default ai1ec-btn-block
|
||||
<?php echo in_array( $key, $selected ) ? 'ai1ec-active' : ''; ?>">
|
||||
<?php echo $val; ?>
|
||||
</a>
|
||||
<input type="hidden" name="<?php echo $name . '_' . $key; ?>"
|
||||
value="<?php echo $key; ?>">
|
||||
</div class="ai1ec-pull-left">
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<input type="hidden" name="<?php echo $name; ?>"
|
||||
value="<?php echo implode( ',', $selected ) ?>">
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* row_monthly function
|
||||
*
|
||||
* Returns monthly selector
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function row_monthly(
|
||||
$visible = false,
|
||||
$count = 1,
|
||||
$bymonthday = true,
|
||||
$month = array(),
|
||||
$day = array()
|
||||
) {
|
||||
global $wp_locale;
|
||||
$start_of_week = $this->_registry->get( 'model.option' )
|
||||
->get( 'start_of_week', 1 );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$options_wd = array();
|
||||
// get days from start_of_week until the last day
|
||||
for ( $i = $start_of_week; $i <= 6; ++$i ) {
|
||||
$options_wd[$this->get_weekday_by_id( $i )] = $wp_locale
|
||||
->weekday[$i];
|
||||
}
|
||||
|
||||
// get days from 0 until start_of_week
|
||||
if ( $start_of_week > 0 ) {
|
||||
for ( $i = 0; $i < $start_of_week; $i++ ) {
|
||||
$options_wd[$this->get_weekday_by_id( $i )] = $wp_locale
|
||||
->weekday[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// get options like 1st/2nd/3rd for "day number"
|
||||
$options_dn = array( 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5 );
|
||||
foreach ( $options_dn as $_dn ) {
|
||||
$options_dn[$_dn] = $this->_registry->get(
|
||||
'date.time',
|
||||
strtotime( $_dn . '-01-1998 12:00:00' )
|
||||
)->format_i18n( 'jS' );
|
||||
}
|
||||
$options_dn['-1'] = Ai1ec_I18n::__( 'last' );
|
||||
|
||||
$byday_checked = $bymonthday ? '' : 'checked';
|
||||
$byday_expanded = $bymonthday ? 'ai1ec-collapse' : 'ai1ec-in';
|
||||
$bymonthday_checked = $bymonthday ? 'checked' : '';
|
||||
$bymonthday_expanded = $bymonthday ? 'ai1ec-in' : 'ai1ec-collapse';
|
||||
|
||||
$args = array(
|
||||
'visible' => $visible,
|
||||
'count' => $this->create_count_input(
|
||||
'ai1ec_monthly_count',
|
||||
$count,
|
||||
12
|
||||
) . Ai1ec_I18n::__( 'month(s)' ),
|
||||
'month' => $this->create_monthly_date_select(
|
||||
$month
|
||||
),
|
||||
'day_nums' => $this->create_select_element(
|
||||
'ai1ec_monthly_byday_num',
|
||||
$options_dn,
|
||||
$this->_get_day_number_from_byday( $day )
|
||||
),
|
||||
'week_days' => $this->create_select_element(
|
||||
'ai1ec_monthly_byday_weekday',
|
||||
$options_wd,
|
||||
$this->_get_day_shortname_from_byday( $day )
|
||||
),
|
||||
'bymonthday_checked' => $bymonthday_checked,
|
||||
'byday_checked' => $byday_checked,
|
||||
'bymonthday_expanded' => $bymonthday_expanded,
|
||||
'byday_expanded' => $byday_expanded,
|
||||
);
|
||||
return $loader->get_file( 'row_monthly.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates selector for dates in monthly repeat tab.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function create_monthly_date_select( $selected = array() ) {
|
||||
$options = array();
|
||||
for ( $i = 1; $i <= 31; ++$i ) {
|
||||
$options[$i] = $i;
|
||||
}
|
||||
return $this->create_list_element(
|
||||
'ai1ec_montly_date_select',
|
||||
$options,
|
||||
$selected
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* create_on_the_select function
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
**/
|
||||
protected function create_on_the_select(
|
||||
$f_selected = false,
|
||||
$s_selected = false
|
||||
) {
|
||||
$ret = '';
|
||||
|
||||
$first_options = array(
|
||||
'0' => Ai1ec_I18n::__( 'first' ),
|
||||
'1' => Ai1ec_I18n::__( 'second' ),
|
||||
'2' => Ai1ec_I18n::__( 'third' ),
|
||||
'3' => Ai1ec_I18n::__( 'fourth' ),
|
||||
'4' => '------',
|
||||
'5' => Ai1ec_I18n::__( 'last' )
|
||||
);
|
||||
$ret = $this->create_select_element(
|
||||
'ai1ec_monthly_each_select',
|
||||
$first_options,
|
||||
$f_selected,
|
||||
array( 4 )
|
||||
);
|
||||
|
||||
$second_options = array(
|
||||
'0' => Ai1ec_I18n::__( 'Sunday' ),
|
||||
'1' => Ai1ec_I18n::__( 'Monday' ),
|
||||
'2' => Ai1ec_I18n::__( 'Tuesday' ),
|
||||
'3' => Ai1ec_I18n::__( 'Wednesday' ),
|
||||
'4' => Ai1ec_I18n::__( 'Thursday' ),
|
||||
'5' => Ai1ec_I18n::__( 'Friday' ),
|
||||
'6' => Ai1ec_I18n::__( 'Saturday' ),
|
||||
'7' => '--------',
|
||||
'8' => Ai1ec_I18n::__( 'day' ),
|
||||
'9' => Ai1ec_I18n::__( 'weekday' ),
|
||||
'10' => Ai1ec_I18n::__( 'weekend day' )
|
||||
);
|
||||
|
||||
return $ret . $this->create_select_element(
|
||||
'ai1ec_monthly_on_the_select',
|
||||
$second_options,
|
||||
$s_selected,
|
||||
array( 7 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* create_select_element function
|
||||
*
|
||||
* Render HTML <select> element
|
||||
*
|
||||
* @param string $name Name of element to be rendered
|
||||
* @param array $options Select <option> values as key=>value pairs
|
||||
* @param string $selected Key to be marked as selected [optional=false]
|
||||
* @param array $disabled_keys List of options to disable [optional=array]
|
||||
*
|
||||
* @return string Rendered <select> HTML element
|
||||
**/
|
||||
protected function create_select_element(
|
||||
$name,
|
||||
array $options = array(),
|
||||
$selected = false,
|
||||
array $disabled_keys = array()
|
||||
) {
|
||||
ob_start();
|
||||
?>
|
||||
<select name="<?php echo $name ?>" id="<?php echo $name ?>">
|
||||
<?php foreach( $options as $key => $val ): ?>
|
||||
<option value="<?php echo $key ?>"
|
||||
<?php echo $key === $selected ? 'selected="selected"' : '' ?>
|
||||
<?php echo in_array( $key, $disabled_keys ) ? 'disabled' : '' ?>>
|
||||
<?php echo $val ?>
|
||||
</option>
|
||||
<?php endforeach ?>
|
||||
</select>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* row_yearly function
|
||||
*
|
||||
* Returns yearly selector
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function row_yearly(
|
||||
$visible = false,
|
||||
$count = 1,
|
||||
$year = array(),
|
||||
$first = false,
|
||||
$second = false
|
||||
) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$args = array(
|
||||
'visible' => $visible,
|
||||
'count' => $this->create_count_input(
|
||||
'ai1ec_yearly_count',
|
||||
$count,
|
||||
10
|
||||
) . Ai1ec_I18n::__( 'year(s)' ),
|
||||
'year' => $this->create_yearly_date_select( $year ),
|
||||
'on_the_select' => $this->create_on_the_select(
|
||||
$first,
|
||||
$second
|
||||
),
|
||||
);
|
||||
return $loader->get_file( 'row_yearly.php', $args, true )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* create_yearly_date_select function
|
||||
*
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
protected function create_yearly_date_select( $selected = array() ) {
|
||||
global $wp_locale;
|
||||
$options = array();
|
||||
for ( $i = 1; $i <= 12; ++$i ) {
|
||||
$options[$i] = $wp_locale->month_abbrev[
|
||||
$wp_locale->month[sprintf( '%02d', $i )]
|
||||
];
|
||||
}
|
||||
return $this->create_list_element(
|
||||
'ai1ec_yearly_date_select',
|
||||
$options,
|
||||
$selected
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts recurrence rule to array of string of dates.
|
||||
*
|
||||
* @param string $rule RUle.
|
||||
*
|
||||
* @return array Array of dates or empty array.
|
||||
* @throws Ai1ec_Bootstrap_Exception
|
||||
*/
|
||||
protected function get_date_array_from_rule( $rule ) {
|
||||
if (
|
||||
'RDATE' !== substr( $rule, 0, 5 ) &&
|
||||
'EXDATE' !== substr( $rule, 0, 6 )
|
||||
) {
|
||||
return array();
|
||||
}
|
||||
$line = new SG_iCal_Line( 'RRULE:' . $rule );
|
||||
$dates = $line->getDataAsArray();
|
||||
$dates_as_strings = array();
|
||||
foreach ( $dates as $date ) {
|
||||
$date = str_replace( array( 'RDATE=', 'EXDATE=' ), '', $date );
|
||||
$date = $this->_registry->get( 'date.time', $date )->set_preferred_timezone( 'UTC' );
|
||||
$dates_as_strings[] = $date->format( 'm/d/Y' );
|
||||
}
|
||||
return $dates_as_strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether recurrence rule has non null ByMonthDay.
|
||||
*
|
||||
* @param SG_iCal_Recurrence $rc iCal class.
|
||||
*
|
||||
* @return bool True or false.
|
||||
*/
|
||||
protected function _is_monthday_empty( SG_iCal_Recurrence $rc ) {
|
||||
return false === $rc->getByMonthDay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns day number from by day array.
|
||||
*
|
||||
* @param array $day
|
||||
*
|
||||
* @return bool|int Day of false if empty array.
|
||||
*/
|
||||
protected function _get_day_number_from_byday( array $day ) {
|
||||
return isset( $day[0] ) ? (int) $day[0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string part from "ByDay" recurrence rule.
|
||||
*
|
||||
* @param array $day Element to parse.
|
||||
*
|
||||
* @return bool|string False if empty or not matched, otherwise short day
|
||||
* name.
|
||||
*/
|
||||
protected function _get_day_shortname_from_byday( $day ) {
|
||||
if ( empty( $day ) ) {
|
||||
return false;
|
||||
}
|
||||
$value = $day[0];
|
||||
if ( preg_match('/[-]?\d([A-Z]+)/', $value, $matches ) ) {
|
||||
return $matches[1];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The get tax options box.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.4
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Admin_Get_Tax_Box extends Ai1ec_Base {
|
||||
/**
|
||||
* get_tax_box function
|
||||
*
|
||||
* @return string
|
||||
**/
|
||||
public function get_tax_box() {
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
$post_id = $_POST['ai1ec_event_id'];
|
||||
$modal = $api->get_tax_options_modal( $post_id );
|
||||
$output = array(
|
||||
'error' => $modal->error,
|
||||
'message' => $modal->data
|
||||
);
|
||||
$json_strategy = $this->_registry->get( 'http.response.render.strategy.json' );
|
||||
$json_strategy->render( array( 'data' => $output ) );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Admin-side navigation elements rendering.
|
||||
*
|
||||
* @author Time.ly Network, Inc.
|
||||
* @since 2.0
|
||||
* @package Ai1EC
|
||||
* @subpackage Ai1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Admin_Navigation extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Adds a link to Settings page in plugin list page.
|
||||
*
|
||||
* @param array $links List of available links.
|
||||
*
|
||||
* @return array Modified links list.
|
||||
*/
|
||||
public function plugin_action_links( $links ) {
|
||||
$settings_link = sprintf(
|
||||
Ai1ec_I18n::__( '<a href="%s">Settings</a>' ),
|
||||
ai1ec_admin_url( AI1EC_SETTINGS_BASE_URL )
|
||||
);
|
||||
array_unshift( $links, $settings_link );
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
$updates_link = sprintf(
|
||||
Ai1ec_I18n::__( '<a href="%s">Check for updates</a>' ),
|
||||
ai1ec_admin_url( AI1EC_FORCE_UPDATES_URL )
|
||||
);
|
||||
array_push( $links, $updates_link );
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The page to manage taxonomies.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Organize extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* @var array The taxonomies for events
|
||||
*/
|
||||
protected $_taxonomies = array();
|
||||
|
||||
/**
|
||||
* Register actions to draw the headers
|
||||
*/
|
||||
public function add_taxonomy_actions() {
|
||||
$taxonomies = get_object_taxonomies( AI1EC_POST_TYPE, 'object' );
|
||||
$dispatcher = $this->_registry->get( 'event.dispatcher' );
|
||||
$taxonomy_metadata = array(
|
||||
'events_categories' => array(
|
||||
'icon' => 'ai1ec-fa ai1ec-fa-folder-open'
|
||||
),
|
||||
'events_tags' => array(
|
||||
'icon' => 'ai1ec-fa ai1ec-fa-tags'
|
||||
)
|
||||
);
|
||||
$taxonomy_metadata = apply_filters(
|
||||
'ai1ec_add_custom_groups',
|
||||
$taxonomy_metadata
|
||||
);
|
||||
do_action( 'ai1ec_taxonomy_management_css' );
|
||||
foreach ( $taxonomies as $taxonomy => $data ) {
|
||||
if ( true === $data->public ) {
|
||||
$active_taxonomy =
|
||||
isset( $_GET['taxonomy'] ) &&
|
||||
$taxonomy === $_GET['taxonomy'];
|
||||
$edit_url = $edit_label = '';
|
||||
if ( isset( $taxonomy_metadata[$taxonomy]['url'] ) ) {
|
||||
$edit_url = $taxonomy_metadata[$taxonomy]['url'];
|
||||
$edit_label = $taxonomy_metadata[$taxonomy]['edit_label'];
|
||||
}
|
||||
$this->_taxonomies[] = array(
|
||||
'taxonomy_name' => $taxonomy,
|
||||
'url' => add_query_arg(
|
||||
array(
|
||||
'post_type' => AI1EC_POST_TYPE,
|
||||
'taxonomy' => $taxonomy
|
||||
),
|
||||
admin_url( 'edit-tags.php' )
|
||||
),
|
||||
'name' => $data->labels->name,
|
||||
'active' => $active_taxonomy,
|
||||
'icon' => isset( $taxonomy_metadata[$taxonomy] ) ?
|
||||
$taxonomy_metadata[$taxonomy]['icon'] :
|
||||
'',
|
||||
'edit_url' => $edit_url,
|
||||
'edit_label' => $edit_label,
|
||||
);
|
||||
|
||||
if ( $active_taxonomy ) {
|
||||
$dispatcher->register_action(
|
||||
$taxonomy . '_pre_add_form',
|
||||
array( 'view.admin.organize', 'render_header' )
|
||||
);
|
||||
$dispatcher->register_action(
|
||||
$taxonomy . '_pre_edit_form',
|
||||
array( 'view.admin.organize', 'render_header' )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render tabbed header to manage taxonomies.
|
||||
*/
|
||||
public function render_header() {
|
||||
echo $this->get_header();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and return tabbed header to manage taxonomies.
|
||||
*
|
||||
* @return string HTML markup for tabbed header
|
||||
*/
|
||||
public function get_header() {
|
||||
return $this->_registry->get( 'theme.loader' )->get_file(
|
||||
'organize/header.twig',
|
||||
array(
|
||||
'taxonomies' => apply_filters(
|
||||
'ai1ec_custom_taxonomies',
|
||||
$this->_taxonomies
|
||||
),
|
||||
'text_title' => Ai1ec_I18n::__( 'Organize Events' ),
|
||||
),
|
||||
true
|
||||
)->get_content();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Calendar Samples page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.1
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Samples extends Ai1ec_View_Admin_Abstract {
|
||||
/**
|
||||
* Adds page to the menu.
|
||||
*
|
||||
* @wp_hook admin_menu
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_page() {
|
||||
// =======================
|
||||
// = Calendar Add Ons Page =
|
||||
// =======================
|
||||
}
|
||||
/**
|
||||
* Display Add Ons list page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_page() {
|
||||
wp_enqueue_style(
|
||||
'ai1ec_samples.css',
|
||||
AI1EC_ADMIN_THEME_CSS_URL . 'samples.css',
|
||||
array(),
|
||||
AI1EC_VERSION
|
||||
);
|
||||
|
||||
$this->_registry->get( 'theme.loader' )->get_file(
|
||||
'samples.twig',
|
||||
array(),
|
||||
true
|
||||
)->render();
|
||||
}
|
||||
|
||||
public function add_meta_box() {
|
||||
}
|
||||
|
||||
public function display_meta_box( $object, $box ) {
|
||||
}
|
||||
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
}
|
||||
349
wp-content/plugins/all-in-one-event-calendar/app/view/admin/settings.php
Executable file
349
wp-content/plugins/all-in-one-event-calendar/app/view/admin/settings.php
Executable file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Settings page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Admin_Settings extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/**
|
||||
* @var string The nonce action
|
||||
*/
|
||||
CONST NONCE_ACTION = 'ai1ec_settings_save';
|
||||
|
||||
/**
|
||||
* @var string The nonce name
|
||||
*/
|
||||
CONST NONCE_NAME = 'ai1ec_settings_nonce';
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Abstract::display_page()
|
||||
*/
|
||||
public function display_page() {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'All-in-One Event Calendar: Settings'
|
||||
),
|
||||
'nonce' => array(
|
||||
'action' => self::NONCE_ACTION,
|
||||
'name' => self::NONCE_NAME,
|
||||
'referrer' => false,
|
||||
),
|
||||
'metabox' => array(
|
||||
'screen' => $settings->get( 'settings_page' ),
|
||||
'action' => 'left',
|
||||
'object' => null
|
||||
),
|
||||
'support' => array(
|
||||
'screen' => $settings->get( 'settings_page' ),
|
||||
'action' => 'right',
|
||||
'object' => null
|
||||
),
|
||||
'action' =>
|
||||
ai1ec_admin_url(
|
||||
'?controller=front&action=ai1ec_save_settings&plugin=' .
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
);
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file( 'setting/page.twig', $args, true );
|
||||
$file->render();
|
||||
if ( apply_filters( 'ai1ec_robots_install', true ) ) {
|
||||
$this->_registry->get( 'robots.helper' )->install();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Abstract::add_page()
|
||||
*/
|
||||
public function add_page() {
|
||||
$settings_page = add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
Ai1ec_I18n::__( 'Settings' ),
|
||||
Ai1ec_I18n::__( 'Settings' ),
|
||||
'manage_ai1ec_options',
|
||||
AI1EC_PLUGIN_NAME . '-settings',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
$this->_registry->get( 'model.settings' )
|
||||
->set( 'settings_page', $settings_page );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds metabox to the page.
|
||||
*
|
||||
* @wp_hook admin_init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_meta_box() {
|
||||
// Add the 'General Settings' meta box.
|
||||
add_meta_box(
|
||||
'ai1ec-general-settings',
|
||||
Ai1ec_I18n::_x( 'General Settings', 'meta box' ),
|
||||
array( $this, 'display_meta_box' ),
|
||||
$this->_registry->get( 'model.settings' )->get( 'settings_page' ),
|
||||
'left',
|
||||
'default'
|
||||
);
|
||||
// Add the 'Timely' meta box.
|
||||
add_meta_box(
|
||||
'ai1ec-support',
|
||||
Ai1ec_I18n::_x( 'Timely', 'meta box', AI1EC_PLUGIN_NAME ),
|
||||
array( $this, 'support_meta_box' ),
|
||||
$this->_registry->get( 'model.settings' )->get( 'settings_page' ),
|
||||
'right',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the Timely blog meta box
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param mixed $box
|
||||
*/
|
||||
public function support_meta_box( $object, $box ) {
|
||||
$newsItems = $this->_registry->get( 'news.feed' )->import_feed();
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file(
|
||||
'box_support.php',
|
||||
array(
|
||||
'news' => $newsItems,
|
||||
),
|
||||
true
|
||||
);
|
||||
$file->render();
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Abstract::handle_post()
|
||||
*/
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the meta box for the settings page.
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param mixed $box
|
||||
*/
|
||||
public function display_meta_box( $object, $box ) {
|
||||
$tabs = array(
|
||||
'viewing-events' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Viewing Events' ),
|
||||
),
|
||||
'editing-events' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Adding/Editing Events' ),
|
||||
),
|
||||
'advanced' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Advanced' ),
|
||||
'items' => array(
|
||||
'advanced' => Ai1ec_I18n::__( 'Advanced Settings' ),
|
||||
'embedded-views' => Ai1ec_I18n::__( 'Shortcodes' ),
|
||||
'email' => Ai1ec_I18n::__( 'Email Templates' ),
|
||||
'apis' => Ai1ec_I18n::__( 'External Services' ),
|
||||
'cache' => Ai1ec_I18n::__( 'Cache Report' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// let other extensions add tabs.
|
||||
$tabs = apply_filters( 'ai1ec_add_setting_tabs', $tabs );
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$plugin_settings = $settings->get_options();
|
||||
$tabs = $this->_get_tabs_to_show( $plugin_settings, $tabs );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$api = $this->_registry->get( 'model.api.api-registration' );
|
||||
$signup_available = $api->is_api_sign_up_available();
|
||||
$signed_to_api = $api->is_signed();
|
||||
$ticketing_message = $api->get_sign_message();
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$account = $api->get_current_account();
|
||||
$signup_args = array(
|
||||
'api_signed' => $signed_to_api,
|
||||
'signup_available' => $signup_available,
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Please, Sign In to Timely Network.'
|
||||
),
|
||||
'nonce' => array(
|
||||
'action' => 'ai1ec_api_ticketing_signup',
|
||||
'name' => 'ai1ec_api_ticketing_nonce',
|
||||
'referrer' => false,
|
||||
),
|
||||
'api_action' =>
|
||||
'?controller=front&action=ai1ec_api_ticketing_signup&plugin=' .
|
||||
AI1EC_PLUGIN_NAME,
|
||||
'required_text' => Ai1ec_I18n::__( 'This field is required.' ),
|
||||
'register_text' => Ai1ec_I18n::__( 'Register' ),
|
||||
'sign_in_text' => Ai1ec_I18n::__( 'Sign in' ),
|
||||
'signed_in_text' => Ai1ec_I18n::__(
|
||||
'You are signed in to <b>Timely Network</b> as ' . $account
|
||||
),
|
||||
'sign_out_text' => Ai1ec_I18n::__( 'Sign out' ),
|
||||
'can_sign_out' => apply_filters( 'ai1ec_api_can_sign_out', true ),
|
||||
'full_name_text' => Ai1ec_I18n::__( 'Full Name:' ),
|
||||
'hide_form_text' => Ai1ec_I18n::__( 'Hide form' ),
|
||||
'show_form_text' => Ai1ec_I18n::__( 'Show form' ),
|
||||
'email_text' => Ai1ec_I18n::__( 'Email:' ),
|
||||
'password_text' => Ai1ec_I18n::__( 'Password:' ),
|
||||
'confirm_password_text' => Ai1ec_I18n::__( 'Confirm Password:' ),
|
||||
'phone_number_text' => Ai1ec_I18n::__( 'Phone Number:' ),
|
||||
'terms_text' => Ai1ec_I18n::__(
|
||||
'I confirm that I have read, understand and agree with the <a href="https://time.ly/tos">terms of service</a>.'
|
||||
),
|
||||
'sign_out_warning' => Ai1ec_I18n::__(
|
||||
'<h4>Attention Required:</h4>If you choose to sign-out of the API Timely Network this will close all the created tickets and remove user access to them. In this case, on the event page, users will see the status “Event closed”.'
|
||||
),
|
||||
'sign_out_cancel' => Ai1ec_I18n::__( 'Cancel' ),
|
||||
'sign_out_confirm' => Ai1ec_I18n::__( 'Sign Out' ),
|
||||
'sign_up_button_text' => Ai1ec_I18n::__( 'Sign Up' ),
|
||||
'sign_in_button_text' => Ai1ec_I18n::__( 'Sign In' ),
|
||||
'calendar_type_text' => Ai1ec_I18n::__( 'Calendar Type:' ),
|
||||
'calendar_types' => array(
|
||||
'tourism' => Ai1ec_I18n::__( 'Tourism' ),
|
||||
'media' => Ai1ec_I18n::__( 'Media' ),
|
||||
'community_hubs' => Ai1ec_I18n::__( 'Community Hubs' ),
|
||||
'education' => Ai1ec_I18n::__( 'Education' ),
|
||||
'venue_business' => Ai1ec_I18n::__( 'Venue/Business' ),
|
||||
'artist_performer' => Ai1ec_I18n::__( 'Artist/Performer' ),
|
||||
'church_spiritual' => Ai1ec_I18n::__( 'Church/Spiritual' ),
|
||||
'association_group' => Ai1ec_I18n::__( 'Association/Group' ),
|
||||
'other' => Ai1ec_I18n::__( 'Other' )
|
||||
),
|
||||
);
|
||||
$loader->get_file( 'setting/api-signup.twig', $signup_args, true )->render();
|
||||
|
||||
|
||||
$args = array(
|
||||
'tabs' => $tabs,
|
||||
'content_class' => 'ai1ec-form-horizontal',
|
||||
'submit' => array(
|
||||
'id' => 'ai1ec_save_settings',
|
||||
'value' => '<i class="ai1ec-fa ai1ec-fa-save ai1ec-fa-fw"></i> ' .
|
||||
Ai1ec_I18n::__( 'Save Settings' ),
|
||||
'args' => array(
|
||||
'class' => 'ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg',
|
||||
),
|
||||
),
|
||||
'pre_tabs_markup' => sprintf(
|
||||
'<div class="ai1ec-gzip-causes-js-failure">' .
|
||||
Ai1ec_I18n::__(
|
||||
'If the form below is not working please follow <a href="%s">this link</a>.'
|
||||
) .
|
||||
'</div>',
|
||||
wp_nonce_url(
|
||||
add_query_arg( 'ai1ec_disable_gzip_compression', '1' ),
|
||||
'ai1ec_disable_gzip_compression'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
$file = $loader->get_file( 'setting/bootstrap_tabs.twig', $args, true );
|
||||
$file->render();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the plugin options, decides what tabs to render.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param array $plugin_settings
|
||||
* @param array $tabs
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _get_tabs_to_show( array $plugin_settings, array $tabs ) {
|
||||
$index = 0;
|
||||
$renderer = $this->_registry->get( 'html.element.setting-renderer' );
|
||||
foreach ( $plugin_settings as $id => $setting ) {
|
||||
// if the setting is shown
|
||||
if ( isset ( $setting['renderer'] ) ) {
|
||||
$tab_to_use = isset( $setting['renderer']['item'] ) ?
|
||||
$setting['renderer']['item'] :
|
||||
$setting['renderer']['tab'];
|
||||
// check if it's the first one
|
||||
if (
|
||||
! isset ( $tabs[$tab_to_use]['elements'] )
|
||||
) {
|
||||
$tabs[$tab_to_use]['elements'] = array();
|
||||
}
|
||||
$setting['id'] = $id;
|
||||
// render the settings
|
||||
$weight = 10;
|
||||
if ( isset( $setting['renderer']['weight'] ) ) {
|
||||
$weight = (int)$setting['renderer']['weight'];
|
||||
}
|
||||
// NOTICE: do NOT change order of two first
|
||||
// elements {weight,index}, otherwise sorting will fail.
|
||||
$tabs[$tab_to_use]['elements'][] = array(
|
||||
'weight' => $weight,
|
||||
'index' => ++$index,
|
||||
'html' => $renderer->render( $setting ),
|
||||
);
|
||||
// if the settings has an item tab, set the item as active.
|
||||
if ( isset( $setting['renderer']['item'] ) ) {
|
||||
if ( ! isset( $tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] ) ) {
|
||||
$tabs[$setting['renderer']['tab']]['items_active'][$setting['renderer']['item']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$tabs_to_display = array();
|
||||
// now let's see what tabs to display.
|
||||
foreach ( $tabs as $name => $tab ) {
|
||||
// sort by weights
|
||||
if ( isset( $tab['elements'] ) ) {
|
||||
asort( $tab['elements'] );
|
||||
}
|
||||
// if a tab has more than one item.
|
||||
if ( isset( $tab['items'] ) ) {
|
||||
// if no item is active, nothing is shown
|
||||
if ( empty( $tab['items_active'] ) ) {
|
||||
continue;
|
||||
}
|
||||
// if only one item is active, do not use the dropdown
|
||||
if ( count( $tab['items_active'] ) === 0 ) {
|
||||
$name = key($tab['items_active']);
|
||||
$tab['name'] = $tab['items'][$name];
|
||||
unset ( $tab['items'] );
|
||||
} else {
|
||||
// check active items for the dropdown
|
||||
foreach ( $tab['items'] as $item => $longname ) {
|
||||
if ( ! isset( $tab['items_active'][$item] ) ) {
|
||||
unset( $tab['items'][$item] );
|
||||
}
|
||||
}
|
||||
}
|
||||
// lets make a check to avoid overriding tabs
|
||||
if ( ! isset( $tabs_to_display[$name] ) ) {
|
||||
$tabs_to_display[$name] = $tab;
|
||||
} else {
|
||||
$tabs_to_display[$name]['elements'] = $tab['elements'];
|
||||
}
|
||||
|
||||
} else {
|
||||
// no items, just check for any element to display.
|
||||
if ( isset( $tab['elements'] ) ) {
|
||||
// lets make a check to avoid overriding tabs
|
||||
if ( ! isset( $tabs_to_display[$name] ) ) {
|
||||
$tabs_to_display[$name] = $tab;
|
||||
} else {
|
||||
$tabs_to_display[$name]['elements'] = $tab['elements'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tabs_to_display;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Theme options page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Theme_Options extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/**
|
||||
* @var string The nonce action
|
||||
*/
|
||||
const NONCE_ACTION = 'ai1ec_theme_options_save';
|
||||
|
||||
/**
|
||||
* @var string The nonce name
|
||||
*/
|
||||
const NONCE_NAME = 'ai1ec_theme_options_nonce';
|
||||
|
||||
/**
|
||||
* @var string The id/name of the submit button.
|
||||
*/
|
||||
const SUBMIT_ID = 'ai1ec_save_themes_options';
|
||||
|
||||
/**
|
||||
* @var string The id/name of the Reset button.
|
||||
*/
|
||||
const RESET_ID = 'ai1ec_reset_themes_options';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $meta_box_id;
|
||||
|
||||
/**
|
||||
* Adds the page to the correct menu.
|
||||
*/
|
||||
public function add_page() {
|
||||
$theme_options_page = add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
Ai1ec_I18n::__( 'Theme Options' ),
|
||||
Ai1ec_I18n::__( 'Theme Options' ),
|
||||
'manage_ai1ec_options',
|
||||
AI1EC_PLUGIN_NAME . '-edit-css',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
if ( false !== $settings->get( 'less_variables_page' ) ) {
|
||||
// Make copy of Theme Options page at its old location.
|
||||
$submenu['themes.php'][] = array(
|
||||
Ai1ec_I18n::__( 'Calendar Theme Options' ),
|
||||
'manage_ai1ec_options',
|
||||
AI1EC_THEME_OPTIONS_BASE_URL,
|
||||
);
|
||||
};
|
||||
$settings->set( 'less_variables_page', $theme_options_page );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta box for page.
|
||||
*
|
||||
* @wp_hook admin_init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_meta_box() {
|
||||
// Add the 'General Settings' meta box.
|
||||
add_meta_box(
|
||||
'ai1ec-less-variables-tabs',
|
||||
Ai1ec_I18n::_x( 'Calendar Theme Options', 'meta box' ),
|
||||
array( $this, 'display_meta_box' ),
|
||||
$this->_registry->get( 'model.settings' )
|
||||
->get( 'less_variables_page' ),
|
||||
'left',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the page html
|
||||
*/
|
||||
public function display_page() {
|
||||
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Calendar Theme Options'
|
||||
),
|
||||
'nonce' => array(
|
||||
'action' => self::NONCE_ACTION,
|
||||
'name' => self::NONCE_NAME,
|
||||
'referrer' => false,
|
||||
),
|
||||
'metabox' => array(
|
||||
'screen' => $settings->get( 'themes_option_page' ),
|
||||
'action' => 'left',
|
||||
'object' => null
|
||||
),
|
||||
'action' =>
|
||||
'?controller=front&action=ai1ec_save_theme_options&plugin=' . AI1EC_PLUGIN_NAME
|
||||
);
|
||||
|
||||
$frontend = $this->_registry->get( 'css.frontend' );
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$file = $loader->get_file( 'theme-options/page.twig', $args, true );
|
||||
|
||||
return $file->render();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the meta box for the settings page.
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param mixed $box
|
||||
*/
|
||||
public function display_meta_box( $object, $box ) {
|
||||
|
||||
$tabs = array(
|
||||
'general' => array(
|
||||
'name' => Ai1ec_I18n::__( 'General' ),
|
||||
),
|
||||
'table' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Tables' ),
|
||||
),
|
||||
'buttons' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Buttons' ),
|
||||
),
|
||||
'forms' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Forms' ),
|
||||
),
|
||||
'calendar' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Calendar general' ),
|
||||
),
|
||||
'month' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Month/week/day view' ),
|
||||
),
|
||||
'agenda' => array(
|
||||
'name' => Ai1ec_I18n::__( 'Agenda view' ),
|
||||
),
|
||||
);
|
||||
|
||||
$tabs = apply_filters( 'ai1ec_less_variables_tabs', $tabs );
|
||||
|
||||
$less_variables = $this->_registry
|
||||
->get( 'less.lessphp' )->get_saved_variables();
|
||||
$tabs = $this->_get_tabs_to_show( $less_variables, $tabs );
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$args = array(
|
||||
'stacked' => true,
|
||||
'content_class' => 'ai1ec-form-horizontal',
|
||||
'tabs' => $tabs,
|
||||
'submit' => array(
|
||||
'id' => self::SUBMIT_ID,
|
||||
'value' => '<i class="ai1ec-fa ai1ec-fa-save ai1ec-fa-fw"></i> ' .
|
||||
Ai1ec_I18n::__( 'Save Options' ),
|
||||
'args' => array(
|
||||
'class' => 'ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg',
|
||||
),
|
||||
),
|
||||
'reset' => array(
|
||||
'id' => self::RESET_ID,
|
||||
'value' => '<i class="ai1ec-fa ai1ec-fa-undo ai1ec-fa-fw"></i> ' .
|
||||
Ai1ec_I18n::__( 'Reset to Defaults' ),
|
||||
'args' => array(
|
||||
'class' => 'ai1ec-btn ai1ec-btn-danger ai1ec-btn-lg',
|
||||
),
|
||||
),
|
||||
);
|
||||
$file = $loader->get_file( 'theme-options/bootstrap_tabs.twig', $args, true );
|
||||
$file->render();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the theme options tabs
|
||||
*
|
||||
* @param array $less_variables
|
||||
* @param array $tabs list of tabs
|
||||
*
|
||||
* @return array the array of tabs to display
|
||||
*/
|
||||
protected function _get_tabs_to_show( array $less_variables, array $tabs) {
|
||||
|
||||
// Inizialize the array of tabs that will be added to the layout
|
||||
$bootstrap_tabs_to_add = array();
|
||||
|
||||
foreach( $tabs as $id => $tab ){
|
||||
$tab['elements'] = array();
|
||||
$bootstrap_tabs_to_add[$id] = $tab;
|
||||
}
|
||||
foreach ( $less_variables as $variable_id => $variable_attributes ) {
|
||||
$variable_attributes['id'] = $variable_id;
|
||||
$renderable = $this->_registry->get(
|
||||
'less.variable.' . $variable_attributes['type'],
|
||||
$variable_attributes
|
||||
);
|
||||
$bootstrap_tabs_to_add[$variable_attributes['tab']]['elements'][] = array(
|
||||
'html' => $renderable->render()
|
||||
);
|
||||
}
|
||||
return $bootstrap_tabs_to_add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle post, likely to be deprecated to use commands.
|
||||
*/
|
||||
public function handle_post() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The Theme selection page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Admin_Theme_Switching extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Abstract::display_page()
|
||||
*/
|
||||
public function display_page() {
|
||||
global $ct;
|
||||
// defaults
|
||||
$activated = isset( $_GET['activated'] ) ? true : false;
|
||||
$deleted = false;
|
||||
|
||||
$_list_table = $this->_registry->get( 'theme.list' );
|
||||
$_list_table->prepare_items();
|
||||
|
||||
$args = array(
|
||||
'activated' => $activated,
|
||||
'deleted' => $deleted,
|
||||
'ct' => $ct,
|
||||
'wp_list_table' => $_list_table,
|
||||
'page_title' => Ai1ec_I18n::__(
|
||||
'All-in-One Event Calendar: Themes'
|
||||
),
|
||||
);
|
||||
|
||||
add_thickbox();
|
||||
wp_enqueue_script( 'theme-preview' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
|
||||
$file = $loader->get_file( 'themes.php', $args, true );
|
||||
return $file->render();
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Abstract::add_page()
|
||||
*/
|
||||
public function add_page() {
|
||||
global $submenu;
|
||||
// ===============
|
||||
// = Themes Page =
|
||||
// ===============
|
||||
$themes_page = add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
Ai1ec_I18n::__( 'Calendar Themes' ),
|
||||
Ai1ec_I18n::__( 'Calendar Themes' ),
|
||||
'switch_ai1ec_themes',
|
||||
AI1EC_PLUGIN_NAME . '-themes',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
}
|
||||
|
||||
public function add_meta_box() {
|
||||
}
|
||||
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tickets page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.4
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View
|
||||
*/
|
||||
class Ai1ec_View_Tickets extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/**
|
||||
* @var string The nonce action
|
||||
*/
|
||||
const NONCE_ACTION = 'ai1ec_api_ticketing_signup';
|
||||
|
||||
/**
|
||||
* @var string The nonce name
|
||||
*/
|
||||
const NONCE_NAME = 'ai1ec_api_ticketing_nonce';
|
||||
|
||||
/**
|
||||
* @var string The id/name of the submit button.
|
||||
*/
|
||||
const SUBMIT_ID = 'ai1ec_api_ticketing_signup';
|
||||
|
||||
/**
|
||||
* Adds the page to the correct menu.
|
||||
*/
|
||||
public function add_page() {
|
||||
add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
__( 'Ticketing', AI1EC_PLUGIN_NAME ),
|
||||
__( 'Ticketing', AI1EC_PLUGIN_NAME ),
|
||||
'manage_ai1ec_feeds',
|
||||
AI1EC_PLUGIN_NAME . '-tickets',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta box for page.
|
||||
*
|
||||
* @wp_hook admin_init
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_meta_box() {}
|
||||
|
||||
/**
|
||||
* Display the page html
|
||||
*/
|
||||
public function display_page() {
|
||||
|
||||
$signed_to_api = $this->_api_registration->is_signed();
|
||||
$signup_available = $this->_api_registration->is_api_sign_up_available();
|
||||
$ticketing_available = $this->_api_registration->is_ticket_available();
|
||||
$ticketing_enabled = $this->_api_registration->has_subscription_active( Ai1ec_Api_Features::CODE_TICKETING );
|
||||
$ticketing_message = $this->_api_registration->get_sign_message();
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
wp_enqueue_style(
|
||||
'ai1ec_samples.css',
|
||||
AI1EC_ADMIN_THEME_CSS_URL . 'samples.css',
|
||||
array(),
|
||||
AI1EC_VERSION
|
||||
);
|
||||
|
||||
if ( ! $signed_to_api ) {
|
||||
|
||||
if ( false === ai1ec_is_blank( $ticketing_message ) ) {
|
||||
$this->_api_registration->clear_sign_message();
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Timely Ticketing'
|
||||
),
|
||||
'sign_up_text' => 'Please, <a href="edit.php?post_type=ai1ec_event&page=all-in-one-event-calendar-settings">Sign Up for a Timely Network account</a> to use Ticketing.',
|
||||
'signup_form' => Ai1ec_I18n::__( 'You need to sign up for a Timely Network account in order to use Ticketing.<br /><br />' ) .
|
||||
(
|
||||
$signup_available
|
||||
? Ai1ec_I18n::__( '<a href="edit.php?post_type=ai1ec_event&page=all-in-one-event-calendar-settings" class="ai1ec-btn ai1ec-btn-primary ai1ec-btn-lg">Sign In to Timely Network</a>' )
|
||||
: Ai1ec_I18n::__( '<b>Signing up for a Timely Network account is currently unavailable. Please, try again later.</b>' )
|
||||
),
|
||||
'show_info' => true
|
||||
|
||||
);
|
||||
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
||||
} elseif ( ! $ticketing_available ) {
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Timely Ticketing'
|
||||
),
|
||||
'sign_up_text' => '',
|
||||
'signup_form' => 'Ticketing is currently not available for this website. Please, try again later.',
|
||||
'show_info' => true
|
||||
|
||||
);
|
||||
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
||||
} elseif ( ! $ticketing_enabled ) {
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Timely Ticketing'
|
||||
),
|
||||
'sign_up_text' => '',
|
||||
'signup_form' => '',
|
||||
'show_info' => true
|
||||
);
|
||||
$file = $loader->get_file( 'ticketing/signup.twig', $args, true );
|
||||
} else {
|
||||
$response = $this->_api_registration->get_payment_preferences();
|
||||
$purchases = $this->_api_registration->get_purchases();
|
||||
$args = array(
|
||||
'title' => Ai1ec_I18n::__(
|
||||
'Timely Ticketing'
|
||||
),
|
||||
'settings_text' => Ai1ec_I18n::__( 'Settings' ),
|
||||
'sales_text' => Ai1ec_I18n::__( 'Sales' ),
|
||||
'select_payment_text' => Ai1ec_I18n::__( 'Please provide your PayPal details.' ),
|
||||
'cheque_text' => Ai1ec_I18n::__( 'Cheque' ),
|
||||
'paypal_text' => Ai1ec_I18n::__( 'PayPal' ),
|
||||
'currency_text' => Ai1ec_I18n::__( 'Preferred currency for tickets:' ),
|
||||
'required_text' => Ai1ec_I18n::__( 'This field is required.' ),
|
||||
'save_changes_text' => Ai1ec_I18n::__( 'Save Changes' ),
|
||||
'date_text' => Ai1ec_I18n::__( 'Date' ),
|
||||
'event_text' => Ai1ec_I18n::__( 'Event' ),
|
||||
'purchaser_text' => Ai1ec_I18n::__( 'Purchaser' ),
|
||||
'tickets_text' => Ai1ec_I18n::__( 'Tickets' ),
|
||||
'email_text' => Ai1ec_I18n::__( 'Email' ),
|
||||
'status_text' => Ai1ec_I18n::__( 'Status' ),
|
||||
'total_text' => Ai1ec_I18n::__( 'Total' ),
|
||||
'sign_out_button_text' => Ai1ec_I18n::__( 'Sign Out' ),
|
||||
'payment_method' => $response->payment_method,
|
||||
'paypal_email' => $response->paypal_email,
|
||||
'first_name' => $response->first_name,
|
||||
'last_name' => $response->last_name,
|
||||
'currency' => $response->currency,
|
||||
'nonce' => array(
|
||||
'action' => self::NONCE_ACTION,
|
||||
'name' => self::NONCE_NAME,
|
||||
'referrer' => false,
|
||||
),
|
||||
'action' =>
|
||||
'?controller=front&action=ai1ec_api_ticketing_signup&plugin=' .
|
||||
AI1EC_PLUGIN_NAME,
|
||||
'purchases' => $purchases,
|
||||
'paypal_currencies' => array (
|
||||
array( 'description' => Ai1ec_I18n::__( 'United States Dollar' ), 'code' => 'USD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Canadian Dollar' ), 'code' => 'CAD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Australian Dollar' ), 'code' => 'AUD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Brazilian Real' ), 'code' => 'BRL', 'note' => Ai1ec_I18n::__( 'Note: This currency is supported as a payment currency and a currency balance for in-country PayPal accounts only.' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Czech Koruna' ), 'code' => 'CZK' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Danish Krone' ), 'code' => 'DKK' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Euro' ), 'code' => 'EUR' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Hong Kong Dollar' ), 'code' => 'HKD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Hungarian Forint' ), 'code' => 'HUF', 'note' => Ai1ec_I18n::__( 'Note: Decimal amounts are not supported for this currency. Passing a decimal amount will throw an error.' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Israeli New Sheqel' ), 'code' => 'ILS' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Japanese Yen' ), 'code' => 'JPY', 'note' => Ai1ec_I18n::__( 'Note: This currency does not support decimals. Passing a decimal amount will throw an error. 1,000,000' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Malaysian Ringgit' ), 'code' => 'MYR', 'note' => Ai1ec_I18n::__( 'Note: This currency is supported as a payment currency and a currency balance for in-country PayPal accounts only.' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Mexican Peso' ), 'code' => 'MXN' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Norwegian Krone' ), 'code' => 'NOK' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'New Zealand Dollar' ), 'code' => 'NZD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Philippine Peso' ), 'code' => 'PHP' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Polish Zloty' ), 'code' => 'PLN' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Pound Sterling' ), 'code' => 'GBP' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Russian Ruble' ), 'code' => 'RUB', 'note' => Ai1ec_I18n::__( 'For in-border payments (payments made within Russia), the Russian Ruble is the only accepted currency. If you use another currency for in-border payments, the transaction will fail' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Singapore Dollar' ), 'code' => 'SGD' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Swedish Krona' ), 'code' => 'SEK' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Swiss Franc' ), 'code' => 'CHF' ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Taiwan New Dollar' ), 'code' => 'TWD', 'note' => Ai1ec_I18n::__( 'Note: Decimal amounts are not supported for this currency. Passing a decimal amount will throw an error.' ) ),
|
||||
array( 'description' => Ai1ec_I18n::__( 'Thai Baht' ), 'code' => 'THB' ),
|
||||
)
|
||||
);
|
||||
$file = $loader->get_file( 'ticketing/manage.twig', $args, true );
|
||||
}
|
||||
|
||||
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
||||
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
||||
);
|
||||
$this->_registry->get( 'css.admin' )->process_enqueue(
|
||||
array(
|
||||
array( 'style', 'ticketing.css', ),
|
||||
)
|
||||
);
|
||||
if ( isset( $_POST['ai1ec_save_settings'] ) ) {
|
||||
$response = $this->_api_registration->save_payment_preferences();
|
||||
|
||||
// this redirect makes sure that the error messages appear on the screen
|
||||
if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
|
||||
header( "Location: " . $_SERVER['HTTP_REFERER'] );
|
||||
}
|
||||
}
|
||||
return $file->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle post, likely to be deprecated to use commands.
|
||||
*/
|
||||
public function handle_post(){}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The SuperWidget creator page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.1
|
||||
*
|
||||
* @package AI1ECSW
|
||||
* @subpackage AI1ECSW.View
|
||||
*/
|
||||
class Ai1ec_View_Widget_Creator extends Ai1ec_View_Admin_Abstract {
|
||||
|
||||
/**
|
||||
* Adds page to the menu.
|
||||
*
|
||||
* @wp_hook admin_menu
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_page() {
|
||||
add_submenu_page(
|
||||
AI1EC_ADMIN_BASE_URL,
|
||||
__( 'Widget Creator', AI1EC_PLUGIN_NAME ),
|
||||
__( 'Widget Creator', AI1EC_PLUGIN_NAME ),
|
||||
'manage_ai1ec_feeds',
|
||||
AI1EC_PLUGIN_NAME . '-widget-creator',
|
||||
array( $this, 'display_page' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display this plugin's feeds page in the admin.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_page() {
|
||||
$this->_registry->get( 'css.admin' )->admin_enqueue_scripts(
|
||||
'ai1ec_event_page_all-in-one-event-calendar-settings'
|
||||
);
|
||||
$this->_registry->get( 'css.admin' )->process_enqueue(
|
||||
array(
|
||||
array( 'style', 'super-widget.css', ),
|
||||
)
|
||||
);
|
||||
$args = array(
|
||||
'title' => __(
|
||||
'Widget Creator',
|
||||
AI1EC_PLUGIN_NAME
|
||||
),
|
||||
'metabox' => array(
|
||||
'screen' => 'ai1ec-super-widget',
|
||||
'action' => 'left',
|
||||
'object' => null
|
||||
),
|
||||
);
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file( 'widget-creator/page.twig', $args, true );
|
||||
$file->render();
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Settings::handle_post()
|
||||
*/
|
||||
public function handle_post() {
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Settings::add_meta_box()
|
||||
*/
|
||||
public function add_meta_box() {
|
||||
add_meta_box(
|
||||
'ai1ec-widget-creator',
|
||||
_x( 'Widget Creator', 'meta box', AI1EC_PLUGIN_NAME ),
|
||||
array( $this, 'display_meta_box' ),
|
||||
'ai1ec-super-widget',
|
||||
'left',
|
||||
'default'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the settings
|
||||
*
|
||||
* @param array $settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_html_from_settings( array $settings ) {
|
||||
$named_elements = array();
|
||||
foreach ( $settings as $id => $setting ) {
|
||||
$named_elements[$id] = $this->_registry->get(
|
||||
'html.element.setting.' . $setting['renderer']['class'],
|
||||
array(
|
||||
'id' => $id,
|
||||
'value' => $setting['value'],
|
||||
'renderer' => $setting['renderer'],
|
||||
)
|
||||
)->render();
|
||||
}
|
||||
return $named_elements;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Ai1ec_View_Admin_Settings::display_meta_box()
|
||||
*/
|
||||
public function display_meta_box( $object, $box ) {
|
||||
$widgets = $this->_registry->get( 'controller.javascript-widget' )
|
||||
->get_widgets();
|
||||
// this is just for the Super Widget which doesn't fully implement Ai1ec_Embeddable
|
||||
$widgets = apply_filters( 'ai1ec_widget_creators_widgets', $widgets );
|
||||
$tabs = array();
|
||||
foreach ( $widgets as $widget_id => $widget_class ) {
|
||||
$widget = $this->_registry->get( $widget_class );
|
||||
$tabs[$widget_id] = array(
|
||||
'name' => $widget->get_name(),
|
||||
'icon' => $widget->get_icon(),
|
||||
'requirements' => $widget->check_requirements(),
|
||||
'elements' => $this->get_html_from_settings(
|
||||
$widget->get_configurable_for_widget_creation()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file(
|
||||
'widget-creator/super-widget-contents.twig',
|
||||
array(
|
||||
'tabs' => $tabs,
|
||||
'siteurl' => trailingslashit( preg_replace( '/^.*?:/', '', ai1ec_get_site_url() ) ),
|
||||
'text_common_info' => Ai1ec_I18n::__( 'Use this tool to generate code snippets you can add to <strong>an external website</strong> to embed new calendars and widgets.' ),
|
||||
'text_alert' => Ai1ec_I18n::__( '<h4>Attention!</h4><p>These widgets are designed to be embedded in <strong>external sites only</strong> and may cause conflicts if used within the same WordPress site.</p>' ),
|
||||
'text_alternatives' => sprintf(
|
||||
Ai1ec_I18n::__( '<p>Use <a href="%s"><strong>Appearance</strong> > <strong>Widgets</strong></a> to add event widgets to your WordPress site as you would any other widget, or use <a href="%s" target="_blank">shortcodes</a> to embed the full calendar.</strong></p>' ),
|
||||
admin_url( 'widgets.php' ),
|
||||
'https://time.ly/document/user-guide/using-calendar/display-multiple-calendars-site/'
|
||||
),
|
||||
'display_alert' => apply_filters( 'ai1ec_display_widget_creator_warning', true ),
|
||||
'text_preview' => Ai1ec_I18n::__( 'Preview:' ),
|
||||
'text_paste' => Ai1ec_I18n::__( 'Paste this code onto your site:' ),
|
||||
'text_updated_code' => Ai1ec_I18n::__( 'This code will update to reflect changes made to the settings. Changing settings will not affect previously embedded widgets.' ),
|
||||
),
|
||||
true
|
||||
);
|
||||
$file->render();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
abstract class Ai1ec_Embeddable extends WP_Widget {
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Registry_Object
|
||||
*/
|
||||
protected $_registry;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_css_loaded = false;
|
||||
|
||||
/**
|
||||
* Get default values for shortcode or widget.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_defaults();
|
||||
|
||||
/**
|
||||
* Get values which are configurable in the Javascript widget.
|
||||
* Some things might not be configurable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_js_widget_configurable_defaults();
|
||||
|
||||
/**
|
||||
* Create the html for the widget. Shared by all versions.
|
||||
*
|
||||
* @param array $args_for_widget
|
||||
* @param bool $remote_request whether the request is for a remote site or not (useful to inline CSS)
|
||||
*/
|
||||
abstract public function get_content( array $args_for_widget, $remote_request = false );
|
||||
|
||||
/**
|
||||
* Add the required javascript for the widget. Needed for shortcode and Wordpress widget
|
||||
*/
|
||||
abstract public function add_js();
|
||||
|
||||
/**
|
||||
* Register the widget to the controller.
|
||||
*
|
||||
* @param string $id_base
|
||||
*/
|
||||
abstract public function register_javascript_widget( $id_base );
|
||||
|
||||
|
||||
/**
|
||||
* Return options needed for thw "Widget creator page
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_configurable_for_widget_creation();
|
||||
|
||||
/**
|
||||
* The human-readable name of the widget.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function get_name();
|
||||
|
||||
/**
|
||||
* The icon class associated with the widget. Defaults to calendar.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon() {
|
||||
return 'ai1ec-fa ai1ec-fa-calendar';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and returns widget requirements.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function check_requirements();
|
||||
|
||||
/**
|
||||
* Register widget class with current WP instance.
|
||||
* This must be static as otherwise the class would be instantiated twice,
|
||||
* one to register it and the other from Wordpress.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function register_widget() {
|
||||
throw new Ai1ec_Exception( 'This should be implemented in child class' );
|
||||
}
|
||||
|
||||
public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
|
||||
$this->_id = $id_base;
|
||||
parent::__construct( $id_base, $name, $widget_options, $control_options );
|
||||
add_shortcode( $id_base, array( $this, 'shortcode' ) );
|
||||
add_filter(
|
||||
'ai1ec_content_remove_shortcode_' . $id_base,
|
||||
array( $this, 'is_this_to_remove_from_event' )
|
||||
);
|
||||
$this->_registry = apply_filters( 'ai1ec_registry', false );
|
||||
$this->register_javascript_widget( $id_base );
|
||||
add_filter( 'ai1ec_js_translations', array( $this, 'add_js_translations' ) );
|
||||
$this->_registry->get( 'css.frontend' )->add_link_to_html_for_frontend();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $translations
|
||||
* @return array
|
||||
*/
|
||||
public function add_js_translations( array $translations ) {
|
||||
$translations['javascript_widgets'][$this->_id] = $this->get_js_widget_configurable_defaults();
|
||||
return $translations;
|
||||
}
|
||||
/**
|
||||
* Widget function.
|
||||
*
|
||||
* Outputs the given instance of the widget to the front-end.
|
||||
*
|
||||
* @param array $args Display arguments passed to the widget
|
||||
* @param array $instance The settings for this widget instance
|
||||
* @return void
|
||||
*/
|
||||
public function widget( $args, $instance ) {
|
||||
$defaults = $this->get_defaults();
|
||||
$instance = wp_parse_args( $instance, $defaults );
|
||||
$this->add_js();
|
||||
$args['widget_html'] = $this->get_content( $instance );
|
||||
if ( ! empty( $args['widget_html'] ) ) {
|
||||
$args['title'] = $instance['title'];
|
||||
$args = $this->_filter_widget_args( $args );
|
||||
// Display theme
|
||||
$this->_registry->get( 'theme.loader' )->get_file(
|
||||
'widget.twig',
|
||||
$args
|
||||
)->render();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders shortcode
|
||||
*
|
||||
* @param array $atts
|
||||
* @param string $content
|
||||
*/
|
||||
public function shortcode( $atts, $content = null ) {
|
||||
$defaults = $this->get_defaults();
|
||||
$atts = shortcode_atts( $defaults, $atts );
|
||||
$this->add_js();
|
||||
return $this->get_content( $atts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders js widget
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
public function javascript_widget( $args ) {
|
||||
$defaults = $this->get_defaults();
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
return $this->get_content( $args, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this shortcode should be removed from event content.
|
||||
*
|
||||
* @return bool True.
|
||||
*/
|
||||
public function is_this_to_remove_from_event() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters default widget parameters like classes, html elements before and
|
||||
* after title or widget. Useful for Feature Events widget which has
|
||||
* different title styling.
|
||||
*
|
||||
* @param array $args Widget arguments.
|
||||
*
|
||||
* @return array Filtered arguments.
|
||||
*/
|
||||
protected function _filter_widget_args( $args ) {
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event avatar.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Avatar extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Get HTML markup for the post's "avatar" image according conditional
|
||||
* fallback model.
|
||||
*
|
||||
* Accepts an ordered array of named avatar $fallbacks. Also accepts a string
|
||||
* of space-separated classes to add to the default classes.
|
||||
* @param Ai1ec_Event $event The event to get the avatar for
|
||||
* @param array|null $fallback_order Order of fallback in searching for
|
||||
* images, or null to use default
|
||||
* @param string $classes A space-separated list of CSS classes
|
||||
* to apply to the outer <div> element.
|
||||
* @param boolean $wrap_permalink Whether to wrap the element in a link
|
||||
* to the event details page.
|
||||
*
|
||||
* @return string String of HTML if image is found
|
||||
*/
|
||||
public function get_event_avatar(
|
||||
Ai1ec_Event $event,
|
||||
$fallback_order = null,
|
||||
$classes = '',
|
||||
$wrap_permalink = true
|
||||
) {
|
||||
$source = $size = null;
|
||||
$url = $this->get_event_avatar_url(
|
||||
$event,
|
||||
$fallback_order,
|
||||
$source,
|
||||
$size
|
||||
);
|
||||
|
||||
if ( empty( $url ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$url = esc_attr( $url );
|
||||
$classes = esc_attr( $classes );
|
||||
|
||||
// Set the alt tag (helpful for SEO).
|
||||
$alt = $event->get( 'post' )->post_title;
|
||||
$location = $this->_registry->get( 'view.event.location' )->get_short_location( $event );
|
||||
if ( ! empty( $location ) ) {
|
||||
$alt .= ' @ ' . $location;
|
||||
}
|
||||
|
||||
$alt = esc_attr( $alt );
|
||||
$size_attr = $size[0] ? "width=\"$size[0]\" height=\"$size[1]\"" : "";
|
||||
$html = '<img src="' . $url . '" alt="' . $alt . '" ' .
|
||||
$size_attr . ' />';
|
||||
|
||||
if ( $wrap_permalink ) {
|
||||
$permalink = add_query_arg(
|
||||
'instance_id',
|
||||
$event->get( 'instance_id' ),
|
||||
get_permalink( $event->get( 'post_id' ) )
|
||||
);
|
||||
$html = '<a href="' . $permalink . '">' . $html . '</a>';
|
||||
}
|
||||
|
||||
$classes .= ' ai1ec-' . $source;
|
||||
$classes .= ( $size[0] > $size[1] )
|
||||
? ' ai1ec-landscape'
|
||||
: ' ai1ec-portrait';
|
||||
$html = '<div class="ai1ec-event-avatar timely ' . $classes . '">' .
|
||||
$html . '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post's "avatar" image url according conditional fallback model.
|
||||
*
|
||||
* Accepts an ordered array of named methods for $fallback order. Returns
|
||||
* image URL or null if no image found. Also returns matching fallback in the
|
||||
* $source reference.
|
||||
*
|
||||
* @param array|null $fallback_order Order of fallbacks in search for images
|
||||
* @param null $source Fallback that returned matching image,
|
||||
* returned format is string
|
||||
* @param null $size (width, height) array of returned image
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_event_avatar_url(
|
||||
Ai1ec_Event $event,
|
||||
$fallback_order = null,
|
||||
&$source = null,
|
||||
&$size = null
|
||||
) {
|
||||
if ( empty( $fallback_order ) ) {
|
||||
$fallback_order = array(
|
||||
'post_thumbnail',
|
||||
'content_img',
|
||||
'category_avatar',
|
||||
'default_avatar',
|
||||
);
|
||||
}
|
||||
|
||||
$valid_fallbacks = $this->_get_valid_fallbacks();
|
||||
|
||||
foreach ( $fallback_order as $fallback ) {
|
||||
if ( ! isset( $valid_fallbacks[$fallback] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$function = $valid_fallbacks[$fallback];
|
||||
$url = null;
|
||||
if (
|
||||
! is_array( $function ) &&
|
||||
method_exists( $this, $function )
|
||||
) {
|
||||
$url = $this->$function( $event, $size );
|
||||
} else if ( is_callable( $function ) ) {
|
||||
$url = call_user_func_array( $function, array( $event, &$size ) );
|
||||
}
|
||||
if ( null !== $url ) {
|
||||
$source = $fallback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $url ) ) {
|
||||
return null;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read post meta for post-thumbnail and return its URL as a string.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
* @param null $size (width, height) array of returned image.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_post_thumbnail_url( Ai1ec_Event $event, &$size = null ) {
|
||||
return $this->_get_post_attachment_url(
|
||||
$event,
|
||||
array(
|
||||
'medium',
|
||||
'large',
|
||||
'full',
|
||||
),
|
||||
$size
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read post meta for post-image and return its URL as a string.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
* @param null $size (width, height) array of returned image.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_post_image_url( Ai1ec_Event $event, &$size = null ) {
|
||||
return $this->_get_post_attachment_url(
|
||||
$event,
|
||||
array(
|
||||
'full',
|
||||
'large',
|
||||
'medium'
|
||||
),
|
||||
$size
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read post meta for featured image and return its URL as a string.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
* @param null $size (width, height) array of returned image.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_featured_image_url( Ai1ec_Event $event, &$size = null ) {
|
||||
$featured_image = get_post_meta( $event->get( 'post_id' ) , '_featured_image', true );
|
||||
if ( empty( $featured_image ) ) {
|
||||
return $this->_get_post_attachment_url(
|
||||
$event,
|
||||
array(
|
||||
'full',
|
||||
'large',
|
||||
'medium'
|
||||
),
|
||||
$size
|
||||
);
|
||||
} else {
|
||||
$priority_order = array( 'large', 'full', 'medium', 'thumbnail' );
|
||||
$url = null;
|
||||
foreach ( $priority_order as $priority ) {
|
||||
foreach ( $featured_image as $values_arr ) {
|
||||
if ( $values_arr[0] === $priority ) {
|
||||
$url = $values_arr[1];
|
||||
$size = array( $values_arr[2], $values_arr[3] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( null !== $url ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the avatar url from the event content
|
||||
*/
|
||||
public function remove_avatar_url( $content ) {
|
||||
return preg_replace( '/<div[^<>]+class=[\'"]?ai1ec-event-avatar[^<>]*[\'"]?[^<>]+>.+<\/div>[.\s]*/'
|
||||
, ''
|
||||
, $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple regex-parse of post_content for matches of <img src="foo" />; if
|
||||
* one is found, return its URL.
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
* @param null $size (width, height) array of returned image
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_content_img_url( Ai1ec_Event $event, &$size = null ) {
|
||||
$matches = $this->get_image_from_content(
|
||||
$event->get( 'post' )->post_content
|
||||
);
|
||||
// Check if we have a result, otherwise a notice is issued.
|
||||
if ( empty( $matches ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = $matches[2];
|
||||
$size = array( 0, 0 );
|
||||
|
||||
// Try to detect width and height.
|
||||
$attrs = $matches[1] . $matches[3];
|
||||
$matches = null;
|
||||
preg_match_all(
|
||||
'/(width|height)=["\']?(\d+)/i',
|
||||
$attrs,
|
||||
$matches,
|
||||
PREG_SET_ORDER
|
||||
);
|
||||
// Check if we have a result, otherwise a notice is issued.
|
||||
if ( ! empty( $matches ) ) {
|
||||
foreach ( $matches as $match ) {
|
||||
$size[ $match[1] === 'width' ? 0 : 1 ] = $match[2];
|
||||
}
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image tag from an html string
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_image_from_content( $content ) {
|
||||
preg_match(
|
||||
'/<img([^>]+)src=["\']?([^"\'\ >]+)([^>]*)>/i',
|
||||
$content,
|
||||
$matches
|
||||
);
|
||||
return $matches;
|
||||
}
|
||||
/**
|
||||
* Returns default avatar image (normally when no other ones are available).
|
||||
*
|
||||
* @param null $size (width, height) array of returned image
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_default_avatar_url( &$size = null ) {
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$file = $loader->get_file( 'default-event-avatar.png', array(), false );
|
||||
$size = array( 256, 256 );
|
||||
return $file->get_url();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns avatar image for event's deepest category, if any.
|
||||
*
|
||||
* @param Ai1ec_Event $event Avatar requester.
|
||||
* @param void $size Unused argument.
|
||||
*
|
||||
* @return string|null Avatar's HTML or null if none.
|
||||
*/
|
||||
public function get_category_avatar_url( Ai1ec_Event $event, &$size = null ) {
|
||||
$db = $this->_registry->get( 'dbi.dbi' );
|
||||
|
||||
$terms = $this->_registry->get( 'model.taxonomy' )->get_post_categories(
|
||||
$event->get( 'post_id' )
|
||||
);
|
||||
if ( empty( $terms ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$terms_by_id = array();
|
||||
// Key $terms by term_id rather than arbitrary int.
|
||||
foreach ( $terms as $term ) {
|
||||
$terms_by_id[$term->term_id] = $term;
|
||||
}
|
||||
|
||||
// Array to store term depths, sorted later.
|
||||
$term_depths = array();
|
||||
foreach ( $terms_by_id as $term ) {
|
||||
$depth = 0;
|
||||
$ancestor = $term;
|
||||
while ( ! empty( $ancestor->parent ) ) {
|
||||
$depth++;
|
||||
if ( ! isset( $terms_by_id[$ancestor->parent] ) ) {
|
||||
break;
|
||||
}
|
||||
$ancestor = $terms_by_id[$ancestor->parent];
|
||||
}
|
||||
// Store negative depths for asort() to order from deepest to shallowest.
|
||||
$term_depths[$term->term_id] = -$depth;
|
||||
}
|
||||
// Order term IDs by depth.
|
||||
asort( $term_depths );
|
||||
|
||||
$url = '';
|
||||
$model = $this->_registry->get( 'model.taxonomy' );
|
||||
// Starting at deepest depth, find the first category that has an avatar.
|
||||
foreach ( $term_depths as $term_id => $depth ) {
|
||||
$term_image = $model->get_category_image( $term_id );
|
||||
if ( $term_image ) {
|
||||
$url = $term_image;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return empty( $url ) ? null : $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read post meta for post-attachment and return its URL as a string.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
* @param array $ordered_img_sizes Image sizes order.
|
||||
* @param null $size (width, height) array of returned
|
||||
* image.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function _get_post_attachment_url(
|
||||
Ai1ec_Event $event,
|
||||
array $ordered_img_sizes,
|
||||
&$size = null
|
||||
) {
|
||||
// Since WP does will return null if the wrong size is targeted,
|
||||
// we iterate over an array of sizes, breaking if a URL is found.
|
||||
foreach ( $ordered_img_sizes as $size ) {
|
||||
$attributes = wp_get_attachment_image_src(
|
||||
get_post_thumbnail_id( $event->get( 'post_id' ) ), $size
|
||||
);
|
||||
if ( $attributes ) {
|
||||
$url = array_shift( $attributes );
|
||||
$size = $attributes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return empty( $url ) ? null : $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of valid fallbacks.
|
||||
*
|
||||
* @return array List of valid fallbacks.
|
||||
*/
|
||||
protected function _get_valid_fallbacks() {
|
||||
static $fallbacks;
|
||||
if ( null === $fallbacks ) {
|
||||
$fallbacks = apply_filters(
|
||||
'ai1ec_avatar_valid_callbacks',
|
||||
array(
|
||||
'post_image' => 'get_post_image_url',
|
||||
'post_thumbnail' => 'get_post_thumbnail_url',
|
||||
'content_img' => 'get_content_img_url',
|
||||
'category_avatar' => 'get_category_avatar_url',
|
||||
'default_avatar' => 'get_default_avatar_url',
|
||||
'featured_image' => 'get_featured_image_url'
|
||||
)
|
||||
);
|
||||
}
|
||||
return $fallbacks;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event colors.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Color extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Faded version of event category color
|
||||
*/
|
||||
protected function _get_color( Ai1ec_Event $event, $type ) {
|
||||
static $categories_cache = array(
|
||||
'rgba' => array(),
|
||||
'faded' => array(),
|
||||
);
|
||||
$methods = array(
|
||||
'rgba' => 'get_event_category_rgba_color',
|
||||
'faded' => 'get_event_category_faded_color',
|
||||
);
|
||||
$categories = $this->_registry->get( 'model.taxonomy' )
|
||||
->get_post_categories( $event->get( 'post_id' ) );
|
||||
if ( ! empty( $categories ) ) {
|
||||
if (
|
||||
! isset( $categories_cache[$type][$categories[0]->term_id] )
|
||||
) {
|
||||
$method = $methods[$type];
|
||||
$categories_cache[$type][$categories[0]->term_id] = $this
|
||||
->$method( $categories[0]->term_id );
|
||||
}
|
||||
return $categories_cache[$type][$categories[0]->term_id];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
public function get_faded_color( Ai1ec_Event $event ) {
|
||||
return $this->_get_color( $event, 'faded' );
|
||||
}
|
||||
|
||||
/**
|
||||
* rgba() format of faded category color.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_rgba_color( Ai1ec_Event $event ) {
|
||||
return $this->_get_color( $event, 'rgba' );
|
||||
}
|
||||
/**
|
||||
* Returns a faded version of the event's category color in hex format.
|
||||
*
|
||||
* @param int $term_id The Event Category's term ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_event_category_faded_color( $term_id ) {
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$color = $taxonomy->get_category_color( $term_id );
|
||||
if( ! is_null( $color ) && ! empty( $color ) ) {
|
||||
|
||||
$color1 = substr( $color, 1 );
|
||||
$color2 = 'ffffff';
|
||||
|
||||
$c1_p1 = hexdec( substr( $color1, 0, 2 ) );
|
||||
$c1_p2 = hexdec( substr( $color1, 2, 2 ) );
|
||||
$c1_p3 = hexdec( substr( $color1, 4, 2 ) );
|
||||
|
||||
$c2_p1 = hexdec( substr( $color2, 0, 2 ) );
|
||||
$c2_p2 = hexdec( substr( $color2, 2, 2 ) );
|
||||
$c2_p3 = hexdec( substr( $color2, 4, 2 ) );
|
||||
|
||||
$m_p1 = dechex( round( $c1_p1 * 0.5 + $c2_p1 * 0.5 ) );
|
||||
$m_p2 = dechex( round( $c1_p2 * 0.5 + $c2_p2 * 0.5 ) );
|
||||
$m_p3 = dechex( round( $c1_p3 * 0.5 + $c2_p3 * 0.5 ) );
|
||||
|
||||
return '#' . $m_p1 . $m_p2 . $m_p3;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rgba() format of the event's category color, with '%s' in place
|
||||
* of the opacity (to be substituted by sprintf).
|
||||
*
|
||||
* @param int $term_id The Event Category's term ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_event_category_rgba_color( $term_id ) {
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$color = $taxonomy->get_category_color( $term_id );
|
||||
if ( ! is_null( $color ) && ! empty( $color ) ) {
|
||||
$p1 = hexdec( substr( $color, 1, 2 ) );
|
||||
$p2 = hexdec( substr( $color, 3, 2 ) );
|
||||
$p3 = hexdec( substr( $color, 5, 2 ) );
|
||||
return "rgba($p1, $p2, $p3, %s)";
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class process event content.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Content extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Render event excerpt header.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event to render excerpt for.
|
||||
*
|
||||
* @return void Content is not returned, just rendered.
|
||||
*/
|
||||
public function excerpt_view( Ai1ec_Event $event ) {
|
||||
$location = $this->_registry->get( 'view.event.location' );
|
||||
$location = esc_html(
|
||||
str_replace(
|
||||
"\n",
|
||||
', ',
|
||||
rtrim( $location->get_location( $event ) )
|
||||
)
|
||||
);
|
||||
$args = array(
|
||||
'event' => $event,
|
||||
'location' => $location,
|
||||
'text_when' => __( 'When:', AI1EC_PLUGIN_NAME ),
|
||||
'text_where' => __( 'Where:', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
echo $loader->get_file(
|
||||
'event-excerpt.twig',
|
||||
$args,
|
||||
true
|
||||
)->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format events excerpt view.
|
||||
*
|
||||
* @param string $text Content to excerpt.
|
||||
*
|
||||
* @return string Formatted event excerpt.
|
||||
*/
|
||||
public function event_excerpt( $text ) {
|
||||
if ( ! $this->_registry->get( 'acl.aco' )->is_our_post_type() ) {
|
||||
return $text;
|
||||
}
|
||||
$event = $this->_registry->get( 'model.event', get_the_ID() );
|
||||
$post = $this->_registry->get( 'view.event.post' );
|
||||
$ob = $this->_registry->get( 'compatibility.ob' );
|
||||
$ob->start();
|
||||
$this->excerpt_view( $event );
|
||||
// Re-apply any filters to the post content that normally would have
|
||||
// been applied if it weren't for our interference (below).
|
||||
echo shortcode_unautop( wpautop( $post->trim_excerpt( $event ) ) );
|
||||
return $ob->get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid re-adding `wpautop` for Ai1EC instances.
|
||||
*
|
||||
* @param string $content Processed content.
|
||||
*
|
||||
* @return string Paragraphs enclosed text.
|
||||
*/
|
||||
public function event_excerpt_noautop( $content ) {
|
||||
if ( ! $this->_registry->get( 'acl.aco' )->is_our_post_type() ) {
|
||||
return wpautop( $content );
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function get_post_excerpt( Ai1ec_Event $event ) {
|
||||
$content = strip_tags(
|
||||
strip_shortcodes(
|
||||
preg_replace(
|
||||
'#<\s*script[^>]*>.+<\s*/\s*script\s*>#x',
|
||||
'',
|
||||
apply_filters(
|
||||
'ai1ec_the_content',
|
||||
apply_filters(
|
||||
'the_content',
|
||||
$event->get( 'post' )->post_content
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
$content = preg_replace( '/\s+/', ' ', $content );
|
||||
$words = explode( ' ', $content );
|
||||
if ( count( $words ) > 25 ) {
|
||||
return implode(
|
||||
' ',
|
||||
array_slice( $words, 0, 25 )
|
||||
) . ' [...]';
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the html for the "Calendar" button for this event.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_back_to_calendar_button_html() {
|
||||
$class = '';
|
||||
$data_type = '';
|
||||
$href = '';
|
||||
if ( isset( $_COOKIE['ai1ec_calendar_url'] ) ) {
|
||||
$href = json_decode(
|
||||
stripslashes( $_COOKIE['ai1ec_calendar_url'] )
|
||||
);
|
||||
setcookie( 'ai1ec_calendar_url', '', time() - 3600 );
|
||||
} else {
|
||||
$href = $this->_registry->get( 'html.element.href', array() );
|
||||
$href = $href->generate_href();
|
||||
}
|
||||
$text = esc_attr( Ai1ec_I18n::__( 'Calendar' ) );
|
||||
$tooltip = esc_attr( Ai1ec_I18n::__( 'View all events' ) );
|
||||
$html = <<<HTML
|
||||
<a class="ai1ec-calendar-link ai1ec-btn ai1ec-btn-default ai1ec-btn-sm
|
||||
ai1ec-tooltip-trigger $class"
|
||||
href="$href"
|
||||
$data_type
|
||||
data-placement="left"
|
||||
title="$tooltip">
|
||||
<i class="ai1ec-fa ai1ec-fa-calendar ai1ec-fa-fw"></i>
|
||||
<span class="ai1ec-hidden-xs">$text</span>
|
||||
</a>
|
||||
HTML;
|
||||
return apply_filters( 'ai1ec_get_back_to_calendar_html', $html, $href );
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple regex-parse of post_content for matches of <img src="foo" />; if
|
||||
* one is found, return its URL.
|
||||
*
|
||||
* @param null $size (width, height) array of returned image
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_content_img_url( Ai1ec_Event $event, &$size = null ) {
|
||||
preg_match(
|
||||
'/<img([^>]+)src=["\']?([^"\'\ >]+)([^>]*)>/i',
|
||||
$event->get( 'post' )->post_content,
|
||||
$matches
|
||||
);
|
||||
|
||||
// Check if we have a result, otherwise a notice is issued.
|
||||
if ( empty( $matches ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Mark found image.
|
||||
$event->get( 'post' )->post_content = str_replace(
|
||||
'<img' . $matches[1],
|
||||
'<img' . $matches[1] . ' data-ai1ec-hidden ',
|
||||
$event->get( 'post' )->post_content
|
||||
);
|
||||
|
||||
$url = $matches[2];
|
||||
$size = array( 0, 0 );
|
||||
|
||||
// Try to detect width and height.
|
||||
$attrs = $matches[1] . $matches[3];
|
||||
$matches = null;
|
||||
preg_match_all(
|
||||
'/(width|height)=["\']?(\d+)/i',
|
||||
$attrs,
|
||||
$matches,
|
||||
PREG_SET_ORDER
|
||||
);
|
||||
// Check if we have a result, otherwise a notice is issued.
|
||||
if ( ! empty( $matches ) ) {
|
||||
foreach ( $matches as $match ) {
|
||||
$size[ $match[1] === 'width' ? 0 : 1 ] = $match[2];
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event location.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Location extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Return location details in brief format, separated by | characters.
|
||||
*
|
||||
* @return $string Short location string
|
||||
*/
|
||||
public function get_short_location( Ai1ec_Event $event ) {
|
||||
$location_items = array();
|
||||
foreach ( array( 'venue', 'city', 'province', 'country' ) as $field ) {
|
||||
if ( $event->get( $field ) !== '' ) {
|
||||
$location_items[] = $event->get( $field );
|
||||
}
|
||||
}
|
||||
return implode( ' | ', $location_items );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return any available location details separated by newlines
|
||||
*/
|
||||
public function get_location( Ai1ec_Event $event ) {
|
||||
$location = '';
|
||||
$venue = $event->get( 'venue' );
|
||||
if ( $venue ) {
|
||||
$location .= $venue . "\n";
|
||||
}
|
||||
$address = $event->get( 'address' );
|
||||
if ( $address ) {
|
||||
$bits = explode( ',', $address );
|
||||
$bits = array_map( 'trim', $bits );
|
||||
|
||||
// If more than three comma-separated values, treat first value as
|
||||
// the street address, last value as the country, and everything
|
||||
// in the middle as the city, state, etc.
|
||||
if ( count( $bits ) >= 3 ) {
|
||||
// Append the street address
|
||||
$street_address = array_shift( $bits ) . "\n";
|
||||
if ( $street_address ) {
|
||||
$location .= $street_address;
|
||||
}
|
||||
// Save the country for the last line
|
||||
$country = array_pop( $bits );
|
||||
// Append the middle bit(s) (filtering out any zero-length strings)
|
||||
$bits = array_filter( $bits, 'strval' );
|
||||
if ( $bits ) {
|
||||
$location .= join( ', ', $bits ) . "\n";
|
||||
}
|
||||
if ( $country ) {
|
||||
$location .= $country . "\n";
|
||||
}
|
||||
} else {
|
||||
// There are two or less comma-separated values, so just append
|
||||
// them each on their own line (filtering out any zero-length strings)
|
||||
$bits = array_filter( $bits, 'strval' );
|
||||
$location .= join( "\n", $bits );
|
||||
}
|
||||
}
|
||||
return $location;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_map_view function
|
||||
*
|
||||
* Returns HTML markup displaying a Google map of the given event, if the event
|
||||
* has show_map set to true. Returns a zero-length string otherwise.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function get_map_view( Ai1ec_Event $event ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
if( ! $event->get( 'show_map' ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$location = $this->get_latlng( $event );
|
||||
if ( ! $location ) {
|
||||
$location = $event->get( 'address' );
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'address' => $location,
|
||||
'gmap_url_link' => $this->get_gmap_url( $event, false ),
|
||||
'hide_maps_until_clicked' => $settings->get( 'hide_maps_until_clicked' ),
|
||||
'text_view_map' => __( 'Click to view map', AI1EC_PLUGIN_NAME ),
|
||||
'text_full_map' => __( 'View Full-Size Map', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
return $loader->get_file( 'event-map.twig', $args, false )->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latitude/longitude coordinates as a textual string
|
||||
* parsable by the Geocoder API.
|
||||
*
|
||||
* @param Ai1ec_Event &$event The event to return data from
|
||||
*
|
||||
* @return string The latitude & longitude string, or null
|
||||
*/
|
||||
public function get_latlng( Ai1ec_Event $event ) {
|
||||
// If the coordinates are set, use those, otherwise use the address.
|
||||
$location = NULL;
|
||||
// If the coordinates are set by hand use them.
|
||||
if ( $event->get( 'show_coordinates' ) ) {
|
||||
$longitude = floatval( $event->get( 'longitude' ) );
|
||||
$latitude = floatval( $event->get( 'latitude' ) );
|
||||
$location = $latitude . ',' . $longitude;
|
||||
}
|
||||
return $location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL to the Google Map for the given event object.
|
||||
*
|
||||
* @param Ai1ec_Event $event The event object to display a map for
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_gmap_url( Ai1ec_Event $event ) {
|
||||
$lang = $this->_registry->get( 'p28n.wpml' )->get_language();
|
||||
$location = $this->get_latlng( $event );
|
||||
if ( ! $location ) {
|
||||
$location = $event->get( 'address' );
|
||||
}
|
||||
return 'https://www.google.com/maps?f=q&hl=' . urlencode( $lang ) .
|
||||
'&source=embed&q=' . urlencode( $location );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event colors.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Post extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Add event-specific messages to be used when one is modified in dashboard.
|
||||
*
|
||||
* @wp_hook post_updated_messages
|
||||
*
|
||||
* @param array $messages List of messages.
|
||||
*
|
||||
* @return array Modified list of messages.
|
||||
*/
|
||||
public function post_updated_messages( $messages ) {
|
||||
global $post, $post_ID;
|
||||
|
||||
$messages[AI1EC_POST_TYPE] = array(
|
||||
0 => '', // Unused. Messages start at index 1.
|
||||
1 => sprintf(
|
||||
Ai1ec_I18n::__( 'Event updated. <a href="%s">View event</a>' ),
|
||||
esc_url( get_permalink( $post_ID ) )
|
||||
),
|
||||
2 => Ai1ec_I18n::__( 'Custom field updated.' ),
|
||||
3 => Ai1ec_I18n::__( 'Custom field deleted.' ),
|
||||
4 => Ai1ec_I18n::__( 'Event updated.' ),
|
||||
/* translators: %s: date and time of the revision */
|
||||
5 => isset( $_GET['revision'] )
|
||||
? sprintf(
|
||||
Ai1ec_I18n::__( 'Event restored to revision from %s' ),
|
||||
wp_post_revision_title( (int) $_GET['revision'], false )
|
||||
)
|
||||
: false,
|
||||
6 => sprintf(
|
||||
Ai1ec_I18n::__( 'Event published. <a href="%s">View event</a>' ),
|
||||
esc_url( get_permalink($post_ID) )
|
||||
),
|
||||
7 => Ai1ec_I18n::__( 'Event saved.' ),
|
||||
8 => sprintf(
|
||||
Ai1ec_I18n::__( 'Event submitted. <a target="_blank" href="%s">Preview event</a>' ),
|
||||
esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) )
|
||||
),
|
||||
9 => sprintf(
|
||||
Ai1ec_I18n::__( 'Event scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview event</a>' ),
|
||||
// translators: Publish box date format, see http://php.net/date
|
||||
$this->_registry->get( 'date.time', $post->post_date )->format_i18n( Ai1ec_I18n::__( 'M j, Y @ G:i' ) ),
|
||||
esc_url( get_permalink($post_ID) )
|
||||
),
|
||||
10 => sprintf(
|
||||
Ai1ec_I18n::__( 'Event draft updated. <a target="_blank" href="%s">Preview event</a>' ),
|
||||
esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) )
|
||||
),
|
||||
);
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an excerpt from the given content string.
|
||||
*
|
||||
* Adapted from WordPress's `wp_trim_excerpt' function that is not useful
|
||||
* for applying to custom content.
|
||||
*
|
||||
* @param string $text The content to trim.
|
||||
*
|
||||
* @return string The excerpt.
|
||||
*/
|
||||
public function trim_excerpt( Ai1ec_Event $event, $length = 35, $more = '[...]' ) {
|
||||
global $post;
|
||||
$original_post = $post;
|
||||
$post = $event->get( 'post' );
|
||||
$raw_excerpt = $event->get( 'post' )->post_content;
|
||||
if ( ! isset( $raw_excerpt{0} ) ) {
|
||||
$raw_excerpt = ' ';
|
||||
}
|
||||
|
||||
$text = preg_replace(
|
||||
'#<\s*script[^>]*>.+<\s*/\s*script\s*>#x',
|
||||
'',
|
||||
apply_filters(
|
||||
'the_excerpt',
|
||||
$raw_excerpt
|
||||
)
|
||||
);
|
||||
$text = strip_shortcodes( $text );
|
||||
$text = str_replace( ']]>', ']]>', $text );
|
||||
$text = strip_tags( $text );
|
||||
|
||||
$excerpt_length = apply_filters( 'excerpt_length', $length );
|
||||
$excerpt_more = apply_filters( 'excerpt_more', $more );
|
||||
$words = preg_split(
|
||||
'/\s+/',
|
||||
$text,
|
||||
$excerpt_length + 1,
|
||||
PREG_SPLIT_NO_EMPTY
|
||||
);
|
||||
if ( count( $words ) > $excerpt_length ) {
|
||||
array_pop( $words );
|
||||
$text = implode( ' ', $words );
|
||||
$text = $text . $excerpt_more;
|
||||
} else {
|
||||
$text = implode( ' ', $words );
|
||||
}
|
||||
$post = $original_post;
|
||||
return apply_filters( 'wp_trim_excerpt', $text, $raw_excerpt );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the single event page.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Single extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Renders the html of the page and returns it.
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
*
|
||||
* @return string the html of the page
|
||||
*/
|
||||
public function get_content( Ai1ec_Event $event ) {
|
||||
$settings = $this->_registry->get( 'model.settings' );
|
||||
$rrule = $this->_registry->get( 'recurrence.rule' );
|
||||
$taxonomy = $this->_registry->get( 'view.event.taxonomy' );
|
||||
$location = $this->_registry->get( 'view.event.location' );
|
||||
$ticket = $this->_registry->get( 'view.event.ticket' );
|
||||
$content = $this->_registry->get( 'view.event.content' );
|
||||
$time = $this->_registry->get( 'view.event.time' );
|
||||
|
||||
$subscribe_url = AI1EC_EXPORT_URL . '&ai1ec_post_ids=' .
|
||||
$event->get( 'post_id' );
|
||||
|
||||
$event->set_runtime(
|
||||
'tickets_url_label',
|
||||
$ticket->get_tickets_url_label( $event, false )
|
||||
);
|
||||
$event->set_runtime(
|
||||
'content_img_url',
|
||||
$content->get_content_img_url( $event )
|
||||
);
|
||||
|
||||
$extra_buttons = apply_filters(
|
||||
'ai1ec_rendering_single_event_actions',
|
||||
'',
|
||||
$event
|
||||
);
|
||||
|
||||
$venues_html = apply_filters(
|
||||
'ai1ec_rendering_single_event_venues',
|
||||
nl2br( $location->get_location( $event ) ),
|
||||
$event
|
||||
);
|
||||
$default_tz = $this->_registry->get( 'date.timezone' )->get_default_timezone();
|
||||
$timezone_info = array(
|
||||
'show_timezone' => $this->_registry->get( 'model.settings' )->get( 'always_use_calendar_timezone' ),
|
||||
'using_calendar_tz' => $this->_registry->get( 'model.settings' )->get( 'always_use_calendar_timezone' ),
|
||||
'event_timezone' => str_replace( '_', ' ', $event->get( 'timezone_name' ) ) . ' ' . __( 'Timezone', AI1EC_PLUGIN_NAME ),
|
||||
'calendar_timezone' => str_replace( '_', ' ', $default_tz ) . ' ' . __( 'Timezone', AI1EC_PLUGIN_NAME ),
|
||||
);
|
||||
|
||||
$banner_image_meta = get_post_meta( $event->get( 'post_id' ), 'ai1ec_banner_image' );
|
||||
$banner_image = $banner_image_meta ? $banner_image_meta[0] : '';
|
||||
|
||||
// objects are passed by reference so an action is ok
|
||||
do_action( 'ai1ec_single_event_page_before_render', $event );
|
||||
|
||||
$filter_groups_html = apply_filters( 'ai1ec_get_filter_groups_html', $event );
|
||||
|
||||
$args = array(
|
||||
'event' => $event,
|
||||
'recurrence' => $rrule->rrule_to_text( $event->get( 'recurrence_rules' ) ),
|
||||
'exclude' => $time->get_exclude_html( $event, $rrule ),
|
||||
'categories' => $taxonomy->get_categories_html( $event ),
|
||||
'tags' => $taxonomy->get_tags_html( $event ),
|
||||
'location' => html_entity_decode( $venues_html ),
|
||||
'filter_groups' => $filter_groups_html,
|
||||
'map' => $location->get_map_view( $event ),
|
||||
'contact' => $ticket->get_contact_html( $event ),
|
||||
'back_to_calendar' => $content->get_back_to_calendar_button_html(),
|
||||
'subscribe_url' => $subscribe_url,
|
||||
'subscribe_url_no_html' => $subscribe_url . '&no_html=true',
|
||||
'edit_instance_url' => null,
|
||||
'edit_instance_text' => null,
|
||||
'google_url' => 'https://www.google.com/calendar/render?cid=' . urlencode( $subscribe_url ),
|
||||
'show_subscribe_buttons' => ! $settings->get( 'turn_off_subscription_buttons' ),
|
||||
'hide_featured_image' => $settings->get( 'hide_featured_image' ),
|
||||
'extra_buttons' => $extra_buttons,
|
||||
'show_get_calendar' => ! $settings->get( 'disable_get_calendar_button' ),
|
||||
'text_add_calendar' => __( 'Add to Calendar', AI1EC_PLUGIN_NAME ),
|
||||
'subscribe_buttons_text' => $this->_registry
|
||||
->get( 'view.calendar.subscribe-button' )
|
||||
->get_labels(),
|
||||
'text_get_calendar' => Ai1ec_I18n::__( 'Get a Timely Calendar' ),
|
||||
'text_when' => __( 'When:', AI1EC_PLUGIN_NAME ),
|
||||
'text_where' => __( 'Where:', AI1EC_PLUGIN_NAME ),
|
||||
'text_cost' => __( 'Cost:', AI1EC_PLUGIN_NAME ),
|
||||
'text_contact' => __( 'Contact:', AI1EC_PLUGIN_NAME ),
|
||||
'text_tickets' => __( 'Tickets:', AI1EC_PLUGIN_NAME ),
|
||||
'text_free' => __( 'Free', AI1EC_PLUGIN_NAME ),
|
||||
'text_categories' => __( 'Categories', AI1EC_PLUGIN_NAME ),
|
||||
'text_tags' => __( 'Tags', AI1EC_PLUGIN_NAME ),
|
||||
'buy_tickets_text' => __( 'Buy Tickets', AI1EC_PLUGIN_NAME ),
|
||||
'timezone_info' => $timezone_info,
|
||||
'banner_image' => $banner_image,
|
||||
'content_img_url' => $event->get_runtime( 'content_img_url' ),
|
||||
'post_id' => $event->get( 'post_id' ),
|
||||
'ticket_url' => $event->get( 'ticket_url' ),
|
||||
'tickets_url_label' => $event->get_runtime( 'tickets_url_label' ),
|
||||
'start' => $event->get( 'start' ),
|
||||
'end' => $event->get( 'end' ),
|
||||
'cost' => $event->get( 'cost' ),
|
||||
'instance_id' => $event->get( 'instance_id' ),
|
||||
);
|
||||
|
||||
if (
|
||||
! empty( $args['recurrence'] ) &&
|
||||
$event->get( 'instance_id' ) &&
|
||||
current_user_can( 'edit_ai1ec_events' )
|
||||
) {
|
||||
$args['edit_instance_url'] = ai1ec_admin_url(
|
||||
'post.php?post=' . $event->get( 'post_id' ) .
|
||||
'&action=edit&instance=' . $event->get( 'instance_id' )
|
||||
);
|
||||
$args['edit_instance_text'] = sprintf(
|
||||
Ai1ec_I18n::__( 'Edit this occurrence (%s)' ),
|
||||
$event->get( 'start' )->format_i18n( 'M j' )
|
||||
);
|
||||
}
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
if ( false === ai1ec_is_blank( $event->get( 'ical_feed_url' ) ) ) {
|
||||
$ticket_url = $api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) );
|
||||
if ( ! empty ( $ticket_url ) ) {
|
||||
$args['ticket_url'] = $ticket_url;
|
||||
}
|
||||
} else {
|
||||
$api_event_id = $api->get_api_event_id( $event->get( 'post_id' ) );
|
||||
if ( $api_event_id ) {
|
||||
$api = $this->_registry->get( 'model.api.api-ticketing' );
|
||||
$ticket_types = json_decode( $api->get_ticket_types( $event->get( 'post_id' ), false ) );
|
||||
$args['has_tickets'] = true;
|
||||
$args['API_URL'] = AI1EC_API_URL;
|
||||
$args['tickets_block'] = $loader->get_file(
|
||||
'tickets.twig',
|
||||
array(
|
||||
'tickets_checkout_url' => $api->get_api_event_buy_ticket_url( $event->get( 'post_id' ) ),
|
||||
'tickets' => $ticket_types->data,
|
||||
'text_tickets' => $args['text_tickets'],
|
||||
'buy_tickets_text' => $args['buy_tickets_text'],
|
||||
'api_event_id' => $api_event_id
|
||||
), false
|
||||
)->get_content();
|
||||
}
|
||||
}
|
||||
|
||||
return $loader->get_file( 'event-single.twig', $args, false )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta OG tags to the event details page
|
||||
*/
|
||||
public function add_meta_tags() {
|
||||
// Add tags only on Event Details page
|
||||
$aco = $this->_registry->get( 'acl.aco' );
|
||||
if ( ! $aco->is_our_post_type() ) return;
|
||||
|
||||
// Get Event and process description
|
||||
$instance_id = ( isset( $_GET[ 'instance_id' ] ) ) ? $_GET[ 'instance_id' ] : null;
|
||||
|
||||
if ( !is_null( $instance_id ) ) {
|
||||
$instance_id = preg_replace( '/\D/', '', $instance_id );
|
||||
}
|
||||
$event = $this->_registry->get( 'model.event', get_the_ID(), $instance_id );
|
||||
$avatar = $this->_registry->get( 'view.event.avatar' );
|
||||
$content = $this->_registry->get( 'view.event.content' );
|
||||
$desc = $event->get( 'post' )->post_content;
|
||||
$desc = apply_filters( 'the_excerpt', $desc );
|
||||
$desc = strip_shortcodes( $desc );
|
||||
$desc = str_replace( ']]>', ']]>', $desc );
|
||||
$desc = strip_tags( $desc );
|
||||
$desc = preg_replace( '/\n+/', ' ', $desc);
|
||||
$desc = substr( $desc, 0, 300 );
|
||||
// Get featured image
|
||||
$image = $avatar->get_post_thumbnail_url( $event );
|
||||
if ( ! $image ) {
|
||||
$image = $content->get_content_img_url( $event );
|
||||
}
|
||||
|
||||
$og = array(
|
||||
'url' => home_url( esc_url( add_query_arg( null, null ) ) ),
|
||||
'title' => htmlspecialchars(
|
||||
$event->get( 'post' )->post_title .
|
||||
' (' . substr( $event->get( 'start' ) , 0, 10 ) . ')'
|
||||
),
|
||||
'type' => 'article',
|
||||
'description' => htmlspecialchars( $desc ),
|
||||
'image' => $image,
|
||||
);
|
||||
foreach ( $og as $key => $val ) {
|
||||
echo "<meta property=\"og:$key\" content=\"$val\" />\n";
|
||||
}
|
||||
// Twitter meta tags
|
||||
$twitter = array(
|
||||
'card' => 'summary',
|
||||
'title' => htmlspecialchars(
|
||||
$event->get( 'post' )->post_title .
|
||||
' (' . substr( $event->get( 'start' ) , 0, 10 ) . ')'
|
||||
),
|
||||
'description' => htmlspecialchars( $desc ),
|
||||
'image' => $image,
|
||||
);
|
||||
foreach ( $twitter as $key => $val ) {
|
||||
if ( empty( $val ) && 'image' !== $key ) {
|
||||
$val = Ai1ec_I18n::__( 'No data' );
|
||||
}
|
||||
echo "<meta name=\"twitter:$key\" content=\"$val\" />\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Ai1ec_Event $event
|
||||
*
|
||||
* @return The html of the footer
|
||||
*/
|
||||
public function get_footer( Ai1ec_Event $event ) {
|
||||
|
||||
$text_calendar_feed = null;
|
||||
|
||||
$feed_url = trim( strtolower( $event->get( 'ical_feed_url' ) ) );
|
||||
|
||||
if ( strpos( $feed_url, 'http' ) === 0 ) {
|
||||
$text_calendar_feed = Ai1ec_I18n::__(
|
||||
'This post was replicated from another site\'s <a href="%s" title="iCalendar feed"><i class="ai1ec-fa ai1ec-fa-calendar"></i> calendar feed</a>.'
|
||||
);
|
||||
} else {
|
||||
$text_calendar_feed = Ai1ec_I18n::__(
|
||||
'This post was imported from a CSV/ICS file.'
|
||||
);
|
||||
}
|
||||
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
$text_calendar_feed = sprintf(
|
||||
$text_calendar_feed,
|
||||
esc_attr( str_replace( 'http://', 'webcal://', $event->get( 'ical_feed_url' ) ) )
|
||||
);
|
||||
$args = array(
|
||||
'event' => $event,
|
||||
'text_calendar_feed' => $text_calendar_feed,
|
||||
'text_view_post' => Ai1ec_I18n::__( 'View original' ),
|
||||
);
|
||||
return $loader->get_file( 'event-single-footer.twig', $args, false )
|
||||
->get_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the full article for the event – title, content, and footer.
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
* @param string $footer Footer HTML to append to event
|
||||
*/
|
||||
public function get_full_article( Ai1ec_Event $event, $footer = '' ) {
|
||||
$title = apply_filters(
|
||||
'the_title',
|
||||
$event->get( 'post' )->post_title,
|
||||
$event->get( 'post_id' )
|
||||
);
|
||||
$event_details = $this->get_content( $event );
|
||||
$content = wpautop(
|
||||
apply_filters(
|
||||
'ai1ec_the_content',
|
||||
apply_filters(
|
||||
'the_content',
|
||||
$event->get( 'post' )->post_content
|
||||
)
|
||||
)
|
||||
);
|
||||
$args = compact( 'title', 'event_details', 'content', 'footer' );
|
||||
$loader = $this->_registry->get( 'theme.loader' );
|
||||
return $loader->get_file( 'event-single-full.twig', $args, false )
|
||||
->get_content();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event taxonomy.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Taxonomy extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* @var Ai1ec_Taxonomy Taxonomy abstraction layer.
|
||||
*/
|
||||
protected $_taxonomy_model = null;
|
||||
|
||||
/**
|
||||
* @var array Caches the color evaluated for each event.
|
||||
*/
|
||||
protected $_event_color_map = array();
|
||||
|
||||
/**
|
||||
* @var array Caches the color squares HTML evaluated for each event.
|
||||
*/
|
||||
protected $_event_color_squares_map = array();
|
||||
|
||||
/**
|
||||
* Returns style attribute for events rendered in Month, Week, or Day view.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
*
|
||||
* @return string Color style attribute.
|
||||
*/
|
||||
public function get_color_style( Ai1ec_Event $event ) {
|
||||
$color = $this->get_color_for_event( $event );
|
||||
|
||||
// Convert to style attribute.
|
||||
if ( $color ) {
|
||||
$color = $event->is_allday() || $event->is_multiday()
|
||||
? 'background-color: ' . $color . ';'
|
||||
: 'color: ' . $color . ' !important;';
|
||||
} else {
|
||||
$color = '';
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML of category color swatches for this event.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
*
|
||||
* @return string HTML of the event's category color swatches.
|
||||
*/
|
||||
public function get_category_colors( Ai1ec_Event $event ) {
|
||||
$post_id = $event->get( 'post_id' );
|
||||
|
||||
if ( ! isset( $this->_event_color_squares_map[$post_id] ) ) {
|
||||
$squares = '';
|
||||
$categories = $this->_taxonomy_model->get_post_categories( $post_id );
|
||||
|
||||
if ( false !== $categories ) {
|
||||
$squares = $this->get_event_category_colors( $categories );
|
||||
}
|
||||
|
||||
// Allow add-ons to modify/add to category color swatch HTML.
|
||||
$squares = apply_filters(
|
||||
'ai1ec_event_color_squares',
|
||||
$squares,
|
||||
$event
|
||||
);
|
||||
|
||||
$this->_event_color_squares_map[$post_id] = $squares;
|
||||
}
|
||||
|
||||
return $this->_event_color_squares_map[$post_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML markup for the category color square.
|
||||
*
|
||||
* @param int $term_id The term ID of event category
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_category_color_square( $term_id ) {
|
||||
$color = $this->_taxonomy_model->get_category_color( $term_id );
|
||||
$event_taxonomy = $this->_registry->get( 'model.event.taxonomy' );
|
||||
if ( null !== $color ) {
|
||||
$taxonomy = $event_taxonomy->get_taxonomy_for_term_id( $term_id );
|
||||
$cat = get_term( $term_id, $taxonomy->taxonomy );
|
||||
return '<span class="ai1ec-color-swatch ai1ec-tooltip-trigger" ' .
|
||||
'style="background:' . $color . '" title="' .
|
||||
esc_attr( $cat->name ) . '"></span>';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML markup for the category image square.
|
||||
*
|
||||
* @param int $term_id The term ID of event category.
|
||||
*
|
||||
* @return string HTML snippet to use for category image.
|
||||
*/
|
||||
public function get_category_image_square( $term_id ) {
|
||||
$image = $this->_taxonomy_model->get_category_image( $term_id );
|
||||
if ( null !== $image ) {
|
||||
return '<img src="' . $image . '" alt="' .
|
||||
Ai1ec_I18n::__( 'Category image' ) .
|
||||
'" class="ai1ec_category_small_image_preview" />';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns category color squares for the list of Event Category objects.
|
||||
*
|
||||
* @param array $cats The Event Category objects as returned by get_terms()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_event_category_colors( array $cats ) {
|
||||
$sqrs = '';
|
||||
foreach ( $cats as $cat ) {
|
||||
$tmp = $this->get_category_color_square( $cat->term_id );
|
||||
if ( ! empty( $tmp ) ) {
|
||||
$sqrs .= $tmp;
|
||||
}
|
||||
}
|
||||
return $sqrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Style attribute for event background color.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
*
|
||||
* @return string Color to assign to event background.
|
||||
*/
|
||||
public function get_category_bg_color( Ai1ec_Event $event ) {
|
||||
$color = $this->get_color_for_event( $event );
|
||||
|
||||
// Convert to HTML attribute.
|
||||
if ( $color ) {
|
||||
$color = 'style="background-color: ' . $color . ';"';
|
||||
} else {
|
||||
$color = '';
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Style attribute for event multi-date divider color.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
*
|
||||
* @return string Color to assign to event background.
|
||||
*/
|
||||
public function get_category_divider_color( Ai1ec_Event $event ) {
|
||||
$color = $this->get_color_for_event( $event );
|
||||
|
||||
// Convert to HTML attribute.
|
||||
if ( $color ) {
|
||||
$color = 'style="border-color: ' . $color . ' transparent transparent transparent;"';
|
||||
} else {
|
||||
$color = '';
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Style attribute for event text color.
|
||||
*
|
||||
* @param Ai1ec_Event $event Event object.
|
||||
*
|
||||
* @return string Color to assign to event text (foreground).
|
||||
*/
|
||||
public function get_category_text_color( Ai1ec_Event $event ) {
|
||||
$color = $this->get_color_for_event( $event );
|
||||
|
||||
// Convert to HTML attribute.
|
||||
if ( $color ) {
|
||||
$color = 'style="color: ' . $color . ';"';
|
||||
} else {
|
||||
$color = '';
|
||||
}
|
||||
|
||||
return $color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches color for event having the given post ID.
|
||||
*
|
||||
* @param int $post_id Event's post ID.
|
||||
*
|
||||
* @return string Color associated with event.
|
||||
*/
|
||||
public function get_color_for_event( $event ) {
|
||||
$post_id = $event->get( 'post_id' );
|
||||
|
||||
// If color for this event is uncached, populate cache.
|
||||
if ( ! isset( $this->_event_color_map[$post_id] ) ) {
|
||||
// Find out if an add-on has provided its own color for the event.
|
||||
$color = apply_filters( 'ai1ec_event_color', '', $event );
|
||||
|
||||
// If none provided, fall back to event categories.
|
||||
if ( empty( $color ) ) {
|
||||
$categories = $this->_taxonomy_model->get_post_categories( $post_id );
|
||||
// Find the first category of this post that defines a color.
|
||||
foreach ( $categories as $category ) {
|
||||
$color = $this->_taxonomy_model->get_category_color(
|
||||
$category->term_id
|
||||
);
|
||||
if ( $color ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->_event_color_map[$post_id] = $color;
|
||||
}
|
||||
|
||||
return $this->_event_color_map[$post_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Categories as HTML, either as blocks or inline.
|
||||
*
|
||||
* @param Ai1ec_Event $event Rendered Event.
|
||||
* @param string $format Return 'blocks' or 'inline' formatted result.
|
||||
*
|
||||
* @return string String of HTML for category blocks.
|
||||
*/
|
||||
public function get_categories_html(
|
||||
Ai1ec_Event $event,
|
||||
$format = 'blocks'
|
||||
) {
|
||||
$categories = $this->_taxonomy_model->get_post_categories(
|
||||
$event->get( 'post_id' )
|
||||
);
|
||||
foreach ( $categories as &$category ) {
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
array( 'cat_ids' => $category->term_id )
|
||||
);
|
||||
|
||||
$class = $data_type = $title = '';
|
||||
if ( $category->description ) {
|
||||
$title = 'title="' .
|
||||
esc_attr( $category->description ) . '" ';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
$class .= ' ai1ec-category';
|
||||
$color_style = '';
|
||||
if ( $format === 'inline' ) {
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$color_style = $taxonomy->get_category_color(
|
||||
$category->term_id
|
||||
);
|
||||
if ( $color_style !== '' ) {
|
||||
$color_style = 'style="color: ' . $color_style . ';" ';
|
||||
}
|
||||
$class .= '-inline';
|
||||
}
|
||||
|
||||
$html .= '<a ' . $data_type . ' class="' . $class .
|
||||
' ai1ec-term-id-' . $category->term_id . ' p-category" ' .
|
||||
$title . $color_style . 'href="' . $href->generate_href() . '">';
|
||||
|
||||
if ( $format === 'blocks' ) {
|
||||
$html .= $this->get_category_color_square(
|
||||
$category->term_id
|
||||
) . ' ';
|
||||
} else {
|
||||
$html .=
|
||||
'<i ' . $color_style .
|
||||
'class="ai1ec-fa ai1ec-fa-folder-open"></i>';
|
||||
}
|
||||
|
||||
$html .= esc_html( $category->name ) . '</a>';
|
||||
$category = $html;
|
||||
}
|
||||
return implode( ' ', $categories );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tags as HTML
|
||||
*/
|
||||
public function get_tags_html( Ai1ec_Event $event ) {
|
||||
$tags = $this->_taxonomy_model->get_post_tags(
|
||||
$event->get( 'post_id' )
|
||||
);
|
||||
if ( ! $tags ) {
|
||||
$tags = array();
|
||||
}
|
||||
foreach ( $tags as &$tag ) {
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
array( 'tag_ids' => $tag->term_id )
|
||||
);
|
||||
$class = '';
|
||||
$data_type = '';
|
||||
$title = '';
|
||||
if ( $tag->description ) {
|
||||
$title = 'title="' . esc_attr( $tag->description ) . '" ';
|
||||
}
|
||||
$tag = '<a ' . $data_type . ' class="ai1ec-tag ' . $class .
|
||||
' ai1ec-term-id-' . $tag->term_id . '" ' . $title .
|
||||
'href="' . $href->generate_href() . '">' .
|
||||
'<i class="ai1ec-fa ai1ec-fa-tag"></i>' .
|
||||
esc_html( $tag->name ) . '</a>';
|
||||
}
|
||||
return implode( ' ', $tags );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Groups as HTML, either as blocks or inline.
|
||||
*
|
||||
* @param Ai1ec_Event $event Rendered Event.
|
||||
* @param array $filter_group Filter Group (Option Model)
|
||||
* @param string $format Return 'blocks' or 'inline' formatted result.
|
||||
*
|
||||
* @return string String of HTML for filter group blocks.
|
||||
*/
|
||||
public function get_filter_group_html(
|
||||
Ai1ec_Event $event,
|
||||
$filter_group,
|
||||
$format = 'blocks'
|
||||
) {
|
||||
|
||||
$filter_groups = $this->_taxonomy_model->get_post_taxonomy(
|
||||
$event->get( 'post_id' ), $filter_group['taxonomy_name']
|
||||
);
|
||||
|
||||
$icon_name = '';
|
||||
if ( 'ai1eccfgi-null' !== $filter_group['icon'] ) {
|
||||
$icon_name = $filter_group['icon'];
|
||||
} else {
|
||||
$icon_name = 'ai1ec-icon-timely';
|
||||
}
|
||||
|
||||
foreach ( $filter_groups as &$group ) {
|
||||
$href = $this->_registry->get(
|
||||
'html.element.href',
|
||||
array( $filter_group['taxonomy_name'] . '_ids' => $group->term_id )
|
||||
);
|
||||
|
||||
$class = $data_type = $title = '';
|
||||
if ( $group->description ) {
|
||||
$title = 'title="' .
|
||||
esc_attr( $group->description ) . '" ';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
$class .= ' ai1ec-category';
|
||||
$color_style = '';
|
||||
if ( 'inline' === $format ) {
|
||||
$taxonomy = $this->_registry->get( 'model.taxonomy' );
|
||||
$color_style = $taxonomy->get_category_color(
|
||||
$group->term_id
|
||||
);
|
||||
if ( $color_style !== '' ) {
|
||||
$color_style = 'style="color: ' . $color_style . ';" ';
|
||||
}
|
||||
$class .= '-inline';
|
||||
}
|
||||
|
||||
$html .= '<a ' . $data_type . ' class="' . $class .
|
||||
' ai1ec-term-id-' . $group->term_id . ' p-category" ' .
|
||||
$title . $color_style . 'href="' . $href->generate_href() . '">';
|
||||
|
||||
if ( 'blocks' === $format ) {
|
||||
$html .= $this->get_category_color_square($group->term_id) . ' ';
|
||||
} else {
|
||||
$html = $html
|
||||
. '<i ' . $color_style . ' class="ai1ec-fa '
|
||||
. $icon_name . '"></i>';
|
||||
}
|
||||
|
||||
$html .= esc_html( $group->name ) . '</a>';
|
||||
$group = $html;
|
||||
}
|
||||
|
||||
return implode( ' ', $filter_groups );
|
||||
}
|
||||
|
||||
public function __construct( Ai1ec_Registry_Object $registry ) {
|
||||
parent::__construct( $registry );
|
||||
$this->_taxonomy_model = $this->_registry->get( 'model.taxonomy' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event ticket.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Ticket {
|
||||
|
||||
/**
|
||||
* Create readable content for buy tickets/register link
|
||||
*
|
||||
* @param bool $long Set to false to use short message version
|
||||
*
|
||||
* @return string Message to be rendered on buy tickets link
|
||||
*/
|
||||
public function get_tickets_url_label( Ai1ec_Event $event, $long = true ) {
|
||||
if ( $event->is_free() ) {
|
||||
return ( $long )
|
||||
? __( 'Register Now', AI1EC_PLUGIN_NAME )
|
||||
: __( 'Register', AI1EC_PLUGIN_NAME );
|
||||
}
|
||||
$output = '';
|
||||
if ( $long ) {
|
||||
$output = apply_filters(
|
||||
'ai1ec_buy_tickets_url_icon',
|
||||
'<i class="ai1ec-fa ai1ec-fa-shopping-cart"></i>'
|
||||
);
|
||||
if ( ! empty( $output ) ) {
|
||||
$output .= ' ';
|
||||
}
|
||||
}
|
||||
$output .= ( $long )
|
||||
? __( 'Buy Tickets', AI1EC_PLUGIN_NAME )
|
||||
: __( 'Tickets', AI1EC_PLUGIN_NAME );
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contact info as HTML
|
||||
*/
|
||||
public function get_contact_html( Ai1ec_Event $event ) {
|
||||
$contact = '<div class="h-card">';
|
||||
$has_contents = false;
|
||||
if ( $event->get( 'contact_name' ) ) {
|
||||
$contact .=
|
||||
'<div class="ai1ec-contact-name p-name">' .
|
||||
'<i class="ai1ec-fa ai1ec-fa-fw ai1ec-fa-user"></i> ' .
|
||||
esc_html( $event->get( 'contact_name' ) ) .
|
||||
'</div> ';
|
||||
$has_contents = true;
|
||||
}
|
||||
if ( $event->get( 'contact_phone' ) ) {
|
||||
$contact .=
|
||||
'<div class="ai1ec-contact-phone p-tel">' .
|
||||
'<i class="ai1ec-fa ai1ec-fa-fw ai1ec-fa-phone"></i> ' .
|
||||
esc_html( $event->get( 'contact_phone' ) ) .
|
||||
'</div> ';
|
||||
$has_contents = true;
|
||||
}
|
||||
if ( $event->get( 'contact_email' ) ) {
|
||||
$contact .=
|
||||
'<div class="ai1ec-contact-email">' .
|
||||
'<a class="u-email" href="mailto:' .
|
||||
esc_attr( $event->get( 'contact_email' ) ) . '">' .
|
||||
'<i class="ai1ec-fa ai1ec-fa-fw ai1ec-fa-envelope-o"></i> ' .
|
||||
__( 'Email', AI1EC_PLUGIN_NAME ) . '</a></div> ';
|
||||
$has_contents = true;
|
||||
}
|
||||
if ( $event->get( 'contact_url' ) ) {
|
||||
$contact .=
|
||||
'<div class="ai1ec-contact-url">' .
|
||||
'<a class="u-url" target="_blank" href="' .
|
||||
esc_attr( $event->get( 'contact_url' ) ) .
|
||||
'"><i class="ai1ec-fa ai1ec-fa-fw ai1ec-fa-link"></i> ' .
|
||||
apply_filters(
|
||||
'ai1ec_contact_url',
|
||||
__( 'Event website', AI1EC_PLUGIN_NAME )
|
||||
) .
|
||||
' <i class="ai1ec-fa ai1ec-fa-external-link"></i></a></div>';
|
||||
$has_contents = true;
|
||||
}
|
||||
$contact .= '</div>';
|
||||
return $has_contents ? $contact : '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This class renders the html for the event time.
|
||||
*
|
||||
* @author Time.ly Network Inc.
|
||||
* @since 2.0
|
||||
*
|
||||
* @package AI1EC
|
||||
* @subpackage AI1EC.View.Event
|
||||
*/
|
||||
class Ai1ec_View_Event_Time extends Ai1ec_Base {
|
||||
|
||||
/**
|
||||
* Returns timespan expression for the event.
|
||||
*
|
||||
* Properly handles:
|
||||
* - instantaneous events
|
||||
* - all-day events
|
||||
* - multi-day events
|
||||
* Display of start date can be hidden (non-all-day events only) or full
|
||||
* date. All-day status, if any, is enclosed in a span.ai1ec-allday-badge
|
||||
* element.
|
||||
*
|
||||
* @param Ai1ec_Event $event Rendered event.
|
||||
* @param string $start_date_display Can be one of 'hidden', 'short',
|
||||
* or 'long'.
|
||||
*
|
||||
* @return string Formatted timespan HTML element.
|
||||
*/
|
||||
public function get_timespan_html(
|
||||
Ai1ec_Event $event,
|
||||
$start_date_display = 'long'
|
||||
) {
|
||||
// Makes no sense to hide start date for all-day events, so fix argument
|
||||
if ( 'hidden' === $start_date_display && $event->is_allday() ) {
|
||||
$start_date_display = 'short';
|
||||
}
|
||||
|
||||
// Localize time.
|
||||
$start = $this->_registry->get( 'date.time', $event->get( 'start' ) );
|
||||
$end = $this->_registry->get( 'date.time', $event->get( 'end' ) );
|
||||
|
||||
// All-day events need to have their end time shifted by 1 second less
|
||||
// to land on the correct day.
|
||||
$end_offset = 0;
|
||||
if ( $event->is_allday() ) {
|
||||
$end->set_time(
|
||||
$end->format( 'H' ),
|
||||
$end->format( 'i' ),
|
||||
$end->format( 's' ) - 1
|
||||
);
|
||||
}
|
||||
|
||||
// Get timestamps of start & end dates without time component.
|
||||
$start_ts = $this->_registry->get( 'date.time', $start )
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
$end_ts = $this->_registry->get( 'date.time', $end )
|
||||
->set_time( 0, 0, 0 )
|
||||
->format();
|
||||
|
||||
$break_years = $start->format( 'Y' ) !== $end->format( 'Y' );
|
||||
$output = '';
|
||||
|
||||
// Display start date, depending on $start_date_display.
|
||||
switch ( $start_date_display ) {
|
||||
case 'hidden':
|
||||
break;
|
||||
case 'short':
|
||||
case 'long':
|
||||
$property = $start_date_display . '_date';
|
||||
$output .= $this->{'get_' . $property}( $start, $break_years );
|
||||
break;
|
||||
default:
|
||||
$start_date_display = 'long';
|
||||
}
|
||||
|
||||
// Output start time for non-all-day events.
|
||||
if ( ! $event->is_allday() ) {
|
||||
if ( 'hidden' !== $start_date_display ) {
|
||||
$output .= apply_filters(
|
||||
'ai1ec_get_timespan_html_time_separator',
|
||||
Ai1ec_I18n::_x( ' @ ', 'Event time separator' )
|
||||
);
|
||||
}
|
||||
$output .= $this->get_short_time( $start );
|
||||
}
|
||||
|
||||
// Find out if we need to output the end time/date. Do not output it for
|
||||
// instantaneous events and all-day events lasting only one day.
|
||||
if (
|
||||
! (
|
||||
$event->is_instant() ||
|
||||
( $event->is_allday() && $start_ts === $end_ts )
|
||||
)
|
||||
) {
|
||||
$output .= apply_filters(
|
||||
'ai1ec_get_timespan_html_date_separator',
|
||||
Ai1ec_I18n::_x( ' – ', 'Event start/end separator' )
|
||||
);
|
||||
|
||||
// If event ends on a different day, output end date.
|
||||
if ( $start_ts !== $end_ts ) {
|
||||
// for short date, use short display type
|
||||
if ( 'short' === $start_date_display ) {
|
||||
$output .= $this->get_short_date( $end, $break_years );
|
||||
} else {
|
||||
$output .= $this->get_long_date( $end );
|
||||
}
|
||||
}
|
||||
|
||||
// Output end time for non-all-day events.
|
||||
if ( ! $event->is_allday() ) {
|
||||
if ( $start_ts !== $end_ts ) {
|
||||
$output .= apply_filters(
|
||||
'ai1ec_get_timespan_html_time_separator',
|
||||
Ai1ec_I18n::_x( ' @ ', 'Event time separator' )
|
||||
);
|
||||
}
|
||||
$output .= $this->get_short_time( $end );
|
||||
}
|
||||
}
|
||||
|
||||
$output = esc_html( $output );
|
||||
|
||||
// Add all-day label.
|
||||
if ( $event->is_allday() ) {
|
||||
$output .= apply_filters(
|
||||
'ai1ec_get_timespan_html_allday_badge',
|
||||
' <span class="ai1ec-allday-badge">' .
|
||||
Ai1ec_I18n::__( 'all-day' ) .
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
return apply_filters(
|
||||
'ai1ec_get_timespan_html',
|
||||
$output,
|
||||
$event,
|
||||
$start_date_display
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the html for the exclude dates and exception rules.
|
||||
*
|
||||
* @param Ai1ec_Event $event
|
||||
* @param Ai1ec_Recurrence_Rule $rrule
|
||||
* @return string
|
||||
*/
|
||||
public function get_exclude_html(
|
||||
Ai1ec_Event $event,
|
||||
Ai1ec_Recurrence_Rule $rrule
|
||||
) {
|
||||
$excludes = array();
|
||||
$exception_rules = $event->get( 'exception_rules' );
|
||||
$exception_dates = $event->get( 'exception_dates' );
|
||||
if ( $exception_rules ) {
|
||||
$excludes[] =
|
||||
$rrule->rrule_to_text( $exception_rules );
|
||||
}
|
||||
if ( $exception_dates && 0 !== strpos( $exception_rules, 'EXDATE' ) ) {
|
||||
$excludes[] =
|
||||
$rrule->exdate_to_text( $exception_dates );
|
||||
}
|
||||
return implode( Ai1ec_I18n::__( ', and ' ), $excludes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the short date
|
||||
*
|
||||
* @param Ai1ec_Date_Time $time
|
||||
* @param bool $add_year Whether to add year or not.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_short_date( Ai1ec_Date_Time $time, $add_year = false ) {
|
||||
$months = apply_filters( 'ai1ec_i18n_months', array() );
|
||||
$m = $time->format_i18n( 'M' );
|
||||
$m = array_key_exists( $m, $months ) ? $months[$m] : $m;
|
||||
if ( $add_year ) {
|
||||
return $m . ' ' . $time->format_i18n( 'j Y' );
|
||||
}
|
||||
return $m . ' ' . $time->format_i18n( 'j' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a long-length date for use in other views (e.g., single event).
|
||||
*
|
||||
* @param Ai1ec_Date_Time $time Object to format.
|
||||
*
|
||||
* @return string Formatted date time [default: `l, M j, Y`].
|
||||
*/
|
||||
public function get_long_date( Ai1ec_Date_Time $time ) {
|
||||
$date_format = $this->_registry->get( 'model.option' )->get(
|
||||
'date_format',
|
||||
'l, M j, Y'
|
||||
);
|
||||
return $time->format_i18n( $date_format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a short-form time for use in compressed (e.g. month) views.
|
||||
*
|
||||
* @param Ai1ec_Date_Time $time Object to format.
|
||||
*
|
||||
* @return string Formatted date time [default: `g:i a`].
|
||||
*/
|
||||
public function get_short_time( Ai1ec_Date_Time $time ) {
|
||||
$time_format = $this->_registry->get( 'model.option' )->get(
|
||||
'time_format',
|
||||
'g:i a'
|
||||
);
|
||||
return $time->format_i18n( $time_format );
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user