Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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