cancel
Showing results for 
Search instead for 
Did you mean: 

ProductRepository does not always respect scope or emulation

ProductRepository does not always respect scope or emulation

Feature request from rhoerr, posted on GitHub Feb 23, 2016

In brief: There seems to be an issue with \Magento\Catalog\Model\ProductRepository whereby it does not respect emulation, nor does it correctly identify the current scope in all situations.

The primary result of this when saving a product through ProductRepository from an affected scope is that (1) some attributes are saved in the fallback scope (default store) when that would not be expected, and (2) it seems to be impossible to associate a product to multiple websites.

Magento version: EE 2.0.2 Context: A custom controller in the admin panel extending \Magento\Backend\App\Action, for importing configurable products.

Tracing the issue:

\Magento\Catalog\Api\ProductRepositoryInterface is injected into the controller via DI. We load $product, already having website_ids = [1, 2] (for reasons unclear, these are not returned by $product->getWebsiteIds().) We call $this->productRepository->save($product); \Magento\Catalog\Model\ProductRepository::save() calls ProductRepository->initializeProductData() calls ProductRepository->assignProductToWebsites() calls ProductRepository->storeManager->getStore() (\Magento\Store\Model\StoreManager) Having no currentStoreId, StoreManager calls StoreManager->storeResolver->getCurrentStoreId() (\Magento\Store\Model\StoreResolver) calls StoreResolver->getStoresData() StoreResolver was initialized by DI with no runMode or scopeCode, therefore $this->runMode defaults to 'website', and $this->scopeCode defaults to 'null'. With this state, StoreResolver::getStoresData() returns:

Array
(
    [0] => Array // $stores
        (
            [0] => 1
        )

    [1] => 1 // $defaultStoreId
)

$store is loaded based on $defaultStoreId and returned to ProductRepository. Bottom line: This results in ProductRepository->storeManager->getStore()->getCode() returning 'default', despite that we are in the admin scope.

Starting emulation on the admin store prior to this process has no bearing on the outcome.

Passing in a parameter of ___store='admin' has no bearing on the outcome (because admin is not a valid website code).

Expected behavior is that ProductRepository obeys the scope of whatever context it is called from, including emulation.

1 Comment
Regular Visitor

The same behavior occurs in my case.

That's why magento can not find the correct allowed countries in checkout select.

It searches in the wrong store configuration.