ALL countries in checkout, although allowed_countries set correctly

We had the problem, that we have a short list of countries we ship to:

Country list configuration in the backend shows a filtered list

But the country list for the invoice and shipping address in the checkout is complete.

Country select in the checkout shows all countries to choose from

Config

The configuration is fine as you can see above. I checked the cache, because I thought it might be wrong - but the config cache too was fine.

Cache

Digging into the issue shows, that more caches are involved:

\Mage_Checkout_Block_Onepage_Abstract::getCountryOptions
public function getCountryOptions()
{
    $options    = false;
    $useCache   = Mage::app()->useCache('config');
    if ($useCache) {
        $cacheId    = 'DIRECTORY_COUNTRY_SELECT_STORE_' . Mage::app()->getStore()->getCode();
        $cacheTags  = array('config');
        if ($optionsCache = Mage::app()->loadCache($cacheId)) {
            $options = unserialize($optionsCache);
        }
    }

    if ($options == false) {
        $options = $this->getCountryCollection()->toOptionArray();
        if ($useCache) {
            Mage::app()->saveCache(serialize($options), $cacheId, $cacheTags);
        }
    }
    return $options;
}

So I checked the cache entries for DIRECTORY_COUNTRY_SELECT_STORE_DE and found a complete list of countries. So the assumption is: Something "poisons" the cache.

So, what is writing into this cache and maybe we have a broken extension - we don't.

\Mage_XmlConnect_Model_Simplexml_Form_Element_CountryListSelect::_getCountryOptions
\Mage_XmlConnect_Block_Checkout_Address_Form::_getCountryOptions
\Mage_Directory_Block_Data::getCountryHtmlSelect
\Mage_Checkout_Block_Onepage_Abstract::getCountryOptions
\Mage_Catalog_Model_Product_Attribute_Source_Countryofmanufacture::getAllOptions

If we look further into it, we can assume the problem is not from here:

\Mage_XmlConnect_Block_Checkout_Address_Form::_getCountryOptions
\Mage_XmlConnect_Model_Simplexml_Form_Element_CountryListSelect::_getCountryOptions
\Mage_Checkout_Block_Onepage_Abstract::getCountryOptions
\Mage_Directory_Block_Data::getCountryHtmlSelect

because all of them filter the country list via Mage::getModel('directory/country')->getResourceCollection()->loadByStore();, therefore the filter of the config is applied.

\Mage_Catalog_Model_Product_Attribute_Source_Countryofmanufacture

The source model doesn't do correct filtering.

How is the cache filled with wrong data?

This is the tricky part. The only place were I know the source model is used is the backend. But Mage::app()->getStore()->getCode() is always admin. Even when you edit data for another store view.

After digging a while I found out, that when I place a configurable product into the cart one of our extensions reads the country of manufacturer in the frontend and poisons the cache.

I fixed the problem with a rewrite:

class Project_Bugfix_Model_Catalog_Product_Attribute_Source_Countryofmanufacture
    extends Mage_Catalog_Model_Product_Attribute_Source_Countryofmanufacture
{
    /**
     * Get list of all available countries
     *
     * @return mixed
     */
    public function getAllOptions()
    {
        $cacheKey = 'DIRECTORY_COUNTRY_SELECT_STORE_' . Mage::app()->getStore()->getCode();
        if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
            $options = unserialize($cache);
        } else {
            if (Mage::app()->getStore()->isAdmin()) {
                $collection = Mage::getModel('directory/country')->getResourceCollection();
            } else {
                $collection = Mage::getModel('directory/country')->getResourceCollection()->loadByStore();
            }
            $options = $collection->toOptionArray();

            if (Mage::app()->useCache('config')) {
                Mage::app()->saveCache(serialize($options), $cacheKey, ['config']);
            }
        }
        return $options;
    }   
}