-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Background
Currently, getDecileInt() and decileForInput() in src/functions.php use filter_input(INPUT_GET). This tightly couples them to the global HTTP request state, which makes them impossible to unit test without complex mocking infrastructure (as noted in TESTING.md).
The Bug
There is a subtle edge-case bug hiding in getDecileInt():
If a user submits the HTML form leaving the decile blank, the browser sends ?p=SW1A+1AA&d=. filter_input processes the empty string, fails the validation, and falls back to the default of 10. This works perfectly.
However, if someone shares a link and manually strips the d parameter entirely—e.g., index.php?p=SW1A+1AA—filter_input returns null because the variable doesn't exist. Casting (int)null results in 0. The SQL query will then execute AND imd_decile <= 0 and return no results.
The Solution
Refactor the function to accept an optional injected parameter and use filter_var instead of filter_input. This fixes the null bug and makes the function 100% unit-testable.
Proposed Code Change:
function getDecileInt(?string $input = null): int
{
// Use injected input, or fallback to $_GET
$val = $input ?? $_GET['d'] ?? null;
// Handle strictly missing or empty string explicitly
if ($val === null || $val === '') {
return 10;
}
return (int)filter_var($val, FILTER_VALIDATE_INT, [
'options' => [
'default' => 10,
'min_range' => 1,
'max_range' => 10,
],
]);
}