Skip to content

Commit 1f11f82

Browse files
author
Olexandr Lysenko
committed
Merge remote-tracking branch 'mainline/develop' into bugfixes
2 parents 3bcaece + 6614360 commit 1f11f82

File tree

27 files changed

+8840
-228
lines changed

27 files changed

+8840
-228
lines changed

app/code/Magento/Ui/Component/Form/Element/DataType/Date.php

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class Date extends AbstractDataType
3232
protected $wrappedComponent;
3333

3434
/**
35+
* Constructor
36+
*
3537
* @param ContextInterface $context
3638
* @param TimezoneInterface $localeDate
3739
* @param ResolverInterface $localeResolver
@@ -58,23 +60,15 @@ public function __construct(
5860
public function prepare()
5961
{
6062
$config = $this->getData('config');
61-
62-
if (!isset($config['timeOffset'])) {
63-
$config['timeOffset'] = (new \DateTime(
64-
'now',
65-
new \DateTimeZone(
66-
$this->localeDate->getConfigTimezone()
67-
)
68-
))->getOffset();
63+
if (!isset($config['storeTimeZone'])) {
64+
$storeTimeZone = $this->localeDate->getConfigTimezone();
65+
$config['storeTimeZone'] = $storeTimeZone;
6966
}
70-
7167
// Set date format pattern by current locale
7268
$localeDateFormat = $this->localeDate->getDateFormat();
7369
$config['options']['dateFormat'] = $localeDateFormat;
7470
$config['outputDateFormat'] = $localeDateFormat;
75-
7671
$this->setData('config', $config);
77-
7872
parent::prepare();
7973
}
8074

app/code/Magento/Ui/Test/Unit/Component/Form/Element/DataType/DateTest.php

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,48 @@
66
namespace Magento\Ui\Test\Unit\Component\Form\Element\DataType;
77

88
use Magento\Ui\Component\Form\Element\DataType\Date;
9+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
11+
use Magento\Framework\View\Element\UiComponent\Context;
12+
use Magento\Framework\Locale\ResolverInterface;
13+
use Magento\Framework\View\Element\UiComponent\Processor;
914

1015
class DateTest extends \PHPUnit_Framework_TestCase
1116
{
12-
/**
13-
* @var \Magento\Framework\View\Element\UiComponent\ContextInterface|\PHPUnit_Framework_MockObject_MockObject
14-
*/
15-
private $context;
17+
/** @var \PHPUnit_Framework_MockObject_MockObject */
18+
private $contextMock;
1619

17-
/**
18-
* @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject
19-
*/
20-
private $localeDate;
20+
/** @var \PHPUnit_Framework_MockObject_MockObject */
21+
private $localeDateMock;
2122

22-
/**
23-
* @var \Magento\Framework\Locale\ResolverInterface|\PHPUnit_Framework_MockObject_MockObject
24-
*/
25-
private $localeResolver;
23+
/** @var \PHPUnit_Framework_MockObject_MockObject */
24+
private $localeResolverMock;
2625

27-
/**
28-
* @var Date
29-
*/
30-
private $model;
31-
32-
public function setUp()
33-
{
34-
$processorMock = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\Processor::class)
35-
->disableOriginalConstructor()
36-
->getMock();
26+
/** @var \Magento\Ui\Component\Form\Element\DataType\Date */
27+
private $date;
3728

38-
$this->context = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\ContextInterface::class)
39-
->getMockForAbstractClass();
40-
$this->context->expects($this->any())
41-
->method('getProcessor')
42-
->willReturn($processorMock);
29+
/** @var \PHPUnit_Framework_MockObject_MockObject */
30+
private $processorMock;
4331

44-
$this->localeDate = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class)
45-
->getMockForAbstractClass();
32+
/** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */
33+
private $objectManagerHelper;
4634

47-
$this->localeResolver = $this->getMockBuilder(\Magento\Framework\Locale\ResolverInterface::class)
48-
->getMockForAbstractClass();
35+
public function setUp()
36+
{
37+
$this->contextMock = $this->getMock(Context::class, [], [], '', false);
38+
$this->localeDateMock = $this->getMock(TimezoneInterface::class, [], [], '', false);
39+
$this->localeResolverMock = $this->getMock(ResolverInterface::class, [], [], '', false);
40+
$this->objectManagerHelper = new ObjectManager($this);
41+
$this->processorMock = $this->getMock(Processor::class, [], [], '', false);
42+
$this->contextMock->expects($this->any())->method('getProcessor')->willReturn($this->processorMock);
4943
}
5044

5145
public function testPrepareWithTimeOffset()
5246
{
53-
$this->model = new Date(
54-
$this->context,
55-
$this->localeDate,
56-
$this->localeResolver,
47+
$this->date = new Date(
48+
$this->contextMock,
49+
$this->localeDateMock,
50+
$this->localeResolverMock,
5751
[],
5852
[
5953
'config' => [
@@ -64,13 +58,13 @@ public function testPrepareWithTimeOffset()
6458

6559
$localeDateFormat = 'dd/MM/y';
6660

67-
$this->localeDate->expects($this->once())
61+
$this->localeDateMock->expects($this->once())
6862
->method('getDateFormat')
6963
->willReturn($localeDateFormat);
7064

71-
$this->model->prepare();
65+
$this->date->prepare();
7266

73-
$config = $this->model->getConfig();
67+
$config = $this->date->getConfig();
7468
$this->assertTrue(is_array($config));
7569

7670
$this->assertArrayHasKey('options', $config);
@@ -85,10 +79,10 @@ public function testPrepareWithoutTimeOffset()
8579
{
8680
$defaultDateFormat = 'MM/dd/y';
8781

88-
$this->model = new Date(
89-
$this->context,
90-
$this->localeDate,
91-
$this->localeResolver,
82+
$this->date = new Date(
83+
$this->contextMock,
84+
$this->localeDateMock,
85+
$this->localeResolverMock,
9286
[],
9387
[
9488
'config' => [
@@ -102,25 +96,42 @@ public function testPrepareWithoutTimeOffset()
10296

10397
$localeDateFormat = 'dd/MM/y';
10498

105-
$this->localeDate->expects($this->once())
99+
$this->localeDateMock->expects($this->once())
106100
->method('getDateFormat')
107101
->willReturn($localeDateFormat);
108-
$this->localeDate->expects($this->once())
102+
$this->localeDateMock->expects($this->any())
109103
->method('getConfigTimezone')
110104
->willReturn('America/Los_Angeles');
111105

112-
$this->model->prepare();
106+
$this->date->prepare();
113107

114-
$config = $this->model->getConfig();
108+
$config = $this->date->getConfig();
115109
$this->assertTrue(is_array($config));
116110

117-
$this->assertArrayHasKey('timeOffset', $config);
118-
119111
$this->assertArrayHasKey('options', $config);
120112
$this->assertArrayHasKey('dateFormat', $config['options']);
121113
$this->assertEquals($localeDateFormat, $config['options']['dateFormat']);
122114

123115
$this->assertArrayHasKey('outputDateFormat', $config);
124116
$this->assertEquals($localeDateFormat, $config['outputDateFormat']);
125117
}
118+
119+
/**
120+
* This tests ensures that userTimeZone is properly saved in the configuration
121+
*/
122+
public function testPrepare()
123+
{
124+
$this->date = $this->objectManagerHelper->getObject(
125+
Date::class,
126+
[
127+
'context' => $this->contextMock,
128+
'localeDate' => $this->localeDateMock,
129+
'localeResolver' => $this->localeResolverMock
130+
]
131+
);
132+
$this->localeDateMock->expects($this->any())->method('getConfigTimezone')->willReturn('America/Chicago');
133+
$this->date->prepare();
134+
$configArray = $this->date->getData('config');
135+
$this->assertEquals('America/Chicago', $configArray['storeTimeZone']);
136+
}
126137
}

app/code/Magento/Ui/view/base/web/js/form/element/date.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
define([
66
'moment',
77
'mageUtils',
8-
'./abstract'
8+
'./abstract',
9+
'moment-timezone-with-data'
910
], function (moment, utils, Abstract) {
1011
'use strict';
1112

1213
return Abstract.extend({
1314
defaults: {
1415
options: {},
1516

16-
timeOffset: 0,
17+
storeTimeZone: 'UTC',
1718

1819
validationParams: {
1920
dateFormat: '${ $.outputDateFormat }'
@@ -61,7 +62,7 @@ define([
6162

6263
/**
6364
* Date/time value shifted to corresponding timezone
64-
* according to this.timeOffset property. This value
65+
* according to this.storeTimeZone property. This value
6566
* will be sent to the server.
6667
*
6768
* @type {String}
@@ -109,7 +110,7 @@ define([
109110

110111
if (value) {
111112
if (this.options.showsTime) {
112-
shiftedValue = moment.utc(value).add(this.timeOffset, 'seconds');
113+
shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone);
113114
} else {
114115
dateFormat = this.shiftedValue() ? this.outputDateFormat : this.inputDateFormat;
115116

@@ -133,12 +134,13 @@ define([
133134
* @param {String} shiftedValue
134135
*/
135136
onShiftedValueChange: function (shiftedValue) {
136-
var value;
137+
var value,
138+
formattedValue;
137139

138140
if (shiftedValue) {
139141
if (this.options.showsTime) {
140-
value = moment.utc(shiftedValue, this.pickerDateTimeFormat);
141-
value = value.subtract(this.timeOffset, 'seconds').toISOString();
142+
formattedValue = moment(shiftedValue).format('YYYY-MM-DD HH:mm');
143+
value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString();
142144
} else {
143145
value = moment(shiftedValue, this.pickerDateTimeFormat);
144146
value = value.format(this.outputDateFormat);

lib/web/mage/utils/misc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ define([
3939
'EEE': 'ddd',
4040
'e': 'd',
4141
'yyyy': 'YYYY',
42+
'yy': 'YY',
4243
'y': 'YYYY',
4344
'a': 'A'
4445
};

lib/web/moment-timezone-with-data.js

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<attribute_sets> <!-- Content of Attribute Sets -->
9+
<attribute_set>
10+
<name>Attribute Set 1</name>
11+
<attributes>
12+
<attribute>
13+
<is_required>1</is_required>
14+
<is_visible_on_front>1</is_visible_on_front>
15+
<is_visible_in_advanced_search>1</is_visible_in_advanced_search>
16+
<attribute_code>mycolor</attribute_code>
17+
<backend_type></backend_type>
18+
<is_searchable>1</is_searchable>
19+
<is_filterable>1</is_filterable>
20+
<is_filterable_in_search>1</is_filterable_in_search>
21+
<frontend_label>my color</frontend_label>
22+
<frontend_input>select</frontend_input>
23+
<default_value>my yellow</default_value>
24+
<options>
25+
<option>
26+
<label>my green</label>
27+
<value>my green</value>
28+
</option>
29+
<option>
30+
<label>my red</label>
31+
<value>my red</value>
32+
</option>
33+
<option>
34+
<label>my yellow</label>
35+
<value>my yellow</value>
36+
</option>
37+
</options>
38+
</attribute>
39+
<attribute>
40+
<is_required>1</is_required>
41+
<is_visible_on_front>1</is_visible_on_front>
42+
<is_visible_in_advanced_search>1</is_visible_in_advanced_search>
43+
<attribute_code>mysize</attribute_code>
44+
<backend_type></backend_type>
45+
<is_searchable>1</is_searchable>
46+
<is_filterable>1</is_filterable>
47+
<is_filterable_in_search>1</is_filterable_in_search>
48+
<frontend_label>my size</frontend_label>
49+
<frontend_input>select</frontend_input>
50+
<default_value>my large</default_value>
51+
<options>
52+
<option>
53+
<label>my small</label>
54+
<value>my small</value>
55+
</option>
56+
<option>
57+
<label>my medium</label>
58+
<value>my medium</value>
59+
</option>
60+
<option>
61+
<label>my large</label>
62+
<value>my large</value>
63+
</option>
64+
</options>
65+
</attribute>
66+
</attributes>
67+
</attribute_set>
68+
<attribute_set>
69+
<name>Attribute Set 2</name>
70+
<attributes>
71+
<attribute>
72+
<is_required>1</is_required>
73+
<is_visible_on_front>1</is_visible_on_front>
74+
<is_visible_in_advanced_search>1</is_visible_in_advanced_search>
75+
<attribute_code>attributeset2attribute1</attribute_code>
76+
<backend_type></backend_type>
77+
<is_searchable>1</is_searchable>
78+
<is_filterable>1</is_filterable>
79+
<is_filterable_in_search>1</is_filterable_in_search>
80+
<frontend_label>Attribute Set 2 - Attribute 1</frontend_label>
81+
<frontend_input>select</frontend_input>
82+
<default_value>attributeset2attribute1option1</default_value>
83+
<options>
84+
<option>
85+
<label>Attribute Set 2 - Attribute 1 - Option a</label>
86+
<value>attributeset2attribute1option1</value>
87+
</option>
88+
<option>
89+
<label>Attribute Set 2 - Attribute 1 - Option b</label>
90+
<value>attributeset2attribute1option2</value>
91+
</option>
92+
<option>
93+
<label>Attribute Set 2 - Attribute 1 - Option c</label>
94+
<value>attributeset2attribute1option3</value>
95+
</option>
96+
</options>
97+
</attribute>
98+
</attributes>
99+
</attribute_set>
100+
<attribute_set>
101+
<name>Attribute Set 3</name>
102+
<attributes>
103+
<attribute>
104+
<is_required>1</is_required>
105+
<is_visible_on_front>1</is_visible_on_front>
106+
<is_visible_in_advanced_search>1</is_visible_in_advanced_search>
107+
<attribute_code>attributeset3attribute1</attribute_code>
108+
<backend_type></backend_type>
109+
<is_searchable>1</is_searchable>
110+
<is_filterable>1</is_filterable>
111+
<is_filterable_in_search>1</is_filterable_in_search>
112+
<frontend_label>Attribute Set 3 - Attribute 1</frontend_label>
113+
<frontend_input>select</frontend_input>
114+
<default_value>attributeset3attribute1option1</default_value>
115+
<options>
116+
<option>
117+
<label>Attribute Set 3 - Attribute 1 - Option a</label>
118+
<value>attributeset3attribute1option1</value>
119+
</option>
120+
<option>
121+
<label>Attribute Set 3 - Attribute 1 - Option b</label>
122+
<value>attributeset3attribute1option2</value>
123+
</option>
124+
<option>
125+
<label>Attribute Set 3 - Attribute 1 - Option c</label>
126+
<value>attributeset3attribute1option3</value>
127+
</option>
128+
</options>
129+
</attribute>
130+
</attributes>
131+
</attribute_set>
132+
</attribute_sets>

0 commit comments

Comments
 (0)