diff --git a/app/code/Magento/Cms/Controller/Adminhtml/Page/PostDataProcessor.php b/app/code/Magento/Cms/Controller/Adminhtml/Page/PostDataProcessor.php index 6150991be15f5..687a2b558a08a 100644 --- a/app/code/Magento/Cms/Controller/Adminhtml/Page/PostDataProcessor.php +++ b/app/code/Magento/Cms/Controller/Adminhtml/Page/PostDataProcessor.php @@ -6,6 +6,14 @@ */ namespace Magento\Cms\Controller\Adminhtml\Page; +use Magento\Cms\Model\Page\DomValidationState; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\Config\Dom\ValidationException; + +/** + * Class PostDataProcessor + * @package Magento\Cms\Controller\Adminhtml\Page + */ class PostDataProcessor { /** @@ -23,19 +31,28 @@ class PostDataProcessor */ protected $messageManager; + /** + * @var DomValidationState + */ + private $validationState; + /** * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory + * @param DomValidationState $validationState */ public function __construct( \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter, \Magento\Framework\Message\ManagerInterface $messageManager, - \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory + \Magento\Framework\View\Model\Layout\Update\ValidatorFactory $validatorFactory, + DomValidationState $validationState = null ) { $this->dateFilter = $dateFilter; $this->messageManager = $messageManager; $this->validatorFactory = $validatorFactory; + $this->validationState = $validationState + ?: ObjectManager::getInstance()->get(DomValidationState::class); } /** @@ -61,27 +78,27 @@ public function filter($data) * Validate post data * * @param array $data - * @return bool Return FALSE if someone item is invalid + * @return bool Return FALSE if some item is invalid */ public function validate($data) { - $errorNo = true; if (!empty($data['layout_update_xml']) || !empty($data['custom_layout_update_xml'])) { - /** @var $validatorCustomLayout \Magento\Framework\View\Model\Layout\Update\Validator */ - $validatorCustomLayout = $this->validatorFactory->create(); - if (!empty($data['layout_update_xml']) && !$validatorCustomLayout->isValid($data['layout_update_xml'])) { - $errorNo = false; - } - if (!empty($data['custom_layout_update_xml']) - && !$validatorCustomLayout->isValid($data['custom_layout_update_xml']) - ) { - $errorNo = false; - } - foreach ($validatorCustomLayout->getMessages() as $message) { - $this->messageManager->addError($message); + /** @var $layoutXmlValidator \Magento\Framework\View\Model\Layout\Update\Validator */ + $layoutXmlValidator = $this->validatorFactory->create( + [ + 'validationState' => $this->validationState, + ] + ); + + if (!$this->validateData($data, $layoutXmlValidator)) { + $validatorMessages = $layoutXmlValidator->getMessages(); + foreach ($validatorMessages as $message) { + $this->messageManager->addErrorMessage($message); + } + return false; } } - return $errorNo; + return true; } /** @@ -108,4 +125,32 @@ public function validateRequireEntry(array $data) } return $errorNo; } + + /** + * Validate data, avoid cyclomatic complexity + * + * @param array $data + * @param \Magento\Framework\View\Model\Layout\Update\Validator $layoutXmlValidator + * @return bool + */ + private function validateData($data, $layoutXmlValidator) + { + try { + if (!empty($data['layout_update_xml']) && !$layoutXmlValidator->isValid($data['layout_update_xml'])) { + return false; + } + if (!empty($data['custom_layout_update_xml']) && + !$layoutXmlValidator->isValid($data['custom_layout_update_xml']) + ) { + return false; + } + } catch (ValidationException $e) { + return false; + } catch (\Exception $e) { + $this->messageManager->addExceptionMessage($e, $e->getMessage()); + return false; + } + + return true; + } } diff --git a/app/code/Magento/Cms/Model/Page/DomValidationState.php b/app/code/Magento/Cms/Model/Page/DomValidationState.php new file mode 100644 index 0000000000000..2dc75b62fbbda --- /dev/null +++ b/app/code/Magento/Cms/Model/Page/DomValidationState.php @@ -0,0 +1,26 @@ +_domConfigFactory = $domConfigFactory; $this->_initMessageTemplates(); @@ -73,6 +83,8 @@ public function __construct( 'urn:magento:framework:View/Layout/etc/layout_merged.xsd' ), ]; + $this->validationState = $validationState + ?: ObjectManager::getInstance()->get(ValidationStateInterface::class); } /** @@ -115,7 +127,13 @@ public function isValid($value, $schema = self::LAYOUT_SCHEMA_PAGE_HANDLE, $isSe try { //wrap XML value in the "layout" and "handle" tags to make it validatable $value = '' . $value . ''; - $this->_domConfigFactory->createDom(['xml' => $value, 'schemaFile' => $this->_xsdSchemas[$schema]]); + $this->_domConfigFactory->createDom( + [ + 'xml' => $value, + 'schemaFile' => $this->_xsdSchemas[$schema], + 'validationState' => $this->validationState, + ] + ); if ($isSecurityCheck) { $value = new \Magento\Framework\Simplexml\Element($value); diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/Update/ValidatorTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/Update/ValidatorTest.php index 771bace3fe6ee..7269a51a3ba67 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/Update/ValidatorTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Model/Layout/Update/ValidatorTest.php @@ -5,7 +5,7 @@ */ namespace Magento\Framework\View\Test\Unit\Model\Layout\Update; -use \Magento\Framework\View\Model\Layout\Update\Validator; +use Magento\Framework\View\Model\Layout\Update\Validator; class ValidatorTest extends \PHPUnit_Framework_TestCase { @@ -14,6 +14,11 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase */ protected $_objectHelper; + /** + * @var \Magento\Framework\Config\ValidationStateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $validationState; + protected function setUp() { $this->_objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -27,7 +32,10 @@ protected function setUp() protected function _createValidator($layoutUpdate, $isSchemaValid = true) { $domConfigFactory = $this->getMockBuilder( - 'Magento\Framework\Config\DomFactory' + \Magento\Framework\Config\DomFactory::class + )->disableOriginalConstructor()->getMock(); + $this->validationState = $this->getMockBuilder( + \Magento\Framework\Config\ValidationStateInterface::class )->disableOriginalConstructor()->getMock(); $urnResolver = new \Magento\Framework\Config\Dom\UrnResolver(); @@ -35,6 +43,7 @@ protected function _createValidator($layoutUpdate, $isSchemaValid = true) 'xml' => '' . trim($layoutUpdate) . '', 'schemaFile' => $urnResolver->getRealPath('urn:magento:framework:View/Layout/etc/page_layout.xsd'), + 'validationState' => $this->validationState, ]; $exceptionMessage = 'validation exception'; @@ -49,10 +58,14 @@ protected function _createValidator($layoutUpdate, $isSchemaValid = true) new \Magento\Framework\Config\Dom\ValidationException($exceptionMessage) ) ); - $urnResolver = $this->_objectHelper->getObject('Magento\Framework\Config\Dom\UrnResolver'); + $urnResolver = $this->_objectHelper->getObject(\Magento\Framework\Config\Dom\UrnResolver::class); $model = $this->_objectHelper->getObject( - 'Magento\Framework\View\Model\Layout\Update\Validator', - ['domConfigFactory' => $domConfigFactory, 'urnResolver' => $urnResolver] + \Magento\Framework\View\Model\Layout\Update\Validator::class, + [ + 'domConfigFactory' => $domConfigFactory, + 'urnResolver' => $urnResolver, + 'validationState' => $this->validationState, + ] ); return $model;