diff --git a/app/code/Magento/Sitemap/Model/EmailNotification.php b/app/code/Magento/Sitemap/Model/EmailNotification.php new file mode 100644 index 0000000000000..27c042870a1d6 --- /dev/null +++ b/app/code/Magento/Sitemap/Model/EmailNotification.php @@ -0,0 +1,105 @@ +inlineTranslation = $inlineTranslation; + $this->scopeConfig = $scopeConfig; + $this->transportBuilder = $transportBuilder; + $this->logger = $logger; + } + + /** + * Send's error email if sitemap generated with errors. + * + * @param array| $errors + */ + public function sendErrors($errors) + { + $this->inlineTranslation->suspend(); + try { + $this->transportBuilder->setTemplateIdentifier( + $this->scopeConfig->getValue( + Observer::XML_PATH_ERROR_TEMPLATE, + ScopeInterface::SCOPE_STORE + ) + )->setTemplateOptions( + [ + 'area' => FrontNameResolver::AREA_CODE, + 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, + ] + )->setTemplateVars( + ['warnings' => join("\n", $errors)] + )->setFrom( + $this->scopeConfig->getValue( + Observer::XML_PATH_ERROR_IDENTITY, + ScopeInterface::SCOPE_STORE + ) + )->addTo( + $this->scopeConfig->getValue( + Observer::XML_PATH_ERROR_RECIPIENT, + ScopeInterface::SCOPE_STORE + ) + ); + + $transport = $this->transportBuilder->getTransport(); + $transport->sendMessage(); + } catch (\Exception $e) { + $this->logger->error('Sitemap sendErrors: '.$e->getMessage()); + } finally { + $this->inlineTranslation->resume(); + } + } +} diff --git a/app/code/Magento/Sitemap/Model/Observer.php b/app/code/Magento/Sitemap/Model/Observer.php index a536ec998b827..bd7a84f601b77 100644 --- a/app/code/Magento/Sitemap/Model/Observer.php +++ b/app/code/Magento/Sitemap/Model/Observer.php @@ -5,6 +5,12 @@ */ namespace Magento\Sitemap\Model; +use Magento\Store\Model\App\Emulation; +use Magento\Sitemap\Model\EmailNotification as SitemapEmail; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Sitemap\Model\ResourceModel\Sitemap\CollectionFactory; +use Magento\Store\Model\ScopeInterface; + /** * Sitemap module observer * @@ -44,47 +50,40 @@ class Observer * * @var \Magento\Framework\App\Config\ScopeConfigInterface */ - protected $_scopeConfig; + private $scopeConfig; /** * @var \Magento\Sitemap\Model\ResourceModel\Sitemap\CollectionFactory */ - protected $_collectionFactory; - - /** - * @var \Magento\Framework\Mail\Template\TransportBuilder - */ - protected $_transportBuilder; + private $collectionFactory; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var Emulation */ - protected $_storeManager; + private $appEmulation; /** - * @var \Magento\Framework\Translate\Inline\StateInterface + * @var $emailNotification */ - protected $inlineTranslation; + private $emailNotification; /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Sitemap\Model\ResourceModel\Sitemap\CollectionFactory $collectionFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder - * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + * Observer constructor. + * @param ScopeConfigInterface $scopeConfig + * @param CollectionFactory $collectionFactory + * @param EmailNotification $emailNotification + * @param Emulation $appEmulation */ public function __construct( - \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Sitemap\Model\ResourceModel\Sitemap\CollectionFactory $collectionFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, - \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation + ScopeConfigInterface $scopeConfig, + CollectionFactory $collectionFactory, + SitemapEmail $emailNotification, + Emulation $appEmulation ) { - $this->_scopeConfig = $scopeConfig; - $this->_collectionFactory = $collectionFactory; - $this->_storeManager = $storeManager; - $this->_transportBuilder = $transportBuilder; - $this->inlineTranslation = $inlineTranslation; + $this->scopeConfig = $scopeConfig; + $this->collectionFactory = $collectionFactory; + $this->appEmulation = $appEmulation; + $this->emailNotification = $emailNotification; } /** @@ -97,61 +96,39 @@ public function __construct( public function scheduledGenerateSitemaps() { $errors = []; - + $recipient = $this->scopeConfig->getValue( + Observer::XML_PATH_ERROR_RECIPIENT, + ScopeInterface::SCOPE_STORE + ); // check if scheduled generation enabled - if (!$this->_scopeConfig->isSetFlag( + if (!$this->scopeConfig->isSetFlag( self::XML_PATH_GENERATION_ENABLED, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ScopeInterface::SCOPE_STORE ) ) { return; } - $collection = $this->_collectionFactory->create(); + $collection = $this->collectionFactory->create(); /* @var $collection \Magento\Sitemap\Model\ResourceModel\Sitemap\Collection */ foreach ($collection as $sitemap) { /* @var $sitemap \Magento\Sitemap\Model\Sitemap */ try { + $this->appEmulation->startEnvironmentEmulation( + $sitemap->getStoreId(), + \Magento\Framework\App\Area::AREA_FRONTEND, + true + ); + $sitemap->generateXml(); } catch (\Exception $e) { $errors[] = $e->getMessage(); + } finally { + $this->appEmulation->stopEnvironmentEmulation(); } } - - if ($errors && $this->_scopeConfig->getValue( - self::XML_PATH_ERROR_RECIPIENT, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - ) { - $this->inlineTranslation->suspend(); - - $this->_transportBuilder->setTemplateIdentifier( - $this->_scopeConfig->getValue( - self::XML_PATH_ERROR_TEMPLATE, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - )->setTemplateOptions( - [ - 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, - ] - )->setTemplateVars( - ['warnings' => join("\n", $errors)] - )->setFrom( - $this->_scopeConfig->getValue( - self::XML_PATH_ERROR_IDENTITY, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - )->addTo( - $this->_scopeConfig->getValue( - self::XML_PATH_ERROR_RECIPIENT, - \Magento\Store\Model\ScopeInterface::SCOPE_STORE - ) - ); - $transport = $this->_transportBuilder->getTransport(); - $transport->sendMessage(); - - $this->inlineTranslation->resume(); + if ($errors && $recipient) { + $this->emailNotification->sendErrors($errors); } } } diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/EmailNotificationTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/EmailNotificationTest.php new file mode 100644 index 0000000000000..eafb47c086bac --- /dev/null +++ b/app/code/Magento/Sitemap/Test/Unit/Model/EmailNotificationTest.php @@ -0,0 +1,134 @@ +objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class) + ->getMock(); + $this->scopeConfigMock = $this->getMockBuilder(ScopeConfigInterface::class) + ->getMock(); + $this->transportBuilderMock = $this->getMockBuilder(TransportBuilder::class) + ->disableOriginalConstructor() + ->getMock(); + $this->inlineTranslationMock = $this->getMockBuilder(StateInterface::class) + ->getMock(); + + $this->objectManager = new ObjectManager($this); + $this->model = $this->objectManager->getObject( + EmailNotification::class, + [ + 'inlineTranslation' => $this->inlineTranslationMock, + 'scopeConfig' => $this->scopeConfigMock, + 'transportBuilder' => $this->transportBuilderMock, + ] + ); + } + + public function testSendErrors() + { + $exception = 'Sitemap Exception'; + $transport = $this->createMock(TransportInterface::class); + + $this->scopeConfigMock->expects($this->at(0)) + ->method('getValue') + ->with( + Observer::XML_PATH_ERROR_TEMPLATE, + ScopeInterface::SCOPE_STORE + ) + ->willReturn('error-recipient@example.com'); + + $this->inlineTranslationMock->expects($this->once()) + ->method('suspend'); + + $this->transportBuilderMock->expects($this->once()) + ->method('setTemplateIdentifier') + ->will($this->returnSelf()); + + $this->transportBuilderMock->expects($this->once()) + ->method('setTemplateOptions') + ->with([ + 'area' => FrontNameResolver::AREA_CODE, + 'store' => Store::DEFAULT_STORE_ID, + ]) + ->will($this->returnSelf()); + + $this->transportBuilderMock->expects($this->once()) + ->method('setTemplateVars') + ->with(['warnings' => $exception]) + ->will($this->returnSelf()); + + $this->transportBuilderMock->expects($this->once()) + ->method('setFrom') + ->will($this->returnSelf()); + + $this->transportBuilderMock->expects($this->once()) + ->method('addTo') + ->will($this->returnSelf()); + + $this->transportBuilderMock->expects($this->once()) + ->method('getTransport') + ->willReturn($transport); + + $transport->expects($this->once()) + ->method('sendMessage'); + + $this->inlineTranslationMock->expects($this->once()) + ->method('resume'); + + $this->model->sendErrors(['Sitemap Exception']); + } +} diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/ObserverTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/ObserverTest.php index ac88f23ff9d69..5fae54ff3c5d0 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/ObserverTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/ObserverTest.php @@ -5,10 +5,14 @@ */ namespace Magento\Sitemap\Test\Unit\Model; +use Magento\Framework\App\Area; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Sitemap\Model\EmailNotification; +use Magento\Store\Model\App\Emulation; /** * Class ObserverTest + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ObserverTest extends \PHPUnit\Framework\TestCase @@ -33,21 +37,6 @@ class ObserverTest extends \PHPUnit\Framework\TestCase */ private $collectionFactoryMock; - /** - * @var \Magento\Framework\Mail\Template\TransportBuilder|\PHPUnit_Framework_MockObject_MockObject - */ - private $transportBuilderMock; - - /** - * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $storeManagerMock; - - /** - * @var \Magento\Framework\Translate\Inline\StateInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $inlineTranslationMock; - /** * @var \Magento\Sitemap\Model\ResourceModel\Sitemap\Collection|\PHPUnit_Framework_MockObject_MockObject */ @@ -63,6 +52,16 @@ class ObserverTest extends \PHPUnit\Framework\TestCase */ private $objectManagerMock; + /** + * @var Emulation|\PHPUnit_Framework_MockObject_MockObject + */ + private $appEmulationMock; + + /** + * @var EmailNotification|\PHPUnit_Framework_MockObject_MockObject + */ + private $emailNotificationMock; + protected function setUp() { $this->objectManagerMock = $this->getMockBuilder(\Magento\Framework\ObjectManagerInterface::class) @@ -74,28 +73,28 @@ protected function setUp() )->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->transportBuilderMock = $this->getMockBuilder(\Magento\Framework\Mail\Template\TransportBuilder::class) - ->disableOriginalConstructor() - ->getMock(); - $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class) - ->getMock(); - $this->inlineTranslationMock = $this->getMockBuilder(\Magento\Framework\Translate\Inline\StateInterface::class) - ->getMock(); $this->sitemapCollectionMock = $this->createPartialMock( \Magento\Sitemap\Model\ResourceModel\Sitemap\Collection::class, ['getIterator'] ); - $this->sitemapMock = $this->createPartialMock(\Magento\Sitemap\Model\Sitemap::class, ['generateXml']); - + $this->sitemapMock = $this->createPartialMock( + \Magento\Sitemap\Model\Sitemap::class, + [ + 'generateXml', + 'getStoreId', + ] + ); + $this->appEmulationMock = $this->createMock(Emulation::class); + $this->emailNotificationMock = $this->createMock(EmailNotification::class); $this->objectManager = new ObjectManager($this); + $this->observer = $this->objectManager->getObject( \Magento\Sitemap\Model\Observer::class, [ 'scopeConfig' => $this->scopeConfigMock, 'collectionFactory' => $this->collectionFactoryMock, - 'storeManager' => $this->storeManagerMock, - 'transportBuilder' => $this->transportBuilderMock, - 'inlineTranslation' => $this->inlineTranslationMock + 'appEmulation' => $this->appEmulationMock, + 'emailNotification' => $this->emailNotificationMock ] ); } @@ -103,7 +102,7 @@ protected function setUp() public function testScheduledGenerateSitemapsSendsExceptionEmail() { $exception = 'Sitemap Exception'; - $transport = $this->createMock(\Magento\Framework\Mail\TransportInterface::class); + $storeId = 1; $this->scopeConfigMock->expects($this->once())->method('isSetFlag')->willReturn(true); @@ -115,11 +114,15 @@ public function testScheduledGenerateSitemapsSendsExceptionEmail() ->method('getIterator') ->willReturn(new \ArrayIterator([$this->sitemapMock])); - $this->sitemapMock->expects($this->once()) + $this->sitemapMock->expects($this->at(0)) + ->method('getStoreId') + ->willReturn($storeId); + + $this->sitemapMock->expects($this->at(1)) ->method('generateXml') ->willThrowException(new \Exception($exception)); - $this->scopeConfigMock->expects($this->at(1)) + $this->scopeConfigMock->expects($this->at(0)) ->method('getValue') ->with( \Magento\Sitemap\Model\Observer::XML_PATH_ERROR_RECIPIENT, @@ -127,43 +130,16 @@ public function testScheduledGenerateSitemapsSendsExceptionEmail() ) ->willReturn('error-recipient@example.com'); - $this->inlineTranslationMock->expects($this->once()) - ->method('suspend'); - - $this->transportBuilderMock->expects($this->once()) - ->method('setTemplateIdentifier') - ->will($this->returnSelf()); - - $this->transportBuilderMock->expects($this->once()) - ->method('setTemplateOptions') - ->with([ - 'area' => \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE, - 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, - ]) - ->will($this->returnSelf()); - - $this->transportBuilderMock->expects($this->once()) - ->method('setTemplateVars') - ->with(['warnings' => $exception]) - ->will($this->returnSelf()); - - $this->transportBuilderMock->expects($this->once()) - ->method('setFrom') - ->will($this->returnSelf()); - - $this->transportBuilderMock->expects($this->once()) - ->method('addTo') - ->will($this->returnSelf()); - - $this->transportBuilderMock->expects($this->once()) - ->method('getTransport') - ->willReturn($transport); - - $transport->expects($this->once()) - ->method('sendMessage'); + $this->appEmulationMock->expects($this->at(0)) + ->method('startEnvironmentEmulation') + ->with( + $storeId, + Area::AREA_FRONTEND, + true + ); - $this->inlineTranslationMock->expects($this->once()) - ->method('resume'); + $this->appEmulationMock->expects($this->at(1)) + ->method('stopEnvironmentEmulation'); $this->observer->scheduledGenerateSitemaps(); }