<?php
/**
* Custom Field Creator
*
* @category Features
* @package My Calendar Pro
* @author Joe Dolson
* @license GPLv2 or later
* @link https://www.joedolson.com/my-calendar-pro/
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Generate a unique array key for a form.
*
* @param string $key Possible unique ID.
* @param array $keys Currently defined keys.
*
* @return string
*/
function mcs_generate_array_key( $key, $keys ) {
if ( ! in_array( $key, $keys, true ) ) {
return $key;
} else {
return mcs_generate_array_key( uniqid(), $keys );
}
}
add_filter( 'mcs_custom_settings_update', 'mcs_custom_field_update', 10, 2 );
/**
* Update settings for responsive options.
*
* @param mixed $value Value.
* @param array $post POST data.
*
* @return string
*/
function mcs_custom_field_update( $value, $post ) {
// save custom field settings.
if ( isset( $post['custom-fields_settings'] ) ) {
$existing = get_option( 'mcs_custom_fields', array() );
$keys = array_keys( $existing );
// New fields.
if ( isset( $post['new_field'] ) ) {
$fields = ( isset( $post['new_field'] ) ) ? map_deep( $post['new_field'], 'sanitize_textarea_field' ) : array();
if ( function_exists( 'transliterator_transliterate' ) ) {
$id = transliterator_transliterate( 'Any-Latin; Latin-ASCII; Lower()', $fields['field_label'] );
$id = sanitize_title( $id );
} else {
$id = sanitize_title( $fields['field_label'] );
}
$fields['id'] = $id;
$key = ( isset( $existing[ $id ] ) ) ? $id . '_' . mcs_generate_array_key( uniqid(), $keys ) : $id;
$fields = array( $key => $fields );
$update = array_merge( $existing, $fields );
update_option( 'mcs_custom_fields', $update );
}
// Updating fields.
if ( isset( $post['fields'] ) ) {
$key = sanitize_title( $post['field_key'] );
if ( ! isset( $post['fields'][ $key ]['id'] ) || '' === $post['fields'][ $key ]['id'] ) {
$post['fields'][ $key ]['id'] = sanitize_title( $post['fields'][ $key ]['field_label'] );
}
$existing[ $key ] = map_deep( $post['fields'][ $key ], 'sanitize_textarea_field' );
update_option( 'mcs_custom_fields', $existing );
}
return __( 'Custom Fields Updated', 'my-calendar-pro' );
}
return $value;
}
add_filter( 'mcs_settings_tabs', 'mcs_custom_field_tabs' );
/**
* Add responsive tab to tab list.
*
* @param array $tabs existing tabs.
*
* @return array $tabs
*/
function mcs_custom_field_tabs( $tabs ) {
$tabs['custom-fields'] = __( 'Custom Fields', 'my-calendar-pro' );
return $tabs;
}
add_filter( 'mcs_settings_panels', 'mcs_custom_field_settings' );
/**
* Add custom fields panel to panel list.
*
* @param array $panels existing panels.
*
* @return array $panels
*/
function mcs_custom_field_settings( $panels ) {
$fields = mcs_get_fields( 'editor' );
$wp_nonce = wp_nonce_field( 'custom-fields', '_wpnonce', true, false );
$editor = '';
foreach ( $fields as $key => $field ) {
$field_output = mcs_create_field_editor( $key, $field );
$editor .= $field_output;
}
$new_field = mcs_create_editor();
$nav = mcs_fields_nav();
$editable = mcs_get_fields( 'editor' );
$add_button = get_submit_button( __( 'Add Custom Field', 'my-calendar-pro' ), 'primary', 'custom-fields_settings' );
$edit_button = ( count( $editable ) > 0 ) ? get_submit_button( __( 'Update Custom Fields', 'my-calendar-pro' ), 'primary', 'custom-fields_settings' ) : '';
// Translators: URL to form builder.
$fields_note = sprintf( __( 'New custom fields are added to Submissions forms using their field tags in shortcodes or in the <a href="%s">form building tool</a>. All fields are added to the admin form automatically. Required fields are only required on the front-end.', 'my-calendar-pro' ), esc_url( admin_url( 'admin.php?page-my-calendar-shortcodes#mc_builder' ) ) );
$controls = "<p id='custom_fields_note'>
" . $fields_note . "
</p>
$new_field
$add_button
</div>
</div>
</div>
</form>
<div class='ui-sortable meta-box-sortables'>
<div class='postbox'>
<h2>" . __( 'Custom Fields', 'my-calendar-pro' ) . "</h2>
<div class='inside'>" . $nav;
$controls .= ( count( $editable ) > 0 ) ? "</div>
</div>
</div>
<form method='post' action='" . admin_url( 'admin.php?page=my-calendar-submissions#mcs_custom-fields_tab' ) . "' enctype='multipart/form-data'>" . $wp_nonce . '
<div class="ui-sortable meta-box-sortables">
<div class="postbox">
<h2>' . __( 'Edit Custom Fields', 'my-calendar-pro' ) . '</h2>
<div class="inside">' . $editor : '';
$panels['custom-fields'] = '<h2>' . __( 'Custom Fields', 'my-calendar-pro' ) . '</h2>
<div class="inside">' . $controls . $edit_button . '</div>';
return $panels;
}
/**
* List fields for in-page navigation.
*
* @return string
*/
function mcs_fields_nav() {
$fields = mcs_get_fields();
$editable = mcs_get_fields( 'editor' );
$diff = array_diff_key( $fields, $editable );
$edit_list = '';
$add_list = '';
if ( count( $editable ) > 0 ) {
foreach ( $editable as $key => $field ) {
$label = ( isset( $field['field_label'] ) && '' !== $field['field_label'] ) ? $field['field_label'] : 'Untitled';
$edit_list .= '<li><a href="#mcs_editor_' . esc_attr( $key ) . '">' . esc_html( stripslashes( $label ) ) . '</a></li>';
}
} else {
$edit_list .= '<li>' . __( 'None', 'my-calendar-pro' ) . '</li>';
}
if ( count( $diff ) > 0 ) {
foreach ( $diff as $key => $field ) {
$label = ( '' !== $field['field_label'] ) ? $field['field_label'] : 'Untitled';
$add_list .= '<li>' . esc_html( stripslashes( $label ) ) . '</li>';
}
} else {
$add_list .= '<li>' . __( 'None', 'my-calendar-pro' ) . '</li>';
}
return '<div class="mc-editor-nav"><div class="mc-editor-editable"><h3>' . __( 'Editable Fields', 'my-calendar-pro' ) . '</h3><ul class="checkboxes">' . $edit_list . '</ul></div><div class="mc-editor-noneditable"><h3>' . __( 'Additional Custom Fields', 'my-calendar-pro' ) . '</h3><p>' . __( 'Fields configured from JSON or PHP sources.', 'my-calendar-pro' ) . '</p><ul class="checkboxes">' . $add_list . '</ul></div></div>';
}
/**
* Create field editor.
*
* @param string $key Editing array key.
* @param array $field Field data.
*
* @return string
*/
function mcs_create_field_editor( $key, $field ) {
$toggle = '<div class="mcs-editor-controls"><button type="submit" class="button hidden" name="custom-fields_settings">' . __( 'Update', 'my-calendar-pro' ) . '</button><button type="button" class="toggle-view toggle button-secondary"><span class="dashicons dashicons-edit" aria-hidden="true" data-key="' . esc_attr( $key ) . '"></span>' . __( 'Edit', 'my-calendar-pro' ) . '</button><button type="button" class="toggle-delete toggle button-secondary"><span class="dashicons dashicons-no" aria-hidden="true" data-key="' . esc_attr( $key ) . '"></span>' . __( 'Delete', 'my-calendar-pro' ) . '</button></div>';
$input = mcs_create_field( $key, $field );
$editor = mcs_create_editor( $key, $field );
$label = isset( $field['field_label'] ) ? $field['field_label'] : '';
// Translators: label for this field.
$delete_text = sprintf( __( 'Delete “%s”', 'my-calendar-pro' ), $label );
return '<div class="field-editor mcs-field-editor" id="mcs_editor_' . esc_attr( $key ) . '">
' . $toggle . '
<div class="field-input-view">' . $input . '</div>
<div class="field-input-editor">' . $editor . '</div>
<div class="field-input-notice"><button type="button" class="confirm-delete button-primary" data-key="' . esc_attr( $key ) . '">' . $delete_text . '</button> <button type="button" class="cancel-delete button-secondary" data-key="' . esc_attr( $key ) . '">Cancel</button></div>
</div>';
}
/**
* Create editor field.
*
* @param string $key Editing array key.
* @param array $source Field data.
*
* @return string
*/
function mcs_create_editor( $key = '', $source = array() ) {
$schema = array(
'field_label' => '',
'field_type' => 'text',
'field_notes' => '',
'field_options' => '',
'id' => '',
'field_required' => '',
'field_default' => '',
);
$field = array_merge( $schema, $source );
// Translators: Name of field currently displayed for editing.
$legend = ( empty( $source ) ) ? __( 'Create New Field', 'my-calendar-pro' ) : sprintf( __( 'Edit %s', 'my-calendar-pro' ), $field['field_label'] );
$label = $field['field_label'];
$type = $field['field_type'];
$notes = $field['field_notes'];
$options = $field['field_options'];
$default = $field['field_default'];
$required = $field['field_required'];
$prefix = ( empty( $key ) ) ? 'new_' : $key . '_';
$name = ( empty( $key ) ) ? 'new_field[{field_name}]' : 'fields[' . $key . '][{field_name}]';
$hidden = ( empty( $key ) ) ? '' : '<input type="hidden" class="field_key" name="field_key" value="' . esc_attr( $key ) . '" />';
$hidden .= ( ! empty( $field['id'] ) ) ? '<input type="hidden" class="field_name" name="' . str_replace( '{field_name}', 'id', $name ) . '" value="' . esc_attr( $field['id'] ) . '" />' : '';
$class = ( empty( $key ) ) ? 'new-field-row' : 'editor-field-row';
$output = '
<div class="field-row ' . $class . '">
' . $hidden . '
<fieldset>
<legend>' . esc_html( stripslashes( $legend ) ) . '</legend>
<div class="field-group">
<div class="field-fields field-label">
<label for="' . $prefix . 'field_label">' . __( 'Field Label', 'my-calendar-pro' ) . ' ' . mcs_required_text() . '</label><br />
<input class="widefat mcs-field field-input-label" type="text" value="' . stripslashes( esc_attr( $label ) ) . '" id="' . $prefix . 'field_label" data-field="field_label" name="' . str_replace( '{field_name}', 'field_label', $name ) . '" required="required" />
</div>
<div class="field-fields field-type">
<label for="' . $prefix . 'field_type">' . __( 'Field Type', 'my-calendar-pro' ) . '</label><br />
<select data-field="field_type" class="widefat mcs-field field-input-type" id="' . $prefix . 'field_type" name="' . str_replace( '{field_name}', 'field_type', $name ) . '">
<option value="text" ' . selected( 'text', $type, false ) . '>text</option>
<option value="email" ' . selected( 'email', $type, false ) . '>email</option>
<option value="number" ' . selected( 'number', $type, false ) . '>number</option>
<option value="date" ' . selected( 'date', $type, false ) . '>date</option>
<option value="time" ' . selected( 'time', $type, false ) . '>time</option>
<option value="url" ' . selected( 'url', $type, false ) . '>url</option>
<option value="tel" ' . selected( 'tel', $type, false ) . '>tel</option>
<option value="select" ' . selected( 'select', $type, false ) . '>select</option>
<option value="checkbox" ' . selected( 'checkbox', $type, false ) . '>checkbox (single)</option>
<option value="checkbox-group" ' . selected( 'checkbox-group', $type, false ) . '>checkbox (group)</option>
<option value="radio" ' . selected( 'radio', $type, false ) . '>radio</option>
<option value="textarea" ' . selected( 'textarea', $type, false ) . '>textarea</option>
<option value="hidden" ' . selected( 'hidden', $type, false ) . '>hidden</option>
</select>
</div>
<div class="field-fields field-notes">
<label for="' . $prefix . 'field_notes">' . __( 'Field Description', 'my-calendar-pro' ) . '</label><br />
<input data-field="field_notes" class="widefat mcs-field field-input-notes" type="text" value="' . stripslashes( esc_attr( $notes ) ) . '" id="' . $prefix . 'field_notes" name="' . str_replace( '{field_name}', 'field_notes', $name ) . '" />
</div>
<div class="field-fields field-options">
<label for="' . $prefix . 'field_options">' . __( 'Field Options (comma separated)', 'my-calendar-pro' ) . '</label><br />
<input data-field="field_options" class="widefat mcs-field field-input-options" type="text" value="' . stripslashes( esc_attr( $options ) ) . '" id="' . $prefix . 'field_options" name="' . str_replace( '{field_name}', 'field_options', $name ) . '" />
</div>
<div class="field-fields field-default">
<label for="' . $prefix . 'field_default">' . __( 'Field Default value', 'my-calendar-pro' ) . '</label><br />
<input data-field="field_default" class="widefat mcs-field field-input-default" type="text" value="' . stripslashes( esc_attr( $default ) ) . '" id="' . $prefix . 'field_default" name="' . str_replace( '{field_name}', 'field_default', $name ) . '" />
</div>
<div class="field-fields field-required checkbox">
<input data-field="field_required" class="mcs-field field-input-required" type="checkbox" value="true"' . checked( $required, 'true', false ) . ' name="' . str_replace( '{field_name}', 'field_required', $name ) . '" id="' . $prefix . 'field_required" /> <label for="' . $prefix . 'field_required">' . __( 'Required', 'my-calendar-pro' ) . '</label>
</div>
</div>
</fieldset>
</div>';
return $output;
}
/**
* Get My Calendar custom fields array.
*
* @param string $form_id Form ID.
*
* @return array
*/
function mcs_get_fields( $form_id = '' ) {
$fields = get_option( 'mcs_custom_fields', array() );
if ( 'editor' !== $form_id ) {
// Don't pick up fields created from filters or JSON in editor.
$json_fields = array();
$file = mc_file_exists( 'mc-custom-fields.json' );
if ( $file ) {
global $wp_filesystem;
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
$json = $wp_filesystem->get_contents( mc_get_file( 'custom-fields.json' ) );
$json = json_decode( $json, true );
$keys = array_keys( $json );
// Make sure the decoded JSON looks like the right format.
if ( is_array( $json ) && ( isset( $json[ $keys[0] ]['field_type'] ) && isset( $json[ $keys[0] ]['field_label'] ) ) ) {
$json_fields = $json;
}
}
$fields = array_merge( $fields, $json_fields );
/**
* Filter custom field array.
*
* @hook mcs_custom_fields
*
* @param {array} $fields Array of field details.
* @param {string} $form_id Form ID for form being rendered.
*
* @return {array}
*/
$fields = apply_filters( 'mcs_custom_fields', $fields, $form_id );
}
return $fields;
}
/**
* Save custom fields into post meta.
*
* @param string $action Current action (add, edit, copy).
* @param object $data Event data.
* @param int $event_id Event ID.
* @param int|bool $result Insertion status.
*/
function mcs_event_save( $action, $data, $event_id, $result ) {
$post = array_merge( $_GET, $_POST );
$post = isset( $post['post'] ) ? $post['post'] : $post;
// Parse serialized data.
if ( is_string( $post ) ) {
parse_str( $post, $data );
$post = map_deep( $data, 'mcs_ajax_sanitize' );
}
$post_id = mc_get_event_post( $event_id );
$fields = mcs_get_fields();
foreach ( $fields as $field ) {
$key = 'mcs_' . $field['id'];
// Collect and sanitize value.
$sanitize = ( isset( $field['sanitize_callback'] ) && function_exists( $field['sanitize_callback'] ) ) ? $field['sanitize_callback'] : 'sanitize_textarea_field';
$value = isset( $post[ $key ] ) ? call_user_func( $sanitize, $post[ $key ] ) : '';
update_post_meta( $post_id, $key, $value );
}
}
add_action( 'mc_save_event', 'mcs_event_save', 20, 4 );
/**
* Add custom field into template tags array.
*
* @param array $details Array of template tags as $tag => $value.
* @param object $event Event object as fetched from database.
*
* @return array $details
*/
function mcs_event_tag( $details, $event ) {
$post_id = $event->event_post;
$fields = mcs_get_fields();
foreach ( $fields as $field ) {
$key = 'mcs_' . $field['id'];
$value = get_post_meta( $post_id, $key, true );
/**
* Filter the value of a tag as rendered in the My Calendar template tagging.
*
* @hook mcs_format_tag
*
* @param {string|array} $value Value saved in post meta.
* @param {array} $field Array of field information.
* @param {int} $post_id Post ID.
*
* @return {string}
*/
$value = apply_filters( 'mcs_format_tag', $value, $field, $post_id );
$display = ( isset( $field['display_callback'] ) ) ? $field['display_callback'] : 'wp_kses_post';
if ( is_array( $value ) ) {
$details[ $key ] = map_deep( $value, $display );
} else {
$details[ $key ] = ( $value ) ? call_user_func( $display, $value ) : '';
}
}
return $details;
}
add_filter( 'mc_filter_shortcodes', 'mcs_event_tag', 10, 2 );
/**
* Add fields that are sortable in My Calendar Pro.
*
* @param array $fields Array of fields available in Pro.
* @param boolean $has_data If true, this is an event being edited or corrected.
* @param object $event The event object saved.
* @param string $context 'public' or 'admin', depending on whether this is being rendered in the Pro submissions form or WP Admin.
* @param string $form_id Unique ID string for this form.
*
* @since My Calendar Pro 2.0.0
*
* @return array of fields
*/
function mcs_customize_event_form( $fields, $has_data, $event, $context, $form_id ) {
$custom_fields = mcs_get_fields();
$all_fields = array_merge( $fields, $custom_fields );
$return = array();
foreach ( $all_fields as $field => $data ) {
if ( in_array( $field, array_keys( $fields ), true ) ) {
$return[ $field ] = $data;
} else {
$return[ $field ] = isset( $custom_fields[ $field ] ) ? mcs_create_field( $field, $custom_fields[ $field ], $event ) : '';
}
}
return $return;
}
add_filter( 'mc_custom_fields', 'mcs_customize_event_form', 10, 5 );
/**
* Add the input field for your custom field into the main section of My Calendar event details.
* These fields will be lumped together in the 'custom_fields' parameter in My Calendar Pro. To make sortable in Pro without being duplicated, make conditional based on the `$context` param. This example will only show in the admin.
*
* @param string $form HTML of any other added custom fields.
* @param boolean $has_data If true, this is an event being edited or corrected.
* @param object $event The event object saved.
* @param string $context 'public' or 'admin', depending on whether this is being rendered in the Pro submissions form or WP Admin.
*
* @return string
*/
function mcs_custom_fields( $form, $has_data, $event, $context ) {
if ( 'admin' === $context ) {
$fields = mcs_get_fields();
foreach ( $fields as $key => $field ) {
$form .= mcs_create_field( $key, $field, $event );
}
}
return $form;
}
add_filter( 'mc_event_details', 'mcs_custom_fields', 10, 4 );
/**
* Create a field from array data.
*
* @param string $key Field key.
* @param array $field Field data array.
* @param object $event Event object if exists.
* @param string $form_id ID for current form if passed.
*
* @return string
*/
function mcs_create_field( $key, $field, $event = null, $form_id = '' ) {
$output = '';
/**
* Test whether a field is called for the current form.
*
* @hook mcs_apply_custom_field
*
* @param {bool} $continue False to ignore this field.
* @param {array} $field Array of field data.
* @param {object} $event Event data.
* @param {string} $form_id ID for this form.
*
* @return bool
*/
$continue = apply_filters( 'mcs_apply_custom_field', true, $field, $event, $form_id );
if ( $continue ) {
$field_id = ( isset( $field['id'] ) ) ? $field['id'] : '';
$default = ( isset( $field['field_default'] ) ) ? $field['field_default'] : '';
// If there's no key, it's not possible to fetch data.
$value = ( $event && $field_id ) ? get_post_meta( $event->event_post, 'mcs_' . $field_id, true ) : $default;
$name = 'mcs_' . esc_attr( $field_id );
$id = $key;
$is_required = ( isset( $field['field_required'] ) && ! empty( $field['field_required'] ) ) ? true : false;
$required = $is_required && ! is_admin() ? ' required' : '';
$req_text = is_admin() ? __( 'required for public submitters', 'my-calendar-pro' ) : __( 'required', 'my-calendar-pro' );
$req_label = $is_required ? ' <span class="required">(' . $req_text . ')</span>' : '';
$type = isset( $field['field_type'] ) ? $field['field_type'] : 'text';
$escape = ( isset( $field['escape_callback'] ) && function_exists( $field['escape_callback'] ) ) ? $field['escape_callback'] : '';
$notes = isset( $field['field_notes'] ) ? '<span class="mcs-field-notes" id="' . $id . '_notes">' . esc_html( stripslashes( $field['field_notes'] ) ) . '</span>' : '';
$labelled = isset( $field['field_notes'] ) ? ' aria-describedby="' . $id . '_notes"' : '';
$label = isset( $field['field_label'] ) ? $field['field_label'] : '';
switch ( $type ) {
case 'text':
case 'number':
case 'email':
case 'url':
case 'date':
case 'tel':
$value = ( $escape ) ? call_user_func( $escape, $value ) : esc_attr( $value );
$output = "<input class='widefat mcs-$type-input' type='" . esc_attr( $type ) . "' name='$name' id='$id' value='$value'$required $labelled />$notes";
break;
case 'textarea':
$value = ( $escape ) ? call_user_func( $escape, $value ) : esc_textarea( $value );
$output = "<textarea class='widefat mcs-textarea-input' rows='6' cols='60' name='$name' id='$id'$required $labelled>" . stripslashes( $value ) . '</textarea>' . $notes;
break;
case 'select':
if ( isset( $field['field_options'] ) ) {
$output = "<select class='widefat mcs-select-input' name='$name' id='$id'$required $labelled>";
if ( ! is_array( $field['field_options'] ) ) {
$field_options = explode( ',', $field['field_options'] );
} else {
$field_options = $field['field_options'];
}
$field_options = map_deep( $field_options, 'trim' );
foreach ( $field_options as $val ) {
$value = stripslashes( $value );
$val = stripslashes( $val );
if ( $value === $val ) {
$selected = " selected='selected'";
} else {
$selected = '';
}
$output .= "<option value='" . esc_attr( trim( $val ) ) . "'$selected>" . esc_html( trim( $val ) ) . "</option>\n";
}
$output .= '</select>' . $notes;
}
break;
case 'checkbox':
if ( isset( $field['field_options'] ) ) {
$values = $field['field_options'];
if ( '' !== $value ) {
$checked = ' checked="checked"';
} else {
$checked = '';
}
$output = "<input class='mcs-checkbox-input' type='" . esc_attr( $field['field_type'] ) . "' name='$name' id='$id' value='" . esc_attr( stripslashes( $values ) ) . "'$checked $required $labelled />";
}
break;
case 'checkbox-group':
case 'radio':
$output = '';
if ( isset( $field['field_options'] ) ) {
if ( ! is_array( $field['field_options'] ) ) {
$field_options = explode( ',', $field['field_options'] );
} else {
$field_options = $field['field_options'];
}
$field_options = map_deep( $field_options, 'trim' );
$output .= '<ul class="mcs-field-list">';
foreach ( $field_options as $val ) {
$els = ( false === stripos( $val, '|' ) ) ? false : explode( '|', $val );
if ( ! $els ) {
$els = array(
'label' => ucwords( $val ),
'value' => $val,
);
} else {
$els = array(
'label' => $els[1],
'value' => $els[0],
);
}
$value = stripslashes( $value );
$val = stripslashes( $els['value'] );
if ( $value === $val ) {
$checked = " checked='checked'";
} else {
$checked = '';
}
$group_label = $els['label'];
$group_id = $id . '-' . md5( $val );
$field_type = ( 'checkbox-group' === $field['field_type'] ) ? 'checkbox' : 'radio';
$output .= "<li><input class='mcs-$field_type-input' type='" . esc_attr( $field_type ) . "' name='$name' id='$group_id' value='" . esc_attr( stripslashes( $val ) ) . "'$checked $required />";
$output .= " <label for='$group_id'><span class='label'>" . esc_html( stripslashes( $group_label ) ) . '</span></label></li>';
}
$output .= '</ul>';
}
break;
case 'hidden':
$output = "<input type='hidden' name='$name' id='$id' value='" . esc_attr( $value ) . "' />";
break;
default:
$output = "<input class='widefat mcs-text' type='text' name='$name' id='$id' value='" . esc_attr( $value ) . "' $required $labelled />$notes";
}
$class = 'mcs-' . sanitize_html_class( sanitize_title( strtolower( $label ) ) );
$tag = ' <code>{mcs_' . $id . '}</code>';
$function = ' <code>mc_template_tag( ' . '$' . "data, 'mcs_" . $id . "' )</code>";
if ( 'checkbox' === $type ) {
$output = "<div class='mcs-custom-field $class mcs-$type'>$output <label for='$id'><span class='label'>" . esc_html( stripslashes( $label ) ) . '</span>' . $req_label . '</label>' . $notes . '</div>';
} elseif ( 'radio' === $type || 'checkbox-group' === $type ) {
$output = "<div class='mcs-custom-field $class mcs-$type'><fieldset aria-labelledby='$id-legend" . ' ' . $id . '_notes' . "'><legend id='$id-legend'>" . esc_html( stripslashes( $label ) ) . "$req_label</legend>$output$notes</fieldset></div>";
} else {
$output = "<div class='mcs-custom-field $class mcs-$type'><p><label for='$id'><span class='label'>" . esc_html( stripslashes( $label ) ) . '</span>' . $req_label . '</label> ' . $output . '</p></div>';
}
if ( isset( $_GET['page'] ) && 'my-calendar-submissions' === $_GET['page'] && ! mcs_core_custom_field( $id ) ) {
$output .= '<ul>
<li>' . __( 'Template tag:', 'my-calendar-pro' ) . $tag . '</li>
<li>' . __( 'Template function:', 'my-calendar-pro' ) . $function . '</li>
</ul>';
}
}
return $output;
}
/**
* Check whether a field is in the core settings fields, because the same function produces custom fields and misc. settings.
*
* @param string $id Field ID.
*
* @return bool
*/
function mcs_core_custom_field( $id ) {
$fields = array( 'multilingual_events', 'private_content', 'custom_hosts', 'migrate_hosts' );
if ( in_array( $id, $fields, true ) ) {
return true;
}
return false;
}
/**
* Delete a custom field.
*
* @param string $field_key An array key referencing a field.
*/
function mcs_delete_field( $field_key = '' ) {
$fields = get_option( 'mcs_custom_fields', array() );
$original = $fields;
unset( $fields[ $field_key ] );
update_option( 'mcs_custom_fields', $fields );
$response = array(
'success' => 1,
'response' => __( 'Field has been deleted', 'my-calendar-pro' ),
'data' => $fields,
'original' => $original,
'key' => $field_key,
);
return $response;
}
/**
* Handle AJAX field update.
*
* @param array $request AJAX Request data.
*
* @return array
*/
function mcs_update_field( $request ) {
$fields = get_option( 'mcs_custom_fields', array() );
$field_key = $request['field_key'];
$editing = isset( $fields[ $field_key ] ) ? $fields[ $field_key ] : false;
$new = $editing;
if ( ! $editing ) {
$response = array(
'success' => 0,
'response' => __( 'Field not found. Save new fields first.', 'my-calendar-pro' ),
);
} else {
$keys = $request['keys'];
$vals = $request['values'];
$index = 0;
$new = array();
foreach ( $keys as $key ) {
$new[ $key ] = $vals[ $index ];
++$index;
}
$updated = array_merge( $editing, $new );
$fields[ $field_key ] = $updated;
update_option( 'mcs_custom_fields', $fields );
$response = array(
'success' => 1,
'response' => __( 'Custom field updated', 'my-calendar-pro' ),
'data' => $updated,
'original' => $editing,
'new' => $new,
);
}
return $response;
}
/**
* Handle AJAX field actions.
*
* @return void
*/
function mcs_fields_action() {
if ( isset( $_REQUEST['action'] ) && 'mcs_fields_action' === $_REQUEST['action'] ) {
$security = $_REQUEST['security'];
$field_key = ( isset( $_REQUEST['field_key'] ) ) ? sanitize_text_field( $_REQUEST['field_key'] ) : false;
if ( ! wp_verify_nonce( $security, 'mcs-fields-action' ) ) {
wp_send_json(
array(
'success' => 0,
'response' => '',
)
);
}
if ( isset( $_REQUEST['mcs_delete_field'] ) ) {
$response = mcs_delete_field( $field_key );
}
if ( isset( $_REQUEST['mcs_update_field'] ) ) {
$response = mcs_update_field( $_REQUEST );
}
wp_send_json( $response );
}
}
add_action( 'wp_ajax_mcs_fields_action', 'mcs_fields_action' );
add_action( 'wp_ajax_nopriv_mcs_fields_action', 'mcs_fields_action' );