Skip to content

Refactor HTTP Input functions to fix null edge-case bug and enable unit testing #2

@charlesroper

Description

@charlesroper

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+1AAfilter_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,
        ],
    ]);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions