Skip to content

Commit

Permalink
Merge branch 'MAGETWO-53121-502-Bad-Gateway' into merged-prs
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksii Korshenko committed Jun 15, 2016
2 parents b7c5930 + 5965448 commit 86bca45
Show file tree
Hide file tree
Showing 27 changed files with 943 additions and 218 deletions.
5 changes: 4 additions & 1 deletion app/code/Magento/Backup/Model/Fs/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ protected function _generateRow($filename)
$row[$key] = $value;
}
$row['size'] = $this->_varDirectory->stat($this->_varDirectory->getRelativePath($filename))['size'];
$row['id'] = $row['time'] . '_' . $row['type'];
if (isset($row['display_name']) && $row['display_name'] == '') {
$row['display_name'] = 'WebSetupWizard';
}
$row['id'] = $row['time'] . '_' . $row['type'] . (isset($row['display_name']) ? $row['display_name'] : '');
return $row;
}
}
109 changes: 109 additions & 0 deletions app/code/Magento/Theme/Model/Design/Config/Validator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Theme\Model\Design\Config;

use \Magento\Framework\Exception\LocalizedException;
use \Magento\Theme\Api\Data\DesignConfigInterface;
use \Magento\Theme\Api\Data\DesignConfigDataInterface;
use \Magento\Framework\Mail\TemplateInterfaceFactory as TemplateFactory;
use \Magento\Framework\Filter\Template;
use \Magento\Framework\Filter\Template\Tokenizer\Parameter as ParameterTokenizer;

/**
* Design configuration validator
*/
class Validator
{
/**
* @var string[]
*/
private $fields = [];

/**
* @var TemplateFactory
*/
private $templateFactory;

/**
* Initialize dependencies.
*
* @param TemplateFactory $templateFactory
* @param string[] $fields
*/
public function __construct(TemplateFactory $templateFactory, $fields = [])
{
$this->templateFactory = $templateFactory;
$this->fields = $fields;
}

/**
* Validate if design configuration has recursive references
*
* @param DesignConfigInterface $designConfig
*
* @throws LocalizedException
* @return void
*/
public function validate(DesignConfigInterface $designConfig)
{
/** @var DesignConfigDataInterface[] $designConfigData */
$designConfigData = $designConfig->getExtensionAttributes()->getDesignConfigData();
$elements = [];
foreach ($designConfigData as $designElement) {
if (!in_array($designElement->getFieldConfig()['field'], $this->fields)) {
continue;
}
/* Save mapping between field names and config paths */
$elements[$designElement->getFieldConfig()['field']] = [
'config_path' => $designElement->getPath(),
'value' => $designElement->getValue()
];
}

foreach ($elements as $name => $data) {
// Load template object by configured template id
$template = $this->templateFactory->create();
$template->emulateDesign($designConfig->getScopeId());
$templateId = $data['value'];
if (is_numeric($templateId)) {
$template->load($templateId);
} else {
$template->loadDefault($templateId);
}
$text = $template->getTemplateText();
$template->revertDesign();
// Check if template body has a reference to the same config path
if (preg_match_all(Template::CONSTRUCTION_TEMPLATE_PATTERN, $text, $constructions, PREG_SET_ORDER)) {
foreach ($constructions as $construction) {
$configPath = isset($construction[2]) ? $construction[2] : '';
$params = $this->getParameters($configPath);
if (isset($params['config_path']) && $params['config_path'] == $data['config_path']) {
throw new LocalizedException(
__(
"Incorrect configuration for %templateName. Template body has a reference to itself",
["templateName" => $name]
)
);
};
}
}
}
}

/**
* Return associative array of parameters.
*
* @param string $value raw parameters
* @return array
*/
private function getParameters($value)
{
$tokenizer = new ParameterTokenizer();
$tokenizer->setString($value);
$params = $tokenizer->tokenize();
return $params;
}
}
26 changes: 26 additions & 0 deletions app/code/Magento/Theme/Model/DesignConfigRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ class DesignConfigRepository implements DesignConfigRepositoryInterface
/** @var ConfigStorage */
protected $configStorage;

/**
* Design config validator
*
* @var \Magento\Theme\Model\Design\Config\Validator
*/
private $validator;

/**
* @param ConfigStorage $configStorage
* @param ReinitableConfigInterface $reinitableConfig
Expand All @@ -39,6 +46,23 @@ public function __construct(
$this->configStorage = $configStorage;
}

/**
* Get config validator
*
* @return Design\Config\Validator
*
* @deprecated
*/
private function getValidator()
{
if (null === $this->validator) {
$this->validator =\Magento\Framework\App\ObjectManager::getInstance()->get(
\Magento\Theme\Model\Design\Config\Validator::class
);
}
return $this->validator;
}

/**
* @inheritDoc
*/
Expand All @@ -58,6 +82,8 @@ public function save(DesignConfigInterface $designConfig)
throw new LocalizedException(__('Can not save empty config'));
}

$this->getValidator()->validate($designConfig);

$this->configStorage->save($designConfig);
$this->reinitableConfig->reinit();
$this->reindexGrid();
Expand Down
123 changes: 123 additions & 0 deletions app/code/Magento/Theme/Test/Unit/Model/Config/ValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Theme\Test\Unit\Model\Config;

/**
* Class ValidatorTest to test \Magento\Theme\Model\Design\Config\Validator
*/
class ValidatorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Magento\Theme\Model\Design\Config\Validator
*/
private $model;

/**
* @var \Magento\Framework\Mail\TemplateInterfaceFactory
*/
private $templateFactoryMock;

protected function setUp()
{
$this->templateFactoryMock = $this->getMockBuilder(\Magento\Framework\Mail\TemplateInterfaceFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();

$objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->model = $objectManagerHelper->getObject(
\Magento\Theme\Model\Design\Config\Validator::class,
[
"templateFactory" => $this->templateFactoryMock,
"fields" => ["email_header_template", "no_reference"]
]
);
}

/**
* @expectedException \Magento\Framework\Exception\LocalizedException
* @expectedExceptionMessage Incorrect configuration for email_header_template. Template body has a reference to
*/
public function testValidateHasRecursiveReference()
{
$fieldConfig = [
'path' => 'design/email/header_template',
'fieldset' => 'other_settings/email',
'field' => 'email_header_template'
];

$designConfigMock = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigInterface::class)
->getMock();
$designConfigExtensionMock =
$this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigExtensionInterface::class)
->setMethods(['getDesignConfigData'])
->getMock();
$designElementMock = $this->getMockBuilder(\Magento\Theme\Model\Data\Design\Config\Data::class)
->disableOriginalConstructor()
->getMock();

$designConfigMock->expects($this->once())
->method('getExtensionAttributes')
->willReturn($designConfigExtensionMock);
$designConfigExtensionMock->expects($this->once())
->method('getDesignConfigData')
->willReturn([$designElementMock]);
$designElementMock->expects($this->any())->method('getFieldConfig')->willReturn($fieldConfig);
$designElementMock->expects($this->once())->method('getPath')->willReturn($fieldConfig['path']);
$designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']);

$templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class)
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign'])
->getMock();

$this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock);
$templateMock->expects($this->once())->method('getTemplateText')->willReturn(
file_get_contents(__DIR__ . '/_files/template_fixture.html')
);

$this->model->validate($designConfigMock);
}

public function testValidateNoRecursiveReference()
{
$fieldConfig = [
'path' => 'no/reference',
'fieldset' => 'no/reference',
'field' => 'no_reference'
];

$designConfigMock = $this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigInterface::class)
->getMock();
$designConfigExtensionMock =
$this->getMockBuilder(\Magento\Theme\Api\Data\DesignConfigExtensionInterface::class)
->setMethods(['getDesignConfigData'])
->getMock();
$designElementMock = $this->getMockBuilder(\Magento\Theme\Model\Data\Design\Config\Data::class)
->disableOriginalConstructor()
->getMock();

$designConfigMock->expects($this->once())
->method('getExtensionAttributes')
->willReturn($designConfigExtensionMock);
$designConfigExtensionMock->expects($this->once())
->method('getDesignConfigData')
->willReturn([$designElementMock]);
$designElementMock->expects($this->any())->method('getFieldConfig')->willReturn($fieldConfig);
$designElementMock->expects($this->once())->method('getPath')->willReturn($fieldConfig['path']);
$designElementMock->expects($this->once())->method('getValue')->willReturn($fieldConfig['field']);

$templateMock = $this->getMockBuilder(\Magento\Email\Model\TemplateInterface::class)
->setMethods(['getTemplateText', 'emulateDesign', 'loadDefault', 'revertDesign'])
->getMock();

$this->templateFactoryMock->expects($this->once())->method('create')->willReturn($templateMock);
$templateMock->expects($this->once())->method('getTemplateText')->willReturn(
file_get_contents(__DIR__ . '/_files/template_fixture.html')
);

$this->model->validate($designConfigMock);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{template config_path="design/email/header_template"}}

<p class="greeting">{{trans "%name," name=$customer.name}}</p>
<p>{{trans "Welcome to %store_name." store_name=$store.getFrontendName()}}</p>
<p>
{{trans
'To sign in to our site, use these credentials during checkout or on the <a href="%customer_url">My Account</a> page:'

customer_url=$this.getUrl($store,'customer/account/',[_nosid:1])
|raw}}
</p>
<ul>
<li><strong>{{trans "Email:"}}</strong> {{var customer.email}}</li>
<li><strong>{{trans "Password:"}}</strong> <em>{{trans "Password you set when creating account"}}</em></li>
</ul>
<p>
{{trans
'Forgot your account password? Click <a href="%reset_url">here</a> to reset it.'

reset_url="$this.getUrl($store,'customer/account/createPassword/',[_query:[id:$customer.id,token:$customer.rp_token],_nosid:1])"
|raw}}
</p>
<p>{{trans "When you sign in to your account, you will be able to:"}}</p>
<ul>
<li>{{trans "Proceed through checkout faster"}}</li>
<li>{{trans "Check the status of orders"}}</li>
<li>{{trans "View past orders"}}</li>
<li>{{trans "Store alternative addresses (for shipping to multiple family members and friends)"}}</li>
</ul>

{{template config_path="design/email/footer_template"}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use Magento\Theme\Model\Data\Design\Config;
use Magento\Theme\Model\DesignConfigRepository;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;

class DesignConfigRepositoryTest extends \PHPUnit_Framework_TestCase
{
Expand Down Expand Up @@ -34,6 +35,11 @@ class DesignConfigRepositoryTest extends \PHPUnit_Framework_TestCase
/** @var DesignConfigRepository */
protected $repository;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $validator;

public function setUp()
{
$this->configStorage = $this->getMock('Magento\Theme\Model\Design\Config\Storage', [], [], '', false);
Expand Down Expand Up @@ -71,10 +77,24 @@ public function setUp()
'',
false
);
$this->repository = new DesignConfigRepository(
$this->configStorage,
$this->reinitableConfig,
$this->indexerRegistry

$this->validator = $this->getMock(
\Magento\Theme\Model\Design\Config\Validator::class,
[],
[],
'',
false,
false
);
$objectManagerHelper = new ObjectManager($this);
$this->repository = $objectManagerHelper->getObject(
DesignConfigRepository::class,
[
'configStorage' => $this->configStorage,
'reinitableConfig' => $this->reinitableConfig,
'indexerRegistry' => $this->indexerRegistry,
'validator' => $this->validator
]
);
}

Expand All @@ -97,6 +117,7 @@ public function testSave()
->willReturn($this->indexer);
$this->indexer->expects($this->once())
->method('reindexAll');
$this->validator->expects($this->once())->method('validate')->with($this->designConfig);
$this->assertSame($this->designConfig, $this->repository->save($this->designConfig));
}

Expand Down
8 changes: 8 additions & 0 deletions app/code/Magento/Theme/etc/adminhtml/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@
</argument>
</arguments>
</type>
<type name="Magento\Theme\Model\Design\Config\Validator">
<arguments>
<argument name="fields" xsi:type="array">
<item name="header" xsi:type="string">email_header_template</item>
<item name="footer" xsi:type="string">email_footer_template</item>
</argument>
</arguments>
</type>
</config>
Loading

0 comments on commit 86bca45

Please sign in to comment.