<?php
/**
* Generate output for standard My Calendar submission fields.
*
* @category Submissions
* @package My Calendar Pro
* @author Joe Dolson
* @license GPLv2 or later
* @link https://www.joedolson.com/my-calendar-pro/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Array of default fields for use in My Calendar submissions.
*
* @return array
*/
function mcs_default_fields() {
// Can users change their names?
$disallow_user_changes = apply_filters( 'mcs_disallow_user_changes', true );
// Are image uploads allowed?
$input_type = mcs_image_input_type();
// Is there a maxlength on event descriptions?
$maxlength = apply_filters( 'mcs_event_description_maxlength', '' );
$description_notes = '';
if ( $maxlength ) {
$description_attr = array(
'data-maxlength' => absint( $maxlength ),
);
// Translators: maximum number of words allowed for this field.
$description_notes = sprintf( __( '(maximum %s words)', 'my-calendar-pro' ), $maxlength );
}
// Custom name value on main description field.
$description_attr['name'] = 'content';
$short_description_attrs = array(
'name' => 'event_short',
);
$event_link_attrs = array(
'placeholder' => 'https://example.com',
);
$default_fields = array(
'submitter' => array(
'field_label' => __( 'Submitter', 'my-calendar-pro' ),
'field_type' => 'section',
'section_contains' => array(
'mcs_name' => array(
'field_label' => __( 'Your Name', 'my-calendar-pro' ),
'field_type' => ( $disallow_user_changes && is_user_logged_in() ) ? 'hidden' : 'text',
'field_notes' => '',
'field_options' => ( is_user_logged_in() ) ? wp_get_current_user()->display_name : '',
'id' => '',
'field_required' => true,
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true, // Unselectable fields are not available to choose in widget setup.
),
'mcs_email' => array(
'field_label' => __( 'Your Email', 'my-calendar-pro' ),
'field_type' => ( $disallow_user_changes && is_user_logged_in() ) ? 'hidden' : 'email',
'field_notes' => '',
'field_options' => ( is_user_logged_in() ) ? wp_get_current_user()->user_email : '',
'id' => '',
'field_required' => true,
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
),
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
'event_title' => array(
'field_label' => __( 'Event Title', 'my-calendar-pro' ),
'field_type' => 'text',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => true,
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
'event_date' => array(
'field_label' => __( 'Date', 'my-calendar-pro' ),
'field_type' => 'date',
'section_contains' => array(
'event_begin' => array(
'field_label' => __( 'Event Date', 'my-calendar-pro' ),
'field_type' => 'date',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => true,
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
'event_time' => array(
'field_label' => __( 'Time', 'my-calendar-pro' ),
'field_type' => 'time',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
),
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => true,
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
'event_allday' => array(
'field_label' => __( 'All day event', 'my-calendar-pro' ),
'field_type' => 'checkbox',
'field_notes' => '',
'field_options' => 'true',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'event_hide_end' => array(
'field_label' => __( 'Hide end time', 'my-calendar-pro' ),
'field_type' => 'checkbox',
'field_notes' => '',
'field_options' => 'true',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'event_end' => array(
'field_label' => __( 'End date', 'my-calendar-pro' ),
'field_type' => 'date',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'event_endtime' => array(
'field_label' => __( 'End time', 'my-calendar-pro' ),
'field_type' => 'time',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'description' => array(
'field_label' => __( 'Description', 'my-calendar-pro' ),
'field_type' => 'textarea',
'field_notes' => $description_notes,
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'wp_kses_post',
'escape_callback' => 'esc_attr',
'attrs' => $description_attr,
),
'short_description' => array(
'field_label' => __( 'Excerpt', 'my-calendar-pro' ),
'field_type' => 'textarea',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_textarea_field',
'escape_callback' => 'esc_textarea',
'attrs' => $short_description_attrs,
),
'event_image' => array(
'field_label' => ( 'file' === $input_type ) ? __( 'Image', 'my-calendar-pro' ) : __( 'Image (URL)', 'my-calendar-pro' ),
'field_type' => $input_type,
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_textarea_field',
'escape_callback' => 'esc_textarea',
'attrs' => '',
),
'event_host' => array(
'field_label' => __( 'Event Host', 'my-calendar-pro' ),
'field_type' => ( count_users() <= 1 ) ? 'hidden' : 'select',
'field_notes' => '',
'field_options' => mc_selected_users( '', 'hosts', 'array' ),
'id' => '',
'field_required' => '',
'validate_callback' => 'mc_validate_host',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => ( count_users() <= 1 ) ? 'esc_attr' : 'mc_kses_callback',
'attrs' => '',
),
'access' => array(
'field_label' => __( 'Event Access', 'my-calendar-pro' ),
'field_type' => 'checkbox-multiple',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'event_link' => array(
'field_label' => __( 'Link', 'my-calendar-pro' ),
'field_type' => 'url',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => $event_link_attrs,
),
'registration' => array(
'field_label' => __( 'Ticketing Information', 'my-calendar-pro' ),
'field_type' => 'section',
'section_contains' => array(
'event_tickets' => array(
'field_label' => __( 'Tickets URL', 'my-calendar-pro' ),
'field_type' => 'url',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_url',
'unselectable' => true,
),
'event_registration' => array(
'field_label' => __( 'Registration Information', 'my-calendar-pro' ),
'field_type' => 'textarea',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_textarea_field',
'escape_callback' => 'mc_kses_post',
'attrs' => array(
'cols' => 40,
'rows' => 4,
),
'unselectable' => true,
),
),
),
'event_recurring' => array(
'field_label' => __( 'Recurring Events', 'my-calendar-pro' ),
'field_type' => 'section',
'section_contains' => array(
'event_every' => array(
'field_label' => __( 'Frequency', 'my-calendar-pro' ),
'field_type' => 'number',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => array(
'size' => '4',
'min' => '1',
'max' => '99',
'maxlength' => '2',
),
'unselectable' => true,
),
'event_recur' => array(
'field_label' => __( 'Period', 'my-calendar-pro' ),
'field_type' => 'select',
'field_notes' => '',
'field_options' => mc_recur_options( '', 'array' ),
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'mc_kses_post',
'attrs' => '',
'unselectable' => true,
),
'event_repeats' => array(
'field_label' => __( 'Repeat Until', 'my-calendar-pro' ),
'field_type' => 'date',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
'unselectable' => true,
),
),
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'sanitize_callback' => 'sanitize_text_field',
'escape_callback' => 'esc_attr',
'attrs' => '',
),
'custom_fields' => '', // Container for all custom fields, if legacy in use.
);
/**
* Filter the default fields available.
*
* @hook mcs_default_fields
*
* @param {array} $default_fields Array of fields used as defaults.
*
* @return {array}
*/
return apply_filters( 'mcs_default_fields', $default_fields );
}
/**
* Validate host select field. Checks whether the supplied data is a valid user ID, and returns false if not.
*
* @param string|int $value Value supplied by user.
* @param array $schema Field schema used.
*
* @return bool
*/
function mc_validate_host( $value, $schema ) {
if ( true === (bool) $schema['field_required'] ) {
if ( ! get_userdata( $value ) ) {
return false;
}
}
return true;
}
/**
* Get default location fields and merge with default fields.
*
* @param string $key array key.
* @param string $value Array value.
*
* @return Needed value.
*/
function mcs_get_field_name( $key, $value ) {
$values = array_merge( mcs_default_fields(), mcs_default_location_fields() );
return ( in_array( $key, array_keys( $values ), true ) ) ? $values[ $key ] : $value;
}
/**
* Default location field label.
*
* @return array
*/
function mcs_default_location_fields() {
return array(
'event_label' => array(
'field_label' => __( 'Location Name', 'my-calendar-pro' ),
'required' => false,
),
'street' => array(
'field_label' => __( 'Street Address', 'my-calendar-pro' ),
'required' => false,
),
'street2' => array(
'field_label' => __( 'Street Address (2)', 'my-calendar-pro' ),
'required' => false,
),
'phone' => array(
'field_label' => __( 'Phone', 'my-calendar-pro' ),
'required' => false,
),
'city' => array(
'field_label' => __( 'City', 'my-calendar-pro' ),
'required' => false,
),
'state' => array(
'field_label' => __( 'State/Province', 'my-calendar-pro' ),
'required' => false,
),
'postcode' => array(
'field_label' => __( 'Postal Code', 'my-calendar-pro' ),
'required' => false,
),
'region' => array(
'field_label' => __( 'Region', 'my-calendar-pro' ),
'required' => false,
),
'country' => array(
'field_label' => __( 'Country', 'my-calendar-pro' ),
'required' => false,
),
'url' => array(
'field_label' => __( 'Location URL', 'my-calendar-pro' ),
'required' => false,
),
'gps' => array(
'field_label' => __( 'GPS Coordinates', 'my-calendar-pro' ),
'required' => false,
),
);
}
/**
* Create a set of options for a select from an array and a selected value.
*
* @param int|string $selected Selected value.
* @param array $options Array of possible values.
*
* @return string
*/
function mcs_create_select_options( $selected, $options ) {
$output = '';
if ( ! is_array( $options ) ) {
return '';
}
foreach ( $options as $option ) {
if ( is_array( $option ) ) {
$value = $option['value'];
$label = $option['label'];
} else {
$value = $option;
$label = $option;
}
$output .= '<option value="' . esc_attr( $value ) . '"' . selected( $selected, $value, false ) . '>' . esc_html( $label ) . '</option>';
}
return $output;
}
/**
* Get data from an event object in the editing form.
*
* @param string $field Field ID.
* @param object $data Event data.
*
* @return mixed
*/
function mcs_get_data( $field, $data ) {
if ( ! is_object( $data ) ) {
return '';
}
if ( property_exists( $data, $field ) && 'event_recur' !== $field ) {
$value = map_deep( $data->{$field}, 'stripslashes' );
} else {
$map = array(
'event_allday' => array( 'mc_is_all_day' ),
'mcs_name' => array( 'mcs_get_name' ),
'mcs_email' => array( 'mcs_get_email' ),
'event_every' => array( 'mcs_get_event_every' ),
'event_recur' => array( 'mcs_get_event_recur' ),
'description' => 'event_desc',
'short_description' => 'event_short',
);
// Handle the fact the submissions field names don't always match main file names.
$key = ( isset( $map[ $field ] ) ) ? $map[ $field ] : false;
if ( ! $key ) {
return '';
} else {
if ( is_string( $key ) ) {
$value = ( property_exists( $data, $key ) ) ? stripslashes( $data->{$key} ) : '';
} else {
$value = ( function_exists( $key[0] ) ) ? call_user_func( $key[0], $data ) : '';
}
}
}
return $value;
}
/**
* Get event every value.
*
* @param object $event Event object.
*
* @return string
*/
function mcs_get_event_every( $event ) {
$recur = $event->event_recur;
$data = str_split( $recur, 1 );
$every = $data[1];
return $every;
}
/**
* Get event recur value.
*
* @param object $event Event object.
*
* @return string
*/
function mcs_get_event_recur( $event ) {
$recur = $event->event_recur;
$data = str_split( $recur, 1 );
$recurs = $data[0];
return $recurs;
}
/**
* Get submitter name for event.
*
* @param object $event Event data.
*
* @return string
*/
function mcs_get_name( $event ) {
$name = '';
$post_id = $event->event_post;
$author = get_post_meta( $post_id, '_submitter_details', true );
if ( is_array( $author ) && ! empty( $author ) ) {
$name = $author['first_name'] . ' ' . $author['last_name'];
}
return $name;
}
/**
* Get submitter email for event.
*
* @param object $event Event data.
*
* @return string
*/
function mcs_get_email( $event ) {
$email = '';
$post_id = $event->event_post;
$author = get_post_meta( $post_id, '_submitter_details', true );
if ( is_array( $author ) && ! empty( $author ) ) {
$email = $author['email'];
}
return $email;
}
/**
* Create My Calendar input field for submissions.
*
* @param string $field Field reference.
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
* @param array $attrs Array of attributes passed from source function.
*
* @return string
*/
function mcs_basic_input( $field, $data, $fields, $attrs = array() ) {
$defaults = mcs_default_fields();
$label = ( isset( $fields[ $field ] ) && 'true' !== $fields[ $field ] ) ? $fields[ $field ] : $defaults[ $field ]['field_label'];
$value = mcs_get_data( $field, $data );
if ( 'mcs_name' === $field ) {
$value = ( is_user_logged_in() ) ? wp_get_current_user()->user_email : $value;
}
if ( 'mcs_name' === $field ) {
$value = ( is_user_logged_in() ) ? wp_get_current_user()->display_name : $value;
}
$schema = $defaults[ $field ];
$type = $schema['field_type'];
$values = $schema['field_options'];
$classes = array( 'mcs-' . sanitize_html_class( $field ), 'mcs-' . sanitize_html_class( $type ), 'mcs-input' );
$schema_attrs = ( is_array( $schema['attrs'] ) ) ? $schema['attrs'] : array();
$attrs = array_merge( $attrs, $schema_attrs );
$required_fields = apply_filters( 'mcs_required_fields', get_option( 'mcs_required_fields', array() ) );
$required = ( in_array( $field, $required_fields, true ) || true === (bool) $schema['field_required'] );
$valid_value = isset( $schema['validate_callback'] ) && function_exists( $schema['validate_callback'] ) ? call_user_func( $schema['validate_callback'], $value, $schema ) : true;
$required_text = '';
if ( ! empty( $data ) && $required && ( ! $value || ! $valid_value ) ) {
$classes[] = 'invalid';
}
if ( $required ) {
$attrs['required'] = 'required';
$required_text = mcs_required_text();
}
$attributes = '';
foreach ( $attrs as $attr => $val ) {
$attributes .= ' ' . esc_attr( $attr ) . '="' . esc_attr( $val ) . '"';
}
$name = $field;
// If field attributes pass a custom name, use that.
if ( isset( $attrs['name'] ) ) {
$name = $attrs['name'];
unset( $attrs['name'] );
}
if ( 'checkbox' === $type || 'radio' === $type ) {
$structure = '<p class="%1$s"><input type="%7$s" value="1" id="mcs_%4$s" ' . checked( $value, '1', false ) . ' name="%8$s" %4$s /> <label for="mcs_%4$s">%2$s</label>
</p>';
} elseif ( 'textarea' === $type ) {
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <textarea name="%8$s" id="mcs_%4$s" %6$s>%5$s</textarea></p>';
} elseif ( 'date' === $type ) {
$start_of_week = absint( get_option( 'start_of_week' ) );
$firstday = ( 1 === $start_of_week || 0 === $start_of_week ) ? $start_of_week : 0;
$attributes .= 'first-day-of-week="' . $firstday . '"';
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <duet-date-picker name="%8$s[]" identifier="mcs_%4$s" value="%5$s" %6$s></duet-date-picker></p>';
} elseif ( 'select' === $type ) {
// translators: Label for this field.
$value = '<option value="">' . sprintf( __( 'Select %s', 'my-calendar-pro' ), $label ) . '</option>';
$value .= mcs_create_select_options( $value, $values );
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <select type="%7$s" name="%8$s" id="mcs_%4$s" %6$s>%5$s</select></p>';
} elseif ( 'hidden' === $type ) {
$structure = '<input type="%7$s" name="%4$s" value="%5$s" />';
} else {
$is_array = '';
if ( 'time' === $type ) {
$is_array = '[]';
}
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <input type="%7$s" name="%8$s' . $is_array . '" id="mcs_%4$s" value="%5$s" %6$s /></p>';
}
$escape_callback = ( isset( $schema['escape_callback'] ) && function_exists( $schema['escape_callback'] ) ) ? $schema['escape_callback'] : ( ( 'textarea' === $type ) ? 'esc_textarea' : 'esc_attr' );
return sprintf(
$structure,
implode( ' ', array_map( 'sanitize_html_class', $classes ) ),
$label,
$required_text,
$field,
call_user_func( $escape_callback, $value ),
$attributes,
$type,
$name
);
}
/**
* Create My Calendar input field inside groups for submissions.
*
* @param string $field Field reference.
* @param string $parent_field Parent field.
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
* @param array $attrs Array of attributes passed from source function.
*
* @return string
*/
function mcs_grouped_input( $field, $parent_field, $data, $fields, $attrs = array() ) {
$defaults = mcs_default_fields();
$label = ( isset( $fields[ $parent_field ][ $field ] ) && ( 'true' !== $fields[ $parent_field ][ $field ] && ! empty( $fields[ $parent_field ][ $field ] ) ) ) ? $fields[ $parent_field ][ $field ] : $defaults[ $parent_field ]['section_contains'][ $field ]['field_label'];
$value = mcs_get_data( $field, $data );
if ( 'mcs_email' === $field ) {
$value = ( is_user_logged_in() ) ? wp_get_current_user()->user_email : $value;
}
if ( 'mcs_name' === $field ) {
$value = ( is_user_logged_in() ) ? wp_get_current_user()->display_name : $value;
}
$schema = $defaults[ $parent_field ]['section_contains'][ $field ];
$type = $schema['field_type'];
$values = $schema['field_options'];
$classes = array( 'mcs-' . sanitize_html_class( $field ), 'mcs-' . sanitize_html_class( $type ), 'mcs-input' );
$schema_attrs = ( isset( $schema['attrs'] ) && is_array( $schema['attrs'] ) ) ? $schema['attrs'] : array();
$attrs = array_merge( $attrs, $schema_attrs );
$required_fields = apply_filters( 'mcs_required_fields', get_option( 'mcs_required_fields', array() ) );
$required = ( in_array( $field, $required_fields, true ) || true === (bool) $schema['field_required'] );
$required_text = '';
if ( ! empty( $data ) && $required && ! $value ) {
$classes[] = 'invalid';
}
if ( $required ) {
$attrs['required'] = 'required';
$required_text = mcs_required_text();
}
$attributes = '';
foreach ( $attrs as $attr => $val ) {
$attributes .= ' ' . esc_attr( $attr ) . '="' . esc_attr( $val ) . '"';
}
$name = $field;
// If field attributes pass a custom name, use that.
if ( isset( $attrs['name'] ) ) {
$name = $attrs['name'];
}
if ( 'checkbox' === $type || 'radio' === $type ) {
$structure = '<p class="%1$s"><input type="%7$s" value="1" id="mcs_%4$s" name="%8$s" %4$s /> <label for="mcs_%4$s">%2$s</label>
</p>';
} elseif ( 'textarea' === $type ) {
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <textarea name="%8$s" id="mcs_%4$s" %6$s>%5$s</textarea></p>';
} elseif ( 'date' === $type ) {
$is_array = ( 'event_repeats' !== $field ) ? '[]' : '';
$start_of_week = absint( get_option( 'start_of_week' ) );
$firstday = ( 1 === $start_of_week || 0 === $start_of_week ) ? $start_of_week : 0;
$attributes .= 'first-day-of-week="' . $firstday . '"';
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <duet-date-picker name="%8$s' . $is_array . '" identifier="mcs_%4$s" value="%5$s" %6$s></duet-date-picker></p>';
} elseif ( 'select' === $type ) {
$value = mcs_create_select_options( $value, $values );
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <select type="%7$s" name="%8$s" id="mcs_%4$s" %6$s>%5$s</select></p>';
} elseif ( 'hidden' === $type ) {
$structure = '<input type="%7$s" name="%4$s" value="%5$s" />';
} else {
$is_array = '';
if ( 'time' === $type ) {
$is_array = '[]';
}
$structure = '<p class="%1$s"><label for="mcs_%4$s">%2$s %3$s</label> <input type="%7$s" name="%8$s' . $is_array . '" id="mcs_%4$s" value="%5$s" %6$s /></p>';
}
$escape_callback = ( isset( $schema['escape_callback'] ) && function_exists( $schema['escape_callback'] ) ) ? $schema['escape_callback'] : ( ( 'textarea' === $type ) ? 'esc_textarea' : 'esc_attr' );
if ( 'select' !== $type ) {
$value = call_user_func( $escape_callback, $value );
}
return sprintf(
$structure,
implode( ' ', array_map( 'sanitize_html_class', $classes ) ),
$label,
$required_text,
$field,
$value,
$attributes,
$type,
$name
);
}
/**
* Create My Calendar title field for submissions.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_title_input( $data, $fields ) {
return mcs_basic_input( 'event_title', $data, $fields );
}
/**
* Create My Calendar all day event field for submissions.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_allday_input( $data, $fields ) {
return mcs_basic_input( 'event_allday', $data, $fields );
}
/**
* Create My Calendar hide end dat event field for submissions.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_hide_end_input( $data, $fields ) {
return mcs_basic_input( 'event_hide_end', $data, $fields );
}
/**
* Create My Calendar event date & time fields for submissions.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_event_date_input( $data, $fields ) {
// Set up min/max range if enabled.
$max = apply_filters( 'mcs_time_max', '00:00' );
$min = apply_filters( 'mcs_time_min', '00:00' );
$attrs = array();
$append = '';
$range = '';
if ( '00:00' !== $max || '00:00' !== $min ) {
// Translators: starting time, ending time.
$range = '<p id="mc_time_range_allowed">' . sprintf( __( 'Times must be between %1$s and %2$s', 'my-calendar-pro' ), mc_date( get_option( 'mc_time_format' ), strtotime( $min ) ), mc_date( get_option( 'mc_time_format' ), strtotime( $max ) ) ) . '</p>';
$append = '<span class="validity"><span class="dashicons dashicons-no" aria-hidden="true"></span>' . __( 'Invalid time', 'my-calendar-pro' ) . '</span>';
}
// Add secondary fields.
$allday_field = '';
$hide_end_field = '';
if ( isset( $fields['event_allday'] ) ) {
$allday_field = mcs_allday_input( $data, $fields );
}
if ( isset( $fields['event_hide_end'] ) ) {
$hide_end_field = mcs_hide_end_input( $data, $fields );
}
$extras = ( '' !== $allday_field . $hide_end_field ) ? '<div class="mc_date_extras">' . $allday_field . $hide_end_field . '</div>' : '';
if ( '00:00' !== $min || '00:00' !== $max ) {
$attrs['min'] = $min;
$attrs['max'] = $max;
$attrs['aria-describedby'] = 'mc_time_range_allowed';
}
$date_input = mcs_date_input( $data, $fields );
$time_input = mcs_time_input( $data, $fields, $attrs );
$output = "
<div class='mc_begin_container mcs-date-time-container'>
$range
$date_input
$time_input
$append
</div>
$extras";
return $output;
}
/**
* Create My Calendar event end date & time fields for submissions.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_end_date_input( $data, $fields ) {
$output = '';
$date_input = ( isset( $fields['end_date'] ) || isset( $fields['event_end'] ) ) ? mcs_event_end_date_input( $data, $fields ) : '';
$time_input = ( isset( $fields['end_time'] ) || isset( $fields['event_end'] ) || isset( $fields['event_endtime'] ) ) ? mcs_end_time_input( $data, $fields ) : '';
if ( $date_input || $time_input ) {
$output = "
<div class='mc_end_container mcs-date-time-container'>
$date_input
$time_input
</div>";
}
return $output;
}
/**
* Build begin date input field.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_date_input( $data, $fields ) {
return mcs_grouped_input( 'event_begin', 'event_date', $data, $fields );
}
/**
* Build begin time input field.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_time_input( $data, $fields ) {
return mcs_grouped_input( 'event_time', 'event_date', $data, $fields );
}
/**
* Build end date input field.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_event_end_date_input( $data, $fields ) {
return mcs_basic_input( 'event_end', $data, $fields );
}
/**
* Build end time input field.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_end_time_input( $data, $fields ) {
return mcs_basic_input( 'event_endtime', $data, $fields );
}
/**
* Name & email input fields.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_name_and_email_input( $data, $fields ) {
$name_input = mcs_name_input( $data, $fields );
$email_input = mcs_email_input( $data, $fields );
if ( is_user_logged_in() ) {
$before = '';
$after = '';
} else {
$before = '<div class="mcs-name-and-email">';
$after = '</div>';
}
return $before . $name_input . $email_input . $after;
}
/**
* Name input fields.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_name_input( $data, $fields ) {
return mcs_grouped_input( 'mcs_name', 'submitter', $data, $fields );
}
/**
* Email input fields.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_email_input( $data, $fields ) {
return mcs_grouped_input( 'mcs_email', 'submitter', $data, $fields );
}
/**
* Event host input field.
*
* @param object $data Event data.
* @param array $fields Field list passed from shortcode.
*
* @return string
*/
function mcs_event_host_input( $data, $fields ) {
return mcs_basic_input( 'event_host', $data, $fields );
}
/**
* Event recurring input fields.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_event_recurring_input( $data, $fields ) {
if ( ! isset( $fields['event_recurring'] ) ) {
return "<div>
<input type='hidden' name='event_repeats' value='0' />
<input type='hidden' name='event_recur' value='S' />
<input type='hidden' name='event_every' value='1' />
</div>";
}
$every = mcs_grouped_input( 'event_every', 'event_recurring', $data, $fields );
$recur = mcs_grouped_input( 'event_recur', 'event_recurring', $data, $fields );
$repeats = mcs_grouped_input( 'event_repeats', 'event_recurring', $data, $fields );
return '<fieldset class="recurring"><legend class="screen-reader-text">' . __( 'Recurring Events', 'my-calendar-pro' ) . '</legend><div class="columns">' . $every . $recur . $repeats . '</div></fieldset>';
}
/**
* Event registration input fields.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_event_registration_input( $data, $fields ) {
$tickets = mcs_grouped_input( 'event_tickets', 'registration', $data, $fields );
$registration = mcs_grouped_input( 'event_registration', 'registration', $data, $fields );
$has_data = ( ! empty( $data ) ) ? true : false;
/**
* Append HTML to end of event registration fields.
*
* @hook mc_event_registration
*
* @param {string} $html HTML to place inside registration fieldset.
* @param {bool} $has_data Whether current event object is populated.
* @param {object} $data Event object.
* @param {string} $public Rendering in public context.
*
* @return {string}
*/
$registration .= apply_filters( 'mc_event_registration', '', $has_data, $data, 'public' );
return '<fieldset class="registration"><legend class="screen-reader-text">' . __( 'Ticketing Information', 'my-calendar-pro' ) . '</legend><div class="rows">' . $tickets . $registration . '</div></fieldset>';
}
/**
* Event description input field.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_description_input( $data, $fields ) {
return mcs_basic_input( 'description', $data, $fields );
}
/**
* Event short description input field.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_short_description_input( $data, $fields ) {
return mcs_basic_input( 'short_description', $data, $fields );
}
/**
* Event link input field.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_event_link_input( $data, $fields ) {
return mcs_basic_input( 'event_link', $data, $fields );
}
/**
* Event image input field.
*
* @param object $data Event data.
* @param array $fields Fields passed from shortcode.
*
* @return string
*/
function mcs_event_image_input( $data, $fields ) {
$required_fields = apply_filters( 'mcs_required_fields', get_option( 'mcs_required_fields', array() ) );
$image_url = ( ! empty( $data ) ) ? esc_attr( $data->event_image ) : '';
$image_id = ( ! empty( $data ) ) ? get_post_thumbnail_id( $data->event_post ) : '';
$image = ( $image_id ) ? $image_id : $image_url;
$alt = ( isset( $_POST['event_image_alt'] ) ) ? esc_attr( sanitize_text_field( $_POST['event_image_alt'] ) ) : '';
$alt = ( $image_id && is_int( $image_id ) ) ? get_post_meta( $image_id, '_wp_attachment_image_alt', true ) : $alt;
if ( ! empty( $data ) ) {
$alt = ( '' === $alt ) ? get_post_meta( $data->event_post, '_mcs_submitted_alt', true ) : $alt;
}
$defaults = mcs_default_fields();
if ( isset( $fields['event_image'] ) || in_array( 'event_image', $required_fields, true ) ) {
$required = ( in_array( 'event_image', $required_fields, true ) ) ? ' required="required"' : '';
$invalid_class = '';
if ( ! empty( $data ) && $required && ! $image ) {
$invalid_class = ' class="invalid"';
}
$input_type = mcs_image_input_type( $image );
if ( isset( $fields['event_image'] ) ) {
$flabel = ( 'true' !== $fields['event_image'] ) ? $fields['event_image'] : $defaults['event_image']['field_label'];
} else {
$flabel = $defaults['event_image']['field_label'];
}
$flabel .= ( '' !== $required ) ? ' ' . mcs_required_text() : '';
$progress = ( 'file' === $input_type && 'true' === get_option( 'mcs_ajax', 'true' ) ) ? '<div class="mcs-upload-process"><button type="button" class="mcs-file-upload-submit mcs-hidden">' . __( 'Upload', 'my-calendar-pro' ) . '</button><div class="mcs-upload-progress" role="alert"></div></div><input type="hidden" name="event_image_id" value="' . esc_attr( $image_id ) . '">' : '';
$current_image = ( $image_url ) ? '<img src="' . esc_url( $image_url ) . '" alt="' . esc_attr( $alt ) . '" />' : '';
$class = ( $image_url ) ? ' has-image' : '';
$current_image = '<p class="mcs-selected-image' . $class . '">' . $current_image . '</p>';
$link = 'https://www.w3.org/WAI/tutorials/images/decision-tree';
/**
* Filter the link for users to learn about alt text.
*
* @hook mc_event_image_alt_link
*
* @param {string} $link Default link to the W3C's alt text decision tree.
*
* @return {string}
*/
$event_image_alt_link = apply_filters( 'mc_event_image_alt_link', $link );
$event_image_alt_link = ( ! $event_image_alt_link ) ? $link : $event_image_alt_link;
$text = __( 'Learn how to describe the purpose of the image.', 'my-calendar-pro' );
/**
* Filter the link text telling users how to learn about alt text.
*
* @hook mc_event_image_alt_info_text
*
* @param {string} $text Default visible text.
*
* @return {string}
*/
$event_image_alt_text = apply_filters( 'mc_event_image_alt_info_text', $text );
$event_image_alt_text = ( ! $event_image_alt_text ) ? $text : $event_image_alt_text;
return "
<div class='mc-image-fields'>
<p$invalid_class>
<label for='mc_event_image'>$flabel</label>
<span>
<input type='$input_type' name='event_image' id='mc_event_image' value='$image' $required />
<button type='button' id='mc_event_image_clear'>" . __( 'Clear', 'my-calendar-pro' ) . "</button>
</span>
</p>
<p class='mc_event_image_alt'>
<label for='event_image_alt'>" . __( 'Alternative text', 'my-calendar-pro' ) . ' ' . mcs_required_text() . "</label>
<input type='text' name='event_image_alt' id='event_image_alt' aria-labelledby='event_image_alt_info' value='$alt' required />
<span id='event_image_alt_info'><a href='" . esc_url( $event_image_alt_link ) . "' class='wpa-allow-target' target='_blank' rel='noopener'>" . $event_image_alt_text . " (new tab <i class='dashicons dashicons-external' aria-hidden='true'></i>)</a></span>" . '
</p>' . $progress . $current_image . '
</div>';
}
return '';
}