Fixed Possible bug in XenForo_DataWriter::get()

Yoskaldyr

Well-known member
Datawriter get() method returns existing data if new data setted to null.
Example:
PHP:
$dw = XenForo_DataWriter::create('Some_DataWriter_Class');
$dw->setExistingData($someId);
$a = $dw->get('somekey'); //$a = 'somedata';
$dw->set('somekey', 'newdata');
$a = $dw->get('somekey'); //$a = 'newdata';
$dw->set('somekey', null);
$a = $dw->get('somekey'); //$a = 'somedata'; not null as expected
$dw->save(); //in db somekey field saved as null
Possible fix for this, replace XenForo_DataWriter::get() with code:
PHP:
    public function get($field, $tableName = '')
    {
        $tables = $this->_getTableList($tableName);
 
        foreach ($tables AS $tableName)
        {
            if (
                isset($this->_newData[$tableName])
                && is_array($this->_newData[$tableName])
                && array_key_exists($field, $this->_newData[$tableName])
            )
            {
                return $this->_newData[$tableName][$field];
            }
            else if (
                isset($this->_existingData[$tableName])
                && is_array($this->_existingData[$tableName])
                && array_key_exists($field, $this->_existingData[$tableName])
            )
            {
                return $this->_existingData[$tableName][$field];
            }
        }
 
        return null;
    }
 
I've never seen setting something to null inside of the DW, but nevermind:D

This change breaks at least one DataWriter method (isChanged), so this would need to be changed too if this is considered as bug and gets implemented

PHP:
public function isChanged($field, $tableName = '')
{
return ($this->getNew($field, $tableName) !== null);
}

if you set the new field to null, it's changed, but the method isChanged would return false

PHP:
$dw = XenForo_DataWriter::create('XenForo_DataWriter_User');
$dw->setExistingData(array('user_id' => 1));
$dw->set('custom_title', 'new title');
echo '1 ' . $dw->get('custom_title') ;
$dw->set('custom_title', null);
echo "\n2 " .  $dw->get('custom_title');
if ($dw->isChanged('custom_title')){
echo "\n isChanged";
}
$dw->set('custom_title', 'new one');
echo "\n3 ".  $dw->get('custom_title') ;
if ($dw->isChanged('custom_title')){
echo "\n isChanged";
}
$dw->preSave();


would output
Code:
1 new title
2
3 new one
4 isChanged

your code fixes the problem and line 2 is empty, but the isChanged method returned false instead of true:)
 
Back
Top Bottom