Skip to content

Commit 4372961

Browse files
committed
Merge pull request #335 from magento-mpi/PR-37282
[MPI] Bugfixes & Feature Parity + Simplification of Payment Configuration
2 parents 82109a5 + da9e154 commit 4372961

40 files changed

+1056
-211
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Config\Model\Config\Compiler;
7+
8+
use Magento\Framework\Object;
9+
use Magento\Framework\Filesystem;
10+
use Magento\Framework\Module\Dir\Reader;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\App\Filesystem\DirectoryList;
13+
use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface;
14+
use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface;
15+
16+
/**
17+
* Class IncludeElement
18+
*/
19+
class IncludeElement implements ElementInterface
20+
{
21+
const INCLUDE_PATH = 'path';
22+
23+
/**
24+
* @var Reader
25+
*/
26+
protected $moduleReader;
27+
28+
/**
29+
* @var Filesystem
30+
*/
31+
protected $filesystem;
32+
33+
/**
34+
* Constructor
35+
*
36+
* @param Reader $moduleReader
37+
* @param Filesystem $filesystem
38+
*/
39+
public function __construct(Reader $moduleReader, Filesystem $filesystem)
40+
{
41+
$this->filesystem = $filesystem;
42+
$this->moduleReader = $moduleReader;
43+
}
44+
45+
/**
46+
* Compiles the Element node
47+
*
48+
* @param CompilerInterface $compiler
49+
* @param \DOMElement $node
50+
* @param Object $processedObject
51+
* @param Object $context
52+
* @return void
53+
*/
54+
public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context)
55+
{
56+
$ownerDocument = $node->ownerDocument;
57+
$parentNode = $node->parentNode;
58+
59+
$document = new \DOMDocument();
60+
$document->loadXML($this->getContent($node->getAttribute(static::INCLUDE_PATH)));
61+
62+
foreach ($this->getChildNodes($document->documentElement) as $child) {
63+
$compiler->compile($child, $processedObject, $context);
64+
}
65+
66+
$newFragment = $ownerDocument->createDocumentFragment();
67+
foreach ($document->documentElement->childNodes as $child) {
68+
$newFragment->appendXML($document->saveXML($child));
69+
}
70+
71+
$parentNode->replaceChild($newFragment, $node);
72+
}
73+
74+
/**
75+
* Get child nodes
76+
*
77+
* @param \DOMElement $node
78+
* @return \DOMElement[]
79+
*/
80+
protected function getChildNodes(\DOMElement $node)
81+
{
82+
$childNodes = [];
83+
foreach ($node->childNodes as $child) {
84+
$childNodes[] = $child;
85+
}
86+
87+
return $childNodes;
88+
}
89+
90+
/**
91+
* Get content include file (in adminhtml area)
92+
*
93+
* @param string $includePath
94+
* @return string
95+
* @throws LocalizedException
96+
*/
97+
protected function getContent($includePath)
98+
{
99+
$modulesDirectory = $this->filesystem->getDirectoryRead(DirectoryList::MODULES);
100+
101+
// <include path="Magento_Payment::my_payment.xml" />
102+
list($moduleName, $filename) = explode('::', $includePath);
103+
104+
$file = $this->moduleReader->getModuleDir('etc', $moduleName) . '/adminhtml/' . $filename;
105+
$path = $modulesDirectory->getRelativePath($file);
106+
107+
if ($modulesDirectory->isExist($path) && $modulesDirectory->isFile($path)) {
108+
return $modulesDirectory->readFile($path);
109+
}
110+
111+
throw new LocalizedException(__('The file "' . $path . '" does not exist'));
112+
}
113+
}

app/code/Magento/Config/Model/Config/Structure/Reader.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
*/
99
namespace Magento\Config\Model\Config\Structure;
1010

11+
use Magento\Framework\Object;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface;
14+
15+
/**
16+
* Class Reader
17+
*/
1118
class Reader extends \Magento\Framework\Config\Reader\Filesystem
1219
{
1320
/**
@@ -25,10 +32,18 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem
2532
];
2633

2734
/**
35+
* @var CompilerInterface
36+
*/
37+
protected $compiler;
38+
39+
/**
40+
* Constructor
41+
*
2842
* @param \Magento\Framework\Config\FileResolverInterface $fileResolver
2943
* @param Converter $converter
3044
* @param \Magento\Config\Model\Config\SchemaLocator $schemaLocator
3145
* @param \Magento\Framework\Config\ValidationStateInterface $validationState
46+
* @param CompilerInterface $compiler
3247
* @param string $fileName
3348
* @param array $idAttributes
3449
* @param string $domDocumentClass
@@ -39,11 +54,13 @@ public function __construct(
3954
Converter $converter,
4055
\Magento\Config\Model\Config\SchemaLocator $schemaLocator,
4156
\Magento\Framework\Config\ValidationStateInterface $validationState,
57+
CompilerInterface $compiler,
4258
$fileName = 'system.xml',
4359
$idAttributes = [],
4460
$domDocumentClass = 'Magento\Framework\Config\Dom',
4561
$defaultScope = 'global'
4662
) {
63+
$this->compiler = $compiler;
4764
parent::__construct(
4865
$fileResolver,
4966
$converter,
@@ -55,4 +72,66 @@ public function __construct(
5572
$defaultScope
5673
);
5774
}
75+
76+
/**
77+
* Read configuration files
78+
*
79+
* @param array $fileList
80+
* @return array
81+
* @throws LocalizedException
82+
*/
83+
protected function _readFiles($fileList)
84+
{
85+
86+
/** @var \Magento\Framework\Config\Dom $configMerger */
87+
$configMerger = null;
88+
foreach ($fileList as $key => $content) {
89+
try {
90+
$content = $this->processingDocument($content);
91+
if (!$configMerger) {
92+
$configMerger = $this->_createConfigMerger($this->_domDocumentClass, $content);
93+
} else {
94+
$configMerger->merge($content);
95+
}
96+
} catch (\Magento\Framework\Config\Dom\ValidationException $e) {
97+
throw new LocalizedException(
98+
new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()])
99+
);
100+
}
101+
}
102+
103+
if ($this->_isValidated) {
104+
$errors = [];
105+
if ($configMerger && !$configMerger->validate($this->_schemaFile, $errors)) {
106+
$message = "Invalid Document \n";
107+
throw new LocalizedException(
108+
new \Magento\Framework\Phrase($message . implode("\n", $errors))
109+
);
110+
}
111+
}
112+
113+
$output = [];
114+
if ($configMerger) {
115+
$output = $this->_converter->convert($configMerger->getDom());
116+
}
117+
118+
return $output;
119+
}
120+
121+
/**
122+
* Processing nodes of the document before merging
123+
*
124+
* @param string $content
125+
* @return string
126+
*/
127+
protected function processingDocument($content)
128+
{
129+
$object = new Object();
130+
$document = new \DOMDocument();
131+
132+
$document->loadXML($content);
133+
$this->compiler->compile($document->documentElement, $object, $object);
134+
135+
return $document->saveXML();
136+
}
58137
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Config\Test\Unit\Model\Compiler;
7+
8+
use Magento\Framework\App\Filesystem\DirectoryList;
9+
10+
/**
11+
* Class IncludeElementTest
12+
*/
13+
class IncludeElementTest extends \PHPUnit_Framework_TestCase
14+
{
15+
/**
16+
* @var \Magento\Config\Model\Config\Compiler\IncludeElement
17+
*/
18+
protected $includeElement;
19+
20+
/**
21+
* @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject
22+
*/
23+
protected $moduleReaderMock;
24+
25+
/**
26+
* @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject
27+
*/
28+
protected $filesystemMock;
29+
30+
/**
31+
* Set up
32+
*
33+
* @return void
34+
*/
35+
protected function setUp()
36+
{
37+
$this->moduleReaderMock = $this->getMockBuilder('Magento\Framework\Module\Dir\Reader')
38+
->disableOriginalConstructor()
39+
->getMock();
40+
$this->filesystemMock = $this->getMockBuilder('Magento\Framework\Filesystem')
41+
->disableOriginalConstructor()
42+
->getMock();
43+
44+
$this->includeElement = new \Magento\Config\Model\Config\Compiler\IncludeElement(
45+
$this->moduleReaderMock,
46+
$this->filesystemMock
47+
);
48+
}
49+
50+
/**
51+
* @return void
52+
*/
53+
public function testCompileSuccess()
54+
{
55+
$xmlContent = '<rootConfig><include path="Module_Name::path/to/file.xml"/></rootConfig>';
56+
57+
$document = new \DOMDocument();
58+
$document->loadXML($xmlContent);
59+
60+
$compilerMock = $this->getMockBuilder('Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface')
61+
->getMockForAbstractClass();
62+
$processedObjectMock = $this->getMockBuilder('Magento\Framework\Object')
63+
->disableOriginalConstructor()
64+
->getMock();
65+
66+
$this->getContentStep();
67+
68+
$compilerMock->expects($this->exactly(2))
69+
->method('compile')
70+
->with($this->isInstanceOf('\DOMElement'), $processedObjectMock, $processedObjectMock);
71+
72+
$this->includeElement->compile(
73+
$compilerMock,
74+
$document->documentElement->firstChild,
75+
$processedObjectMock,
76+
$processedObjectMock
77+
);
78+
79+
$this->assertEquals(
80+
'<?xml version="1.0"?><rootConfig><item id="1"><test/></item><item id="2"/></rootConfig>',
81+
str_replace(PHP_EOL, '', $document->saveXML())
82+
);
83+
}
84+
85+
/**
86+
* @expectedException \Magento\Framework\Exception\LocalizedException
87+
* @expectedExceptionMessage The file "relative/path/to/file.xml" does not exist
88+
*/
89+
public function testCompileException()
90+
{
91+
$xmlContent = '<rootConfig><include path="Module_Name::path/to/file.xml"/></rootConfig>';
92+
93+
$document = new \DOMDocument();
94+
$document->loadXML($xmlContent);
95+
96+
$compilerMock = $this->getMockBuilder('Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface')
97+
->getMockForAbstractClass();
98+
$processedObjectMock = $this->getMockBuilder('Magento\Framework\Object')
99+
->disableOriginalConstructor()
100+
->getMock();
101+
102+
$this->getContentStep(false);
103+
104+
$compilerMock->expects($this->never())
105+
->method('compile')
106+
->with($this->isInstanceOf('\DOMElement'), $processedObjectMock, $processedObjectMock);
107+
108+
$this->includeElement->compile(
109+
$compilerMock,
110+
$document->documentElement->firstChild,
111+
$processedObjectMock,
112+
$processedObjectMock
113+
);
114+
}
115+
116+
/**
117+
* @param bool $check
118+
*/
119+
protected function getContentStep($check = true)
120+
{
121+
$resultPath = 'relative/path/to/file.xml';
122+
$includeXmlContent = '<config><item id="1"><test/></item><item id="2"></item></config>';
123+
124+
$modulesDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface')
125+
->getMockForAbstractClass();
126+
127+
$this->filesystemMock->expects($this->once())
128+
->method('getDirectoryRead')
129+
->with(DirectoryList::MODULES)
130+
->willReturn($modulesDirectoryMock);
131+
132+
$this->moduleReaderMock->expects($this->once())
133+
->method('getModuleDir')
134+
->with('etc', 'Module_Name')
135+
->willReturn('path/in/application/module');
136+
137+
$modulesDirectoryMock->expects($this->once())
138+
->method('getRelativePath')
139+
->with('path/in/application/module/adminhtml/path/to/file.xml')
140+
->willReturn($resultPath);
141+
142+
$modulesDirectoryMock->expects($this->once())
143+
->method('isExist')
144+
->with($resultPath)
145+
->willReturn($check);
146+
147+
if ($check) {
148+
$modulesDirectoryMock->expects($this->once())
149+
->method('isFile')
150+
->with($resultPath)
151+
->willReturn($check);
152+
$modulesDirectoryMock->expects($this->once())
153+
->method('readFile')
154+
->with($resultPath)
155+
->willReturn($includeXmlContent);
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)