Description
Preconditions (*)
- Magento 2.2.7 (need to confirm but likely 2.3 still has issue)
Steps to reproduce (*)
- Create two configurable attributes (A and B) as text/visual swatches, each with multiple options
- Create configurable products for both A and B
- Change attribute A to be a dropdown
Expected result (*)
- Product configurable on attribute A displays as dropdown
- Product configurable on attribute B displays still as swatch
Actual result (*)
- Products with both attribute A and B both display as a dropdown
- Products configurable on attribute B display a javascript error (need to reconfirm this)
If you look at table eav_attribute_option_swatch, once the attributes are made this is populated with options for both attributes. After changing the type of attribute A back to dropdown this table clears completely, removing both the swatch option data for attribute A and (incorrectly) attribute B.
The cause of this looks to be the fix put in place for #12695. Code was added to clear down the entries for this table when changing an attribute from swatch to dropdown, but there was an error in construction of the SQL meaning that the WHERE statement got partially cleared, so that too much data gets cleared.
Here is the code that causes the issue, from app/code/Magento/Swatches/Model/ResourceModel/Swatch.php:
public function clearSwatchOptionByOptionIdAndType($optionIDs, $type = null)
{
if (count($optionIDs)) {
foreach ($optionIDs as $optionId) {
$where = ['option_id' => $optionId];
if ($type !== null) {
$where['type = ?'] = $type;
}
$this->getConnection()->delete($this->getMainTable(), $where);
}
}
}
The line that causes the problem is $where = ['option_id' => $optionId];
. When the data is passed to the Zend framework, it expects the format to be ['option_id = ?' => optionId]
. This is because Zend will look for the '?' to strip out (whilst preparing the SQL, it uses this for data binding). So if the '= ?' is missing Zend will strip out the intended field value. This turns the SQL into a DELETE FROM eav_attribute_option_swatch WHERE (option_id);
hence why the table is cleared down.
We have added a plugin on our installation to replace this missing = ?
and this seems to resolve it in 2.2.7.
Checking 2.3, the same error is still in the Swatch.php, so we suspect this is still an issue on that version.