<?php
/**
* Shopping Cart.
*
* @category Core
* @package My Tickets
* @author Joe Dolson
* @license GPLv2 or later
* @link https://www.joedolson.com/my-tickets/
*/
add_filter( 'the_content', 'my_tickets_cart', 20, 2 );
/**
* Display My Tickets shopping cart on purchase page.
*
* @param string $content Post Content.
*
* @return string
*/
function my_tickets_cart( $content ) {
$options = mt_get_settings();
$id = ( '' !== $options['mt_purchase_page'] ) ? $options['mt_purchase_page'] : false;
if ( is_main_query() && $id && ( is_single( $id ) || is_page( $id ) ) ) {
// by default, any page content is appended after the cart. This can be changed.
$content_before = apply_filters( 'mt_content_before_cart', '' );
$content_after = apply_filters( 'mt_content_after_cart', $content );
$cart = mt_generate_cart();
$content = $content_before . $cart . $content_after;
}
return $content;
}
add_action( 'init', 'mt_handle_response_message' );
/**
* Delete cart data if payment response message is 'thank you'.
*
* @return void
*/
function mt_handle_response_message() {
// if we've got a thank you message, we don't need this cart any more.
if ( isset( $_GET['response_code'] ) && 'thanks' === $_GET['response_code'] ) {
mt_delete_data( 'cart' );
mt_delete_data( 'payment' );
}
}
add_filter( 'mt_content_before_cart', 'mt_response_messages' );
/**
* Display response messages from cart on purchase page.
*
* @return string
*/
function mt_response_messages() {
$message = '';
$response_code = '';
if ( isset( $_GET['response_code'] ) ) {
$response_code = sanitize_text_field( $_GET['response_code'] );
if ( 'cancel' === $response_code ) {
$message = __( "We're sorry you were unable to complete your purchase! Please contact us if you had any issues in the purchase process.", 'my-tickets' );
}
if ( 'thanks' === $response_code ) {
$message = __( 'Thanks for your purchase!', 'my-tickets' );
if ( isset( $_GET['payment_id'] ) ) {
$payment_id = (int) $_GET['payment_id'];
$gateway = get_post_meta( $payment_id, '_gateway', true );
if ( 'offline' === $gateway ) {
wp_publish_post( $payment_id );
$message = __( 'Thanks for your order!', 'my-tickets' );
}
}
}
if ( 'required-fields' === $response_code ) {
$message = __( 'First name, last name, and email are required fields. Please fill in these fields and submit again!', 'my-tickets' );
}
if ( ! $message ) {
$message = ( isset( $_GET['reason'] ) ) ? sanitize_text_field( $_GET['reason'] ) : '';
if ( ! $message ) {
$message = ( isset( $_GET['response_reason_text'] ) ) ? sanitize_text_field( $_GET['response_reason_text'] ) : '';
}
$message = sanitize_text_field( $message );
}
return apply_filters( 'mt_response_messages', $message, $response_code );
}
return $message;
}
add_filter( 'mt_response_messages', 'mt_wrap_response_messages', 20, 2 );
/**
* Generate filterable HTML to wrap response messages.
*
* @param string $message Text of response message.
* @param string $code Error code received.
*
* @return string
*/
function mt_wrap_response_messages( $message, $code ) {
return "<p class='mt-message error-" . esc_attr( $code ) . "'>$message</p>";
}
/**
* Check whether cart includes any items that disallow shipping tickets.
*
* @param array $cart Cart data.
*
* @return bool
*/
function mt_cart_no_postal( $cart ) {
foreach ( $cart as $event => $data ) {
$prices = mt_get_prices( $event );
if ( is_array( $data ) ) {
foreach ( $data as $type => $count ) {
if ( $count > 0 ) {
if ( isset( $prices[ $type ] ) ) {
if ( mt_no_postal( $event ) && ! mt_event_expired( $event ) ) {
return true;
}
}
}
}
}
}
return false;
}
/**
* Incorporated basic required fields into cart data. Name, Email, ticket type selector.
*
* @param array $cart Cart data.
* @param string $custom_fields HTML for custom fields added by plugins.
*
* @return mixed|string
*/
function mt_required_fields( $cart, $custom_fields ) {
$options = mt_get_settings();
$output = mt_render_field( 'name' );
$output .= mt_render_field( 'email' );
$output .= ( isset( $options['mt_phone'] ) && 'on' === $options['mt_phone'] ) ? mt_render_field( 'phone' ) : '';
$output .= ( isset( $options['mt_vat'] ) && 'on' === $options['mt_vat'] ) ? mt_render_field( 'vat' ) : '';
$output .= apply_filters( 'mt_filter_custom_field_output', $custom_fields, $cart );
$opt_types = $options['mt_ticketing'];
if ( isset( $opt_types['postal'] ) ) {
$no_postal = mt_cart_no_postal( $cart );
if ( $no_postal ) {
unset( $opt_types['postal'] );
}
}
$types = array_keys( $opt_types );
if ( 1 === count( $types ) ) {
foreach ( $types as $type ) {
$output .= mt_render_type( $type );
}
} else {
$output .= mt_render_types( $types );
}
return $output;
}
/**
* Test whether user is logged in and whether user registration is allowed. Return invitation to log-in or register.
* Displays only if public registration is enabled.
*
* @return string
*/
function mt_invite_login_or_register() {
if ( ! is_user_logged_in() && '1' === get_option( 'users_can_register' ) ) {
$login = apply_filters( 'mt_login_html', "<a href='" . wp_login_url() . "'>" . __( 'Log in', 'my-tickets' ) . '</a>' );
if ( '1' === get_option( 'users_can_register' ) ) {
$register = apply_filters( 'mt_register_html', "<a href='" . wp_registration_url() . "'>" . __( 'Create an account', 'my-tickets' ) . '</a>' );
} else {
$register = '';
}
if ( '' !== $register ) {
// Translators: Login link, register link.
$text = wpautop( sprintf( __( '%1$s or %2$s', 'my-tickets' ), $login, $register ) );
} else {
// Translators: Login link.
$text = wpautop( sprintf( __( '%1$s now!', 'my-tickets' ), $login ) );
}
return apply_filters( 'mt_invite_login_or_register', "<div class='mt-invite-login-or-register'>$text</div>" );
}
return '';
}
/**
* If multiple types are available, allow to choose whether or not to use an e-ticket. Notify of multiple methods that are available.
*
* @param array $types Types of tickets enabled.
*
* @return string
*/
function mt_render_types( $types ) {
$options = mt_get_settings();
$ticketing = apply_filters( 'mt_ticketing_availability', $options['mt_ticketing'], $types );
$default = isset( $options['mt_ticket_type_default'] ) ? $options['mt_ticket_type_default'] : '';
$output = '<p class="mt-ticket-type"><label for="ticketing_method">' . __( 'Ticket Type', 'my-tickets' ) . '</label> <select name="ticketing_method" id="ticketing_method">';
foreach ( $ticketing as $key => $method ) {
if ( in_array( $key, $types, true ) ) {
$selected = selected( $key, $default, false );
$output .= "<option value='$key'$selected>$method</option>";
}
}
$output .= '</select></p>';
return $output;
}
/**
* Display notice informing purchaser of the format that their ticket will be delivered in.
*
* @param string $type Ticket type.
*
* @return string
*/
function mt_render_type( $type ) {
$options = mt_get_settings();
switch ( $type ) {
case 'eticket':
$return = __( 'Your ticket will be delivered as an e-ticket. You will receive a link in your email.', 'my-tickets' );
break;
case 'printable':
$return = __( 'Your ticket will be provided for printing after purchase. You will receive a link to the ticket in your email. Please print your ticket and bring it with you to the event.', 'my-tickets' );
break;
case 'postal':
// Translators: estimated number of days for ticket shipping.
$return = sprintf( __( 'Your ticket will be sent to you by mail. You should receive your ticket within %s days, after payment is completed.', 'my-tickets' ), $options['mt_shipping_time'] );
break;
case 'willcall':
$return = __( 'Your ticket will be under your name at the box office. Please arrive early to allow time to pick up your ticket.', 'my-tickets' );
break;
default:
$return = '';
}
return "<input type='hidden' name='ticketing_method' value='$type' />" . apply_filters( 'mt_render_ticket_type_message', "<p class='ticket-type-message'>" . $return . '</p>', $type );
}
/**
* Display input field on cart screen. (Pre Confirmation)
*
* @param string $field Name of field to display.
* @param bool $argument Custom arguments.
*
* @return mixed|void
*/
function mt_render_field( $field, $argument = false ) {
$current_user = wp_get_current_user();
$output = '';
$defaults = array(
'street' => '',
'street2' => '',
'city' => '',
'state' => '',
'country' => '',
'code' => '',
);
$payment_id = false;
if ( isset( $_GET['payment'] ) || mt_get_data( 'payment' ) ) {
$payment_id = ( isset( $_GET['payment'] ) ) ? (int) $_GET['payment'] : mt_get_data( 'payment' );
}
switch ( $field ) {
case 'address':
// only show shipping fields if postal ticketing in use.
if ( ( isset( $_POST['ticketing_method'] ) && 'postal' === $_POST['ticketing_method'] ) || mt_always_collect_shipping() ) {
$user_address = ( is_user_logged_in() ) ? get_user_meta( $current_user->ID, '_mt_shipping_address', true ) : $defaults;
if ( get_user_meta( $current_user->ID, '_mt_shipping_address', true ) ) {
$save_address_label = __( 'Update Address', 'my-tickets' );
} else {
$save_address_label = __( 'Save Address', 'my-tickets' );
}
$save_address = ( is_user_logged_in() ) ? '<p><button type="button" class="mt_save_shipping">' . $save_address_label . "<span class='mt-processing'><img src='" . admin_url( 'images/spinner-2x.gif' ) . "' alt='" . __( 'Working', 'my-tickets' ) . "' /></span></button></p>" : '';
$address = ( isset( $_POST['mt_shipping']['address'] ) ) ? $_POST['mt_shipping']['address'] : (array) $user_address;
$address = array_merge( $defaults, $address );
$required = ' ' . __( '(required)', 'my-tickets' );
$output = '
<fieldset class="mt-shipping-address">
<legend>' . __( 'Shipping Address', 'my-tickets' ) . '</legend>
<p>
<label for="mt_address_street">' . __( 'Street', 'my-tickets' ) . $required . '</label>
<input type="text" name="mt_shipping_street" id="mt_address_street" class="mt_street" value="' . esc_attr( stripslashes( $address['street'] ) ) . '" autocomplete="address-line1" required />
</p>
<p>
<label for="mt_address_street2">' . __( 'Street (2)', 'my-tickets' ) . '</label>
<input type="text" name="mt_shipping_street2" id="mt_address_street2" class="mt_street2" value="' . esc_attr( stripslashes( $address['street2'] ) ) . '" autocomplete="address-line2" />
</p>
<p>
<label for="mt_address_city">' . __( 'City', 'my-tickets' ) . $required . '</label>
<input type="text" name="mt_shipping_city" id="mt_address_city" class="mt_city" value="' . esc_attr( stripslashes( $address['city'] ) ) . '" autocomplete="address-level2" required />
</p>
<p>
<label for="mt_address_state">' . __( 'State/Province', 'my-tickets' ) . '</label>
<input type="text" name="mt_shipping_state" id="mt_address_state" class="mt_state" value="' . esc_attr( stripslashes( $address['state'] ) ) . '" autocomplete="address-level1" />
</p>
<p>
<label for="mt_address_code">' . __( 'Postal Code', 'my-tickets' ) . $required . '</label>
<input type="text" name="mt_shipping_code" size="10" id="mt_address_code" class="mt_code" value="' . esc_attr( stripslashes( $address['code'] ) ) . '" autocomplete="postal-code" required />
</p>
<p>
<label for="mt_address_country">' . __( 'Country', 'my-tickets' ) . $required . '</label>
<select name="mt_shipping_country" id="mt_address_country" class="mt_country" autocomplete="country">
<option value="">Select Country</option>
' . mt_shipping_country( $address['country'] ) . '
</select>
</p>' . $save_address . '
<div class="mt-response" aria-live="assertive"></div>
</fieldset>';
}
$output = apply_filters( 'mt_shipping_fields', $output, $argument );
break;
case 'name':
$user_fname = ( is_user_logged_in() ) ? $current_user->user_firstname : '';
$user_lname = ( is_user_logged_in() ) ? $current_user->user_lastname : '';
$fname = ( isset( $_POST['mt_fname'] ) ) ? sanitize_text_field( $_POST['mt_fname'] ) : $user_fname;
$lname = ( isset( $_POST['mt_lname'] ) ) ? sanitize_text_field( $_POST['mt_lname'] ) : $user_lname;
if ( $payment_id ) {
$fname = get_post_meta( $payment_id, '_first_name', true );
$lname = get_post_meta( $payment_id, '_last_name', true );
}
$output = '<div class="mt-names"><p><label for="mt_fname">' . __( 'First Name (required)', 'my-tickets' ) . '</label> <input type="text" name="mt_fname" id="mt_fname" value="' . esc_attr( stripslashes( $fname ) ) . '" autocomplete="given-name" required aria-required="true" /></p><p><label for="mt_lname">' . __( 'Last Name (required)', 'my-tickets' ) . '</label> <input type="text" name="mt_lname" id="mt_lname" value="' . esc_attr( stripslashes( $lname ) ) . '" autocomplete="family-name" required aria-required="true" /></p></div>';
break;
case 'email':
$user_email = ( is_user_logged_in() ) ? $current_user->user_email : '';
$email = ( isset( $_POST['mt_email'] ) ) ? sanitize_text_field( $_POST['mt_email'] ) : $user_email;
if ( $payment_id ) {
$email = get_post_meta( $payment_id, '_email', true );
}
$output = '<div class="mt-emails"><p><label for="mt_email">' . __( 'E-mail (required)', 'my-tickets' ) . '</label> <input type="email" name="mt_email" id="mt_email" value="' . esc_attr( stripslashes( $email ) ) . '" autocomplete="email" required aria-required="true" /></p>';
$output .= '<p><label for="mt_email2">' . __( 'E-mail (confirm)', 'my-tickets' ) . '</label> <input type="email" name="mt_email2" id="mt_email2" aria-describedby="mt_email_check" value="' . esc_attr( stripslashes( $email ) ) . '" required aria-required="true" /><span class="mt_email_check" aria-live="polite" id="mt_email_check"><span class="ok"><i class="dashicons dashicons-yes" aria-hidden="true"></i>' . __( 'Email address matches', 'my-tickets' ) . '</span><span class="notemail"><i class="dashicons dashicons-no" aria-hidden="true"></i>' . __( 'Not a valid email address', 'my-tickets' ) . '</span><span class="mismatch"><i class="dashicons dashicons-no" aria-hidden="true"></i>' . __( 'Email address does not match', 'my-tickets' ) . '</span></span></span></p></div>';
break;
case 'phone':
$user_phone = ( is_user_logged_in() ) ? get_user_meta( $current_user->ID, 'mt_phone', true ) : '';
$phone = ( isset( $_POST['mt_phone'] ) ) ? sanitize_text_field( $_POST['mt_phone'] ) : $user_phone;
if ( $payment_id ) {
$phone = get_post_meta( $payment_id, '_phone', true );
}
$output = '<p><label for="mt_phone">' . __( 'Phone (required)', 'my-tickets' ) . '</label> <input type="text" name="mt_phone" id="mt_phone" value="' . esc_attr( stripslashes( $phone ) ) . '" autocomplete="tel" required aria-required="true" /></p>';
break;
case 'vat':
$user_vat = ( is_user_logged_in() ) ? get_user_meta( $current_user->ID, 'mt_vat', true ) : '';
$vat = ( isset( $_POST['mt_vat'] ) ) ? sanitize_text_field( $_POST['mt_vat'] ) : $user_vat;
if ( $payment_id ) {
$vat = get_post_meta( $payment_id, '_vat', true );
}
$output = '<p><label for="mt_vat">' . __( 'VAT Number', 'my-tickets' ) . '</label> <input type="text" name="mt_vat" id="mt_vat" value="' . esc_attr( stripslashes( $vat ) ) . '" required aria-required="true" /></p>';
break;
}
return apply_filters( 'mt_render_field', $output, $field );
}
/**
* Generate option list of country codes.
*
* @param string $country selected country or country code.
*
* @return string
*/
function mt_shipping_country( $country = '' ) {
$countries = array(
'AF' => __( 'Afghanistan', 'my-tickets' ),
'AX' => __( 'Aland Islands', 'my-tickets' ),
'AL' => __( 'Albania', 'my-tickets' ),
'DZ' => __( 'Algeria', 'my-tickets' ),
'AS' => __( 'American Samoa', 'my-tickets' ),
'AD' => __( 'Andorra', 'my-tickets' ),
'AO' => __( 'Angola', 'my-tickets' ),
'AI' => __( 'Anguilla', 'my-tickets' ),
'AQ' => __( 'Antarctica', 'my-tickets' ),
'AG' => __( 'Antigua And Barbuda', 'my-tickets' ),
'AR' => __( 'Argentina', 'my-tickets' ),
'AM' => __( 'Armenia', 'my-tickets' ),
'AW' => __( 'Aruba', 'my-tickets' ),
'AU' => __( 'Australia', 'my-tickets' ),
'AT' => __( 'Austria', 'my-tickets' ),
'AZ' => __( 'Azerbaijan', 'my-tickets' ),
'BS' => __( 'Bahamas', 'my-tickets' ),
'BH' => __( 'Bahrain', 'my-tickets' ),
'BD' => __( 'Bangladesh', 'my-tickets' ),
'BB' => __( 'Barbados', 'my-tickets' ),
'BY' => __( 'Belarus', 'my-tickets' ),
'BE' => __( 'Belgium', 'my-tickets' ),
'BZ' => __( 'Belize', 'my-tickets' ),
'BJ' => __( 'Benin', 'my-tickets' ),
'BM' => __( 'Bermuda', 'my-tickets' ),
'BT' => __( 'Bhutan', 'my-tickets' ),
'BO' => __( 'Bolivia', 'my-tickets' ),
'BA' => __( 'Bosnia And Herzegovina', 'my-tickets' ),
'BW' => __( 'Botswana', 'my-tickets' ),
'BV' => __( 'Bouvet Island', 'my-tickets' ),
'BR' => __( 'Brazil', 'my-tickets' ),
'IO' => __( 'British Indian Ocean Territory', 'my-tickets' ),
'BN' => __( 'Brunei Darussalam', 'my-tickets' ),
'BG' => __( 'Bulgaria', 'my-tickets' ),
'BF' => __( 'Burkina Faso', 'my-tickets' ),
'BI' => __( 'Burundi', 'my-tickets' ),
'KH' => __( 'Cambodia', 'my-tickets' ),
'CM' => __( 'Cameroon', 'my-tickets' ),
'CA' => __( 'Canada', 'my-tickets' ),
'CV' => __( 'Cape Verde', 'my-tickets' ),
'KY' => __( 'Cayman Islands', 'my-tickets' ),
'CF' => __( 'Central African Republic', 'my-tickets' ),
'TD' => __( 'Chad', 'my-tickets' ),
'CL' => __( 'Chile', 'my-tickets' ),
'CN' => __( 'China', 'my-tickets' ),
'CX' => __( 'Christmas Island', 'my-tickets' ),
'CC' => __( 'Cocos (Keeling) Islands', 'my-tickets' ),
'CO' => __( 'Colombia', 'my-tickets' ),
'KM' => __( 'Comoros', 'my-tickets' ),
'CG' => __( 'Congo', 'my-tickets' ),
'CD' => __( 'Congo, Democratic Republic', 'my-tickets' ),
'CK' => __( 'Cook Islands', 'my-tickets' ),
'CR' => __( 'Costa Rica', 'my-tickets' ),
'CI' => __( 'Cote D\'Ivoire', 'my-tickets' ),
'HR' => __( 'Croatia', 'my-tickets' ),
'CU' => __( 'Cuba', 'my-tickets' ),
'CY' => __( 'Cyprus', 'my-tickets' ),
'CZ' => __( 'Czech Republic', 'my-tickets' ),
'DK' => __( 'Denmark', 'my-tickets' ),
'DJ' => __( 'Djibouti', 'my-tickets' ),
'DM' => __( 'Dominica', 'my-tickets' ),
'DO' => __( 'Dominican Republic', 'my-tickets' ),
'EC' => __( 'Ecuador', 'my-tickets' ),
'EG' => __( 'Egypt', 'my-tickets' ),
'SV' => __( 'El Salvador', 'my-tickets' ),
'GQ' => __( 'Equatorial Guinea', 'my-tickets' ),
'ER' => __( 'Eritrea', 'my-tickets' ),
'EE' => __( 'Estonia', 'my-tickets' ),
'ET' => __( 'Ethiopia', 'my-tickets' ),
'FK' => __( 'Falkland Islands (Malvinas)', 'my-tickets' ),
'FO' => __( 'Faroe Islands', 'my-tickets' ),
'FJ' => __( 'Fiji', 'my-tickets' ),
'FI' => __( 'Finland', 'my-tickets' ),
'FR' => __( 'France', 'my-tickets' ),
'GF' => __( 'French Guiana', 'my-tickets' ),
'PF' => __( 'French Polynesia', 'my-tickets' ),
'TF' => __( 'French Southern Territories', 'my-tickets' ),
'GA' => __( 'Gabon', 'my-tickets' ),
'GM' => __( 'Gambia', 'my-tickets' ),
'GE' => __( 'Georgia', 'my-tickets' ),
'DE' => __( 'Germany', 'my-tickets' ),
'GH' => __( 'Ghana', 'my-tickets' ),
'GI' => __( 'Gibraltar', 'my-tickets' ),
'GR' => __( 'Greece', 'my-tickets' ),
'GL' => __( 'Greenland', 'my-tickets' ),
'GD' => __( 'Grenada', 'my-tickets' ),
'GP' => __( 'Guadeloupe', 'my-tickets' ),
'GU' => __( 'Guam', 'my-tickets' ),
'GT' => __( 'Guatemala', 'my-tickets' ),
'GG' => __( 'Guernsey', 'my-tickets' ),
'GN' => __( 'Guinea', 'my-tickets' ),
'GW' => __( 'Guinea-Bissau', 'my-tickets' ),
'GY' => __( 'Guyana', 'my-tickets' ),
'HT' => __( 'Haiti', 'my-tickets' ),
'HM' => __( 'Heard Island & Mcdonald Islands', 'my-tickets' ),
'VA' => __( 'Holy See (Vatican City State)', 'my-tickets' ),
'HN' => __( 'Honduras', 'my-tickets' ),
'HK' => __( 'Hong Kong', 'my-tickets' ),
'HU' => __( 'Hungary', 'my-tickets' ),
'IS' => __( 'Iceland', 'my-tickets' ),
'IN' => __( 'India', 'my-tickets' ),
'ID' => __( 'Indonesia', 'my-tickets' ),
'IR' => __( 'Iran, Islamic Republic Of', 'my-tickets' ),
'IQ' => __( 'Iraq', 'my-tickets' ),
'IE' => __( 'Ireland', 'my-tickets' ),
'IM' => __( 'Isle Of Man', 'my-tickets' ),
'IL' => __( 'Israel', 'my-tickets' ),
'IT' => __( 'Italy', 'my-tickets' ),
'JM' => __( 'Jamaica', 'my-tickets' ),
'JP' => __( 'Japan', 'my-tickets' ),
'JE' => __( 'Jersey', 'my-tickets' ),
'JO' => __( 'Jordan', 'my-tickets' ),
'KZ' => __( 'Kazakhstan', 'my-tickets' ),
'KE' => __( 'Kenya', 'my-tickets' ),
'KI' => __( 'Kiribati', 'my-tickets' ),
'KR' => __( 'Korea', 'my-tickets' ),
'KW' => __( 'Kuwait', 'my-tickets' ),
'KG' => __( 'Kyrgyzstan', 'my-tickets' ),
'LA' => __( 'Lao People\'s Democratic Republic', 'my-tickets' ),
'LV' => __( 'Latvia', 'my-tickets' ),
'LB' => __( 'Lebanon', 'my-tickets' ),
'LS' => __( 'Lesotho', 'my-tickets' ),
'LR' => __( 'Liberia', 'my-tickets' ),
'LY' => __( 'Libyan Arab Jamahiriya', 'my-tickets' ),
'LI' => __( 'Liechtenstein', 'my-tickets' ),
'LT' => __( 'Lithuania', 'my-tickets' ),
'LU' => __( 'Luxembourg', 'my-tickets' ),
'MO' => __( 'Macao', 'my-tickets' ),
'MK' => __( 'Macedonia', 'my-tickets' ),
'MG' => __( 'Madagascar', 'my-tickets' ),
'MW' => __( 'Malawi', 'my-tickets' ),
'MY' => __( 'Malaysia', 'my-tickets' ),
'MV' => __( 'Maldives', 'my-tickets' ),
'ML' => __( 'Mali', 'my-tickets' ),
'MT' => __( 'Malta', 'my-tickets' ),
'MH' => __( 'Marshall Islands', 'my-tickets' ),
'MQ' => __( 'Martinique', 'my-tickets' ),
'MR' => __( 'Mauritania', 'my-tickets' ),
'MU' => __( 'Mauritius', 'my-tickets' ),
'YT' => __( 'Mayotte', 'my-tickets' ),
'MX' => __( 'Mexico', 'my-tickets' ),
'FM' => __( 'Micronesia, Federated States Of', 'my-tickets' ),
'MD' => __( 'Moldova', 'my-tickets' ),
'MC' => __( 'Monaco', 'my-tickets' ),
'MN' => __( 'Mongolia', 'my-tickets' ),
'ME' => __( 'Montenegro', 'my-tickets' ),
'MS' => __( 'Montserrat', 'my-tickets' ),
'MA' => __( 'Morocco', 'my-tickets' ),
'MZ' => __( 'Mozambique', 'my-tickets' ),
'MM' => __( 'Myanmar', 'my-tickets' ),
'NA' => __( 'Namibia', 'my-tickets' ),
'NR' => __( 'Nauru', 'my-tickets' ),
'NP' => __( 'Nepal', 'my-tickets' ),
'NL' => __( 'Netherlands', 'my-tickets' ),
'AN' => __( 'Netherlands Antilles', 'my-tickets' ),
'NC' => __( 'New Caledonia', 'my-tickets' ),
'NZ' => __( 'New Zealand', 'my-tickets' ),
'NI' => __( 'Nicaragua', 'my-tickets' ),
'NE' => __( 'Niger', 'my-tickets' ),
'NG' => __( 'Nigeria', 'my-tickets' ),
'NU' => __( 'Niue', 'my-tickets' ),
'NF' => __( 'Norfolk Island', 'my-tickets' ),
'MP' => __( 'Northern Mariana Islands', 'my-tickets' ),
'NO' => __( 'Norway', 'my-tickets' ),
'OM' => __( 'Oman', 'my-tickets' ),
'PK' => __( 'Pakistan', 'my-tickets' ),
'PW' => __( 'Palau', 'my-tickets' ),
'PS' => __( 'Palestinian Territory, Occupied', 'my-tickets' ),
'PA' => __( 'Panama', 'my-tickets' ),
'PG' => __( 'Papua New Guinea', 'my-tickets' ),
'PY' => __( 'Paraguay', 'my-tickets' ),
'PE' => __( 'Peru', 'my-tickets' ),
'PH' => __( 'Philippines', 'my-tickets' ),
'PN' => __( 'Pitcairn', 'my-tickets' ),
'PL' => __( 'Poland', 'my-tickets' ),
'PT' => __( 'Portugal', 'my-tickets' ),
'PR' => __( 'Puerto Rico', 'my-tickets' ),
'QA' => __( 'Qatar', 'my-tickets' ),
'RE' => __( 'Reunion', 'my-tickets' ),
'RO' => __( 'Romania', 'my-tickets' ),
'RU' => __( 'Russian Federation', 'my-tickets' ),
'RW' => __( 'Rwanda', 'my-tickets' ),
'BL' => __( 'Saint Barthelemy', 'my-tickets' ),
'SH' => __( 'Saint Helena', 'my-tickets' ),
'KN' => __( 'Saint Kitts And Nevis', 'my-tickets' ),
'LC' => __( 'Saint Lucia', 'my-tickets' ),
'MF' => __( 'Saint Martin', 'my-tickets' ),
'PM' => __( 'Saint Pierre And Miquelon', 'my-tickets' ),
'VC' => __( 'Saint Vincent And Grenadines', 'my-tickets' ),
'WS' => __( 'Samoa', 'my-tickets' ),
'SM' => __( 'San Marino', 'my-tickets' ),
'ST' => __( 'Sao Tome And Principe', 'my-tickets' ),
'SA' => __( 'Saudi Arabia', 'my-tickets' ),
'SN' => __( 'Senegal', 'my-tickets' ),
'RS' => __( 'Serbia', 'my-tickets' ),
'SC' => __( 'Seychelles', 'my-tickets' ),
'SL' => __( 'Sierra Leone', 'my-tickets' ),
'SG' => __( 'Singapore', 'my-tickets' ),
'SK' => __( 'Slovakia', 'my-tickets' ),
'SI' => __( 'Slovenia', 'my-tickets' ),
'SB' => __( 'Solomon Islands', 'my-tickets' ),
'SO' => __( 'Somalia', 'my-tickets' ),
'ZA' => __( 'South Africa', 'my-tickets' ),
'GS' => __( 'South Georgia And Sandwich Isl.', 'my-tickets' ),
'ES' => __( 'Spain', 'my-tickets' ),
'LK' => __( 'Sri Lanka', 'my-tickets' ),
'SD' => __( 'Sudan', 'my-tickets' ),
'SR' => __( 'Suriname', 'my-tickets' ),
'SJ' => __( 'Svalbard And Jan Mayen', 'my-tickets' ),
'SZ' => __( 'Swaziland', 'my-tickets' ),
'SE' => __( 'Sweden', 'my-tickets' ),
'CH' => __( 'Switzerland', 'my-tickets' ),
'SY' => __( 'Syrian Arab Republic', 'my-tickets' ),
'TW' => __( 'Taiwan', 'my-tickets' ),
'TJ' => __( 'Tajikistan', 'my-tickets' ),
'TZ' => __( 'Tanzania', 'my-tickets' ),
'TH' => __( 'Thailand', 'my-tickets' ),
'TL' => __( 'Timor-Leste', 'my-tickets' ),
'TG' => __( 'Togo', 'my-tickets' ),
'TK' => __( 'Tokelau', 'my-tickets' ),
'TO' => __( 'Tonga', 'my-tickets' ),
'TT' => __( 'Trinidad And Tobago', 'my-tickets' ),
'TN' => __( 'Tunisia', 'my-tickets' ),
'TR' => __( 'Turkey', 'my-tickets' ),
'TM' => __( 'Turkmenistan', 'my-tickets' ),
'TC' => __( 'Turks And Caicos Islands', 'my-tickets' ),
'TV' => __( 'Tuvalu', 'my-tickets' ),
'UG' => __( 'Uganda', 'my-tickets' ),
'UA' => __( 'Ukraine', 'my-tickets' ),
'AE' => __( 'United Arab Emirates', 'my-tickets' ),
'GB' => __( 'United Kingdom', 'my-tickets' ),
'US' => __( 'United States', 'my-tickets' ),
'UM' => __( 'United States Outlying Islands', 'my-tickets' ),
'UY' => __( 'Uruguay', 'my-tickets' ),
'UZ' => __( 'Uzbekistan', 'my-tickets' ),
'VU' => __( 'Vanuatu', 'my-tickets' ),
'VE' => __( 'Venezuela', 'my-tickets' ),
'VN' => __( 'Viet Nam', 'my-tickets' ),
'VG' => __( 'Virgin Islands, British', 'my-tickets' ),
'VI' => __( 'Virgin Islands, U.S.', 'my-tickets' ),
'WF' => __( 'Wallis And Futuna', 'my-tickets' ),
'EH' => __( 'Western Sahara', 'my-tickets' ),
'YE' => __( 'Yemen', 'my-tickets' ),
'ZM' => __( 'Zambia', 'my-tickets' ),
'ZW' => __( 'Zimbabwe', 'my-tickets' ),
);
/**
* Filter the available array of countries for shipping addresses.
*
* @hook mt_shipping_countries
*
* @param {array} $countries Array of available countries.
* @param {string} $country Currently selected country, if any.
*
* @return {array}
*/
$countries = apply_filters( 'mt_shipping_countries', $countries, $country );
$options = '';
foreach ( $countries as $key => $value ) {
$selected = ( $country === $key || $country === $value ) ? ' selected="selected"' : '';
$options .= '<option value="' . esc_attr( $key ) . '"' . $selected . '>' . esc_html( $value ) . '</option>';
}
return $options;
}
/**
* Check whether the options to collect addresses are turned on.
*
* @return bool
*/
function mt_always_collect_shipping() {
$options = mt_get_settings();
$shipping = ( isset( $options['mt_collect_shipping'] ) ) ? $options['mt_collect_shipping'] : false;
$shipping = ( 'true' === $shipping ) ? true : false;
return $shipping;
}
/**
* Generate selector for choosing payment gateway.
*
* @return string
*/
function mt_gateways() {
$selector = '';
$options = mt_get_settings();
$enabled = $options['mt_gateway'];
if ( 1 === count( $enabled ) ) {
return '';
} else {
$labels = mt_setup_gateways();
foreach ( $enabled as $gate ) {
$current_gate = ( isset( $_GET['mt_gateway'] ) && in_array( $_GET['mt_gateway'], $enabled, true ) ) ? $_GET['mt_gateway'] : $options['mt_default_gateway'];
if ( isset( $labels[ $gate ] ) ) {
$checked = ( $gate === $current_gate ) ? ' class="active"' : '';
$current = ( $gate === $current_gate ) ? ' aria-current="true"' : '';
$label = $labels[ $gate ]['label'];
if ( isset( $options['mt_gateways'][ $gate ]['selector'] ) ) {
$label = ( '' === $options['mt_gateways'][ $gate ]['selector'] ) ? $label : $options['mt_gateways'][ $gate ]['selector'];
}
$selector .= "<li$checked><button type='button' class='mt-gateway-selector " . esc_attr( $gate ) . "' data-assign='" . esc_attr( $gate ) . "'$current>$label</button></li>";
}
}
return "<div class='gateway-selector'><ul><li>" . __( 'Payment Gateway', 'my-tickets' ) . ": $selector</ul></div>";
}
}
/**
* Display time remaining before cart expiration.
*
* @return string
*/
function mt_generate_expiration() {
// If this is a post-payment page, remove data and don't display message.
if ( isset( $_GET['payment_id'] ) ) {
mt_delete_data( 'cart' );
return '';
}
$expiration = mt_get_expiration();
$output = '';
if ( 0 === $expiration ) {
return '';
}
if ( ( $expiration - time() ) > 24 * HOUR_IN_SECONDS ) {
// No message if more than a day.
} elseif ( ( $expiration - time() ) > 60 * MINUTE_IN_SECONDS ) {
// translators: amount of time remaining before the cart expires.
$output = '<div class="mt-expiration-notice"><p>' . sprintf( __( 'Your shopping cart will be saved for another %s.', 'my-tickets' ), human_time_diff( time(), $expiration ) ) . '</p></div>';
} else {
// translators: 1) value in seconds, 2) human readable time remaining that the cart is saved.
$output = '<div class="mt-expiration-notice"><div class="mt-expiration-update"><p>' . sprintf( __( 'Your shopping cart will expire in <span id="mt-timer" class="mt-timer" data-start="%1$d">%2$s</span>.', 'my-tickets' ), ( $expiration - time() ), human_time_diff( time(), $expiration ) ) . '</p></div><div class="mt-expiration-controls"><button class="mt-extend-button" type="button"><span class="dashicons dashicons-clock" aria-hidden="true"></span> ' . __( 'Add 5 minutes', 'my-tickets' ) . '</button></div></div>';
}
return $output;
}
/**
* Generate breadcrumb path for cart purchase process
*
* @param string|boolean $gateway Has a value if we're on payment process; false if not set.
*
* @return string
*/
function mt_generate_path( $gateway ) {
$path = '<span class="active"><a href="' . apply_filters( 'mt_home_breadcrumb_url', home_url() ) . '">' . __( 'Home', 'my-tickets' ) . '</a></span>';
if ( false === $gateway ) {
$path .= '<span class="inactive"><strong>' . __( 'Cart', 'my-tickets' ) . '</strong></span>';
} else {
$path .= '<span class="active"><a href="' . mt_get_cart_url() . '">' . __( 'Cart', 'my-tickets' ) . '</a></span>';
}
if ( false === $gateway ) {
$path .= '<span class="inactive">' . __( 'Payment', 'my-tickets' ) . '</span>';
} else {
$path .= '<span class="inactive"><strong>' . __( 'Payment', 'my-tickets' ) . '</strong></span>';
}
return "<div class='mt_purchase_path'>" . $path . '</div>';
}
/**
* Generate cart. Show all events with tickets in cart unless event is already past the time when it can be ordered.
* TODO: Display notice if item has been removed from cart.
*
* @param bool $user_ID User ID.
*
* @return mixed|string|void
*/
function mt_generate_cart( $user_ID = false ) {
// if submitted successfully & payment required, toggle to payment form.
$options = mt_get_settings();
$gateway = isset( $_POST['mt_gateway'] ) ? sanitize_text_field( $_POST['mt_gateway'] ) : false;
$expiration = mt_generate_expiration();
$breadcrumbs = mt_generate_path( $gateway );
// TODO: If gateway is offline, mt_generate_gateway is never run. Use mt_generate_gateway to create button in both cases.
// Need to handle the case where multiple gateways are available, however; can't display the gateway until after gateway is selected.
if ( $gateway ) {
$response = mt_update_cart( map_deep( $_POST['mt_cart_order'], 'sanitize_textarea_field' ) );
$cart = $response['cart'];
$output = mt_generate_gateway( $cart );
} else {
$cart = mt_get_cart( $user_ID );
$total = apply_filters( 'mt_generate_cart_total', mt_total_cart( $cart ), $cart );
$count = mt_count_cart( $cart );
$nonce = wp_nonce_field( 'mt_cart_nonce', '_wpnonce', true, false );
$enabled = $options['mt_gateway'];
$current_gate = ( isset( $_GET['mt_gateway'] ) && in_array( $_GET['mt_gateway'], $enabled, true ) ) ? sanitize_text_field( $_GET['mt_gateway'] ) : $options['mt_default_gateway'];
$current_gate = ( ! $total ) ? 'offline' : $current_gate; // Must be offline gateway if price is free.
$handling_total = mt_get_cart_handling( $options, $current_gate );
$handling = apply_filters( 'mt_money_format', $handling_total );
$gateway = "<input type='hidden' name='mt_gateway' value='" . esc_attr( $current_gate ) . "' />";
$cart_page = mt_get_cart_url();
if ( is_array( $cart ) && ! empty( $cart ) && $count > 0 ) {
$output = '
<div class="mt_cart">
<div class="mt-response" aria-live="assertive"></div>
<form action="' . esc_url( $cart_page ) . '" method="POST">' . "
<input class='screen-reader-text' type='submit' name='mt_submit' value='" . apply_filters( 'mt_submit_button_text', __( 'Review cart and make payment', 'my-tickets' ), $current_gate ) . "' />" . '
' . $nonce . '
' . $gateway;
$output .= mt_generate_cart_table( $cart );
if ( $handling_total && 0 !== (int) $handling_total ) {
// Translators: amount of handling fee.
$output .= "<div class='mt_cart_handling'>" . apply_filters( 'mt_cart_handling_text', sprintf( __( 'A handling fee of %s will be applied to this purchase.', 'my-tickets' ), $handling ), $current_gate ) . '</div>';
}
if ( mt_handling_notice() ) {
$output .= "<div class='mt_ticket_handling'>" . mt_handling_notice() . '</div>';
}
/**
* Filter cart custom fields when generating the shopping cart.
*
* @hook mt_cart_custom_fields
*
* @param {array} $fields Array of defined custom fields. Initialized as empty array.
* @param {array} $cart Shopping cart contents.
* @param {string} $gateway Gateway in use.
*
* @return {array}
*/
$custom_fields = apply_filters( 'mt_cart_custom_fields', array(), $cart, $gateway );
$custom_output = '';
foreach ( $custom_fields as $key => $field ) {
$custom_output .= $field;
}
$button = "<p class='mt_submit'><input type='submit' name='mt_submit' value='" . apply_filters( 'mt_submit_button_text', __( 'Review cart and make payment', 'my-tickets' ), $current_gate ) . "' /></p>";
$output .= "<div class='mt_cart_total' aria-live='assertive'>" . apply_filters( 'mt_cart_total_content', '', $current_gate, $cart ) . apply_filters( 'mt_cart_ticket_total_text', __( 'Ticket Total:', 'my-tickets' ), $current_gate ) . " <span class='mt_total_number'>" . apply_filters( 'mt_money_format', $total ) . "</span></div>\n" . mt_invite_login_or_register() . "\n" . mt_required_fields( $cart, $custom_output ) . "\n" . mt_gateways() . "$button\n<input type='hidden' name='my-tickets' value='true' />" . apply_filters( 'mt_cart_hidden_fields', '' ) . '</form>' . mt_copy_cart() . '</div>';
} else {
do_action( 'mt_cart_is_empty' );
$expiration = '';
// clear POST data to prevent re-submission of data.
$_POST = array();
if ( isset( $_GET['payment_id'] ) ) {
$post_id = absint( $_GET['payment_id'] );
$date = get_post_modified_time( 'U', false, $post_id );
if ( $date < ( mt_current_time() - 300 ) ) {
// This transaction data is only available publically for 5 minutes after post is updated.
return '';
} else {
$receipt = get_post_meta( $post_id, '_receipt', true );
$options = mt_get_settings();
$link = add_query_arg( 'receipt_id', $receipt, get_permalink( $options['mt_receipt_page'] ) );
$purchase = get_post_meta( $post_id, '_purchased' );
/**
* Filter messages shown after a transaction has been confirmed.
*
* @hook mt_confirmed_transaction
*
* @param {string} $message Default empty string.
* @param {string} $receipt Receipt ID.
* @param {array} $purchase Array of purchased tickets.
* @param {int} $post_id Payment ID.
*
* @return {string}
*/
$append = apply_filters( 'mt_confirmed_transaction', '', $receipt, $purchase, $post_id );
$output = "<div class='transaction-purchase panel'><div class='inner'><p>" . __( 'Receipt ID:', 'my-tickets' ) . " <code><a href='$link'>$receipt</a></code></p>" . mt_format_purchase( $purchase, 'html', $post_id ) . $append . '</div></div>';
/**
* Purchase is now completed.
*
* @hook mt_purchase_completed
*
* @param {int} $post_id Payment ID.
* @param {string} $link Receipt link.
* @param {array} $purchase Array of purchase information.
*/
do_action( 'mt_purchase_completed', $post_id, $link, $purchase );
}
} else {
$output = apply_filters( 'mt_cart_is_empty_text', "<p class='cart-empty'>" . __( 'Your cart is currently empty.', 'my-tickets' ) . '</p>' );
}
}
}
return '<div class="my-tickets">' . $expiration . $breadcrumbs . $output . '</div>';
}
/**
* Render the link to copy a public cart into admin.
*
* @return string
*/
function mt_copy_cart() {
if ( current_user_can( 'mt-copy-cart' ) || current_user_can( 'manage_options' ) ) {
$unique_id = mt_get_unique_id();
if ( $unique_id ) {
return "<p class='create-admin-payment'><a id='create-admin-payment' href='" . esc_url( admin_url( "post-new.php?post_type=mt-payments&cart=$unique_id" ) ) . "'>" . __( 'Create new admin payment with this cart', 'my-tickets' ) . '</a> <span class="dashicons dashicons-tickets" aria-hidden="true"></span></p>';
}
}
return '';
}
add_filter( 'mt_link_title', 'mt_core_link_title', 10, 2 );
/**
* Filter event titles to display as linked in cart when a link is available. Occurrence IDs are not available, so details link can't be provided.
*
* @param string $event_title Title of event.
* @param object $event Event post object.
*
* @return string linked title if a link is available (any event post or event with a link)
*/
function mt_core_link_title( $event_title, $event ) {
$event_title = apply_filters( 'mt_the_title', $event_title, $event );
$event_id = get_post_meta( $event->ID, '_mc_event_id', true );
if ( $event_id && function_exists( 'mc_get_details_link' ) ) {
$event = mc_get_event_core( $event_id );
$link = mc_get_details_link( $event );
} else {
$link = mt_get_event_link( $event->ID );
}
if ( $link ) {
return "<a href='$link'>$event_title</a>";
} else {
return $event_title;
}
}
/**
* Generate tabular data for cart. Include custom fields if defined.
*
* @param array $cart Cart data.
* @param bool|int $payment Payment ID, if available.
* @param string $format Format to display.
*
* @return string
*/
function mt_generate_cart_table( $cart, $payment = false, $format = 'cart' ) {
if ( ! is_admin() ) {
$caption = ( 'confirmation' === $format ) ? __( 'Review and Purchase', 'my-tickets' ) : __( 'Shopping Cart', 'my-tickets' );
$class = ' mt_cart';
} else {
$caption = __( 'Ticket Order', 'my-tickets' );
$class = '';
}
$output = '
<table class="widefat' . $class . '"><caption>' . $caption . '</caption>
<thead>
<tr>
<th scope="col">' . __( 'Event', 'my-tickets' ) . '</th><th scope="col">' . __( 'Order', 'my-tickets' ) . '</th>';
if ( 'cart' === $format ) {
$output .= '<th scope="col" class="mt-update-column">' . __( 'Update', 'my-tickets' ) . '</th>';
}
$output .= '</tr></thead><tbody>';
$total = 0;
if ( is_array( $cart ) && ! empty( $cart ) ) {
foreach ( $cart as $event_id => $order ) {
// If this post doesn't exist, don't include in cart, e.g. event was deleted after being added to cart.
// Also omit trashed status.
if ( false === get_post_status( $event_id ) || 'trash' === get_post_status( $event_id ) ) {
continue;
}
$expired = mt_event_expired( $event_id );
if ( ! $expired ) {
// There is no payment ID yet, but $_POST data and $_COOKIE data should be available for pricing.
$prices = mt_get_prices( $event_id );
$event = get_post( $event_id );
if ( ! is_object( $event ) ) {
// this is coming from a deleted event.
continue;
}
/**
* Filter the title used in the My Tickets shopping cart for an event.
*
* @hook mt_link_title
*
* @param {string} $post_title Event post title.
* @param {WP_Post} $event Post object.
*
* @return {string}
*/
$title = apply_filters( 'mt_link_title', $event->post_title, $event );
$image = ( has_post_thumbnail( $event_id ) ) ? get_the_post_thumbnail( $event_id, array( 80, 80 ) ) : '';
$data = get_post_meta( $event_id, '_mc_event_data', true );
if ( ! is_array( $data ) || empty( $data ) || ! isset( $data['event_begin'] ) ) {
continue;
}
$registration = get_post_meta( $event_id, '_mt_registration_options', true );
$general = ( isset( $data['general_admission'] ) && 'on' === $data['general_admission'] ) ? true : false;
$validity = ( isset( $data['event_valid'] ) ) ? $data['event_valid'] : 0;
$sales_type = $registration['counting_method'];
if ( 'expire' === $validity && isset( $data['expire_date'] ) && ! empty( $data['expire_date'] ) ) {
$valid_dt = $data['expire_date'];
} else {
$valid_dt = ( 'infinite' !== $validity ) ? strtotime( ' + ' . $validity ) : '';
}
if ( 'infinite' === $validity ) {
$date = __( 'Ticket does not expire', 'my-tickets' );
} else {
$valid_til = mt_date( get_option( 'date_format' ), $valid_dt );
// Translators: Date ticket valid until.
$date = ( $general ) ? sprintf( __( 'Tickets valid until %s', 'my-tickets' ), $valid_til ) : $data['event_begin'] . ' ' . $data['event_time'];
}
$dt_format = apply_filters( 'mt_cart_datetime', get_option( 'date_format' ) . ' @ ' . get_option( 'time_format' ) );
$datetime = "<span class='mt-datetime'>" . ( ( $general ) ? $date : date_i18n( $dt_format, strtotime( $date ) ) ) . '</span>';
if ( is_array( $order ) && ! empty( $order ) ) {
foreach ( $order as $type => $count ) {
if ( ! mt_can_order( $type ) || ! $count ) {
continue;
}
if ( $count > 0 ) {
if ( isset( $prices[ $type ] ) ) {
$price = mt_handling_price( $prices[ $type ]['price'], $event_id, $type );
$orig_price = ( isset( $prices[ $type ]['orig_price'] ) ) ? mt_handling_price( $prices[ $type ]['orig_price'], $event_id, $type ) : $price;
$label = $prices[ $type ]['label'];
$inventory = mt_check_inventory( $event_id, $type, false );
$total = $inventory['total'];
$sold = $inventory['sold'];
$default_available = apply_filters( 'mt_default_available', 100, $registration );
$remaining = ( 'general' === $registration['counting_method'] ) ? $default_available : $total - $sold;
$max_limit = apply_filters( 'mt_max_sale_per_event', false );
if ( $max_limit ) {
$max = ( $max_limit > $remaining ) ? $remaining : $max_limit;
} else {
$max = $remaining;
}
if ( $count > $max ) {
$count = $max;
}
if ( 'event' === $sales_type ) {
$datetime = "<span class='mt-datetime'>" . date_i18n( $dt_format, strtotime( $label ) ) . '</span>';
$label = '';
} else {
$label = ': <em>' . $label . '</em>';
}
if ( 'cart' === $format || is_admin() ) {
$hidden = "
<input type='hidden' class='mt_count' name='mt_cart_order[$event_id][$type][count]' value='$count' />
<input type='hidden' name='mt_cart_order[$event_id][$type][price]' value='$price' />";
if ( isset( $prices[ $type ]['orig_price'] ) ) {
$hidden .= "<input type='hidden' name='mt_cart_order[$event_id][$type][orig_price]' value='$orig_price' />";
}
} else {
$hidden = '';
}
$total = $total + ( $price * $count );
/**
* Show custom fields associated with individual cart items.
*
* @hook mt_show_in_cart_fields
*
* @param {string} $fields HTML output of displayed fields. Default empty.
* @param {int} $event_id The event currently displayed.
* @param {int|bool} $payment The payment ID if available.
* @param {string} $type The current ticket type.
* @param {int} $count Number of tickets purchased of this type. May change dynamically.
* @param {string} $format Whether we're in the cart or confirmation view.
*
* @return {string}
*/
$custom = apply_filters( 'mt_show_in_cart_fields', '', $event_id, $payment, $type, $count, $format );
// Translators: (number of tickets) at (price per ticket).
$cart_message = sprintf( __( '%1$s at %2$s', 'my-tickets' ), "<span class='count' data-limit='$max'>$count</span>", apply_filters( 'mt_money_format', $price ) );
$output .= "
<tr id='mt_cart_order_$event_id" . '_' . "$type' class='mt_row_$event_id'>
<th scope='row'>$image$title$label<br />$datetime$hidden$custom</th>
<td class='mt-order' aria-live='assertive'>" . $cart_message . '</td>';
if ( 'cart' === $format && apply_filters( 'mt_include_update_column', true ) ) {
if ( 'true' === $registration['multiple'] ) {
$output .= "<td class='mt-update-column'><div class='mt-update-buttons'><button data-id='$event_id' data-type='$type' rel='#mt_cart_order_$event_id" . '_' . "$type' class='more'><span aria-hidden='true' class='dashicons dashicons-plus'></span><span class='screen-reader-text'> " . __( 'Add a ticket', 'my-tickets' ) . "</span></button> <button data-id='$event_id' data-type='$type' rel='#mt_cart_order_$event_id" . '_' . "$type' class='less'><span aria-hidden='true' class='dashicons dashicons-minus'></span><span class='screen-reader-text'> " . __( 'Remove a ticket', 'my-tickets' ) . "</span></button> <button data-id='$event_id' data-type='$type' rel='#mt_cart_order_$event_id" . '_' . "$type' class='remove'><span aria-hidden='true' class='dashicons dashicons-no'></span><span class='screen-reader-text'> " . __( 'Remove from cart', 'my-tickets' ) . '</span></button></div></td>';
} else {
$output .= "<td class='mt-update-column'><div class='mt-update-buttons'><button data-id='$event_id' data-type='$type' rel='#mt_cart_order_$event_id" . '_' . "$type' class='remove'><span aria-hidden='true' class='dashicons dashicons-no'></span><span class='screen-reader-text'> " . __( 'Remove from cart', 'my-tickets' ) . '</span></button>' . apply_filters( 'mt_no_multiple_registration', '' ) . '</div></td>';
}
}
$output .= '</tr>';
}
}
}
}
}
}
}
$output .= '</tbody></table>';
return $output;
}
/**
* Get total $ value of saved cart.
*
* @param array $cart Cart data.
* @param int $payment_id Payment ID.
* @param bool $apply_discounts 'False' to get original total without discounts.
*
* @return float
*/
function mt_total_cart( $cart, $payment_id = false, $apply_discounts = true ) {
$total = 0;
if ( is_array( $cart ) ) {
foreach ( $cart as $event => $order ) {
$expired = mt_event_expired( $event );
if ( ! $expired ) {
$prices = mt_get_prices( $event, $payment_id );
if ( is_array( $order ) ) {
foreach ( $order as $type => $count ) {
if ( $count > 0 ) {
$count = intval( $count );
$price = ( isset( $prices[ $type ] ) ) ? $prices[ $type ]['price'] : '0';
if ( $price ) {
$price = mt_handling_price( $price, $event );
}
$total = $total + ( $price * $count );
}
}
}
}
}
}
return ( $apply_discounts ) ? apply_filters( 'mt_apply_total_discount', $total, $payment_id ) : $total;
}
/**
* Get number of tickets in current cart.
*
* @param array $cart Cart data.
*
* @return int
*/
function mt_count_cart( $cart = array() ) {
$total = 0;
$cart = ( empty( $cart ) ) ? mt_get_cart() : $cart;
if ( is_array( $cart ) ) {
foreach ( $cart as $event => $order ) {
$expired = mt_event_expired( $event );
if ( ! $expired ) {
if ( is_array( $order ) ) {
foreach ( $order as $type => $count ) {
$total = $total + intval( $count );
}
}
}
}
}
return $total;
}
/**
* Generate payment gateway code from selected gateway.
*
* @param array $cart cart data.
*
* uses: filter mt_gateway (pull gateway form).
* uses: filter mt_form_wrapper (html wrapper around gateway).
*
* @return string
*/
function mt_generate_gateway( $cart ) {
$options = mt_get_settings();
$return_url = mt_get_cart_url();
// Translators: cart url.
$link = apply_filters( 'mt_return_link', "<p class='return-to-cart'>" . sprintf( __( '<a href="%s">Return to cart</a>', 'my-tickets' ), $return_url ) . '</p>' );
$payment = mt_get_data( 'payment' );
$confirmation = mt_generate_cart_table( $cart, $payment, 'confirmation' );
$total = mt_total_cart( $cart, $payment );
$count = mt_count_cart( $cart );
if ( $count > 0 ) {
$mt_gateway = ( isset( $_POST['mt_gateway'] ) ) ? sanitize_text_field( $_POST['mt_gateway'] ) : 'offline';
$ticket_method = ( isset( $_POST['ticketing_method'] ) ) ? sanitize_text_field( $_POST['ticketing_method'] ) : 'willcall';
$shipping_total = ( 'postal' === $ticket_method && is_numeric( $options['mt_shipping'] ) ) ? $options['mt_shipping'] : 0;
$handling_total = mt_get_cart_handling( $options, $mt_gateway );
$shipping = ( $shipping_total ) ? "<div class='mt_cart_shipping mt_cart_label'>" . __( 'Shipping:', 'my-tickets' ) . " <span class='mt_shipping_number mt_cart_value'>" . apply_filters( 'mt_money_format', $shipping_total ) . '</span></div>' : '';
$handling = ( $handling_total ) ? "<div class='mt_cart_handling mt_cart_label'>" . __( 'Handling:', 'my-tickets' ) . " <span class='mt_handling_number mt_cart_value'>" . apply_filters( 'mt_money_format', $handling_total ) . '</span></div>' : '';
$tick_handling = mt_handling_notice();
$other_charges = apply_filters( 'mt_custom_charges', 0, $cart, $mt_gateway );
$other_notices = apply_filters( 'mt_custom_notices', '', $cart, $mt_gateway );
// If there is no cost, don't pass through payment gateway.
$check_total = (float) ( $total + $shipping_total + $handling_total + $other_charges );
if ( 0.0 === $check_total && 'offline' !== $mt_gateway ) {
$mt_gateway = 'offline';
}
$report_total = "<div class='mt_cart_total'>" . apply_filters( 'mt_cart_total_text', __( 'Total:', 'my-tickets' ), $mt_gateway ) . " <span class='mt_total_number'>" . apply_filters( 'mt_money_format', $total + $shipping_total + $handling_total + $other_charges ) . '</span></div>';
$args = apply_filters(
'mt_payment_form_args',
array(
'cart' => $cart,
'total' => $total,
'payment' => $payment,
'method' => $ticket_method,
)
);
$form = apply_filters( 'mt_gateway', '', $mt_gateway, $args );
$form = apply_filters( 'mt_form_wrapper', $form );
$form .= "<span id='mt_unsubmitted'></span>";
return $link . $confirmation . "<div class='mt-after-cart'>" . $tick_handling . $shipping . $handling . $other_notices . $report_total . '</div>' . $form;
} else {
do_action( 'mt_cart_is_empty' );
return apply_filters( 'mt_cart_is_empty_text', "<p class='cart-empty'>" . __( 'Your cart is currently empty.', 'my-tickets' ) . '</p>' );
}
}
add_filter( 'mt_form_wrapper', 'mt_wrap_payment_button' );
/**
* Generate HTML to wrap gateway form.
*
* @param string $form Form HTML.
*
* @return string
*/
function mt_wrap_payment_button( $form ) {
return "<div class='mt-payment-form'>" . $form . '</div>';
}
/**
* If SSL is enabled, replace HTTP in URL.
*
* @param string $url site URL.
*
* @return mixed
*/
function mt_replace_http( $url ) {
$options = mt_get_settings();
if ( 'true' === $options['mt_ssl'] ) {
$url = preg_replace( '|^http://|', 'https://', $url );
}
return $url;
}
/**
* Test whether an event is no longer available for purchase. If user has capability to order expired events, allow.
*
* @param int $event An event ID.
* @param boolean $react Should a reaction happen.
*
* @return bool
*/
function mt_event_expired( $event, $react = false ) {
if ( current_user_can( 'mt-order-expired' ) || current_user_can( 'manage_options' ) ) {
return false;
}
$options = get_post_meta( $event, '_mt_registration_options', true );
if ( ! $options ) {
// If there are no ticketing options, treat as if expired and exit early.
return true;
}
if ( 'general' === $options['counting_method'] ) {
// General admissions sales do not expire.
return false;
}
if ( 'event' === $options['counting_method'] ) {
// Event type sales expire as individual sub-events, not as a full event.
return false;
}
$expired = get_post_meta( $event, '_mt_event_expired', true );
if ( 'true' === $expired ) {
// The event is no longer available for sale, but not all type emails may have been sent.
mt_handle_expiration_status( $event );
return true;
} else {
$data = get_post_meta( $event, '_mc_event_data', true );
if ( is_array( $data ) && is_array( $options ) && ! empty( $options ) ) {
if ( ! isset( $data['event_begin'] ) || ( isset( $data['general_admission'] ) && 'on' === $data['general_admission'] ) ) {
return false;
}
$expires = ( isset( $options['reg_expires'] ) ) ? $options['reg_expires'] : 0;
$expiration = $expires * 60 * 60;
$begin = strtotime( $data['event_begin'] . ' ' . $data['event_time'] ) - $expiration;
if ( mt_date_comp( mt_date( 'Y-m-d H:i:s', $begin ), mt_date( 'Y-m-d H:i:s', mt_current_time() ) ) && $react ) {
update_post_meta( $event, '_mt_event_expired', 'true' );
/**
* Executed an action when ticket sales are transitioned from open to closed.
*
* @hook mt_ticket_sales_closed
*
* @param {int} $event Event ID.
* @param {array} $options Registration options array for this event.
* @param {string} $closed The string 'closed'.
*/
do_action( 'mt_ticket_sales_closed', $event, $options, 'closed' );
return true;
}
}
return false;
}
return false;
}
/**
* Check the expiration of a single ticket type.
*
* @param int $event An event ID.
* @param string $type Ticket type key.
*
* @return bool
*/
function mt_ticket_type_expired( $event, $type ) {
$expired = get_post_meta( $event, '_mt_event_expired_' . sanitize_title( $type ), true );
if ( 'true' === $expired ) {
return true;
}
return false;
}
/**
* Handle the expiration of a single ticket type.
*
* @param int $event An event ID.
* @param string $type Ticket type key.
*
* @return bool
*/
function mt_handle_ticket_type_expired( $event, $type ) {
$expired = get_post_meta( $event, '_mt_event_expired_' . sanitize_title( $type ), true );
if ( 'true' === $expired ) {
return true;
} else {
update_post_meta( $event, '_mt_event_expired_' . sanitize_title( $type ), 'true' );
/**
* Executed an action when ticket sales are transitioned from open to closed for a specific ticket type.
*
* @hook mt_ticket_type_close_sales
*
* @param {int} $event Event ID.
* @param {string} $type Ticket type.
* @param {string} $closed The string 'type'.
*/
do_action( 'mt_ticket_type_close_sales', $event, $type, 'type' );
return true;
}
return false;
}
/**
* Handle expiration status by ticket type. Run ticket type closure actions for 'event' types if not already executed.
*
* @param int $event_id Event Post ID.
*
* @return void
*/
function mt_handle_expiration_status( $event_id ) {
$registration = get_post_meta( $event_id, '_mt_registration_options', true );
if ( ! is_array( $registration ) || ! 'event' === $registration['counting_method'] ) {
return;
}
$pricing = $registration['prices'];
foreach ( $pricing as $type => $ticket_type ) {
$close = mt_get_ticket_type_close( $ticket_type, $registration );
$type_sales_closed = ( $close < mt_date() ) ? true : false;
$diff = ( $type_sales_closed ) ? mt_date() - $close : 0;
// If type sales closed more than a week ago, don't send notifications.
if ( $type_sales_closed && $diff < WEEK_IN_SECONDS ) {
mt_handle_ticket_type_expired( $event_id, $type );
}
// Update the post meta, so this check doesn't run again.
if ( $type_sales_closed && $diff > WEEK_IN_SECONDS ) {
update_post_meta( $event_id, '_mt_event_expired_' . sanitize_title( $type ), 'true' );
}
}
}
/**
* Utility function to get My Tickets cart URL.
*
* @return string|bool URL or false if not set.
*/
function mt_get_cart_url() {
$options = mt_get_settings();
$purchase_page = $options['mt_purchase_page'];
$url = ( $purchase_page && is_string( get_post_status( $purchase_page ) ) ) ? get_permalink( $purchase_page ) : false;
return $url;
}