first commit

This commit is contained in:
DESKTOP-GBA0BK8\Admin
2023-04-08 12:19:53 -04:00
commit 7c8c8b1c76
4586 changed files with 2050693 additions and 0 deletions
@@ -0,0 +1,67 @@
<?php
/**
* Gets the absolute url to edit a form
*
* @param int $form_id ID of the form
* @param string $tab Tab identifier to open
*
* @return string
*/
function mc4wp_get_edit_form_url($form_id, $tab = '')
{
$url = admin_url(sprintf('admin.php?page=mailchimp-for-wp-forms&view=edit-form&form_id=%d', $form_id));
if (! empty($tab)) {
$url .= sprintf('&tab=%s', $tab);
}
return $url;
}
/**
* Get absolute URL to create a new form
*
* @return string
*/
function mc4wp_get_add_form_url()
{
$url = admin_url('admin.php?page=mailchimp-for-wp-forms&view=add-form');
return $url;
}
/**
* @param $key
* @param $label
* @param $value
* @param string $help_text
*
* @return string
*/
//function mc4wp_form_message_setting_row( $key, $label, $value = '', $help_text = '' ) {
//
//
// $id = 'mc4wp_form_message_' . $key;
// echo $name = sprintf( 'mc4wp_form[messages][%s]', $key );
//
// echo '<tr valign="top">';
//
// # Label
// echo '<th scope="row">';
// echo sprintf( '<label for="%s">%s</label>', $id, $label );
// echo '</th>';
//
// # Input
// echo '<td>';
// echo sprintf( '<input type="text" class="widefat" id="%s" name="%s" value="%s" />', $id, $name, esc_attr( $value ) );
//
// # Help text
// if( ! empty( $help_text ) ) {
// echo sprintf( '<p class="help">%s</p>', $help_text );
// }
//
// echo '</td>';
// echo '</tr>';
//
// return '';
//}
@@ -0,0 +1,487 @@
<?php
/**
* Class MC4WP_Forms_Admin
*
* @ignore
* @access private
*/
class MC4WP_Forms_Admin
{
/**
* @var MC4WP_Admin_Messages
*/
protected $messages;
/**
* @var MC4WP_MailChimp
*/
protected $mailchimp;
/**
* @param MC4WP_Admin_Messages $messages
* @param MC4WP_MailChimp $mailchimp
*/
public function __construct(MC4WP_Admin_Messages $messages, MC4WP_MailChimp $mailchimp)
{
$this->messages = $messages;
$this->mailchimp = $mailchimp;
}
/**
* Add hooks
*/
public function add_hooks()
{
add_action('register_shortcode_ui', array( $this, 'register_shortcake_ui' ));
add_action('mc4wp_save_form', array( $this, 'update_form_stylesheets' ));
add_action('mc4wp_admin_edit_form', array( $this, 'process_save_form' ));
add_action('mc4wp_admin_add_form', array( $this, 'process_add_form' ));
add_filter('mc4wp_admin_menu_items', array( $this, 'add_menu_item' ), 5);
add_action('mc4wp_admin_show_forms_page-edit-form', array( $this, 'show_edit_page' ));
add_action('mc4wp_admin_show_forms_page-add-form', array( $this, 'show_add_page' ));
add_action('mc4wp_admin_enqueue_assets', array( $this, 'enqueue_assets' ), 10, 2);
add_action('enqueue_block_editor_assets', array($this, 'enqueue_gutenberg_assets'));
}
public function enqueue_gutenberg_assets()
{
wp_enqueue_script('mc4wp-form-block', MC4WP_PLUGIN_URL . 'assets/js/forms-block.js', array('wp-blocks', 'wp-i18n', 'wp-element', 'wp-components'));
$forms = mc4wp_get_forms();
$data = array();
foreach ($forms as $form) {
$data[] = array( 'name' => $form->name, 'id' => $form->ID );
}
wp_localize_script('mc4wp-form-block', 'mc4wp_forms', $data );
}
/**
* @param string $suffix
* @param string $page
*/
public function enqueue_assets($suffix, $page = '')
{
if ($page !== 'forms' || empty($_GET['view']) || $_GET['view'] !== 'edit-form') {
return;
}
wp_register_script('mc4wp-forms-admin', MC4WP_PLUGIN_URL . 'assets/js/forms-admin' . $suffix . '.js', array( 'mc4wp-admin' ), MC4WP_VERSION, true);
wp_enqueue_script('mc4wp-forms-admin');
wp_localize_script('mc4wp-forms-admin', 'mc4wp_forms_i18n', array(
'addToForm' => __("Add to form", 'mailchimp-for-wp'),
'agreeToTerms' => __("I have read and agree to the terms & conditions", 'mailchimp-for-wp'),
'agreeToTermsShort' => __("Agree to terms", 'mailchimp-for-wp'),
'agreeToTermsLink' => __('Link to your terms & conditions page', 'mailchimp-for-wp'),
'city' => __('City', 'mailchimp-for-wp'),
'checkboxes' => __('Checkboxes', 'mailchimp-for-wp'),
'choices' => __('Choices', 'mailchimp-for-wp'),
'choiceType' => __("Choice type", 'mailchimp-for-wp'),
'chooseField' => __("Choose a field to add to the form", 'mailchimp-for-wp'),
'close' => __('Close', 'mailchimp-for-wp'),
'country' => __('Country', 'mailchimp-for-wp'),
'dropdown' => __('Dropdown', 'mailchimp-for-wp'),
'emailAddress' => __('Email address', 'mailchimp-for-wp'),
'fieldType' => __('Field type', 'mailchimp-for-wp'),
'fieldLabel' => __("Field label", 'mailchimp-for-wp'),
'formAction' => __('Form action', 'mailchimp-for-wp'),
'formActionDescription' => __('This field will allow your visitors to choose whether they would like to subscribe or unsubscribe', 'mailchimp-for-wp'),
'formFields' => __('Form fields', 'mailchimp-for-wp'),
'forceRequired' => __('This field is marked as required in Mailchimp.', 'mailchimp-for-wp'),
'initialValue' => __("Initial value", 'mailchimp-for-wp'),
'interestCategories' => __('Interest categories', 'mailchimp-for-wp'),
'isFieldRequired' => __("Is this field required?", 'mailchimp-for-wp'),
'listChoice' => __('List choice', 'mailchimp-for-wp'),
'listChoiceDescription' => __('This field will allow your visitors to choose a list to subscribe to.', 'mailchimp-for-wp'),
'listFields' => __('List fields', 'mailchimp-for-wp'),
'min' => __('Min', 'mailchimp-for-wp'),
'max' => __('Max', 'mailchimp-for-wp'),
'noAvailableFields' => __('No available fields. Did you select a Mailchimp list in the form settings?', 'mailchimp-for-wp'),
'optional' => __('Optional', 'mailchimp-for-wp'),
'placeholder' => __('Placeholder', 'mailchimp-for-wp'),
'placeholderHelp' => __("Text to show when field has no value.", 'mailchimp-for-wp'),
'preselect' => __('Preselect', 'mailchimp-for-wp'),
'remove' => __('Remove', 'mailchimp-for-wp'),
'radioButtons' => __('Radio buttons', 'mailchimp-for-wp'),
'streetAddress' => __('Street Address', 'mailchimp-for-wp'),
'state' => __('State', 'mailchimp-for-wp'),
'subscribe' => __('Subscribe', 'mailchimp-for-wp'),
'submitButton' => __('Submit button', 'mailchimp-for-wp'),
'wrapInParagraphTags' => __("Wrap in paragraph tags?", 'mailchimp-for-wp'),
'value' => __("Value", 'mailchimp-for-wp'),
'valueHelp' => __("Text to prefill this field with.", 'mailchimp-for-wp'),
'zip' => __('ZIP', 'mailchimp-for-wp'),
));
}
/**
* @param $items
*
* @return mixed
*/
public function add_menu_item($items)
{
$items['forms'] = array(
'title' => __('Forms', 'mailchimp-for-wp'),
'text' => __('Form', 'mailchimp-for-wp'),
'slug' => 'forms',
'callback' => array( $this, 'show_forms_page' ),
'load_callback' => array( $this, 'redirect_to_form_action' ),
'position' => 10
);
return $items;
}
/**
* Act on the "add form" form
*/
public function process_add_form()
{
check_admin_referer('add_form', '_mc4wp_nonce');
$form_data = $_POST['mc4wp_form'];
$form_content = include MC4WP_PLUGIN_DIR . 'config/default-form-content.php';
// Fix for MultiSite stripping KSES for roles other than administrator
remove_all_filters('content_save_pre');
$form_id = wp_insert_post(
array(
'post_type' => 'mc4wp-form',
'post_status' => 'publish',
'post_title' => $form_data['name'],
'post_content' => $form_content,
)
);
// if settings were passed, save those too.
if (isset($form_data['settings'])) {
update_post_meta($form_id, '_mc4wp_settings', $form_data['settings']);
}
// set default form ID
$this->set_default_form_id($form_id);
$this->messages->flash(__("<strong>Success!</strong> Form successfully saved.", 'mailchimp-for-wp'));
wp_redirect(mc4wp_get_edit_form_url($form_id));
exit;
}
/**
* Saves a form to the database
*
* @param array $data
* @return int
*/
public function save_form($data)
{
$keys = array(
'settings' => array(),
'messages' => array(),
'name' => '',
'content' => ''
);
$data = array_merge($keys, $data);
$data = $this->sanitize_form_data($data);
$post_data = array(
'post_type' => 'mc4wp-form',
'post_status' => ! empty($data['status']) ? $data['status'] : 'publish',
'post_title' => $data['name'],
'post_content' => $data['content']
);
// if an `ID` is given, make sure post is of type `mc4wp-form`
if (! empty($data['ID'])) {
$post = get_post($data['ID']);
if ($post instanceof WP_Post && $post->post_type === 'mc4wp-form') {
$post_data['ID'] = $data['ID'];
// merge new settings with current settings to allow passing partial data
$current_settings = get_post_meta($post->ID, '_mc4wp_settings', true);
if (is_array($current_settings)) {
$data['settings'] = array_merge($current_settings, $data['settings']);
}
}
}
// Fix for MultiSite stripping KSES for roles other than administrator
remove_all_filters('content_save_pre');
$form_id = wp_insert_post($post_data);
update_post_meta($form_id, '_mc4wp_settings', $data['settings']);
// save form messages in individual meta keys
foreach ($data['messages'] as $key => $message) {
update_post_meta($form_id, 'text_' . $key, $message);
}
/**
* Runs right after a form is updated.
*
* @since 3.0
*
* @param int $form_id
*/
do_action('mc4wp_save_form', $form_id);
return $form_id;
}
/**
* @param array $data
* @return array
*/
public function sanitize_form_data($data)
{
$raw_data = $data;
// strip <form> tags from content
$data['content'] = preg_replace('/<\/?form(.|\s)*?>/i', '', $data['content']);
// replace lowercased name="name" to prevent 404
$data['content'] = str_ireplace(' name=\"name\"', ' name=\"NAME\"', $data['content']);
// sanitize text fields
$data['settings']['redirect'] = sanitize_text_field($data['settings']['redirect']);
// strip tags from messages
foreach ($data['messages'] as $key => $message) {
$data['messages'][$key] = strip_tags($message, '<strong><b><br><a><script><u><em><i><span><img>');
}
// make sure lists is an array
if (! isset($data['settings']['lists'])) {
$data['settings']['lists'] = array();
}
$data['settings']['lists'] = array_filter((array) $data['settings']['lists']);
/**
* Filters the form data just before it is saved.
*
* @param array $data Sanitized array of form data.
* @param array $raw_data Raw array of form data.
*
* @since 3.0.8
* @ignore
*/
$data = (array) apply_filters('mc4wp_form_sanitized_data', $data, $raw_data);
return $data;
}
/**
* Saves a form
*/
public function process_save_form()
{
check_admin_referer('edit_form', '_mc4wp_nonce');
// save global settings (if submitted)
$options = get_option('mc4wp', array());
$posted = $_POST['mc4wp'];
foreach($posted as $key => $value) {
$options[$key] = trim($value);
}
update_option('mc4wp', $options);
// save form + settings
$form_id = (int) $_POST['mc4wp_form_id'];
$form_data = $_POST['mc4wp_form'];
$form_data['ID'] = $form_id;
$this->save_form($form_data);
$this->set_default_form_id($form_id);
$this->messages->flash(__("<strong>Success!</strong> Form successfully saved.", 'mailchimp-for-wp'));
}
/**
* @param int $form_id
*/
private function set_default_form_id($form_id)
{
$default_form_id = (int) get_option('mc4wp_default_form_id', 0);
if (empty($default_form_id)) {
update_option('mc4wp_default_form_id', $form_id);
}
}
/**
* Goes through each form and aggregates array of stylesheet slugs to load.
*
* @hooked `mc4wp_save_form`
*/
public function update_form_stylesheets()
{
$stylesheets = array();
$forms = mc4wp_get_forms();
foreach ($forms as $form) {
$stylesheet = $form->get_stylesheet();
if (! empty($stylesheet) && ! in_array($stylesheet, $stylesheets)) {
$stylesheets[] = $stylesheet;
}
}
update_option('mc4wp_form_stylesheets', $stylesheets);
}
/**
* Redirect to correct form action
*
* @ignore
*/
public function redirect_to_form_action()
{
if (! empty($_GET['view'])) {
return;
}
try {
// try default form first
$default_form = mc4wp_get_form();
$redirect_url = mc4wp_get_edit_form_url($default_form->ID);
} catch (Exception $e) {
// no default form, query first available form and go there
$forms = mc4wp_get_forms(array( 'numberposts' => 1 ));
if ($forms) {
// if we have a post, go to the "edit form" screen
$form = array_pop($forms);
$redirect_url = mc4wp_get_edit_form_url($form->ID);
} else {
// we don't have a form yet, go to "add new" screen
$redirect_url = mc4wp_get_add_form_url();
}
}
if (headers_sent()) {
echo sprintf('<meta http-equiv="refresh" content="0;url=%s" />', $redirect_url);
} else {
wp_redirect($redirect_url);
}
exit;
}
/**
* Show the Forms Settings page
*
* @internal
*/
public function show_forms_page()
{
$view = ! empty($_GET['view']) ? $_GET['view'] : '';
/**
* @ignore
*/
do_action('mc4wp_admin_show_forms_page', $view);
/**
* @ignore
*/
do_action('mc4wp_admin_show_forms_page-' . $view);
}
/**
* Show the "Edit Form" page
*
* @internal
*/
public function show_edit_page()
{
$form_id = (! empty($_GET['form_id'])) ? (int) $_GET['form_id'] : 0;
$lists = $this->mailchimp->get_lists();
try {
$form = mc4wp_get_form($form_id);
} catch (Exception $e) {
echo '<h2>' . __("Form not found.", 'mailchimp-for-wp') . '</h2>';
echo '<p>' . $e->getMessage() . '</p>';
echo '<p><a href="javascript:history.go(-1);"> &lsaquo; '. __('Go back') .'</a></p>';
return;
}
$opts = $form->settings;
$active_tab = (isset($_GET['tab'])) ? $_GET['tab'] : 'fields';
$form_preview_url = add_query_arg(array(
'mc4wp_preview_form' => $form_id,
), site_url('/', 'admin'));
require dirname(__FILE__) . '/views/edit-form.php';
}
/**
* Shows the "Add Form" page
*
* @internal
*/
public function show_add_page()
{
$lists = $this->mailchimp->get_lists();
$number_of_lists = count($lists);
require dirname(__FILE__) . '/views/add-form.php';
}
/**
* Get URL for a tab on the current page.
*
* @since 3.0
* @internal
* @param $tab
* @return string
*/
public function tab_url($tab)
{
return add_query_arg(array( 'tab' => $tab ), remove_query_arg('tab'));
}
/**
* Registers UI for when shortcake is activated
*/
public function register_shortcake_ui()
{
$assets = new MC4WP_Form_Asset_Manager();
$assets->load_stylesheets();
$forms = mc4wp_get_forms();
$options = array();
foreach ($forms as $form) {
$options[ $form->ID ] = $form->name;
}
/**
* Register UI for your shortcode
*
* @param string $shortcode_tag
* @param array $ui_args
*/
shortcode_ui_register_for_shortcode(
'mc4wp_form',
array(
'label' => esc_html__('Mailchimp Sign-Up Form', 'mailchimp-for-wp'),
'listItemImage' => 'dashicons-feedback',
'attrs' => array(
array(
'label' => esc_html__('Select the form to show', 'mailchimp-for-wp'),
'attr' => 'id',
'type' => 'select',
'options' => $options
)
),
)
);
}
}
@@ -0,0 +1,248 @@
<?php
/**
* This class takes care of all form related functionality
*
* @access private
* @ignore
*/
class MC4WP_Form_Asset_Manager
{
/**
* @var bool
*/
protected $load_scripts = false;
/**
* @var string
*/
protected $filename_suffix = '';
/**
* MC4WP_Form_Asset_Manager constructor.
*/
public function __construct()
{
$this->filename_suffix =(defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? '' : '.min';
}
/**
* Add hooks
*/
public function hook()
{
// load checkbox css if necessary
add_action('wp_enqueue_scripts', array( $this, 'load_stylesheets' ));
add_action('mc4wp_output_form', array( $this, 'before_output_form' ));
add_action('wp_footer', array( $this, 'load_scripts' ));
$this->register_assets();
}
/**
* Register the various JS files used by the plugin
*/
public function register_assets()
{
$suffix = $this->filename_suffix;
wp_register_script('mc4wp-forms-api', MC4WP_PLUGIN_URL . 'assets/js/forms-api'. $this->filename_suffix .'.js', array(), MC4WP_VERSION, true);
/**
* Runs right after all assets (scripts & stylesheets) for forms have been registered
*
* @since 3.0
* @deprecated 3.1.9
*
* @param string $suffix The suffix to add to the filename, before the file extension. Is usually set to ".min".
* @ignore
*/
do_action('mc4wp_register_form_assets', $suffix);
}
/**
* @param string $stylesheet
*
* @return bool
*/
public function is_registered_stylesheet($stylesheet)
{
$stylesheets = $this->get_registered_stylesheets();
return in_array($stylesheet, $stylesheets);
}
/**
* @return array
*/
public function get_registered_stylesheets()
{
return array(
'basic',
'themes'
);
}
/**
* @param string $stylesheet
*
* @return string
*/
public function get_stylesheet_url($stylesheet)
{
if (! $this->is_registered_stylesheet($stylesheet)) {
return '';
}
$suffix = $this->filename_suffix;
return MC4WP_PLUGIN_URL . 'assets/css/form-' . $stylesheet . $suffix . '.css';
}
/**
* Get array of stylesheet handles which should be enqueued.
*
* @return array
*/
public function get_active_stylesheets()
{
$stylesheets = (array) get_option('mc4wp_form_stylesheets', array());
/**
* Filters the stylesheets to be loaded
*
* Should be an array of stylesheet handles previously registered using `wp_register_style`.
* Each value is prefixed with `mc4wp-form-` to get the handle.
*
* Return an empty array if you want to disable the loading of all stylesheets.
*
* @since 3.0
* @param array $stylesheets Array of valid stylesheet handles
*/
$stylesheets = (array) apply_filters('mc4wp_form_stylesheets', $stylesheets);
return $stylesheets;
}
/**
* Load the various stylesheets
*/
public function load_stylesheets()
{
$stylesheets = $this->get_active_stylesheets();
foreach ($stylesheets as $stylesheet) {
if (! $this->is_registered_stylesheet($stylesheet)) {
continue;
}
$handle = 'mc4wp-form-' . $stylesheet;
wp_enqueue_style($handle, $this->get_stylesheet_url($stylesheet), array(), MC4WP_VERSION);
add_editor_style($this->get_stylesheet_url($stylesheet));
}
/**
* @ignore
*/
do_action('mc4wp_load_form_stylesheets', $stylesheets);
return true;
}
/**
* Get configuration object for client-side use.
*
* @return array
*/
public function get_javascript_config()
{
$submitted_form = mc4wp_get_submitted_form();
if (! $submitted_form instanceof MC4WP_Form) {
return array();
}
$config = array(
'submitted_form' => array(
'id' => $submitted_form->ID,
'event' => $submitted_form->last_event,
'data' => $submitted_form->get_data(),
'element_id' => $submitted_form->config['element_id'],
)
);
if ($submitted_form->has_errors()) {
$config['submitted_form']['errors'] = $submitted_form->errors;
}
$auto_scroll = true;
/**
* Filters the `auto_scroll` setting for when a form is submitted.
* Set to false to disable scrolling to form.
*
* @param boolean $auto_scroll
* @since 3.0
*/
$config['auto_scroll'] = apply_filters('mc4wp_form_auto_scroll', $auto_scroll);
return $config;
}
/**
* Load JavaScript files
*/
public function before_output_form()
{
// print dummy JS
$this->print_dummy_javascript();
// set flags
$this->load_scripts = true;
}
/**
* Prints dummy JavaScript which allows people to call `mc4wp.forms.on()` before the JS is loaded.
*/
public function print_dummy_javascript()
{
$file = dirname(__FILE__) . '/views/js/dummy-api.js';
echo '<script>';
include $file;
echo '</script>';
}
/**
* Outputs the inline JavaScript that is used to enhance forms
*/
public function load_scripts()
{
$load_scripts = $this->load_scripts;
/** @ignore */
$load_scripts = apply_filters('mc4wp_load_form_scripts', $load_scripts);
if (! $load_scripts) {
return;
}
global $wp_scripts;
// make sure scripts are loaded
wp_enqueue_script('mc4wp-forms-api');
wp_localize_script('mc4wp-forms-api', 'mc4wp_forms_config', $this->get_javascript_config());
// load placeholder polyfill if browser is Internet Explorer
wp_enqueue_script('mc4wp-forms-placeholders', MC4WP_PLUGIN_URL . 'assets/js/third-party/placeholders.min.js', array(), MC4WP_VERSION, true);
$wp_scripts->add_data('mc4wp-forms-placeholders', 'conditional', 'lte IE 9');
// print inline scripts depending on printed fields
echo '<script>';
echo '(function() {';
include dirname(__FILE__) . '/views/js/general-form-enhancements.js';
include dirname(__FILE__) . '/views/js/url-fields.js';
include dirname(__FILE__) . '/views/js/date-fields.js';
echo '})();';
echo '</script>';
/** @ignore */
do_action('mc4wp_load_form_scripts');
}
}
@@ -0,0 +1,376 @@
<?php
/**
* Class MC4WP_Form_Element
*
* @since 3.0
* @ignore
* @access private
*/
class MC4WP_Form_Element
{
/**
* @var string
*/
public $ID;
/**
* @var MC4WP_Form
*/
public $form;
/**
* @var array
*
* Can be used to set element-specific config settings. Accepts the following keys.
*
* - lists: Customized number of Mailchimp list ID's to subscribe to.
* - email_type: The email type
*/
public $config = array();
/**
* @var bool
*/
public $is_submitted = false;
/**
* @param MC4WP_Form $form
* @param string $ID
* @param $config array
*/
public function __construct(MC4WP_Form $form, $ID, $config = array())
{
$this->form = $form;
$this->ID = $ID;
$this->config = $config;
$this->is_submitted = $this->form->is_submitted
&& $this->form->config['element_id'] == $this->ID;
}
/**
* @return string
*/
protected function get_visible_fields()
{
$content = $this->form->content;
$form = $this->form;
$element = $this;
/**
* Filters the HTML for the form fields.
*
* Use this filter to add custom HTML to a form programmatically
*
* @param string $content
* @param MC4WP_Form $form
* @param MC4WP_Form_Element $element
* @since 2.0
*/
$visible_fields = (string) apply_filters('mc4wp_form_content', $content, $form, $element);
return $visible_fields;
}
/**
* @return string
*/
protected function get_hidden_fields()
{
// hidden fields
$hidden_fields = '<label style="display: none !important;">' . __('Leave this field empty if you\'re human:', 'mailchimp-for-wp') . ' ' . '<input type="text" name="_mc4wp_honeypot" value="" tabindex="-1" autocomplete="off" /></label>';
$hidden_fields .= '<input type="hidden" name="_mc4wp_timestamp" value="'. time() . '" />';
$hidden_fields .= '<input type="hidden" name="_mc4wp_form_id" value="'. esc_attr($this->form->ID) .'" />';
$hidden_fields .= '<input type="hidden" name="_mc4wp_form_element_id" value="'. esc_attr($this->ID) .'" />';
// was "lists" parameter passed in shortcode arguments?
if (! empty($this->config['lists'])) {
$lists_string = is_array($this->config['lists']) ? join(',', $this->config['lists']) : $this->config['lists'];
$hidden_fields .= '<input type="hidden" name="_mc4wp_lists" value="'. esc_attr($lists_string) . '" />';
}
// was "lists" parameter passed in shortcode arguments?
if (! empty($this->config['email_type'])) {
$hidden_fields .= '<input type="hidden" name="_mc4wp_email_type" value="'. esc_attr($this->config['email_type']) . '" />';
}
return (string) $hidden_fields;
}
/**
* Get HTML string for a notice, including wrapper element.
*
* @param MC4WP_Form_Notice $notice
*
* @return string
*/
protected function get_notice_html(MC4WP_Form_Notice $notice)
{
if ($notice->text === '') {
return '';
}
$html = sprintf('<div class="mc4wp-alert mc4wp-%s"><p>%s</p></div>', esc_attr($notice->type), $notice->text);
return $html;
}
/**
* Gets the form response string
*
* @param boolean $force_show
* @return string
*/
public function get_response_html($force_show = false)
{
$html = '';
$form = $this->form;
if ($this->is_submitted || $force_show) {
foreach ($this->form->notices as $notice) {
$html .= $this->get_notice_html($notice);
}
}
/**
* Filter the form response HTML
*
* Use this to add your own HTML to the form response. The form instance is passed to the callback function.
*
* @since 3.0
*
* @param string $html The complete HTML string of the response, excluding the wrapper element.
* @param MC4WP_Form $form The form object
*/
$html = (string) apply_filters('mc4wp_form_response_html', $html, $form);
// wrap entire response in div, regardless of a form was submitted
$html = '<div class="mc4wp-response">' . $html . '</div>';
return $html;
}
/**
* @return string
*/
protected function get_response_position()
{
$position = 'after';
$form = $this->form;
// check if content contains {response} tag
if (stripos($this->form->content, '{response}') !== false) {
return '';
}
/**
* Filters the position for the form response.
*
* Valid values are "before" and "after". Will have no effect if `{response}` is used in the form content.
*
* @param string $position
* @param MC4WP_Form $form
* @since 2.0
*/
$response_position = (string) apply_filters('mc4wp_form_response_position', $position, $form);
return $response_position;
}
/**
* Get HTML to be added _before_ the HTML of the form fields.
*
* @return string
*/
protected function get_html_before_fields()
{
$html = '';
$form = $this->form;
/**
* Filters the HTML before the form fields.
*
* @param string $html
* @param MC4WP_Form $form
* @ignore
*/
$html = (string) apply_filters('mc4wp_form_before_fields', $html, $form);
if ($this->get_response_position() === 'before') {
$html = $html . $this->get_response_html();
}
return $html;
}
/**
* Get HTML to be added _after_ the HTML of the form fields.
*
* @return string
*/
protected function get_html_after_fields()
{
$html = '';
$form = $this->form;
/**
* Filters the HTML after the form fields.
*
* @param string $html
* @param MC4WP_Form $form
* @ignore
*/
$html = (string) apply_filters('mc4wp_form_after_fields', $html, $form);
if ($this->get_response_position() === 'after') {
$html = $this->get_response_html() . $html;
}
return $html;
}
/**
* Get all HTMl attributes for the form element
*
* @return string
*/
protected function get_form_element_attributes()
{
$form = $this;
$form_action_attribute = null;
$attributes = array(
'id' => $this->ID,
'class' => $this->get_css_classes()
);
/**
* Filters the `action` attribute of the `<form>` element.
*
* Defaults to `null`, which means no `action` attribute will be printed.
*
* @param string $form_action_attribute
* @param MC4WP_Form $form
*/
$form_action_attribute = apply_filters('mc4wp_form_action', $form_action_attribute, $form);
if (is_string($form_action_attribute)) {
$attributes['action'] = $form_action_attribute;
}
/**
* Filters all attributes to be added to the `<form>` element
*
* @param array $attributes Key-value pairs of attributes.
* @param MC4WP_Form $form
*/
$attributes = (array) apply_filters('mc4wp_form_element_attributes', $attributes, $form);
// hardcoded attributes, can not be changed.
$attributes['method'] = 'post';
$attributes['data-id'] = $this->form->ID;
$attributes['data-name'] = $this->form->name;
// build string of key="value" from array
$string = '';
foreach ($attributes as $name => $value) {
$string .= sprintf('%s="%s" ', $name, esc_attr($value));
}
return $string;
}
/**
* @param array|null $config Use this to override the configuration for this form element
* @return string
*/
public function generate_html(array $config = null)
{
if ($config) {
$this->config = $config;
}
// return empty string if form is in trash
if ($this->form->status !== 'publish') {
return '';
}
// Start building content string
$opening_html = '<!-- Mailchimp for WordPress v' . MC4WP_VERSION . ' - https://wordpress.org/plugins/mailchimp-for-wp/ -->';
$opening_html .= '<form '. $this->get_form_element_attributes() .'>';
$before_fields = $this->get_html_before_fields();
$fields = '';
$after_fields = $this->get_html_after_fields();
$closing_html = '</form><!-- / Mailchimp for WordPress Plugin -->';
if (! $this->is_submitted
|| ! $this->form->settings['hide_after_success']
|| $this->form->has_errors()) {
// add HTML for fields + wrapper element.
$fields = '<div class="mc4wp-form-fields">' .
$this->get_visible_fields() .
'</div>' .
$this->get_hidden_fields();
}
// concatenate everything
$output = $opening_html .
$before_fields .
$fields .
$after_fields .
$closing_html;
return $output;
}
/**
* Get a space separated list of CSS classes for this form
*
* @return string
*/
protected function get_css_classes()
{
$classes = array();
$form = $this->form;
$classes[] = 'mc4wp-form';
$classes[] = 'mc4wp-form-' . $form->ID;
// Add form classes if this specific form element was submitted
if ($this->is_submitted) {
$classes[] = 'mc4wp-form-submitted';
if (! $form->has_errors()) {
$classes[] = 'mc4wp-form-success';
} else {
$classes[] = 'mc4wp-form-error';
}
}
// add class for CSS targeting in custom stylesheets
if (! empty($form->settings['css'])) {
if (strpos($form->settings['css'], 'theme-') === 0) {
$classes[] = 'mc4wp-form-theme';
}
$classes[] = 'mc4wp-form-' . $form->settings['css'];
}
// add classes from config array
if (! empty($this->config['element_class'])) {
$classes = array_merge($classes, explode(' ', $this->config['element_class']));
}
/**
* Filters `class` attributes for the `<form>` element.
*
* @param array $classes
* @param MC4WP_Form $form
*/
$classes = apply_filters('mc4wp_form_css_classes', $classes, $form);
return implode(' ', $classes);
}
}
@@ -0,0 +1,327 @@
<?php
/**
* Class MC4WP_Form_Listener
*
* @since 3.0
* @access private
*/
class MC4WP_Form_Listener
{
/**
* @var MC4WP_Form The submitted form instance
*/
public $submitted_form;
public function add_hooks()
{
add_action('init', array( $this, 'listen' ));
}
/**
* Listen for submitted forms
* @return bool
*/
public function listen()
{
if (empty($_POST['_mc4wp_form_id'])) {
return false;
}
// get form instance
try {
$form_id = (int) $_POST['_mc4wp_form_id'];
$form = mc4wp_get_form($form_id);
} catch (Exception $e) {
return false;
}
// sanitize request data
$request_data = $_POST;
$request_data = mc4wp_sanitize_deep($request_data);
$request_data = stripslashes_deep($request_data);
// bind request to form & validate
$form->handle_request($request_data);
$form->validate();
// store submitted form
$this->submitted_form = $form;
// did form have errors?
if (! $form->has_errors()) {
switch ($form->get_action()) {
case "subscribe":
$this->process_subscribe_form($form);
break;
case "unsubscribe":
$this->process_unsubscribe_form($form);
break;
}
} else {
foreach ($form->errors as $error_code) {
$form->add_notice($form->get_message($error_code), 'error');
}
$this->get_log()->info(sprintf("Form %d > Submitted with errors: %s", $form->ID, join(', ', $form->errors)));
}
$this->respond($form);
return true;
}
/**
* Process a subscribe form.
*
* @param MC4WP_Form $form
*/
public function process_subscribe_form(MC4WP_Form $form)
{
$result = false;
$mailchimp = new MC4WP_MailChimp();
$email_type = $form->get_email_type();
$data = $form->get_data();
$ip_address = mc4wp_get_request_ip_address();
/** @var MC4WP_MailChimp_Subscriber $subscriber */
$subscriber = null;
/**
* @ignore
* @deprecated 4.0
*/
$data = apply_filters('mc4wp_merge_vars', $data);
/**
* @ignore
* @deprecated 4.0
*/
$data = (array) apply_filters('mc4wp_form_merge_vars', $data, $form);
// create a map of all lists with list-specific data
$mapper = new MC4WP_List_Data_Mapper($data, $form->get_lists());
/** @var MC4WP_MailChimp_Subscriber[] $map */
$map = $mapper->map();
// loop through lists
foreach ($map as $list_id => $subscriber) {
$subscriber->status = $form->settings['double_optin'] ? 'pending' : 'subscribed';
$subscriber->email_type = $email_type;
$subscriber->ip_signup = $ip_address;
$subscriber->tags = $form->get_subscriber_tags();
/**
* Filters subscriber data before it is sent to Mailchimp. Fires for both form & integration requests.
*
* @param MC4WP_MailChimp_Subscriber $subscriber
*/
$subscriber = apply_filters('mc4wp_subscriber_data', $subscriber);
/**
* Filters subscriber data before it is sent to Mailchimp. Only fires for form requests.
*
* @param MC4WP_MailChimp_Subscriber $subscriber
*/
$subscriber = apply_filters('mc4wp_form_subscriber_data', $subscriber);
// send a subscribe request to Mailchimp for each list
$result = $mailchimp->list_subscribe($list_id, $subscriber->email_address, $subscriber->to_array(), $form->settings['update_existing'], $form->settings['replace_interests']);
}
$log = $this->get_log();
// do stuff on failure
if (! is_object($result) || empty($result->id)) {
$error_code = $mailchimp->get_error_code();
$error_message = $mailchimp->get_error_message();
if ($mailchimp->get_error_code() == 214) {
$form->add_error('already_subscribed');
$form->add_notice($form->messages['already_subscribed'], 'notice');
$log->warning(sprintf("Form %d > %s is already subscribed to the selected list(s)", $form->ID, $data['EMAIL']));
} else {
$form->add_error($error_code);
$form->add_notice($form->messages['error'], 'error');
$log->error(sprintf('Form %d > Mailchimp API error: %s %s', $form->ID, $error_code, $error_message));
/**
* Fire action hook so API errors can be hooked into.
*
* @param MC4WP_Form $form
* @param string $error_message
*/
do_action('mc4wp_form_api_error', $form, $error_message);
}
// bail
return;
}
// Success! Did we update or newly subscribe?
if ($result->status === 'subscribed' && $result->was_already_on_list) {
$form->last_event = 'updated_subscriber';
$form->add_notice($form->messages['updated'], 'success');
$log->info(sprintf("Form %d > Successfully updated %s", $form->ID, $data['EMAIL']));
/**
* Fires right after a form was used to update an existing subscriber.
*
* @since 3.0
*
* @param MC4WP_Form $form Instance of the submitted form
* @param string $email
* @param array $data
*/
do_action('mc4wp_form_updated_subscriber', $form, $subscriber->email_address, $data);
} else {
$form->last_event = 'subscribed';
$form->add_notice($form->messages['subscribed'], 'success');
$log->info(sprintf("Form %d > Successfully subscribed %s", $form->ID, $data['EMAIL']));
}
/**
* Fires right after a form was used to add a new subscriber (or update an existing one).
*
* @since 3.0
*
* @param MC4WP_Form $form Instance of the submitted form
* @param string $email
* @param array $data
* @param MC4WP_MailChimp_Subscriber[] $subscriber
*/
do_action('mc4wp_form_subscribed', $form, $subscriber->email_address, $data, $map);
}
/**
* @param MC4WP_Form $form
*/
public function process_unsubscribe_form(MC4WP_Form $form)
{
$mailchimp = new MC4WP_MailChimp();
$log = $this->get_log();
$result = null;
$data = $form->get_data();
// unsubscribe from each list
foreach ($form->get_lists() as $list_id) {
$result = $mailchimp->list_unsubscribe($list_id, $data['EMAIL']);
}
if (! $result) {
$form->add_notice($form->messages['error'], 'error');
$log->error(sprintf('Form %d > Mailchimp API error: %s', $form->ID, $mailchimp->get_error_message()));
// bail
return;
}
// Success! Unsubscribed.
$form->last_event = 'unsubscribed';
$form->add_notice($form->messages['unsubscribed'], 'notice');
$log->info(sprintf("Form %d > Successfully unsubscribed %s", $form->ID, $data['EMAIL']));
/**
* Fires right after a form was used to unsubscribe.
*
* @since 3.0
*
* @param MC4WP_Form $form Instance of the submitted form.
* @param string $email
*/
do_action('mc4wp_form_unsubscribed', $form, $data['EMAIL']);
}
/**
* @param MC4WP_Form $form
*/
public function respond(MC4WP_Form $form)
{
$success = ! $form->has_errors();
if ($success) {
/**
* Fires right after a form is submitted without any errors (success).
*
* @since 3.0
*
* @param MC4WP_Form $form Instance of the submitted form
*/
do_action('mc4wp_form_success', $form);
} else {
/**
* Fires right after a form is submitted with errors.
*
* @since 3.0
*
* @param MC4WP_Form $form The submitted form instance.
*/
do_action('mc4wp_form_error', $form);
// fire a dedicated event for each error
foreach ($form->errors as $error) {
/**
* Fires right after a form was submitted with errors.
*
* The dynamic portion of the hook, `$error`, refers to the error that occurred.
*
* Default errors give us the following possible hooks:
*
* - mc4wp_form_error_error General errors
* - mc4wp_form_error_spam
* - mc4wp_form_error_invalid_email Invalid email address
* - mc4wp_form_error_already_subscribed Email is already on selected list(s)
* - mc4wp_form_error_required_field_missing One or more required fields are missing
* - mc4wp_form_error_no_lists_selected No Mailchimp lists were selected
*
* @since 3.0
*
* @param MC4WP_Form $form The form instance of the submitted form.
*/
do_action('mc4wp_form_error_' . $error, $form);
}
}
/**
* Fires right before responding to the form request.
*
* @since 3.0
*
* @param MC4WP_Form $form Instance of the submitted form.
*/
do_action('mc4wp_form_respond', $form);
// do stuff on success (non-AJAX only)
if ($success && (! defined('DOING_AJAX') || ! DOING_AJAX)) {
// do we want to redirect?
$redirect_url = $form->get_redirect_url();
if (! empty($redirect_url)) {
wp_redirect($redirect_url);
exit;
}
}
}
/**
* @return MC4WP_API_v3
*/
protected function get_api()
{
return mc4wp('api');
}
/**
* @return MC4WP_Debug_Log
*/
protected function get_log()
{
return mc4wp('log');
}
}
@@ -0,0 +1,158 @@
<?php
/**
* This class takes care of all form related functionality
*
* Do not interact with this class directly, use `mc4wp_form` functions tagged with @access public instead.
*
* @class MC4WP_Form_Manager
* @ignore
* @access private
*/
class MC4WP_Form_Manager
{
/**
* @var MC4WP_Form_Output_Manager
*/
protected $output_manager;
/**
* @var MC4WP_Form_Listener
*/
protected $listener;
/**
* @var MC4WP_Form_Tags
*/
protected $tags;
/**
* @var MC4WP_Form_Previewer
*/
protected $previewer;
protected $recaptcha;
/**
* Constructor
*/
public function __construct()
{
$this->output_manager = new MC4WP_Form_Output_Manager();
$this->tags = new MC4WP_Form_Tags();
$this->listener = new MC4WP_Form_Listener();
$this->previewer = new MC4WP_Form_Previewer();
$this->recaptcha = new MC4WP_Google_Recaptcha();
}
/**
* Hook!
*/
public function add_hooks()
{
add_action('init', array( $this, 'initialize' ));
add_action('wp', array( $this, 'init_asset_manager' ), 90);
add_action('widgets_init', array( $this, 'register_widget' ));
$this->listener->add_hooks();
$this->output_manager->add_hooks();
$this->tags->add_hooks();
$this->previewer->add_hooks();
$this->recaptcha->add_hooks();
}
/**
* Initialize
*/
public function initialize()
{
$this->register_post_type();
$this->register_block_type();
}
private function register_block_type()
{
// Bail if register_block_type does not exist (available since WP 5.0)
if (! function_exists('register_block_type')) {
return;
}
register_block_type( 'mailchimp-for-wp/form', array(
'render_callback' => array($this->output_manager, 'shortcode'),
));
}
/**
* Register post type "mc4wp-form"
*/
private function register_post_type()
{
// register post type
register_post_type(
'mc4wp-form',
array(
'labels' => array(
'name' => 'Mailchimp Sign-up Forms',
'singular_name' => 'Sign-up Form',
),
'public' => false
)
);
}
/**
* Initialise asset manager
*
* @hooked `template_redirect`
*/
public function init_asset_manager()
{
$assets = new MC4WP_Form_Asset_Manager();
$assets->hook();
}
/**
* Register our Form widget
*/
public function register_widget()
{
register_widget('MC4WP_Form_Widget');
}
/**
* @param $form_id
* @param array $config
* @param bool $echo
*
* @return string
*/
public function output_form($form_id, $config = array(), $echo = true)
{
return $this->output_manager->output_form($form_id, $config, $echo);
}
/**
* Gets the currently submitted form
*
* @return MC4WP_Form|null
*/
public function get_submitted_form()
{
if ($this->listener->submitted_form instanceof MC4WP_Form) {
return $this->listener->submitted_form;
}
return null;
}
/**
* Return all tags
*
* @return array
*/
public function get_tags()
{
return $this->tags->get();
}
}
@@ -0,0 +1,42 @@
<?php
/**
* Class MC4WP_Form_Notice
*
* @ignore
* @access private
*/
class MC4WP_Form_Notice
{
/**
* @var string
*/
public $type = 'error';
/**
* @var string
*/
public $text;
/**
* @param string $text
* @param string $type
*/
public function __construct($text, $type = 'error')
{
$this->text = $text;
if (! empty($type)) {
$this->type = $type;
}
}
/**
* @return string
*/
public function __toString()
{
return $this->text;
}
}
@@ -0,0 +1,40 @@
<?php
class MC4WP_Form_Previewer
{
public function add_hooks()
{
add_action('parse_request', array( $this, 'listen' ));
}
public function listen()
{
if (empty($_GET['mc4wp_preview_form'])) {
return;
}
try {
$form = mc4wp_get_form($_GET['mc4wp_preview_form']);
} catch (Exception $e) {
return;
}
show_admin_bar(false);
add_filter('pre_handle_404', '__return_true');
remove_all_actions('template_redirect');
add_action('template_redirect', array( $this, 'load_preview' ));
}
public function load_preview()
{
// clear output, some plugin or hooked code might have thrown errors by now.
if (ob_get_level() > 0) {
ob_end_clean();
}
$form_id = (int) $_GET['mc4wp_preview_form'];
status_header(200);
require dirname(__FILE__) . '/views/preview.php';
exit;
}
}
@@ -0,0 +1,305 @@
<?php
/**
* Class MC4WP_Form_Tags
*
* @access private
* @ignore
*/
class MC4WP_Form_Tags
{
/**
* @var MC4WP_Dynamic_Content_Tags
*/
protected $tags;
/**
* @var MC4WP_Form
*/
protected $form;
/**
* @var MC4WP_Form_Element
*/
protected $form_element;
/**
* Constructor
*/
public function __construct()
{
$this->tags = new MC4WP_Dynamic_Content_Tags('form');
}
public function add_hooks()
{
add_filter('mc4wp_dynamic_content_tags_form', array( $this, 'register' ));
add_filter('mc4wp_form_response_html', array( $this, 'replace' ), 10, 2);
add_filter('mc4wp_form_content', array( $this, 'replace' ), 10, 3);
add_filter('mc4wp_form_redirect_url', array( $this, 'replace_in_url' ), 10, 2);
}
/**
* @return array
*/
public function get()
{
return $this->tags->all();
}
/**
* @param array $tags
* @return array
*/
public function register(array $tags)
{
$tags['response'] = array(
'description' => __('Replaced with the form response (error or success messages).', 'mailchimp-for-wp'),
'callback' => array( $this, 'get_form_response' )
);
$tags['data'] = array(
'description' => sprintf(__("Data from the URL or a submitted form.", 'mailchimp-for-wp')),
'callback' => array( $this, 'get_data' ),
'example' => "data key='UTM_SOURCE' default='Default Source'"
);
$tags['cookie'] = array(
'description' => sprintf(__("Data from a cookie.", 'mailchimp-for-wp')),
'callback' => array( $this, 'get_cookie' ),
'example' => "cookie name='my_cookie' default='Default Value'"
);
$tags['subscriber_count'] = array(
'description' => __('Replaced with the number of subscribers on the selected list(s)', 'mailchimp-for-wp'),
'callback' => array( $this, 'get_subscriber_count' )
);
$tags['email'] = array(
'description' => __('The email address of the current visitor (if known).', 'mailchimp-for-wp'),
'callback' => array( $this, 'get_email' ),
);
$tags['current_url'] = array(
'description' => __('The URL of the page.', 'mailchimp-for-wp'),
'callback' => 'mc4wp_get_request_url',
);
$tags['current_path'] = array(
'description' => __('The path of the page.', 'mailchimp-for-wp'),
'callback' => 'mc4wp_get_request_path',
);
$tags['date'] = array(
'description' => sprintf(__('The current date. Example: %s.', 'mailchimp-for-wp'), '<strong>' . date('Y/m/d') . '</strong>'),
'replacement' => date('Y/m/d')
);
$tags['time'] = array(
'description' => sprintf(__('The current time. Example: %s.', 'mailchimp-for-wp'), '<strong>' . date('H:i:s') . '</strong>'),
'replacement' => date('H:i:s')
);
$tags['language'] = array(
'description' => sprintf(__('The site\'s language. Example: %s.', 'mailchimp-for-wp'), '<strong>' . get_locale() . '</strong>'),
'callback' => 'get_locale',
);
$tags['ip'] = array(
'description' => sprintf(__('The visitor\'s IP address. Example: %s.', 'mailchimp-for-wp'), '<strong>' . mc4wp('request')->get_client_ip() . '</strong>'),
'callback' => 'mc4wp_get_request_ip_address',
);
$tags['user'] = array(
'description' => sprintf(__("The property of the currently logged-in user.", 'mailchimp-for-wp')),
'callback' => array( $this, 'get_user_property' ),
'example' => "user property='user_email'"
);
$tags['post'] = array(
'description' => sprintf(__("Property of the current page or post.", 'mailchimp-for-wp')),
'callback' => array( $this, 'get_post_property' ),
'example' => "post property='ID'"
);
return $tags;
}
/**
* Replaces the registered tags in the given string
*
* @hooked `mc4wp_form_message_html`
* @hooked `mc4wp_form_content`
*
* @param string $string
* @param MC4WP_Form $form
* @param MC4WP_Form_Element $element
*
* @return string
*/
public function replace($string, MC4WP_Form $form, MC4WP_Form_Element $element = null)
{
$this->form = $form;
$this->form_element = $element;
$string = $this->tags->replace($string);
return $string;
}
/**
* @hooked `mc4wp_form_redirect_url`
*
* @param $string
* @param MC4WP_Form $form
*
* @return string
*/
public function replace_in_url($string, MC4WP_Form $form)
{
$this->form = $form;
$string = $this->tags->replace_in_url($string);
return $string;
}
/**
* Returns the number of subscribers on the selected lists (for the form context)
*
* @return int
*/
public function get_subscriber_count()
{
$mailchimp = new MC4WP_MailChimp();
$count = $mailchimp->get_subscriber_count($this->form->get_lists());
return number_format($count);
}
/**
* Returns the form response
*
* @return string
*/
public function get_form_response()
{
if ($this->form_element instanceof MC4WP_Form_Element) {
return $this->form_element->get_response_html();
}
return '';
}
/**
* Gets data value from GET or POST variables.
*
* @param $args
*
* @return string
*/
public function get_data($args = array())
{
if (empty($args['key'])) {
return '';
}
$default = isset($args['default']) ? $args['default'] : '';
$key = $args['key'];
$data = array_merge($_GET, $_POST);
$value = isset($data[$key]) ? $data[$key] : $default;
// turn array into readable value
if (is_array($value)) {
$value = array_filter($value);
$value = join(', ', $value);
}
return esc_html($value);
}
/**
* Gets data variable from cookie.
*
* @param array $args
*
* @return string
*/
public function get_cookie($args = array())
{
if (empty($args['name'])) {
return '';
}
$name = $args['name'];
$default = isset($args['default']) ? $args['default'] : '';
if (isset($_COOKIE[ $name ])) {
return esc_html(stripslashes($_COOKIE[ $name ]));
}
return $default;
}
/*
* Get property of currently logged-in user
*
* @param array $args
*
* @return string
*/
public function get_user_property($args = array())
{
$property = empty($args['property']) ? 'user_email' : $args['property'];
$default = isset($args['default']) ? $args['default'] : '';
$user = wp_get_current_user();
if ($user instanceof WP_User && isset($user->{$property})) {
return esc_html($user->{$property});
}
return $default;
}
/*
* Get property of viewed post
*
* @param array $args
*
* @return string
*/
public function get_post_property($args = array())
{
global $post;
$property = empty($args['property']) ? 'ID' : $args['property'];
$default = isset($args['default']) ? $args['default'] : '';
if ($post instanceof WP_Post && isset($post->{$property})) {
return $post->{$property};
}
return $default;
}
/**
* @return string
*/
public function get_email()
{
// first, try request
$request = mc4wp('request');
$email = $request->params->get('EMAIL', '');
if ($email) {
return $email;
}
// then , try logged-in user
if (is_user_logged_in()) {
$user = wp_get_current_user();
return $user->user_email;
}
// TODO: Read from cookie? Or add $_COOKIE support to {data} tag?
return '';
}
}
@@ -0,0 +1,794 @@
<?php
/**
* Class MC4WP_Form
*
* Represents a Form object.
*
* To get a form instance, use `mc4wp_get_form( $id );` where `$id` is the post ID.
*
* @access public
* @since 3.0
*/
class MC4WP_Form
{
/**
* @var array Array of instantiated form objects.
*/
public static $instances = array();
/**
* Get a shared form instance.
*
* @param WP_Post|int $post Post instance or post ID.
* @return MC4WP_Form
* @throws Exception
*/
public static function get_instance($post = 0)
{
if ($post instanceof WP_Post) {
$post_id = $post->ID;
} else {
$post_id = (int) $post;
if (empty($post_id)) {
$post_id = (int) get_option('mc4wp_default_form_id', 0);
}
}
if (isset(self::$instances[ $post_id ])) {
return self::$instances[ $post_id ];
}
// get post object if we don't have it by now
if (! $post instanceof WP_Post) {
$post = get_post($post_id);
}
// check post object
if (! is_object($post) || ! isset($post->post_type) || $post->post_type !== 'mc4wp-form') {
$message = sprintf(__('There is no form with ID %d, perhaps it was deleted?', 'mailchimp-for-wp'), $post_id);
throw new Exception($message);
}
$post_meta = get_post_meta($post_id);
$form = new MC4WP_Form($post_id, $post, $post_meta);
// store instance
self::$instances[ $post_id ] = $form;
return $form;
}
/**
* @var int The form ID, matches the underlying post its ID
*/
public $ID = 0;
/**
* @var string The form name
*/
public $name = 'Default Form';
/**
* @var string The form HTML content
*/
public $content = '';
/**
* @var array Array of settings
*/
public $settings = array();
/**
* @var array Array of messages
*/
public $messages = array();
/**
* @var array Array of notices to be shown when this form is rendered
*/
public $notices = array();
/**
* @var array Array of error codes
*/
public $errors = array();
/**
* @var bool Was this form submitted?
*/
public $is_submitted = false;
/**
* @var array Array of the data that was submitted, in name => value pairs.
*
* Keys in this array are uppercased and keys starting with _ are stripped.
*/
private $data = array();
/**
* @var array Array of the raw form data that was submitted.
*/
public $raw_data = array();
/**
* @var array
*/
public $config = array(
'action' => 'subscribe',
'lists' => array(),
'email_type' => '',
'element_id' => ''
);
/**
* @var string
*/
public $last_event = '';
/**
* @var string
*/
public $status;
/**
* @param int $id The post ID
* @param WP_Post $post
* @param array $post_meta
*/
public function __construct($id, $post, $post_meta = array())
{
$this->ID = $id = (int) $id;
$this->name = $post->post_title;
$this->content = $post->post_content;
$this->status = $post->post_status;
$this->settings = $this->load_settings($post_meta);
$this->messages = $this->load_messages($post_meta);
// update config from settings
$this->config['lists'] = $this->settings['lists'];
}
/**
* @param string $name
*
* @return mixed
*/
public function __get($name)
{
$method_name = sprintf("get_%s", $name);
if (method_exists($this, $method_name)) {
return $this->$method_name();
}
}
/**
* Gets the form response string
*
* This does not take the submitted form element into account.
*
* @see MC4WP_Form_Element::get_response_html()
*
* @return string
*/
public function get_response_html()
{
return $this->get_element()->get_response_html(true);
}
/**
* @param string $element_id
* @param array $config
* @return MC4WP_Form_element
*/
public function get_element($element_id = 'mc4wp-form', $config = array())
{
return new MC4WP_Form_Element($this, $element_id, $config);
}
/**
* Get HTML string for this form.
*
* If you want to output a form, use `mc4wp_show_form` instead as it.
*
* @param string $element_id
* @param array $config
*
* @return string
*/
public function get_html($element_id = 'mc4wp-form', array $config = array())
{
$element = $this->get_element($element_id, $config);
$html = $element->generate_html();
return $html;
}
/**
* @staticvar $defaults
* @return array
*/
protected function load_settings($post_meta = array())
{
$form = $this;
static $default_settings;
// get default settings
if (! $default_settings) {
$default_settings = include MC4WP_PLUGIN_DIR . 'config/default-form-settings.php';
}
// start with defaults
$settings = $default_settings;
// get custom settings from meta
if (! empty($post_meta['_mc4wp_settings'])) {
$meta = $post_meta['_mc4wp_settings'][0];
$meta = (array) maybe_unserialize($meta);
// ensure lists is an array
if (empty($meta['lists'])) {
$meta['lists'] = array();
}
// merge with current settings (defaults)
$settings = array_merge($settings, $meta);
}
/**
* Filters the form settings
*
* @since 3.0
*
* @param array $settings
* @param MC4WP_Form $form
*/
$settings = (array) apply_filters('mc4wp_form_settings', $settings, $form);
return $settings;
}
/**
* @staticvar $default_messages
* @return array
*/
protected function load_messages($post_meta = array())
{
$form = $this;
// get default messages
$default_messages = include MC4WP_PLUGIN_DIR . 'config/default-form-messages.php';
// start with default messages
$messages = $default_messages;
/**
* Filters the form messages
*
* @since 3.0
*
* @param array $registered_messages
* @param MC4WP_Form $form
*/
$messages = (array) apply_filters('mc4wp_form_messages', $messages, $form);
// for backwards compatiblity, grab text of each message (if is array)
foreach ($messages as $key => $message) {
if (is_array($message) && isset($message['text'])) {
$messages[$key] = $message['text'];
}
}
foreach ($messages as $key => $message_text) {
// overwrite default text with text in form meta.
if (isset($post_meta[ 'text_' . $key ][0])) {
$message_text = $post_meta[ 'text_' . $key ][0];
}
$messages[$key] = $message_text;
}
return $messages;
}
/**
* Does this form has a field of the given type?
*
* @param $type
*
* @return bool
*/
public function has_field_type($type)
{
return in_array(strtolower($type), $this->get_field_types());
}
/**
* Get an array of field types which are present in this form.
*
* @return array
*/
public function get_field_types()
{
preg_match_all('/type=\"(\w+)?\"/', strtolower($this->content), $result);
$field_types = $result[1];
return $field_types;
}
/**
* Add notice to this form when it is rendered
* @param string $text
* @param string $type
*/
public function add_notice($text, $type = 'notice')
{
$this->notices[] = new MC4WP_Form_Notice($text, $type);
}
/**
* Output this form
*
* @return string
*/
public function __toString()
{
return mc4wp_show_form($this->ID, array(), false);
}
/**
* Get "redirect to url after success" setting for this form
*
* @return string
*/
public function get_redirect_url()
{
$form = $this;
$url = trim($this->settings['redirect']);
/**
* Filters the redirect URL setting
*
* @since 3.0
*
* @param string $url
* @param MC4WP_Form $form
*/
$url = (string) apply_filters('mc4wp_form_redirect_url', $url, $form);
return $url;
}
/**
* Is this form valid?
*
* Will always return true if the form is not yet submitted. Otherwise, it will run validation and store any errors.
* This method should be called before `get_errors()`
*
* @return bool
*/
public function validate()
{
if (! $this->is_submitted) {
return true;
}
$form = $this;
$errors = array();
if (empty($this->config['lists'])) {
$errors[] = 'no_lists_selected';
}
if (! isset($this->raw_data['_mc4wp_timestamp']) || $this->raw_data['_mc4wp_timestamp'] > (time() - 2)) {
$errors[] = 'spam';
} elseif (! isset($this->raw_data['_mc4wp_honeypot']) || ! empty($this->raw_data['_mc4wp_honeypot'])) {
$errors[] = 'spam';
}
if (empty($errors)) {
// validate email field
if (empty($this->data['EMAIL']) || ! is_email($this->data['EMAIL'])) {
$errors[] = 'invalid_email';
}
// validate other required fields
foreach ($this->get_required_fields() as $field) {
$value = mc4wp_array_get($this->data, $field);
// check for empty string or array here instead of empty() since we want to allow for "0" values.
if ($value === "" || $value === array()) {
$errors[] = 'required_field_missing';
break;
}
}
}
/**
* Filters whether this form has errors. Runs only when a form is submitted.
* Expects an array of message keys with an error type (string).
*
* Beware: all non-string values added to this array will be filtered out.
*
* @since 3.0
*
* @param array $errors
* @param MC4WP_Form $form
*/
$errors = (array) apply_filters('mc4wp_form_errors', $errors, $form);
/**
* @ignore
* @deprecated 3.0 Use `mc4wp_form_errors` instead
*/
$form_validity = apply_filters('mc4wp_valid_form_request', true, $this->data);
if (is_string($form_validity)) {
$errors[] = $form_validity;
}
// filter out all non-string values
$errors = array_filter($errors, 'is_string');
// set property on self
$this->errors = $errors;
// return whether we have errors
return ! $this->has_errors();
}
/**
* Handle an incoming request. Should be called before calling validate() method.
*
* @see MC4WP_Form::validate
* @param array $data
* @return void
*/
public function handle_request(array $data)
{
$this->is_submitted = true;
$this->raw_data = $data;
$this->data = $this->parse_request_data($data);
$this->last_event = '';
// update form configuration from given data
$config = array();
$map = array(
'_mc4wp_lists' => 'lists',
'_mc4wp_action' => 'action',
'_mc4wp_form_element_id' => 'element_id',
'_mc4wp_email_type' => 'email_type'
);
// use isset here to allow empty lists (which should show a notice)
foreach ($map as $param_key => $config_key) {
if (isset($this->raw_data[ $param_key ])) {
$value = $this->raw_data[ $param_key ];
if (is_array($value)) {
$value = array_filter($value);
}
$config[ $config_key ] = $value;
}
}
if (! empty($config)) {
$this->set_config($config);
}
}
/**
* Parse a request for data which should be binded to `$data` property.
*
* This does the following on all post data.
*
* - Removes fields starting with an underscore.
* - Remove fields which are set to be ignored.
* - Uppercase all field names
*
* @param array $data
*
* @return array
*/
protected function parse_request_data(array $data)
{
$form = $this;
$filtered = array();
$ignored_field_names = array();
/**
* Filters field names which should be ignored when showing data.
*
* @since 3.0
*
* @param array $ignored_field_names Array of ignored field names
* @param MC4WP_Form $form The form instance.
*/
$ignored_field_names = apply_filters('mc4wp_form_ignored_field_names', $ignored_field_names, $form);
foreach ($data as $key => $value) {
// skip fields in ignored field names
if ($key[0] === '_' || in_array($key, $ignored_field_names)) {
continue;
}
// uppercase key
$key = strtoupper($key);
// filter empty array values
if (is_array($value)) {
$value = array_filter($value);
}
$filtered[$key] = $value;
}
return $filtered;
}
/**
* Update configuration for this form
*
* @param array $config
* @return array
*/
public function set_config(array $config)
{
$this->config = array_merge($this->config, $config);
// make sure lists is an array
if (! is_array($this->config['lists'])) {
$this->config['lists'] = array_map('trim', explode(',', $this->config['lists']));
}
// make sure action is valid
if (! in_array($this->config['action'], array( 'subscribe', 'unsubscribe' ))) {
$this->config['action'] = 'subscribe';
}
// email_type should be a valid value
if (! in_array($this->config['email_type'], array( 'html', 'text' ))) {
$this->config['email_type'] = '';
}
return $this->config;
}
/**
* Get Mailchimp lists this form subscribes to
*
* @return array
*/
public function get_lists()
{
$lists = $this->config['lists'];
$form = $this;
/**
* Filters Mailchimp lists new subscribers should be added to.
*
* @param array $lists
*/
$lists = (array) apply_filters('mc4wp_lists', $lists);
/**
* Filters Mailchimp lists new subscribers coming from this form should be added to.
*
* @param array $lists
* @param MC4WP_Form $form
*/
$lists = (array) apply_filters('mc4wp_form_lists', $lists, $form);
// filter out empty array elements
$lists = array_filter($lists);
return $lists;
}
/**
* Does this form have errors?
*
* Should always evaluate to false when form has not been submitted.
*
* @see `mc4wp_form_errors` filter.
* @return bool
*/
public function has_errors()
{
return count($this->errors) > 0;
}
/**
* Add an error to this form
*
* @param string $error_code
*/
public function add_error($error_code)
{
// only add each error once
if (! in_array($error_code, $this->errors)) {
$this->errors[] = $error_code;
}
}
/**
* Get the form action
*
* Valid return values are "subscribe" and "unsubscribe"
*
* @return string
*/
public function get_action()
{
return $this->config['action'];
}
/**
* @return array
*/
public function get_data()
{
$data = $this->data;
$form = $this;
/**
* Filters the form data.
*
* @param array $data
* @param MC4WP_Form $form
*/
$data = apply_filters('mc4wp_form_data', $data, $form);
return $data;
}
/**
* Get array of name attributes for the required fields in this form.
*
* @return array
*/
public function get_required_fields()
{
$form = $this;
// explode required fields (generated in JS) to an array (uppercased)
$required_fields_string = strtoupper($this->settings['required_fields']);
// remove array-formatted fields
// workaround for #261 (https://github.com/ibericode/mailchimp-for-wordpress/issues/261)
$required_fields_string = preg_replace('/\[\w+\]/', '', $required_fields_string);
// turn into an array
$required_fields = explode(',', $required_fields_string);
// EMAIL is not a required field as it has its own validation rules
$required_fields = array_diff($required_fields, array( 'EMAIL' ));
// filter duplicate & empty values
$required_fields = array_unique($required_fields);
$required_fields = array_filter($required_fields);
// fix uppercased subkeys, see https://github.com/ibericode/mailchimp-for-wordpress/issues/516
foreach ($required_fields as $key => $value) {
$pos = strpos($value, '.');
if ($pos > 0) {
$required_fields[$key] = substr($value, 0, $pos) . strtolower(substr($value, $pos));
}
}
/**
* Filters the required fields for a form
*
* By default, this holds the following fields.
*
* - All fields which are required for the selected Mailchimp lists
* - All fields in the form with a `required` attribute.
*
* @param array $required_fields
* @param MC4WP_Form $form
*/
$required_fields = (array) apply_filters('mc4wp_form_required_fields', $required_fields, $form);
return $required_fields;
}
/**
* Get "email_type" setting for new Mailchimp subscribers added by this form.
*
* @return string
*/
public function get_email_type()
{
$email_type = $this->config['email_type'];
if (empty($email_type)) {
$email_type = mc4wp_get_email_type();
}
return $email_type;
}
/**
* Gets the filename of the stylesheet to load for this form.
*
* @return string
*/
public function get_stylesheet()
{
$stylesheet = $this->settings['css'];
if (empty($stylesheet)) {
return '';
}
// form themes live in the same stylesheet
if (strpos($stylesheet, 'theme-') !== false) {
$stylesheet = 'themes';
}
return $stylesheet;
}
/**
* @param string $key
* @return string
*/
public function get_message($key)
{
$message = isset($this->messages[ $key]) ? $this->messages[ $key ] : $this->messages['error'] ;
if ($key === 'no_lists_selected' && current_user_can('manage_options')) {
$message .= sprintf(' (<a href="%s">%s</a>)', mc4wp_get_edit_form_url($this->ID, 'settings'), 'edit form settings');
}
return $message;
}
/**
* Get HTML string for a message, including wrapper element.
*
* @deprecated 3.1
*
* @param string $key
*
* @return string
*/
public function get_message_html($key)
{
_deprecated_function(__METHOD__, '3.2');
return '';
}
/**
* Add a notice to this form
*/
public function add_message($key)
{
_deprecated_function(__METHOD__, '3.3');
$this->add_notice($this->get_message($key));
}
/**
* @since 4.4
* @return array
*/
public function get_subscriber_tags()
{
if (empty($this->settings['subscriber_tags'])) {
return array();
}
$tags = explode(',', $this->settings['subscriber_tags']);
$tags = array_map('trim', $tags);
// remove empty tag values
foreach($tags as $i => $tag) {
if ($tag === '') {
unset($tags[$i]);
}
}
return array_values($tags);
}
}
@@ -0,0 +1,197 @@
<?php
class MC4WP_Google_Recaptcha {
private $form_ids = array();
public function add_hooks() {
add_filter('mc4wp_form_settings', array($this, 'add_default_form_settings'));
add_filter('mc4wp_settings', array($this, 'add_default_settings'));
add_action('mc4wp_output_form', array($this, 'on_output_form'), 20);
add_filter('mc4wp_form_errors', array($this, 'verify_token'), 10, 2);
add_action('mc4wp_admin_form_after_behaviour_settings_rows', array($this, 'show_settings'), 30, 2);
add_filter('mc4wp_form_sanitized_data', array($this, 'sanitize_settings'), 20, 2);
add_action('wp_footer', array($this, 'load_script'), 8000);
}
public function add_default_settings($settings) {
$defaults = array(
'grecaptcha_site_key' => '',
'grecaptcha_secret_key' => '',
);
$settings = array_merge($defaults, $settings);
return $settings;
}
public function add_default_form_settings($settings) {
$defaults = array(
'grecaptcha_enabled' => 0,
);
$settings = array_merge($defaults, $settings);
return $settings;
}
public function sanitize_settings($data, $raw_data) {
if (!isset($data['settings']['grecaptcha_enabled']) || !$data['settings']['grecaptcha_enabled']) {
return $data;
}
// only enable grecaptcha if both site & secret key are set
$global_settings = mc4wp_get_settings();
$data['settings']['grecaptcha_enabled'] = isset($global_settings['grecaptcha_site_key'])
&& isset($global_settings['grecaptcha_secret_key'])
&& strlen($global_settings['grecaptcha_site_key']) === 40
&& strlen($global_settings['grecaptcha_secret_key']) === 40 ? '1' : '0';
return $data;
}
public function load_script() {
$global_settings = mc4wp_get_settings();
// do not load if no forms with Google reCAPTCHA enabled were outputted
if (empty($this->form_ids) || empty($global_settings['grecaptcha_site_key']) || empty($global_settings['grecaptcha_secret_key'])) {
return;
}
// load Google reCAPTCHA script
echo sprintf('<script src="https://www.google.com/recaptcha/api.js?render=%s"></script>', esc_attr($global_settings['grecaptcha_site_key']));
// hook into form submit
?><script>
(function() {
var formIds = <?php echo json_encode($this->form_ids); ?>;
function addGoogleReCaptchaTokenToForm(form, event) {
event.preventDefault();
var submitForm = function() {
if(form.element.className.indexOf('mc4wp-ajax') > -1) {
mc4wp.forms.trigger('submit', [form, event]);
} else {
form.element.submit();
}
};
var previousToken = form.element.querySelector('input[name=_mc4wp_grecaptcha_token]');
if (previousToken) {
previousToken.parentElement.removeChild(previousToken);
}
window.grecaptcha
.execute('<?php echo esc_attr($global_settings['grecaptcha_site_key']); ?>', {action: 'mc4wp_form_submit'})
.then(function (token) {
var tokenEl = document.createElement('input');
tokenEl.type = 'hidden';
tokenEl.value = token;
tokenEl.name = '_mc4wp_grecaptcha_token';
form.element.appendChild(tokenEl);
submitForm();
})
}
for(var i=0; i<formIds.length; i++) {
mc4wp.forms.on(formIds[i]+'.submit', addGoogleReCaptchaTokenToForm)
}
})();
</script><?php
}
public function on_output_form(MC4WP_Form $form) {
// Check if form has Google ReCaptcha enabled
if (!$form->settings['grecaptcha_enabled']) {
return;
}
if (!in_array($form->ID, $this->form_ids)) {
$this->form_ids[] = $form->ID;
}
}
public function verify_token(array $errors, MC4WP_Form $form) {
// Check if form has Google ReCaptcha enabled
if (!$form->settings['grecaptcha_enabled']) {
return $errors;
}
// Verify token
if (empty($_POST['_mc4wp_grecaptcha_token'])) {
$errors[] = 'spam';
return $errors;
}
$global_settings = mc4wp_get_settings();
$token = $_POST['_mc4wp_grecaptcha_token'];
$response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', array(
'body' => array(
'secret' => $global_settings['grecaptcha_secret_key'],
'response' => $token,
),
));
$response_code = wp_remote_retrieve_response_code($response);
if ($response_code >= 400) {
// The request somehow failed... Allow the sign-up to go through to not break sign-up forms when Google reCaptcha is down (unlikely)
return $errors;
}
$response_body = wp_remote_retrieve_body($response);
$data = json_decode($response_body, true);
$score_treshold = apply_filters('mc4wp_grecaptcha_score_treshold', 0.5);
if (isset($data['error-codes']) && in_array('invalid-input-secret', $data['error-codes'])) {
$this->get_log()->warning(sprintf('Form %d > Invalid Google reCAPTCHA secret key', $form->ID));
return $errors;
}
if ($data['success'] === false || !isset($data['score']) || $data['score'] <= $score_treshold || $data['action'] !== 'mc4wp_form_submit') {
$errors[] = 'spam';
return $errors;
}
return $errors;
}
public function show_settings(array $settings, MC4WP_Form $form) {
$global_settings = mc4wp_get_settings();
?>
<tr valign="top">
<th scope="row"><?php _e('Enable Google reCaptcha', 'mailchimp-for-wp' ); ?></th>
<td>
<label><input type="radio" name="mc4wp_form[settings][grecaptcha_enabled]" value="1" <?php checked($settings['grecaptcha_enabled'], 1); ?> /> <?php _e('Yes'); ?> &rlm;</label>
&nbsp;
<label><input type="radio" name="mc4wp_form[settings][grecaptcha_enabled]" value="0" <?php checked($settings['grecaptcha_enabled'], 0); ?> /> <?php _e('No'); ?> &rlm;</label>
<p class="help">
<?php _e( 'Select "yes" to enable Google reCAPTCHA spam protection for this form.', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<?php $config = array( 'element' => 'mc4wp_form[settings][grecaptcha_enabled]', 'value' => 1 ); ?>
<tr valign="top" data-showif="<?php echo esc_attr(json_encode($config)); ?>">
<th scope="row"><label for="mc4wp_grecaptcha_site_key"><?php _e('Google reCAPTCHA Site Key', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" name="mc4wp[grecaptcha_site_key]" id="mc4wp_grecaptcha_site_key" placeholder="<?php echo str_repeat('●', 40); ?>" value="<?php echo esc_attr($global_settings['grecaptcha_site_key']); ?>" />
<p class="help">
<?php printf(__('Enter your Google reCAPTCHA keys here. You can <a href="%s">retrieve your keys in the Google reCAPTCHA admin console</a> or read our help article on <a href="%s">how to configure Google reCAPTCHA</a>.', 'mailchimp-for-wp'), 'https://g.co/recaptcha/v3', 'https://kb.mc4wp.com/google-recaptcha-forms/'); ?>
</p>
</td>
</tr>
<?php $config = array( 'element' => 'mc4wp_form[settings][grecaptcha_enabled]', 'value' => 1 ); ?>
<tr valign="top" data-showif="<?php echo esc_attr(json_encode($config)); ?>">
<th scope="row"><label for="mc4wp_grecaptcha_secret_key"><?php _e('Google reCAPTCHA Secret Key', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" name="mc4wp[grecaptcha_secret_key]" id="mc4wp_grecaptcha_secret_key" placeholder="<?php echo str_repeat('●', 40); ?>" value="<?php echo esc_attr($global_settings['grecaptcha_secret_key']); ?>" />
<p class="help">
<?php _e('', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<?php
}
/**
* @return MC4WP_Debug_Log
*/
private function get_log() {
return mc4wp('log');
}
}
@@ -0,0 +1,142 @@
<?php
/**
* Class MC4WP_Form_Output_Manager
*
* @ignore
* @access private
*/
class MC4WP_Form_Output_Manager
{
/**
* @var int The # of forms outputted
*/
public $count = 0;
/**
* @const string
*/
const SHORTCODE = 'mc4wp_form';
/**
* Constructor
*/
public function __construct()
{
}
/**
* Add hooks
*/
public function add_hooks()
{
// enable shortcodes in text widgets
add_filter('widget_text', 'shortcode_unautop');
add_filter('widget_text', 'do_shortcode', 11);
// enable shortcodes in form content
add_filter('mc4wp_form_content', 'do_shortcode');
add_action('init', array( $this, 'register_shortcode' ));
}
/**
* Registers the [mc4wp_form] shortcode
*/
public function register_shortcode()
{
// register shortcodes
add_shortcode(self::SHORTCODE, array( $this, 'shortcode' ));
}
/**
* @param array $attributes
* @param string $content
* @return string
*/
public function shortcode($attributes = array(), $content = '')
{
$default_attributes = array(
'id' => '',
'lists' => '',
'email_type' => '',
'element_id' => '',
'element_class' => '',
);
$attributes = shortcode_atts(
$default_attributes,
$attributes,
self::SHORTCODE
);
$config = array(
'element_id' => $attributes['element_id'],
'lists' => $attributes['lists'],
'email_type' => $attributes['email_type'],
'element_class' => $attributes['element_class'],
);
return $this->output_form($attributes['id'], $config, false);
}
/**
* @param int $id
* @param array $config
* @param bool $echo
*
* @return string
*/
public function output_form($id = 0, $config = array(), $echo = true)
{
try {
$form = mc4wp_get_form($id);
} catch (Exception $e) {
if (current_user_can('manage_options')) {
return sprintf('<strong>Mailchimp for WordPress error:</strong> %s', $e->getMessage());
}
return '';
}
$this->count++;
// set a default element_id if none is given
if (empty($config['element_id'])) {
$config['element_id'] = 'mc4wp-form-' . $this->count;
}
$form_html = $form->get_html($config['element_id'], $config);
try {
// start new output buffer
ob_start();
/**
* Runs just before a form element is outputted.
*
* @since 3.0
*
* @param MC4WP_Form $form
*/
do_action('mc4wp_output_form', $form);
// output the form (in output buffer)
echo $form_html;
// grab all contents in current output buffer & then clean + end it.
$html = ob_get_clean();
} catch (Error $e) {
$html = $form_html;
}
// echo content if necessary
if ($echo) {
echo $html;
}
return $html;
}
}
@@ -0,0 +1,131 @@
<?php
defined('ABSPATH') or exit;
/**
* Adds MC4WP_Widget widget.
*
* @ignore
*/
class MC4WP_Form_Widget extends WP_Widget
{
/**
* @var array
*/
private $default_instance_settings = array(
'title' => '',
'form_id' => ''
);
/**
* Register widget with WordPress.
*/
public function __construct()
{
// translate default widget title
$this->default_instance_settings['title'] = __('Newsletter', 'mailchimp-for-wp');
parent::__construct(
'mc4wp_form_widget', // Base ID
__('Mailchimp Sign-Up Form', 'mailchimp-for-wp'), // Name
array(
'description' => __('Displays your Mailchimp for WordPress sign-up form', 'mailchimp-for-wp'),
)
);
}
/**
* Front-end display of widget.
*
* @see WP_Widget::widget()
*
* @param array $args Widget arguments.
* @param array $instance_settings Saved values from database.
*/
public function widget($args, $instance_settings)
{
// ensure $instance_settings is an array
if (! is_array($instance_settings)) {
$instance_settings = array();
}
$instance_settings = array_merge($this->default_instance_settings, $instance_settings);
$title = apply_filters('widget_title', $instance_settings['title']);
echo $args['before_widget'];
if (! empty($title)) {
echo $args['before_title'] . $title . $args['after_title'];
}
mc4wp_show_form($instance_settings['form_id']);
echo $args['after_widget'];
}
/**
* Back-end widget form.
*
* @see WP_Widget::form()
*
* @param array $settings Previously saved values from database.
*
* @return string|void
*/
public function form($settings)
{
$settings = array_merge($this->default_instance_settings, (array) $settings); ?>
<p>
<label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'mailchimp-for-wp'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo esc_attr($settings['title']); ?>" />
</p>
<?php
/**
* Runs right after the widget settings form is outputted
*
* @param array $settings
* @param MC4WP_Form_Widget $this
* @ignore
*/
do_action('mc4wp_form_widget_form', $settings, $this); ?>
<p class="help">
<?php printf(__('You can edit your sign-up form in the <a href="%s">Mailchimp for WordPress form settings</a>.', 'mailchimp-for-wp'), admin_url('admin.php?page=mailchimp-for-wp-forms')); ?>
</p>
<?php
}
/**
* Validates widget form values as they are saved.
*
* @see WP_Widget::update()
*
* @param array $new_settings Values just sent to be saved.
* @param array $old_settings Previously saved values from database.
*
* @return array Updated safe values to be saved.
*/
public function update($new_settings, $old_settings)
{
if (! empty($new_settings['title'])) {
$new_settings['title'] = sanitize_text_field($new_settings['title']);
}
/**
* Filters the widget settings before they are saved.
*
* @param array $new_settings
* @param array $old_settings
* @param MC4WP_Form_Widget $widget
* @ignore
*/
$new_settings = apply_filters('mc4wp_form_widget_update_settings', $new_settings, $old_settings, $this);
return $new_settings;
}
} // class MC4WP_Widget
@@ -0,0 +1,128 @@
<?php
/**
* Returns a Form instance
*
* @access public
*
* @param int|WP_Post $form_id.
*
* @return MC4WP_Form
*/
function mc4wp_get_form($form_id = 0)
{
return MC4WP_Form::get_instance($form_id);
}
/**
* Get an array of Form instances
*
* @access public
* @uses get_posts
*
* @param array $args Array of parameters
*
* @return MC4WP_Form[]
*/
function mc4wp_get_forms(array $args = array())
{
$default_args = array(
'post_status' => 'publish',
'numberposts' => -1,
);
$args = array_merge($default_args, $args);
$args['post_type'] = 'mc4wp-form';
$posts = get_posts($args);
$forms = array();
foreach ($posts as $post) {
try {
$form = mc4wp_get_form($post);
} catch (Exception $e) {
continue;
}
$forms[] = $form;
}
return $forms;
}
/**
* Echoes the given form
*
* @access public
*
* @param int $form_id
* @param array $config
* @param bool $echo
*
* @return string
*/
function mc4wp_show_form($form_id = 0, $config = array(), $echo = true)
{
/** @var MC4WP_Form_Manager $forms */
$forms = mc4wp('forms');
return $forms->output_form($form_id, $config, $echo);
}
/**
* Check whether a form was submitted
*
* @ignore
* @since 2.3.8
* @deprecated 3.0
* @use mc4wp_get_form
*
* @param int $form_id The ID of the form you want to check. (optional)
* @param string $element_id The ID of the form element you want to check, eg id="mc4wp-form-1" (optional)
*
* @return boolean
*/
function mc4wp_form_is_submitted($form_id = 0, $element_id = null)
{
try {
$form = mc4wp_get_form($form_id);
} catch (Exception $e) {
return false;
}
if ($element_id) {
$form_element = new MC4WP_Form_Element($form, array( 'element_id' => $element_id ));
return $form_element->is_submitted;
}
return $form->is_submitted;
}
/**
* @since 2.3.8
* @deprecated 3.0
* @ignore
* @use mc4wp_get_form
*
* @param int $form_id (optional)
*
* @return string
*/
function mc4wp_form_get_response_html($form_id = 0)
{
try {
$form = mc4wp_get_form($form_id);
} catch (Exception $e) {
return '';
}
return $form->get_response_html();
}
/**
* Gets an instance of the submitted form, if any.
*
* @access public
*
* @return MC4WP_Form|null
*/
function mc4wp_get_submitted_form()
{
return mc4wp('forms')->get_submitted_form();
}
@@ -0,0 +1,86 @@
<?php defined('ABSPATH') or exit; ?>
<div id="mc4wp-admin" class="wrap mc4wp-settings">
<div class="row">
<!-- Main Content -->
<div class="main-content col col-4">
<h1 class="page-title">
<?php _e("Add new form", 'mailchimp-for-wp'); ?>
</h1>
<h2 style="display: none;"></h2><?php // fake h2 for admin notices?>
<div style="max-width: 480px;">
<!-- Wrap entire page in <form> -->
<form method="post">
<input type="hidden" name="_mc4wp_action" value="add_form" />
<?php wp_nonce_field('add_form', '_mc4wp_nonce'); ?>
<div class="small-margin">
<h3>
<label>
<?php _e('What is the name of this form?', 'mailchimp-for-wp'); ?>
</label>
</h3>
<input type="text" name="mc4wp_form[name]" class="widefat" value="" spellcheck="true" autocomplete="off" placeholder="<?php _e('Enter your form title..', 'mailchimp-for-wp'); ?>">
</div>
<div class="small-margin">
<h3>
<label>
<?php _e('To which Mailchimp lists should this form subscribe?', 'mailchimp-for-wp'); ?>
</label>
</h3>
<?php if (! empty($lists)) {
?>
<ul id="mc4wp-lists">
<?php foreach ($lists as $list) {
?>
<li>
<label>
<input type="checkbox" name="mc4wp_form[settings][lists][<?php echo esc_attr($list->id); ?>]" value="<?php echo esc_attr($list->id); ?>" <?php checked($number_of_lists, 1); ?> >
<?php echo esc_html($list->name); ?>
</label>
</li>
<?php
} ?>
</ul>
<?php
} else {
?>
<p class="mc4wp-notice">
<?php printf(__('No lists found. Did you <a href="%s">connect with Mailchimp</a>?', 'mailchimp-for-wp'), admin_url('admin.php?page=mailchimp-for-wp')); ?>
</p>
<?php
} ?>
</div>
<?php submit_button(__('Add new form', 'mailchimp-for-wp')); ?>
</form><!-- Entire page form wrap -->
</div>
<?php include MC4WP_PLUGIN_DIR . 'includes/views/parts/admin-footer.php'; ?>
</div><!-- / Main content -->
<!-- Sidebar -->
<div class="sidebar col col-2">
<?php include MC4WP_PLUGIN_DIR . 'includes/views/parts/admin-sidebar.php'; ?>
</div>
</div>
</div>
@@ -0,0 +1,127 @@
<?php defined('ABSPATH') or exit;
$tabs = array(
'fields' => __('Fields', 'mailchimp-for-wp'),
'messages' => __('Messages', 'mailchimp-for-wp'),
'settings' => __('Settings', 'mailchimp-for-wp'),
'appearance' => __('Appearance', 'mailchimp-for-wp')
);
/**
* Filters the setting tabs on the "edit form" screen.
*
* @param array $tabs
* @ignore
*/
$tabs = apply_filters('mc4wp_admin_edit_form_tabs', $tabs);
?>
<div id="mc4wp-admin" class="wrap mc4wp-settings">
<p class="breadcrumbs">
<span class="prefix"><?php echo __('You are here: ', 'mailchimp-for-wp'); ?></span>
<a href="<?php echo admin_url('admin.php?page=mailchimp-for-wp'); ?>">Mailchimp for WordPress</a> &rsaquo;
<a href="<?php echo admin_url('admin.php?page=mailchimp-for-wp-forms'); ?>"><?php _e('Forms', 'mailchimp-for-wp'); ?></a>
&rsaquo;
<span class="current-crumb"><strong><?php echo __('Form', 'mailchimp-for-wp'); ?> <?php echo $form_id; ?>
| <?php echo esc_html($form->name); ?></strong></span>
</p>
<div class="row">
<!-- Main Content -->
<div class="main-content col col-5">
<h1 class="page-title">
<?php _e("Edit Form", 'mailchimp-for-wp'); ?>
<!-- Form actions -->
<?php
/**
* @ignore
*/
do_action('mc4wp_admin_edit_form_after_title');
?>
</h1>
<h2 style="display: none;"></h2><?php // fake h2 for admin notices?>
<!-- Wrap entire page in <form> -->
<form method="post">
<?php // default submit button to prevent opening preview?>
<input type="submit" style="display: none; "/>
<input type="hidden" name="_mc4wp_action" value="edit_form"/>
<input type="hidden" name="mc4wp_form_id" value="<?php echo esc_attr($form->ID); ?>"/>
<?php wp_nonce_field('edit_form', '_mc4wp_nonce'); ?>
<div id="titlediv" class="small-margin">
<div id="titlewrap">
<label class="screen-reader-text"
for="title"><?php _e('Enter form title here', 'mailchimp-for-wp'); ?></label>
<input type="text" name="mc4wp_form[name]" size="30"
value="<?php echo esc_attr($form->name); ?>" id="title" spellcheck="true"
autocomplete="off"
placeholder="<?php echo __("Enter the title of your sign-up form", 'mailchimp-for-wp'); ?>"
style="line-height: initial;">
</div>
<div>
<?php printf(__('Use the shortcode %s to display this form inside a post, page or text widget.', 'mailchimp-for-wp'), '<input type="text" onfocus="this.select();" readonly="readonly" value="'. esc_attr(sprintf('[mc4wp_form id="%d"]', $form->ID)) .'" size="'. (strlen($form->ID) + 18) .'">'); ?>
</div>
</div>
<div>
<h2 class="nav-tab-wrapper" id="mc4wp-tabs-nav">
<?php foreach ($tabs as $tab => $name) {
$class = ($active_tab === $tab) ? 'nav-tab-active' : '';
echo sprintf('<a class="nav-tab nav-tab-%s %s" href="%s">%s</a>', $tab, $class, esc_attr($this->tab_url($tab)), $name);
} ?>
</h2>
<div id="mc4wp-tabs">
<?php foreach ($tabs as $tab => $name) :
$class = ($active_tab === $tab) ? 'tab-active' : '';
// start of .tab
echo sprintf('<div class="tab %s" id="tab-%s">', $class, $tab);
/**
* Runs when outputting a tab section on the "edit form" screen
*
* @param string $tab
* @ignore
*/
do_action('mc4wp_admin_edit_form_output_' . $tab . '_tab', $opts, $form);
$tab_file = dirname(__FILE__) . '/tabs/form-' . $tab . '.php';
if (file_exists($tab_file)) {
include $tab_file;
}
// end of .tab
echo '</div>';
endforeach; // foreach tabs?>
</div><!-- / tabs -->
</div>
</form><!-- Entire page form wrap -->
<?php include MC4WP_PLUGIN_DIR . 'includes/views/parts/admin-footer.php'; ?>
</div>
<!-- Sidebar -->
<div class="sidebar col col-1">
<?php include MC4WP_PLUGIN_DIR . 'includes/views/parts/admin-sidebar.php'; ?>
</div>
</div>
</div>
@@ -0,0 +1,17 @@
/* test if browser supports date fields */
var testInput = document.createElement('input');
testInput.setAttribute('type', 'date');
if( testInput.type !== 'date') {
/* add placeholder & pattern to all date fields */
var dateFields = document.querySelectorAll('.mc4wp-form input[type="date"]');
for(var i=0; i<dateFields.length; i++) {
if(!dateFields[i].placeholder) {
dateFields[i].placeholder = 'YYYY-MM-DD';
}
if(!dateFields[i].pattern) {
dateFields[i].pattern = '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])';
}
}
}
@@ -0,0 +1,15 @@
(function() {
if (!window.mc4wp) {
window.mc4wp = {
listeners: [],
forms : {
on: function (event, callback) {
window.mc4wp.listeners.push({
event : event,
callback: callback
});
}
}
}
}
})();
@@ -0,0 +1,7 @@
function addEventListener(element,event,handler) {
if(element.addEventListener) {
element.addEventListener(event,handler, false);
} else if(element.attachEvent){
element.attachEvent('on'+event,handler);
}
}
@@ -0,0 +1,12 @@
function maybePrefixUrlField() {
if(this.value.trim() !== '' && this.value.indexOf('http') !== 0) {
this.value = "http://" + this.value;
}
}
var urlFields = document.querySelectorAll('.mc4wp-form input[type="url"]');
if( urlFields && urlFields.length > 0 ) {
for( var j=0; j < urlFields.length; j++ ) {
addEventListener(urlFields[j],'blur',maybePrefixUrlField);
}
}
@@ -0,0 +1,53 @@
<?php defined('ABSPATH') or exit; ?>
<div class="mc4wp-admin">
<h2><?php _e('Add more fields', 'mailchimp-for-wp'); ?></h2>
<div class="help-text">
<p>
<?php echo __('To add more fields to your form, you will need to create those fields in Mailchimp first.', 'mailchimp-for-wp'); ?>
</p>
<p><strong><?php echo __("Here's how:", 'mailchimp-for-wp'); ?></strong></p>
<ol>
<li>
<p>
<?php echo __('Log in to your Mailchimp account.', 'mailchimp-for-wp'); ?>
</p>
</li>
<li>
<p>
<?php echo __('Add list fields to any of your selected lists.', 'mailchimp-for-wp'); ?>
<?php echo __('Clicking the following links will take you to the right screen.', 'mailchimp-for-wp'); ?>
</p>
<ul class="children lists--only-selected">
<?php foreach ($lists as $list) {
?>
<li data-list-id="<?php echo $list->id; ?>" style="display: <?php echo in_array($list->id, $opts['lists']) ? '' : 'none'; ?>">
<a href="https://admin.mailchimp.com/lists/settings/merge-tags?id=<?php echo $list->web_id; ?>">
<span class="screen-reader-text"><?php _e('Edit list fields for', 'mailchimp-for-wp'); ?> </span>
<?php echo $list->name; ?>
</a>
</li>
<?php
} ?>
</ul>
</li>
<li>
<p>
<?php echo __('Click the following button to have Mailchimp for WordPress pick up on your changes.', 'mailchimp-for-wp'); ?>
</p>
<p>
<a class="button button-primary" href="<?php echo esc_attr(add_query_arg(array( '_mc4wp_action' => 'empty_lists_cache' ))); ?>">
<?php _e('Renew Mailchimp lists', 'mailchimp-for-wp'); ?>
</a>
</p>
</li>
</ol>
</div>
</div>
@@ -0,0 +1,21 @@
<?php
defined('ABSPATH') or exit;
$tags = mc4wp('forms')->get_tags();
?>
<h2><?php _e('Add dynamic form variable', 'mailchimp-for-wp'); ?></h2>
<p>
<?php echo sprintf(__('The following list of variables can be used to <a href="%s">add some dynamic content to your form or success and error messages</a>.', 'mailchimp-for-wp'), 'https://kb.mc4wp.com/using-variables-in-your-form-or-messages/') . ' ' . __('This allows you to personalise your form or response messages.', 'mailchimp-for-wp'); ?>
</p>
<table class="widefat striped">
<?php foreach ($tags as $tag => $config) {
$tag = ! empty($config['example']) ? $config['example'] : $tag; ?>
<tr>
<td>
<input type="text" class="widefat" value="<?php echo esc_attr(sprintf('{%s}', $tag)); ?>" readonly="readonly" onfocus="this.select();" />
<p class="help" style="margin-bottom:0;"><?php echo strip_tags($config['description'], '<strong><b><em><i><a><code>'); ?></p>
</td>
</tr>
<?php
} ?>
</table>
@@ -0,0 +1,53 @@
<?php
defined('ABSPATH') or exit;
// fake post to prevent notices in wp_enqueue_scripts call
$GLOBALS['post'] = new \WP_Post((object) array( 'filter' => 'raw' ));
// render simple page with form in it.
?><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" />
<?php
wp_enqueue_scripts();
wp_print_styles();
wp_print_head_scripts();
if (function_exists('wp_custom_css_cb')) {
wp_custom_css_cb();
}
?>
<style type="text/css">
body{
background: white;
width: 100%;
max-width: 100%;
text-align: left;
}
/* hide all other elements */
body::before,
body::after,
body > *:not(#form-preview) {
display:none !important;
}
#form-preview {
display: block !important;
width: 100%;
height: 100%;
padding: 20px;
border: 0;
margin: 0;
}
</style>
</head>
<body class="page-template-default page ">
<div id="form-preview" class="page type-page status-publish hentry post post-content">
<?php mc4wp_show_form($form_id); ?>
</div>
<?php wp_footer(); ?>
</body>
</html>
@@ -0,0 +1,60 @@
<?php
$theme = wp_get_theme();
$css_options = array(
'0' => sprintf(__('Inherit from %s theme', 'mailchimp-for-wp'), $theme->Name),
'basic' => __('Basic', 'mailchimp-for-wp'),
__('Form Themes', 'mailchimp-for-wp') => array(
'theme-light' => __('Light Theme', 'mailchimp-for-wp'),
'theme-dark' => __('Dark Theme', 'mailchimp-for-wp'),
'theme-red' => __('Red Theme', 'mailchimp-for-wp'),
'theme-green' => __('Green Theme', 'mailchimp-for-wp'),
'theme-blue' => __('Blue Theme', 'mailchimp-for-wp'),
)
);
/**
* Filters the <option>'s in the "CSS Stylesheet" <select> box.
*
* @ignore
*/
$css_options = apply_filters('mc4wp_admin_form_css_options', $css_options);
?>
<h2><?php _e('Form Appearance', 'mailchimp-for-wp'); ?></h2>
<table class="form-table">
<tr valign="top">
<th scope="row"><label for="mc4wp_load_stylesheet_select"><?php _e('Form Style', 'mailchimp-for-wp'); ?></label></th>
<td class="nowrap valigntop">
<select name="mc4wp_form[settings][css]" id="mc4wp_load_stylesheet_select">
<?php foreach ($css_options as $key => $option) {
if (is_array($option)) {
$label = $key;
$options = $option;
printf('<optgroup label="%s">', $label);
foreach ($options as $key => $option) {
printf('<option value="%s" %s>%s</option>', $key, selected($opts['css'], $key, false), $option);
}
print('</optgroup>');
} else {
printf('<option value="%s" %s>%s</option>', $key, selected($opts['css'], $key, false), $option);
}
} ?>
</select>
<p class="help">
<?php _e('If you want to load some default CSS styles, select "basic formatting styles" or choose one of the color themes', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<?php
/** @ignore */
do_action('mc4wp_admin_form_after_appearance_settings_rows', $opts, $form);
?>
</table>
<?php submit_button(); ?>
@@ -0,0 +1,50 @@
<?php add_thickbox(); ?>
<div class="alignright">
<a href="#TB_inline?width=0&height=550&inlineId=mc4wp-form-variables" class="thickbox button-secondary">
<span class="dashicons dashicons-info"></span>
<?php _e('Form variables', 'mailchimp-for-wp'); ?>
</a>
<a href="#TB_inline?width=600&height=400&inlineId=mc4wp-add-field-help" class="thickbox button-secondary">
<span class="dashicons dashicons-editor-help"></span>
<?php _e('Add more fields', 'mailchimp-for-wp'); ?>
</a>
</div>
<h2><?php _e("Form Fields", 'mailchimp-for-wp'); ?></h2>
<!-- Placeholder for the field wizard -->
<div id="mc4wp-field-wizard"></div>
<div class="mc4wp-row">
<div class="mc4wp-col mc4wp-col-3 mc4wp-form-editor-wrap">
<h4 style="margin: 0"><label><?php _e('Form code', 'mailchimp-for-wp'); ?></label></h4>
<!-- Textarea for the actual form content HTML -->
<textarea class="widefat" cols="160" rows="20" id="mc4wp-form-content" name="mc4wp_form[content]" placeholder="<?php _e('Enter the HTML code for your form fields..', 'mailchimp-for-wp'); ?>" autocomplete="false" autocorrect="false" autocapitalize="false" spellcheck="false"><?php echo htmlspecialchars($form->content, ENT_QUOTES, get_option('blog_charset')); ?></textarea>
</div>
<div class="mc4wp-col mc4wp-col-3 mc4wp-form-preview-wrap">
<h4 style="margin: 0;">
<label><?php _e('Form preview', 'mailchimp-for-wp'); ?>
<span class="mc4wp-tooltip dashicons dashicons-editor-help" title="<?php esc_attr_e('The form may look slightly different than this when shown in a post, page or widget area.', 'mailchimp-for-wp'); ?>"></span>
</label>
</h4>
<iframe id="mc4wp-form-preview" src="<?php echo esc_attr($form_preview_url); ?>"></iframe>
</div>
</div>
<!-- This field is updated by JavaScript as the form content changes -->
<input type="hidden" id="required-fields" name="mc4wp_form[settings][required_fields]" value="<?php echo esc_attr($form->settings['required_fields']); ?>" />
<?php submit_button(); ?>
<p class="mc4wp-form-usage"><?php printf(__('Use the shortcode %s to display this form inside a post, page or text widget.', 'mailchimp-for-wp'), '<input type="text" onfocus="this.select();" readonly="readonly" value="'. esc_attr(sprintf('[mc4wp_form id="%d"]', $form->ID)) .'" size="'. (strlen($form->ID) + 18) .'">'); ?></p>
<?php // Content for Thickboxes?>
<div id="mc4wp-form-variables" style="display: none;">
<?php include dirname(__FILE__) . '/../parts/dynamic-content-tags.php'; ?>
</div>
<div id="mc4wp-add-field-help" style="display: none;">
<?php include dirname(__FILE__) . '/../parts/add-fields-help.php'; ?>
</div>
@@ -0,0 +1,95 @@
<?php defined('ABSPATH') or exit;
/** @var MC4WP_Form $form */
?>
<h2><?php _e('Form Messages', 'mailchimp-for-wp'); ?></h2>
<table class="form-table mc4wp-form-messages">
<?php
/** @ignore */
do_action('mc4wp_admin_form_before_messages_settings_rows', $opts, $form);
?>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_subscribed"><?php _e('Successfully subscribed', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_subscribed" name="mc4wp_form[messages][subscribed]" value="<?php echo esc_attr($form->messages['subscribed']); ?>" />
<p class="help"><?php _e('The text that shows when an email address is successfully subscribed to the selected list(s).', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_invalid_email"><?php _e('Invalid email address', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_invalid_email" name="mc4wp_form[messages][invalid_email]" value="<?php echo esc_attr($form->messages['invalid_email']); ?>" required />
<p class="help"><?php _e('The text that shows when an invalid email address is given.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_required_field_missing"><?php _e('Required field missing', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_required_field_missing" name="mc4wp_form[messages][required_field_missing]" value="<?php echo esc_attr($form->messages['required_field_missing']); ?>" required />
<p class="help"><?php _e('The text that shows when a required field for the selected list(s) is missing.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_already_subscribed"><?php _e('Already subscribed', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_already_subscribed" name="mc4wp_form[messages][already_subscribed]" value="<?php echo esc_attr($form->messages['already_subscribed']); ?>" required />
<p class="help"><?php _e('The text that shows when the given email is already subscribed to the selected list(s).', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_error"><?php _e('General error', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_error" name="mc4wp_form[messages][error]" value="<?php echo esc_attr($form->messages['error']); ?>" required />
<p class="help"><?php _e('The text that shows when a general error occured.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_unsubscribed"><?php _e('Unsubscribed', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_unsubscribed" name="mc4wp_form[messages][unsubscribed]" value="<?php echo esc_attr($form->messages['unsubscribed']); ?>" required />
<p class="help"><?php _e('When using the unsubscribe method, this is the text that shows when the given email address is successfully unsubscribed from the selected list(s).', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_not_subscribed"><?php _e('Not subscribed', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_not_subscribed" name="mc4wp_form[messages][not_subscribed]" value="<?php echo esc_attr($form->messages['not_subscribed']); ?>" required />
<p class="help"><?php _e('When using the unsubscribe method, this is the text that shows when the given email address is not on the selected list(s).', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_no_lists_selected"><?php _e('No list selected', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_no_lists_selected" name="mc4wp_form[messages][no_lists_selected]" value="<?php echo esc_attr($form->messages[ 'no_lists_selected']); ?>" required />
<p class="help"><?php _e('When offering a list choice, this is the text that shows when no lists were selected.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<?php $config = array( 'element' => 'mc4wp_form[settings][update_existing]', 'value' => 1 ); ?>
<tr valign="top" data-showif="<?php echo esc_attr(json_encode($config)); ?>">
<th scope="row"><label for="mc4wp_form_updated"><?php _e('Updated', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" id="mc4wp_form_updated" name="mc4wp_form[messages][updated]" value="<?php echo esc_attr($form->messages['updated']); ?>" />
<p class="help"><?php _e('The text that shows when an existing subscriber is updated.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<?php
/** @ignore */
do_action('mc4wp_admin_form_after_messages_settings_rows', array(), $form);
?>
<tr valign="top">
<th></th>
<td>
<p class="help"><?php printf(__('HTML tags like %s are allowed in the message fields.', 'mailchimp-for-wp'), '<code>' . esc_html('<strong><em><a>') . '</code>'); ?></p>
</td>
</tr>
</table>
<?php submit_button(); ?>
@@ -0,0 +1,156 @@
<h2><?php echo __('Form Settings', 'mailchimp-for-wp'); ?></h2>
<div class="medium-margin"></div>
<h3><?php echo __('Mailchimp specific settings', 'mailchimp-for-wp'); ?></h3>
<table class="form-table" style="table-layout: fixed;">
<?php
/** @ignore */
do_action('mc4wp_admin_form_after_mailchimp_settings_rows', $opts, $form);
?>
<tr valign="top">
<th scope="row" style="width: 250px;"><?php _e('Lists this form subscribes to', 'mailchimp-for-wp'); ?></th>
<?php // loop through lists
if (empty($lists)) {
?><td colspan="2"><?php printf(__('No lists found, <a href="%s">are you connected to Mailchimp</a>?', 'mailchimp-for-wp'), admin_url('admin.php?page=mailchimp-for-wp')); ?></td><?php
} else {
?>
<td >
<ul id="mc4wp-lists" style="margin-bottom: 20px; max-height: 300px; overflow-y: auto;">
<?php foreach ($lists as $list) {
?>
<li>
<label>
<input class="mc4wp-list-input" type="checkbox" name="mc4wp_form[settings][lists][]" value="<?php echo esc_attr($list->id); ?>" <?php checked(in_array($list->id, $opts['lists']), true); ?>> <?php echo esc_html($list->name); ?>
</label>
</li>
<?php
} ?>
</ul>
<p class="help"><?php _e('Select the list(s) to which people who submit this form should be subscribed.', 'mailchimp-for-wp'); ?></p>
</td>
<?php
} ?>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Use double opt-in?', 'mailchimp-for-wp'); ?></th>
<td class="nowrap">
<label>
<input type="radio" name="mc4wp_form[settings][double_optin]" value="1" <?php checked($opts['double_optin'], 1); ?> />&rlm;
<?php _e('Yes'); ?>
</label> &nbsp;
<label>
<input type="radio" name="mc4wp_form[settings][double_optin]" value="0" <?php checked($opts['double_optin'], 0); ?> onclick="return confirm('<?php esc_attr_e('Are you sure you want to disable double opt-in?', 'mailchimp-for-wp'); ?>');" />&rlm;
<?php _e('No'); ?>
</label>
<p class="help"><?php _e('We strongly suggest keeping double opt-in enabled. Disabling double opt-in may result in abuse.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e('Update existing subscribers?', 'mailchimp-for-wp'); ?></th>
<td class="nowrap">
<label>
<input type="radio" name="mc4wp_form[settings][update_existing]" value="1" <?php checked($opts['update_existing'], 1); ?> />&rlm;
<?php _e('Yes'); ?>
</label> &nbsp;
<label>
<input type="radio" name="mc4wp_form[settings][update_existing]" value="0" <?php checked($opts['update_existing'], 0); ?> />&rlm;
<?php _e('No'); ?>
</label>
<p class="help"><?php _e('Select "yes" if you want to update existing subscribers with the data that is sent.', 'mailchimp-for-wp'); ?></p>
</td>
</tr>
<?php $config = array( 'element' => 'mc4wp_form[settings][update_existing]', 'value' => 1 ); ?>
<tr valign="top" data-showif="<?php echo esc_attr(json_encode($config)); ?>">
<th scope="row"><?php _e('Replace interest groups?', 'mailchimp-for-wp'); ?></th>
<td class="nowrap">
<label>
<input type="radio" name="mc4wp_form[settings][replace_interests]" value="1" <?php checked($opts['replace_interests'], 1); ?> />&rlm;
<?php _e('Yes'); ?>
</label> &nbsp;
<label>
<input type="radio" name="mc4wp_form[settings][replace_interests]" value="0" <?php checked($opts['replace_interests'], 0); ?> />&rlm;
<?php _e('No'); ?>
</label>
<p class="help">
<?php _e('Select "no" if you want to add the selected interests to any previously selected interests when updating a subscriber.', 'mailchimp-for-wp'); ?>
<?php printf(' <a href="%s" target="_blank">' . __('What does this do?', 'mailchimp-for-wp') . '</a>', 'https://kb.mc4wp.com/what-does-replace-groupings-mean/#utm_source=wp-plugin&utm_medium=mailchimp-for-wp&utm_campaign=settings-page'); ?>
</p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_subscriber_tags"><?php _e('Subscriber tags', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" name="mc4wp_form[settings][subscriber_tags]" id="mc4wp_form_subscriber_tags" placeholder="<?php echo __('Example: My tag, another tag', 'mailchimp-for-wp'); ?>" value="<?php echo esc_attr($opts['subscriber_tags']); ?>" />
<p class="help">
<?php _e('The listed tags will be applied to all new subscribers added by this form.', 'mailchimp-for-wp'); ?>
<?php _e('Separate multiple values with a comma.', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<?php
/** @ignore */
do_action('mc4wp_admin_form_after_mailchimp_settings_rows', $opts, $form);
?>
</table>
<div class="medium-margin"></div>
<h3><?php _e('Form behaviour', 'mailchimp-for-wp'); ?></h3>
<table class="form-table" style="table-layout: fixed;">
<?php
/** @ignore */
do_action('mc4wp_admin_form_before_behaviour_settings_rows', $opts, $form);
?>
<tr valign="top">
<th scope="row"><?php _e('Hide form after a successful sign-up?', 'mailchimp-for-wp'); ?></th>
<td class="nowrap">
<label>
<input type="radio" name="mc4wp_form[settings][hide_after_success]" value="1" <?php checked($opts['hide_after_success'], 1); ?> />&rlm;
<?php _e('Yes'); ?>
</label> &nbsp;
<label>
<input type="radio" name="mc4wp_form[settings][hide_after_success]" value="0" <?php checked($opts['hide_after_success'], 0); ?> />&rlm;
<?php _e('No'); ?>
</label>
<p class="help">
<?php _e('Select "yes" to hide the form fields after a successful sign-up.', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<tr valign="top">
<th scope="row"><label for="mc4wp_form_redirect"><?php _e('Redirect to URL after successful sign-ups', 'mailchimp-for-wp'); ?></label></th>
<td>
<input type="text" class="widefat" name="mc4wp_form[settings][redirect]" id="mc4wp_form_redirect" placeholder="<?php printf(__('Example: %s', 'mailchimp-for-wp'), esc_attr(site_url('/thank-you/'))); ?>" value="<?php echo esc_attr($opts['redirect']); ?>" />
<p class="help">
<?php _e('Leave empty or enter <code>0</code> for no redirect. Otherwise, use complete (absolute) URLs, including <code>http://</code>.', 'mailchimp-for-wp'); ?>
</p>
<p class="help">
<?php _e('Your "subscribed" message will not show when redirecting to another page, so make sure to let your visitors know they were successfully subscribed.', 'mailchimp-for-wp'); ?>
</p>
</td>
</tr>
<?php
/** @ignore */
do_action('mc4wp_admin_form_after_behaviour_settings_rows', $opts, $form);
?>
</table>
<?php submit_button(); ?>