Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions assets/scripts/wplf-admin-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ $(document).ready(function() {
'<div class="wplf-form-field widget-top"><div class="widget-title"><h4>' + $(this).prop('name') + '</h4></div></div>'
);

// check if we are in nojs fallback state and show warning if user uses input name reserved for WordPress core
if( wplf.nojs_fallback && $.inArray( $(this).prop('name'), wplf.wp_reserved_names ) > -1 ) {
$fieldbox.css('border-color', '#dc3232');
$fieldbox.css('color', '#dc3232');
$fieldbox.find('h4').append('<br><br><i style="font-weight:400;white-space:normal;line-height:1.2em;">' + wplf.is_wp_reserved_name + '</i>');
}

if( $(this).prop('required') ) {
// mark as required field for validation
$fieldbox.addClass('required');
Expand Down
6 changes: 6 additions & 0 deletions assets/scripts/wplf-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
!function(t){function e(){}function n(t,e){return function(){t.apply(e,arguments)}}function o(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(t,this)}function r(t,e){for(;3===t._state;)t=t._value;return 0===t._state?void t._deferreds.push(e):(t._handled=!0,void a(function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null===n)return void(1===t._state?i:f)(e.promise,t._value);var o;try{o=n(t._value)}catch(r){return void f(e.promise,r)}i(e.promise,o)}))}function i(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var r=e.then;if(e instanceof o)return t._state=3,t._value=e,void u(t);if("function"==typeof r)return void s(n(r,e),t)}t._state=1,t._value=e,u(t)}catch(i){f(t,i)}}function f(t,e){t._state=2,t._value=e,u(t)}function u(t){2===t._state&&0===t._deferreds.length&&a(function(){t._handled||d(t._value)});for(var e=0,n=t._deferreds.length;n>e;e++)r(t,t._deferreds[e]);t._deferreds=null}function c(t,e,n){this.onFulfilled="function"==typeof t?t:null,this.onRejected="function"==typeof e?e:null,this.promise=n}function s(t,e){var n=!1;try{t(function(t){n||(n=!0,i(e,t))},function(t){n||(n=!0,f(e,t))})}catch(o){if(n)return;n=!0,f(e,o)}}var l=setTimeout,a="function"==typeof setImmediate&&setImmediate||function(t){l(t,0)},d=function(t){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",t)};o.prototype["catch"]=function(t){return this.then(null,t)},o.prototype.then=function(t,n){var o=new this.constructor(e);return r(this,new c(t,n,o)),o},o.all=function(t){var e=Array.prototype.slice.call(t);return new o(function(t,n){function o(i,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(t){o(i,t)},n)}e[i]=f,0===--r&&t(e)}catch(c){n(c)}}if(0===e.length)return t([]);for(var r=e.length,i=0;i<e.length;i++)o(i,e[i])})},o.resolve=function(t){return t&&"object"==typeof t&&t.constructor===o?t:new o(function(e){e(t)})},o.reject=function(t){return new o(function(e,n){n(t)})},o.race=function(t){return new o(function(e,n){for(var o=0,r=t.length;r>o;o++)t[o].then(e,n)})},o._setImmediateFn=function(t){a=t},o._setUnhandledRejectionFn=function(t){d=t},"undefined"!=typeof module&&module.exports?module.exports=o:t.Promise||(t.Promise=o)}(this);

(function() {

// remove nojs fallback marker from forms
[].forEach.call(document.querySelectorAll(".libre-form .wplf-nojs"), function(element) {
element.parentNode.removeChild(element);
});

window.wplf = {
successCallbacks: [],
errorCallbacks: [],
Expand Down
149 changes: 147 additions & 2 deletions classes/class-cpt-wplf-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private function __construct() {
add_action( 'wp', array( $this, 'maybe_set_404_for_single_form' ) );
add_filter( 'the_content', array( $this, 'use_shortcode_for_preview' ), 0 );
add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_frontend_script' ) );
add_action( 'init', array( $this, 'maybe_do_nojs_submit' ) );

// default filters for the_content, but we don't want to use actual the_content
add_filter( 'wplf_form', 'convert_smilies' );
Expand Down Expand Up @@ -148,6 +149,11 @@ function admin_post_scripts_cpt( $hook ) {

// enqueue the custom JS for this view
wp_enqueue_script( 'wplf-form-edit-js', plugins_url( 'assets/scripts/wplf-admin-form.js', dirname( __FILE__ ) ) );
wp_localize_script( 'wplf-form-edit-js', 'wplf', array(
'nojs_fallback' => apply_filters( 'wplf_form_nojs_fallback', false ),
'wp_reserved_names' => $this->get_wp_reserved_terms(),
'is_wp_reserved_name' => __( 'Name of this field is <a href="#wplf-wp-reserved-names">reserved for WordPress</a> and may conflict with core functionality when no-js fallback is used.', 'wp-libre-form' )
) );
}


Expand Down Expand Up @@ -268,6 +274,18 @@ function add_meta_boxes_cpt() {
'high'
);

// Maybe WP reserved terms meta box
if ( apply_filters( 'wplf_form_nojs_fallback', false ) ) {
add_meta_box(
'wplf-wp-reserved-names',
__( 'Field names reserved for WordPress', 'wp-libre-form' ),
array( $this, 'metabox_wp_reserved_terms' ),
'wplf-form',
'normal',
'high'
);
}

// Form Fields meta box
add_meta_box(
'wplf-fields',
Expand Down Expand Up @@ -328,6 +346,20 @@ function metabox_thank_you( $post ) {
wp_nonce_field( 'wplf_form_meta', 'wplf_form_meta_nonce' );
}

/**
* Meta box callback for displaying reserved terms
*/
function metabox_wp_reserved_terms() {
?>
<p><?php _e( 'Following field names are reserved for WordPress and may conflict with core functionality when no-js fallback is used. Please avoid using these terms.', 'wp-libre-form' ) ?></p>
<ul style="list-style:disc;padding-left:20px;">
<?php foreach ( $this->get_wp_reserved_terms() as $term ) : ?>
<li><?php echo $term; ?></li>
<?php endforeach; ?>
</ul>
<?php
}


/**
* Meta box callback for form fields meta box
Expand Down Expand Up @@ -499,6 +531,10 @@ function strip_form_tags( $content ) {
function wplf_form( $id, $content = '', $xclass = '', $attributes = [] ) {
global $post;

if ( isset( $_GET['wplf_success'] ) ) {
return apply_filters( 'the_content', get_post_meta( $id, '_wplf_thank_you', true ) );
}

if ( 'publish' === get_post_status( $id ) || 'true' === $_GET['preview'] ) {
$form = get_post( $id );
if ( empty( $content ) ) {
Expand All @@ -525,12 +561,16 @@ class="libre-form libre-form-<?php echo esc_attr( $id . ' ' . $xclass ); ?>"
|| false !== strpos( $content, 'type=file' )
) : ?>
enctype="multipart/form-data"
<?php endif; ?>
<?php
<?php endif;

// add custom attributes from shortcode to <form> element
foreach ( $attributes as $attr_name => $attr_value ) {
echo esc_attr( $attr_name ) . '="' . esc_attr( $attr_value ) . "\"\n";
}

if ( apply_filters( 'wplf_form_nojs_fallback', false ) ) : ?>
method="post"
<?php endif;
?>
>
<?php if ( is_singular( 'wplf-form' ) && current_user_can( 'edit_post', $id ) ) : ?>
Expand All @@ -556,8 +596,14 @@ class="libre-form libre-form-<?php echo esc_attr( $id . ' ' . $xclass ); ?>"
<input type="hidden" name="referrer" value="<?php the_permalink(); ?>">
<input type="hidden" name="_referrer_id" value="<?php echo esc_attr( get_the_id() ) ?>">
<input type="hidden" name="_form_id" value="<?php echo esc_attr( $id ); ?>">
<input type="hidden" class="wplf-nojs" name="_wplf_nojs" />
</form>
<?php

if ( ! empty( $_GET['wplf_error'] ) ) {
return apply_filters( 'the_content', urldecode( $_GET['wplf_error'] ) );
}

$output = ob_get_clean();

// enqueue our footer script here
Expand Down Expand Up @@ -593,6 +639,15 @@ function maybe_enqueue_frontend_script() {
) );
}

/**
* Handle form subission when nojs fallback is on and javascript is not used on submit
*/
function maybe_do_nojs_submit() {
if ( apply_filters( 'wplf_form_nojs_fallback', false ) && isset( $_POST['_wplf_nojs'] ) ) {
wplf_ajax_submit_handler( true );
}
}


/**
* Shortcode for displaying a Form
Expand Down Expand Up @@ -662,6 +717,96 @@ function get_publicly_visible_state( $id ) {
function minify_html( $html ) {
return str_replace( array( "\n", "\r" ), ' ', $html );
}

/**
* Get terms that are reserved for WordPress core
*/
function get_wp_reserved_terms() {
return apply_filters( 'wplf-wp-reserved-terms', array(
'attachment',
'attachment_id',
'author',
'author_name',
'calendar',
'cat',
'category',
'category__and',
'category__in',
'category__not_in',
'category_name',
'comments_per_page',
'comments_popup',
'custom',
'customize_messenger_channel',
'customized',
'cpage',
'day',
'debug',
'embed',
'error',
'exact',
'feed',
'hour',
'link_category',
'm',
'minute',
'monthnum',
'more',
'name',
'nav_menu',
'nonce',
'nopaging',
'offset',
'order',
'orderby',
'p',
'page',
'page_id',
'paged',
'pagename',
'pb',
'perm',
'post',
'post__in',
'post__not_in',
'post_format',
'post_mime_type',
'post_status',
'post_tag',
'post_type',
'posts',
'posts_per_archive_page',
'posts_per_page',
'preview',
'robots',
's',
'search',
'second',
'sentence',
'showposts',
'static',
'subpost',
'subpost_id',
'tag',
'tag__and',
'tag__in',
'tag__not_in',
'tag_id',
'tag_slug__and',
'tag_slug__in',
'taxonomy',
'tb',
'term',
'terms',
'theme',
'title',
'type',
'w',
'withcomments',
'withoutcomments',
'year',
) );
}
}

endif;
21 changes: 17 additions & 4 deletions inc/wplf-ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

add_action( 'wp_ajax_wplf_submit', 'wplf_ajax_submit_handler' );
add_action( 'wp_ajax_nopriv_wplf_submit', 'wplf_ajax_submit_handler' );
function wplf_ajax_submit_handler() {
function wplf_ajax_submit_handler( $is_nojs_fallback_call = false ) {
$return = new stdClass();
$return->ok = 1;

Expand Down Expand Up @@ -88,7 +88,20 @@ function wplf_ajax_submit_handler() {
do_action( "wplf_{$form->ID}_post_validate_submission", $return );
}

// respond with json
wp_send_json( $return );
wp_die();
// Respond with json if was a js call
if ( ! $is_nojs_fallback_call ) {
wp_send_json( $return );
wp_die();
} else {
if( $return->ok ) {
$nojs_redirect = get_permalink( $_POST['_referrer_id'] ) . '?wplf_success=true';
$nojs_redirect = apply_filters( 'wplf_nojs_success_redirect', $nojs_redirect );
$nojs_redirect = apply_filters( "wplf_$form->post_name}_nojs_success_redirect", $nojs_redirect );
$nojs_redirect = apply_filters( "wplf_{$form->ID}_nojs_success_redirect", $nojs_redirect );
} else {
$nojs_redirect = get_permalink( $_POST['_referrer_id'] ) . '?wplf_error=' . urlencode( $return->error );
}

wp_safe_redirect( $nojs_redirect );
}
}