Fixed Entity column LIST_COMMA/LIST_LINES does not round-trip with integer sub-style

Xon

Well-known member
Affected version
2.0.3
If you have an entity column LIST_COMMA/LIST_LINES, with a list sub-type of integer, it will not round trip as expected.

This is because decodeValueFromSource ignores the sub-tyle information while applyValueConstraints applies it.

Column definition;
PHP:
$structure->columns['extra_user_group_ids'] = ['type' => self::LIST_COMMA, 'default' => [],
   'list' => ['type' => 'posint', 'unique' => true, 'sort' => SORT_NUMERIC]
]

On the request setting:
PHP:
$entity->extra_user_group_ids= [1,2,3,4];

var_dump($entity->extra_user_group_ids);
returns:
PHP:
array(4) {
  [0] => int(1)
  [1] => int(2)
  [2] => int(3)
  [3] =>int(4)
}

On future requests (ie not loaded from cache)
PHP:
var_dump($entity->extra_user_group_ids);
returns:
PHP:
array(4) {
  [0] => string(1) "1"
  [1] => string(1) "2"
  [2] => string(1) "3"
  [3] => string(1) "4"
}

Since decodeValueFromSource 's handling of LIST_COMMA/LIST_LINES is to use `explode()`, these will be string-types no integer types.
 
Note; _columnValueIsDifferent() (and thus isChanged())) always returns true if you set an integer list since decodeValueFromSource returns a list of strings.
 
I think if decodeValueFromSource did array_map('intval', $list) for integer-like lists would be enough.
Wouldn't it be much better to make use of value formatter instead of making it hard use intval?

Something like this worked very well for me
PHP:
    public function getProperIsEarthFlat()
    {
        $isEarthFlatValues = $this->getExistingValue('is_earth_flat');
        $column = $this->structure()->columns['is_earth_flat'];
        $this->em()->getValueFormatter()->applyValueConstraints($isEarthFlatValues, $column['type'], $column, $error);
        return $isEarthFlatValues;
    }
 
Last edited:
This has been fixed now. There's a new ValueFormatter::decodeValueFromSourceExtended() method that takes the full set of column options as well, which allows us to react to things like the list type. Places that used to call decodeValueFromSource will now call the extended version (though that internally calls the old method, in case you have extended that).

This should allow the values to be consistent before and after updating.
 
Back
Top Bottom