XF options do not round-trip integer/boolean values as expected

Xon

Well-known member
Affected version
2.3.6
PHP:
var_dump(\XF::Options()->changeLogLength);

$option = Helper::find(\XF\Entity\Option::class, 'changeLogLength');
$option->option_value = 0;
var_dump($option->option_value);

Both of these will output a string type instead of the expected int type. This matters because xf-dev:generate-options-stub CLI command gives strongly typed hints, and phpstorm (and other php code formatting tools) will suggest to unwrap any casts. Except the underlying type is stringy so strict checks (=== / !==) will unexpectedly fail.

The solution appears for \XF\Entity\getOptionValue() and \XF\Entity\getDefaultValue() to call castOptionValue instead of the partial customized version of castOptionValue. Or if castOptionValue is too strict using isDataTypeNumeric before casting to an int
 
Last edited:
Something like:
PHP:
public function getOptionValue()
{
    $v = $this->option_value_;
    if ($this->isDataTypeNumeric())
    {
        return (int)$v;
    }
    else if ($this->data_type === 'bool')
    {
        return (bool)$v;
    }
    else if ($this->data_type === 'array')
    {
        $value = json_decode($v, true);
        if (!is_array($value))
        {
            return [];
        }

        return $value;
    }
   
    return $v;
}

But duplicating this code for getDefaultValue feels kinda wrong, especially as it is largely duplicating castOptionValue but without any throw statements.
 
Instead of a raw cast to int, something like strval(floatval($v)) + 0; should be used as that handles floats+ints
 
Back
Top Bottom