Bulk Action Validator
Validates selected IDs, action name, CSRF, and permission before bulk admin actions.
Function signature
ogValidateBulkActionRequest(post_data = array(), policy = array())
Categories
- Security
Parameters
post_dataPOST-derived request data already selected by the caller for bulk-action validation.policyCaller-approved workflow policy for the ecommerce, admin, privacy, or export decision.Return value
Public-safe status string returned by the function for explicit controller branching or logging.
- success
- message
- data
Compatibility
Existing function name, slug, path, and call order preserved; advertised metadata corrected to the actual source behavior.
Minimum PHP version: 7.4
Security notes
Use caller-owned allowlists and context-specific escaping; validate admin actions, export fields, privacy plans, cache keys, templates, settings, routes, and ecommerce policies before production use.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Validates selected IDs, action name, CSRF token, and role before a bulk admin action.
*
* This function returns a validated request plan. It does not execute deletes,
* updates, exports, or any other destructive work.
*
* @param array $post_data Submitted POST-style data.
* @param array $policy Allowed actions, roles, max IDs, and CSRF settings.
* @return array Validated bulk action request or errors.
*/
function ogValidateBulkActionRequest($post_data = array(), $policy = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($post_data)) {
$result['message'] = 'Submitted data must be an array.';
return $result;
}
if (!is_array($policy)) {
$policy = array();
}
$allowed_actions = array();
if (!empty($policy['allowed_actions']) && is_array($policy['allowed_actions'])) {
$allowed_actions = $policy['allowed_actions'];
}
$allowed_roles = array('admin');
if (!empty($policy['allowed_roles']) && is_array($policy['allowed_roles'])) {
$allowed_roles = $policy['allowed_roles'];
}
$max_ids = 100;
if (!empty($policy['max_ids'])) {
$max_ids = (int)$policy['max_ids'];
}
if ($max_ids < 1) {
$max_ids = 1;
}
$errors = array();
$action = '';
if (!empty($post_data['action'])) {
$action = trim((string)$post_data['action']);
}
$user_role = '';
if (!empty($post_data['user_role'])) {
$user_role = trim((string)$post_data['user_role']);
}
if (empty($action) || !in_array($action, $allowed_actions, true)) {
$errors[] = 'Bulk action is not allowed.';
}
if (empty($user_role) || !in_array($user_role, $allowed_roles, true)) {
$errors[] = 'User role is not allowed for this bulk action.';
}
if (!empty($policy['csrf_token'])) {
$expected = (string)$policy['csrf_token'];
$submitted = '';
if (!empty($post_data['csrf_token'])) {
$submitted = (string)$post_data['csrf_token'];
}
if (empty($submitted) || !hash_equals($expected, $submitted)) {
$errors[] = 'Invalid request token.';
}
}
$ids = array();
if (!empty($post_data['selected_ids']) && is_array($post_data['selected_ids'])) {
foreach ($post_data['selected_ids'] as $id) {
$id = (int)$id;
if ($id > 0 && !in_array($id, $ids, true)) {
$ids[] = $id;
}
}
}
if (empty($ids)) {
$errors[] = 'No valid IDs were selected.';
}
if (count($ids) > $max_ids) {
$errors[] = 'Too many IDs were selected.';
}
$result['success'] = empty($errors);
if (empty($errors)) {
$result['message'] = 'Bulk action request validated.';
} else {
$result['message'] = 'Bulk action request failed validation.';
}
$result['data'] = array(
'action' => $action,
'user_role' => $user_role,
'selected_ids' => $ids,
'errors' => $errors
);
return $result;
}