Question

I need to pass the content of the order items table from the new order email to an external service. In Magento 1 I used this approach and it worked fine:

      $appEmulation = Mage::getSingleton('core/app_emulation');                                                                  
      $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($order->getStoreId());                                  
      $layout = Mage::getModel('core/layout');                                                                                   
      $layoutUpdate = $layout->getUpdate();                                                                                      
      $layoutUpdate->load('sales_email_order_items');                                                                            
      $layout->generateXml();                                                                                                    
      $layout->generateBlocks();                                                                                                 
      $items = $layout->getBlock('items');                                                                                       
      $items->setOrder($order);                                                                                                  
      $orderItemsHtml = $items->toHtml();                                                                                        
      $appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);            
                                                                                   
      return $orderItemsHtml;       

I use this approach instead of rendering the block directly because various extensions extend the layout that is used to create that table.

I'm trying to port this to M2 and struggle to get access the order block.

I tried various versions but the layout never seems to be loaded. I.e.

public function __construct(                                                     
    \Magento\Framework\View\Result\PageFactory $pageFactory                    
)                                                                                
{                                                                                                                                                   
    $this->pageFactory = $pageFactory;                                       
}

...

protected function getOrderItemsHtml($order)      
    $emulation->startEnvironmentEmulation($order->getStoreId(), \Magento\Framework\App\Area::AREA_FRONTEND, true);

    /** @var \Magento\Framework\View\Result\Page */                          
    $page = $this->pageFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE);
    $page->addHandle('sales_email_order_items');                             
    $blocks = $page->getLayout()->getAllBlocks();                             
    var_dump(array_keys($blocks)); die;       
}

This will output:

array (size=1)
  0 => string 'messages' (length=8)

If anyone has any idea what I'm missing or if anyone can point me to an alternative approach for this I would be very grateful. Thanks!

Was it helpful?

Solution

Ok figured it out. The problem is that in M2 you have to emulate the area code as well. Allan Storm has an article on that.

The final working solution looks like this:

  protected function getOrderItemsHtml($order)                                                                                                      
  {                                                                            
      $emulation = $this->emulation;                                                                                                                
      $layoutFactory = $this->layoutFactory;                                                                                                        
                                                                                                                                                    
      $orderItemsHtml = $this->appState->emulateAreaCode(                                                                                           
          \Magento\Framework\App\Area::AREA_FRONTEND,                                                                                               
          function() use ($order, $emulation, $layoutFactory) {                                                                                     
              $emulation->startEnvironmentEmulation($order->getStoreId(), \Magento\Framework\App\Area::AREA_FRONTEND, true);                        
                                                                                                                                                    
              $page = $layoutFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_PAGE);                                               
              $page->addHandle('sales_email_order_items');                       
              $block = $page->getLayout()->getBlock('items');                  
              $block->setData('order', $order);                                
              $orderItemsHtml = $block->toHtml();                              
                                                                               
              $this->emulation->stopEnvironmentEmulation();                    
                                                                               
              return $orderItemsHtml;                                          
          }                                                                    
      );                                                                       
                                                                               
      return $orderItemsHtml;                                                                                                                       
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top