| 1 |
<?php |
| 2 |
/* |
| 3 |
Plugin Name: Essential Form |
| 4 |
Description: The lightest contact form for WordPress. So essential you'll either love it or hate it. Ultra lightweight and no spam. |
| 5 |
Author: Jose Mortellaro |
| 6 |
Author URI: https://josemortellaro.com/ |
| 7 |
Domain Path: /languages/ |
| 8 |
Text Domain: essential-form |
| 9 |
Version: 0.0.7 |
| 10 |
*/ |
| 11 |
/* This program is free software; you can redistribute it and/or modify |
| 12 |
it under the terms of the GNU General Public License as published by |
| 13 |
the Free Software Foundation; either version 2 of the License, or |
| 14 |
(at your option) any later version. |
| 15 |
This program is distributed in the hope that it will be useful, |
| 16 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 |
GNU General Public License for more details. |
| 19 |
*/ |
| 20 |
defined( 'ABSPATH' ) || exit; // Exit if accessed directly |
| 21 |
|
| 22 |
// Definitions. |
| 23 |
define( 'ESSENTIAL_FORM_VERSION','0.0.7' ); |
| 24 |
define( 'ESSENTIAL_FORM_PLUGIN_DIR', untrailingslashit( dirname( __FILE__ ) ) ); |
| 25 |
define( 'ESSENTIAL_FORM_PLUGIN_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) ); |
| 26 |
|
| 27 |
$keys = essential_form_get_keys(); |
| 28 |
if( $keys && is_array( $keys ) ){ |
| 29 |
define( 'ESSENTIAL_FORM_AJAX_KEY','essential_form_'.sanitize_key( $keys[0] ) ); |
| 30 |
} |
| 31 |
|
| 32 |
if( wp_doing_ajax() && defined( 'ESSENTIAL_FORM_AJAX_KEY' ) ){ |
| 33 |
if( isset( $_REQUEST['action'] ) && in_array( sanitize_text_field( $_REQUEST['action'] ),apply_filters( 'essential_form_allowed_actions',array( 'essential_form_'.sanitize_key( $keys[0] ),'essential_form_'.sanitize_key( $keys[0] ).'_get_key' ) ) ) ){ |
| 34 |
require_once ESSENTIAL_FORM_PLUGIN_DIR.'/inc/ef-ajax.php'; |
| 35 |
} |
| 36 |
} |
| 37 |
elseif( is_admin() ){ |
| 38 |
require_once ESSENTIAL_FORM_PLUGIN_DIR.'/admin/ef-admin.php'; |
| 39 |
} |
| 40 |
|
| 41 |
// Actions triggered after plugin activation. |
| 42 |
register_activation_hook( __FILE__,function( $networkwide ){ |
| 43 |
require ESSENTIAL_FORM_PLUGIN_DIR.'/plugin-activation.php'; |
| 44 |
} ); |
| 45 |
|
| 46 |
// Get options in case of single or multisite installation. |
| 47 |
function essential_form_get_option( $option ){ |
| 48 |
if( !is_multisite() ){ |
| 49 |
return get_option( $option ); |
| 50 |
} |
| 51 |
else{ |
| 52 |
return get_blog_option( get_current_blog_id(),$option ); |
| 53 |
} |
| 54 |
} |
| 55 |
|
| 56 |
// Update options in case of single or multisite installation. |
| 57 |
function essential_form_update_option( $option,$newvalue,$autoload = false ){ |
| 58 |
if( !is_multisite() ){ |
| 59 |
return update_option( $option,$newvalue,$autoload ); |
| 60 |
} |
| 61 |
else{ |
| 62 |
return update_blog_option( get_current_blog_id(),$option,$newvalue ); |
| 63 |
} |
| 64 |
} |
| 65 |
|
| 66 |
// Filtered settings. |
| 67 |
function essential_form_filtered_settings(){ |
| 68 |
$settings = array(); |
| 69 |
$default_settings = essential_form_default_settings(); |
| 70 |
$filtered = apply_filters( 'essential_form_settings',$default_settings ); |
| 71 |
foreach( $default_settings as $key => $value ){ |
| 72 |
$settings[$key] = isset( $filtered[$key] ) ? $filtered[$key] : $default_settings[$key]; |
| 73 |
} |
| 74 |
return $settings; |
| 75 |
} |
| 76 |
|
| 77 |
// Default settings. |
| 78 |
function essential_form_default_settings(){ |
| 79 |
$privacy_page = (int) get_site_option( 'wp_page_for_privacy_policy' ); |
| 80 |
if( function_exists( 'icl_object_id' ) ){ |
| 81 |
$privacy_page_lang = icl_object_id( $privacy_page,'page', false,ICL_LANGUAGE_CODE ); |
| 82 |
$privacy_page = $privacy_page_lang ? $privacy_page_lang : $privacy_page; |
| 83 |
} |
| 84 |
$url = get_permalink( $privacy_page ); |
| 85 |
$url = $url ? $url : '#'; |
| 86 |
return array( |
| 87 |
'email_from' => get_bloginfo( 'admin_email' ), |
| 88 |
'email_to' => get_bloginfo( 'admin_email' ), |
| 89 |
'email_subject' => sprintf( esc_html__( 'Message from %s','essential-form' ),get_bloginfo( 'name' ) ), |
| 90 |
'label_name' => __( 'Name','essential-form' ), |
| 91 |
'label_email' => __( 'Email','essential-form' ), |
| 92 |
'label_message' => __( 'Message','essential-form' ), |
| 93 |
'button_text' => __( 'Send','essential-form' ), |
| 94 |
'agreement_text' => sprintf( __( 'By submitting this form I agree with the %sprivacy policy%s','essential-form' ),'<a href="'.esc_url( $url ).'" target="_blank">','</a>' ), |
| 95 |
'success_message' => __( 'Form submitted successfully! Thank you for your message!','essential-form' ), |
| 96 |
'name_missing_error' => __( 'Name is a required field!','essential-form' ), |
| 97 |
'email_missing_error' => __( 'Email is a required field!','essential-form' ), |
| 98 |
'email_not_valid_error' => __( 'Email not valid!','essential-form' ), |
| 99 |
'message_missing_error' => __( 'Message is a required field!','essential-form' ), |
| 100 |
'message_too_long_error' => __( 'This message is too long! Please, write not more than 50000 characters.','essential-form' ), |
| 101 |
'missing_agreement_error' => __( 'You have to agree with our privacy policy to submit the form.','essential-form' ) |
| 102 |
); |
| 103 |
} |
| 104 |
|
| 105 |
add_shortcode( 'essential_form',function( $atts ){ |
| 106 |
//Form shortcode. |
| 107 |
static $s = 0; |
| 108 |
$opts = essential_form_get_option( 'essential_form' ); |
| 109 |
if( isset( $opts['activation_keys'] ) ){ |
| 110 |
do_action( 'essential_form_init' ); |
| 111 |
global $post; |
| 112 |
++$s; |
| 113 |
$settings = essential_form_filtered_settings(); |
| 114 |
extract( $settings ); |
| 115 |
$label_name = isset( $atts['label_name'] ) ? sanitize_text_field( $atts['label_name'] ) : apply_filters( 'essential_form_label_name',$label_name ); |
| 116 |
$label_email = isset( $atts['label_email'] ) ? sanitize_text_field( $atts['label_email'] ) : apply_filters( 'essential_form_label_email',$label_email ); |
| 117 |
$label_message = isset( $atts['label_message'] ) ? sanitize_text_field( $atts['label_message'] ) : apply_filters( 'essential_form_label_message',$label_message ); |
| 118 |
$button_text = isset( $atts['button_text'] ) ? sanitize_text_field( $atts['button_text'] ) : apply_filters( 'essential_form_button_text',$button_text ); |
| 119 |
$agreement_text = isset( $atts['agreement_text'] ) ? wp_kses( $atts['agreement_text'],array( 'a' => array( 'href' => array(),'target' => array() ) ) ) : apply_filters( 'essential_form_agreement_text',$agreement_text ); |
| 120 |
$success_message = isset( $atts['success_message'] ) ? sanitize_text_field( $atts['success_message'] ) : apply_filters( 'essential_form_success_message',$success_message ); |
| 121 |
$keys = essential_form_get_keys(); |
| 122 |
$output = '<style id="'.esc_attr( $keys[0] ).'-'.$s.'-css">'; |
| 123 |
$output .= '.'.esc_attr( $keys[0] ).'-wrp .ef-error{border:1px solid red;padding:10px;margin-bottom:16px}'; |
| 124 |
$output .= '.'.esc_attr( $keys[0] ).'-wrp .ef-success{border:1px solid green;padding:10px;margin-bottom:16px}'; |
| 125 |
$output .= '.'.esc_attr( $keys[0] ).' input:not([type=checkbox]),.'.esc_attr( $keys[0] ).' textarea{width:100%}.'.esc_attr( $keys[0] ).' textarea{min-height:150px}.'.esc_attr( $keys[0] ).'>div{margin-bottom:16px}.'.esc_attr( $keys[0] ).' button{background-position:-999999px -9999999px !important}.'.esc_attr( $keys[0] ).'.ef-progress button{background-position:center !important;pointer-events:none !important}'; |
| 126 |
$output .= '</style>'; |
| 127 |
$output .= '<div id="fw-'.esc_attr( $keys[0] ).'-'.$s.'" class="'.esc_attr( $keys[0] ).'-wrp ef-ctrl-wrp">'; |
| 128 |
$output .= '<div id="'.esc_attr( $keys[7] ).'-'.$s.'" style="display:none" class="ef-success">'.esc_html( $success_message ).'</div>'; |
| 129 |
$output .= '<div id="'.esc_attr( $keys[8] ).'-'.$s.'" style="display:none" class="ef-error"></div>'; |
| 130 |
$output .= '<form id="'.esc_attr( $keys[0] ).'-'.$s.'" class="'.esc_attr( $keys[0] ).'">'; |
| 131 |
$output = apply_filters( 'essential_form_before_name', $output, $post, $settings, $atts ); |
| 132 |
$output .= '<div class="ef-ctrl-wrp">'; |
| 133 |
$output .= '<div><label for="'.esc_attr( $keys[1] ).'-'.$s.'">'.esc_html( $label_name ).'</label></div>'; |
| 134 |
$output .= '<div><input type="text" id="'.esc_attr( $keys[1] ).'-'.$s.'" class="'.esc_attr( $keys[1] ).'" required /></div>'; |
| 135 |
$output .= '</div>'; |
| 136 |
$output = apply_filters( 'essential_form_after_name', $output, $post, $settings, $atts ); |
| 137 |
$output .= '<div class="ef-ctrl-wrp">'; |
| 138 |
$output .= '<div><label for="'.esc_attr( $keys[2] ).'-'.$s.'">'.esc_html( $label_email ).'</label></div>'; |
| 139 |
$output .= '<div><input type="email" id="'.esc_attr( $keys[2] ).'-'.$s.'" class="'.esc_attr( $keys[2] ).'" required /></div>'; |
| 140 |
$output .= '</div>'; |
| 141 |
$output = apply_filters( 'essential_form_after_email', $output, $post, $settings, $atts ); |
| 142 |
$output .= '<div class="ef-ctrl-wrp">'; |
| 143 |
$output .= '<div><label for="'.esc_attr( $keys[3] ).'-'.$s.'">'.esc_html( $label_message ).'</label></div>'; |
| 144 |
$output .= '<div><textarea id="'.esc_attr( $keys[3] ).'-'.$s.'" class="'.esc_attr( $keys[3] ).'" required></textarea></div>'; |
| 145 |
$output .= '</div>'; |
| 146 |
$output = apply_filters( 'essential_form_after_message', $output, $post, $settings, $atts ); |
| 147 |
$checkbox_required = ''; |
| 148 |
$checkbox_wrapper_style = ' style="display:none"'; |
| 149 |
if( ! defined( 'ESSENTIAL_FORM_ASK_FOR_AGREEMENT' ) || ESSENTIAL_FORM_ASK_FOR_AGREEMENT ) { |
| 150 |
$checkbox_required = ' ' . apply_filters( 'essential_form_agreement_checkbox_required', 'required' ); |
| 151 |
$checkbox_wrapper_style = ''; |
| 152 |
} |
| 153 |
$checkbox_input_style = ' required' === $checkbox_required ? '' : ' style="display:none"'; |
| 154 |
$output .= '<div' . $checkbox_wrapper_style . '><input' . $checkbox_input_style . ' type="checkbox" id="'.esc_attr( $keys[4] ).'-'.$s.'" class="'.esc_attr( $keys[4] ).'"' . $checkbox_required . ' value="on" /> '.wp_kses( $agreement_text ,array( 'a' => array( 'href' => array(),'target' => array() ) ) ).'</div>'; |
| 155 |
$output = apply_filters( 'essential_form_after_checkbox', $output, $post, $settings, $atts ); |
| 156 |
$output .= '<div><button id="'.esc_attr( $keys[3] ).'-'.$s.'" type="submit" class="button" style="background-size:22px 22px !important;background-repeat:no-repeat !important;background-image:url('.includes_url( '/images/spinner.gif' ).') !important" onclick="essential_form_'.sanitize_key( $keys[0] ).'('.$s.');return false;">'.esc_html( $button_text ).'</div>'; |
| 157 |
$output = apply_filters( 'essential_form_after_submit', $output, $post, $settings, $atts ); |
| 158 |
$output .= '<input type="hidden" value="'.esc_attr( implode( ',',$keys ) ).'" id="'.esc_attr( $keys[5] ).'-'.$s.'" />'; |
| 159 |
$output .= '<input type="hidden" value="" id="'.esc_attr( $keys[6] ).'-'.$s.'" />'; |
| 160 |
$output .= '</form>'; |
| 161 |
$output .= '<div id="'.esc_attr( $keys[8] ).'-'.$s.'" style="margin-bottom:16px"></div>'; |
| 162 |
$output .= '</div>'; |
| 163 |
if( 1 === $s ){ |
| 164 |
$output .= '<script id="'.esc_attr( $keys[0] ).'-'.$s.'-js" type="text/javascript">'; |
| 165 |
$output .= 'essential_form_random_key = Math.floor(Math.random() * 99999999999999);'; |
| 166 |
$output .= 'function essential_form_'.sanitize_key( $keys[0] ).'_init(){'; |
| 167 |
$output .= 'var r = new XMLHttpRequest(),f=new FormData();'; |
| 168 |
$output .= 'r.open("POST","'.esc_js( admin_url( 'admin-ajax.php' ) ).'?action='.ESSENTIAL_FORM_AJAX_KEY.'_get_key",true);'; |
| 169 |
$output .= 'r.onload = function(e){'; |
| 170 |
$output .= 'if(this.readyState === 4 && "" !== e.target.responseText){'; |
| 171 |
$output .= 'document.getElementById("'.esc_attr( $keys[6] ).'-'.$s.'").value = e.target.responseText;'; |
| 172 |
$output .= '}'; |
| 173 |
$output .= '};'; |
| 174 |
$output .= 'f.append("random_key",essential_form_random_key);'; |
| 175 |
$output .= 'r.send(f);'; |
| 176 |
$output .= '}'; |
| 177 |
$output .= 'essential_form_'.sanitize_key( $keys[0] ).'_init();'; |
| 178 |
$output .= 'function essential_form_'.sanitize_key( $keys[0] ).'(n){'; |
| 179 |
$output .= 'var req = new XMLHttpRequest(),fd=new FormData(),succ=document.getElementById("'.esc_attr( $keys[7] ).'-'.$s.'"),err=document.getElementById("'.esc_attr( $keys[8] ).'-'.$s.'"),fe=document.getElementById("'.esc_attr( $keys[0] ).'-" + n);'; |
| 180 |
$output .= 'fe.className += " ef-progress";'; |
| 181 |
$output .= 'succ.style.display="none";'; |
| 182 |
$output .= 'err.style.display="none";'; |
| 183 |
$output .= 'req.onload = function(e){'; |
| 184 |
$output .= 'if(this.readyState === 4 && "" !== e.target.responseText){'; |
| 185 |
$output .= 'if("1" === e.target.responseText){'; |
| 186 |
$output .= 'succ.style.display="block";'; |
| 187 |
$output .= 'err.style.display="none";'; |
| 188 |
$output .= 'document.getElementById("'.esc_attr( $keys[0] ).'-'.$s.'").style.visibility="hidden";'; |
| 189 |
$output .= '}else{'; |
| 190 |
$output .= 'err.style.display="block";'; |
| 191 |
$output .= 'err.innerHTML=e.target.responseText;'; |
| 192 |
$output .= '}'; |
| 193 |
$output .= '}'; |
| 194 |
$output .= 'fe.className = fe.className.replace(" ef-progress","");'; |
| 195 |
$output .= 'return false;'; |
| 196 |
$output .= '};'; |
| 197 |
$f = 1; |
| 198 |
foreach( essential_form_fields_array() as $fkey ){ |
| 199 |
if( 'agreement' === $fkey ){ |
| 200 |
$output .= 'fd.append("'.esc_js( esc_attr( $fkey ) ).'",document.getElementById("'.esc_js( esc_attr( $keys[$f] ) ).'-" + n).checked);'; |
| 201 |
} |
| 202 |
elseif( false === strpos( $fkey, 'custom_' ) ){ |
| 203 |
$output .= 'fd.append("'.esc_js( esc_attr( $fkey ) ).'",document.getElementById("'.esc_js( esc_attr( $keys[$f] ) ).'-" + n).value);'; |
| 204 |
} |
| 205 |
++$f; |
| 206 |
} |
| 207 |
$output .= apply_filters( 'essential_form_append_custom_field', '' ); |
| 208 |
global $post; |
| 209 |
if( $post && is_object( $post ) && isset( $post->ID ) ){ |
| 210 |
$output .= 'fd.append("post_id",'.absint( $post->ID ).');'; |
| 211 |
} |
| 212 |
$output .= 'fd.append("random_key",essential_form_random_key);'; |
| 213 |
$output .= 'req.open("POST","'.esc_js( admin_url( 'admin-ajax.php' ) ).'?action='.ESSENTIAL_FORM_AJAX_KEY.'",true);'; |
| 214 |
$output .= 'req.send(fd);'; |
| 215 |
$output .= 'return false;'; |
| 216 |
$output .= '}'; |
| 217 |
$output .= '</script>'; |
| 218 |
} |
| 219 |
return $output; |
| 220 |
} |
| 221 |
} ); |
| 222 |
|
| 223 |
// Return array of fields. |
| 224 |
function essential_form_fields_array(){ |
| 225 |
return apply_filters( 'essential_form_fields_array', array( |
| 226 |
'name', |
| 227 |
'email', |
| 228 |
'message', |
| 229 |
'agreement', |
| 230 |
'keys', |
| 231 |
'temp_key' |
| 232 |
) ); |
| 233 |
} |
| 234 |
|
| 235 |
// Get keys for the anti-spam system. |
| 236 |
function essential_form_get_keys(){ |
| 237 |
$keys = false; |
| 238 |
$opts = essential_form_get_option( 'essential_form' ); |
| 239 |
if( $opts && isset( $opts['activation_keys'] ) ){ |
| 240 |
$keys = $opts['activation_keys']; |
| 241 |
foreach( $keys as &$key ){ |
| 242 |
$key = 'f'.sanitize_text_field( substr( md5( $key ),0,8 ) ); |
| 243 |
} |
| 244 |
} |
| 245 |
return $keys; |
| 246 |
} |
| 247 |
|
| 248 |
add_filter( 'plugin_action_links_'.untrailingslashit( plugin_basename( __FILE__ ) ),function( $links ) { |
| 249 |
// It action links in the plugins page. |
| 250 |
$links[] = sprintf( 'Shortcode: %s','<span class="ef-shortcode" style="color:#000">[essential_form]</span>' ); |
| 251 |
$links[] = '<a href="https://wordpress.org/plugins/essential-form/" target="_blank" rel="noopener">'.esc_html__( 'Description','essential-form' ).'</a>'; |
| 252 |
return $links; |
| 253 |
} ); |
| 254 |
|
| 255 |
add_action( 'init',function(){ |
| 256 |
// It loads plugin translation files. |
| 257 |
load_plugin_textdomain( 'essential-form',false,ESSENTIAL_FORM_PLUGIN_DIR.'/languages/' ); |
| 258 |
} ); |
| 259 |
|
| 260 |
add_filter( 'load_textdomain_mofile',function( $mofile,$domain ){ |
| 261 |
// Filter function to read plugin translation files. |
| 262 |
if ( 'essential-form' === $domain ) { |
| 263 |
$loc = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale(); |
| 264 |
$mofile = ESSENTIAL_FORM_PLUGIN_DIR . '/languages/essential-form-' . $loc . '.mo'; |
| 265 |
} |
| 266 |
return $mofile; |
| 267 |
},10,2 ); |
| 268 |
|
| 269 |
|
| 270 |
// Helper function to add custom field. |
| 271 |
function essential_form_add_field( $slug, $type, $title, $required = false, $near_field = 'message', $error_message = false, $field_class = '' ) { |
| 272 |
require_once ESSENTIAL_FORM_PLUGIN_DIR . '/classes/ef-class-add-fields-factory.php'; |
| 273 |
$new_field = new Essential_Form_Fields_Factory( $slug, $type, $title, $required, $near_field, $error_message, $field_class ); |
| 274 |
} |