I have a PHP script (Wordpress plugin) which attempts to offer a workaround for missing feature Blocklist for moderating listings by blocking Wordpress web forms data submission/update, in case form data contains blocklisted/blacklisted phrases (defined in a text file).
But HivePress at /account/listings/1234/ still reports “Changes have been saved.” (despite the listing was not updated and a browser dev. console shows XHR request forbidden 403. /submit-listing/details/ just reloads/clears the form without bothering to explain what happened.
Please what to replace by what so the user is informed that their submission (no matter if new or update) failed. Maybe ideally mentioning what was the blocked string (it may contain any character incl. ‘ “ ; fancy text: Lᴜᴄʏ).
Following PHP code may by used as a WP plugin /wp-content/plugins/global-form-blocker/global-form-blocker.php while the blocklist would be at /wp-content/plugins/global-form-blocker/blocked-phrases.txt (one string per line)
<?php
/*
Plugin Name: Global Form Blocker
Description: Avoid any web form submission if it contains words/strings/phrases contained in the file /wp-content/plugins/global-form-blocker/blocked-phrases.txt
Version: 1.0
*/
if (!defined('ABSPATH')) exit;
// 1. Path to file
$file = __DIR__ . '/blocked-phrases.txt';
// 2. Check File Existence Immediately
if (!file_exists($file)) {
// Force error for ALL contexts
if (defined('DOING_AJAX') && DOING_AJAX) {
wp_send_json_error(['message' => 'CRITICAL ERROR: Blocklist file blocked-phrases.txt of a form input filtering plugin is missing.']);
} else {
die('<h1>CRITICAL ERROR</h1><p>Blocklist file blocked-phrases.txt of a form input filtering plugin is missing.</p>');
}
}
// 3. Load Phrases
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$phrases = array_map('trim', $lines);
// 4. Main Check Logic
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input_data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
$blocked = false;
$reason = '';
foreach ($phrases as $phrase) {
if (empty($phrase)) continue;
// ESCAPE the phrase for regex to handle quotes, slashes, etc.
// We do NOT use \b (word boundary) because it breaks on quotes like s'pam
// We just search for the exact escaped string
$escaped_phrase = preg_quote($phrase, '/');
// Case insensitive search
if (preg_match('/' . $escaped_phrase . '/i', $input_data)) {
$blocked = true;
$reason = "Blocked phrase detected: " . esc_html($phrase);
break;
}
}
if ($blocked) {
// FORCE STOP AND RETURN ERROR
if (defined('DOING_AJAX') && DOING_AJAX) {
// HIVEPRESS SPECIFIC FIX:
// HivePress expects a specific JSON structure.
// We return 'success' => false and put the message in 'data' => 'message'
wp_send_json_error([
'message' => $reason,
'errors' => ['_general' => $reason] // HivePress looks here sometimes
]);
exit; // Hard exit
}
// Non-AJAX fallback
if (ob_get_level()) ob_end_clean();
header('HTTP/1.1 403 Forbidden');
die('<h1>Submission Blocked</h1><p>' . $reason . '</p>');
}
}
// 5. HIVEPRESS SPECIFIC HOOK - HARD STOP WITH 403
add_filter('hivepress/v1/forms/*/submit/response', function($response, $form) {
$file = __DIR__ . '/blocked-phrases.txt';
// 1. Check File
if (!file_exists($file)) {
status_header(403);
header('Content-Type: application/json');
echo json_encode([
'success' => false,
'message' => 'CRITICAL ERROR: Blocklist file missing.',
'errors' => ['_general' => 'CRITICAL ERROR: Blocklist file missing.']
]);
exit;
}
$lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$phrases = array_map('trim', $lines);
$input_data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
foreach ($phrases as $phrase) {
if (empty($phrase)) continue;
$escaped = preg_quote($phrase, '/');
if (preg_match('/' . $escaped . '/i', $input_data)) {
// 2. FORCE 403 HEADER AND EXIT
status_header(403);
header('Content-Type: application/json');
// Manually build JSON to ensure no escaping issues with quotes
$error_msg = 'BLOCKED: Your submission contains restricted content: "' . $phrase . '"';
echo json_encode([
'success' => false,
'message' => $error_msg,
'errors' => [
'_general' => $error_msg,
'form' => $error_msg
]
]);
exit; // CRITICAL: Stop execution immediately
}
}
return $response;
}, 1, 2);
If any donation is needed, please forward your payment address and amount via PM.