Problem
I need to gain access to the children blocks from the parent block alias of customer_account_navigation
from the frontend layout to be used in the adminhtml system configuration.
Current Attempt
As the code is being run in the admin area (adminhtml) I assume emulation is required in order to retrieve anything from the frontend, I have used the $appState->emulateAreaCode
method which has a call back and the initialised the ObjectManager
as frontend.
class AccountLinks implements \Magento\Framework\Option\ArrayInterface
{
protected $_options = [];
/**
* @var \Magento\Framework\ObjectManagerInterface
*/
protected $_objectManager;
/**
* @var \Magento\Framework\ObjectManager\ConfigLoaderInterface
*/
protected $_configLoader;
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectManager,
\Magento\Framework\ObjectManager\ConfigLoaderInterface $configLoader
)
{
$this->_objectManager = $objectManager;
$this->_configLoader = $configLoader;
}
/**
* Retrieve my account menu links.
*
* @return array
*/
public function toOptionArray()
{
if (!$this->_options) {
/* @var $appState \Magento\Framework\App\State */
$appState = $this->_objectManager->get('Magento\Framework\App\State');
$appState->emulateAreaCode('frontend', [$this, 'emulateDesignCallback']);
}
return $this->_options;
}
public function emulateDesignCallback()
{
$this->_objectManager->configure($this->_configLoader->load('frontend'));
/* @var $layout \Magento\Framework\View\Layout */
$layout = $this->_objectManager->create('\Magento\Framework\View\LayoutInterface');
$layout->getUpdate()->addHandle('default');
$layout->getUpdate()->addHandle('customer_account_index');
$layout->getUpdate()->load();
$layout->generateXml();
$layout->generateElements();
$blocks = $layout->getChildBlocks('customer_account_navigation');
return $this;
}
}
Debugging
I can see 2 frontend blocks which seems to imply that using addHandle
is not working correctly to generate the correct blocks.
I am also unsure if I am loading the layout after setting the handles correctly.
The _configScope
is incorrectly saying it's current scope is adminhtml even with the emulation, I wonder if this is causing the problem but I can't work out how to set it
Any ideas? Thanks.
Best Answer
I have a solution, whether it is a good one I am not sure about but it does work. Disadvantages is that you have to have the
Magento/blank
theme installed and uses xpath so if Magento change their layout declaration it might break, both quite unlikely scenarios.Here is my final solution:
It doesn't use
appState
emulation, I would be interested in seeing an example that involves using it to access layout as I have bypassed a ton of abstraction in order to get a working solution but I tried many things and couldn't get it to register the frontend handle and return the child blocks.