Skip to content

Instantly share code, notes, and snippets.

@xlplugins
Last active April 8, 2025 10:44
Show Gist options
  • Save xlplugins/cac2be4a5b18964007ca7860bf74f8ff to your computer and use it in GitHub Desktop.
Save xlplugins/cac2be4a5b18964007ca7860bf74f8ff to your computer and use it in GitHub Desktop.
Funnelkit Checkout: WooCommerce Checkout Field Special Character Validator
class WFACP_Field_Validator {
/**
* Disallowed characters in checkout fields
*/
private $disallowed_chars = array( '-', '#', '/', '\\', '=', '<', '>', '(', ')' );
/**
* Fields to validate against disallowed characters
*/
private $fields_to_validate = array(
'billing_first_name',
'billing_last_name',
'billing_address_1',
'billing_address_2',
'billing_city',
'billing_state',
'billing_postcode',
'billing_country',
'shipping_address_1',
'shipping_address_2',
'shipping_city',
'shipping_state',
'shipping_postcode',
'shipping_country'
);
/**
* Constructor
*/
public function __construct() {
// Add validation hook for WooCommerce checkout process
add_action('woocommerce_checkout_process', array($this, 'validate_checkout_fields'));
// For AJAX validation (if needed)
add_filter('woocommerce_checkout_fields', array($this, 'add_field_validation'));
}
/**
* Validate checkout fields for disallowed characters
*/
public function validate_checkout_fields() {
try {
$posted_data = $_POST;
$has_error = false;
foreach ($this->fields_to_validate as $field) {
if (isset($posted_data[$field]) && !empty($posted_data[$field])) {
$value = $posted_data[$field];
foreach ($this->disallowed_chars as $char) {
if (strpos($value, $char) !== false) {
// Add error message
$field_label = $this->get_field_label($field);
wc_add_notice(sprintf(__('Special character "%s" is not allowed in %s field.', 'woocommerce'), $char, $field_label), 'error');
$has_error = true;
break; // Break out of character loop after first error for this field
}
}
}
}
// Return result for possible external use
return !$has_error;
} catch (Exception $e) {
// Log the error
if (function_exists('error_log')) {
error_log('WFACP field validation error: ' . $e->getMessage());
}
return false;
}
}
/**
* Get readable field label
*
* @param string $field_key Field key
* @return string Readable field label
*/
private function get_field_label($field_key) {
$field_labels = array(
'billing_first_name' => 'Billing First Name',
'billing_last_name' => 'Billing Last Name',
'billing_address_1' => 'Billing Address',
'billing_address_2' => 'Billing Address Line 2',
'billing_city' => 'Billing City',
'billing_state' => 'Billing State',
'billing_postcode' => 'Billing Postcode',
'billing_country' => 'Billing Country',
'shipping_address_1' => 'Shipping Address',
'shipping_address_2' => 'Shipping Address Line 2',
'shipping_city' => 'Shipping City',
'shipping_state' => 'Shipping State',
'shipping_postcode' => 'Shipping Postcode',
'shipping_country' => 'Shipping Country'
);
return isset($field_labels[$field_key]) ? $field_labels[$field_key] : $field_key;
}
/**
* Add JS validation (optional - for better UX)
*/
public function add_field_validation($fields) {
// List of disallowed chars for JS
$disallowed_chars_js = implode('', $this->disallowed_chars);
$disallowed_chars_js = preg_quote($disallowed_chars_js, '/');
// Add pattern validation to each field
foreach ($this->fields_to_validate as $field_key) {
$type = explode('_', $field_key)[0]; // billing or shipping
$name = str_replace($type . '_', '', $field_key); // field name without prefix
if (isset($fields[$type][$field_key])) {
// Add custom validation class
if (!isset($fields[$type][$field_key]['class'])) {
$fields[$type][$field_key]['class'] = array();
}
$fields[$type][$field_key]['class'][] = 'wfacp-special-char-validate';
// You could add HTML5 pattern validation here, but it's complicated with these characters
// Instead, we'll rely on the PHP server-side validation
}
}
// Add JavaScript for client-side validation (for better UX)
add_action('wp_footer', array($this, 'add_validation_script'));
return $fields;
}
/**
* Add client-side validation script
*/
public function add_validation_script() {
// Convert disallowed chars to JS-safe string
$disallowed_chars_js = json_encode($this->disallowed_chars);
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
// List of disallowed characters
var disallowedChars = <?php echo $disallowed_chars_js; ?>;
// Fields to validate
var fieldsToValidate = <?php echo json_encode($this->fields_to_validate); ?>;
// Function to check for disallowed characters
function checkDisallowedChars(value) {
for (var i = 0; i < disallowedChars.length; i++) {
if (value.indexOf(disallowedChars[i]) !== -1) {
return disallowedChars[i];
}
}
return false;
}
// Validate on input change
fieldsToValidate.forEach(function(field) {
$(document.body).on('change', '#' + field, function() {
var $this = $(this);
var value = $this.val();
var foundChar = checkDisallowedChars(value);
// Clear previous error
$this.removeClass('wfacp-error');
$this.next('.wfacp-error-message').remove();
// Add error if disallowed character found
if (foundChar) {
// $this.addClass('wfacp-error');
$this.after('<span class="wfacp-error-message">Special character "' + foundChar + '" is not allowed.</span>');
}
});
});
// Validate on form submission
$(document.body).on('checkout_place_order', function() {
var hasError = false;
fieldsToValidate.forEach(function(field) {
var $field = $('#' + field);
var value = $field.val();
if (value) {
var foundChar = checkDisallowedChars(value);
if (foundChar) {
hasError = true;
// $field.addClass('wfacp-error');
// Only add message if it doesn't exist
if ($field.next('.wfacp-error-message').length === 0) {
$field.after('<span class="wfacp-error-message">Special character "' + foundChar + '" is not allowed.</span>');
}
// Scroll to first error
if ($('.wfacp-error').first().length) {
$('html, body').animate({
scrollTop: $('.wfacp-error').first().offset().top - 100
}, 500);
}
}
}
});
return !hasError;
});
});
</script>
<style>
.wfacp-error {
border-color: #e2401c !important;
}
.wfacp-error-message {
color: #e2401c;
display: block;
margin-top: 5px;
font-size: 0.857em;
}
</style>
<?php
}
}
// Initialize the validator
new WFACP_Field_Validator();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment