Skip to content

Commit f540160

Browse files
authored
Merge pull request #5097 from magento-tsg-csl3/2.4-develop-pr1
[TSG-CSL3] For 2.4 (pr1)
2 parents 27a3905 + 0bf0c9f commit f540160

File tree

43 files changed

+1416
-280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1416
-280
lines changed

app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@
77
namespace Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab;
88

99
use Magento\Backend\Block\Widget\Form\Generic;
10+
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
1011
use Magento\Config\Model\Config\Source\Yesno;
1112
use Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker;
1213
use Magento\Eav\Helper\Data;
1314
use Magento\Framework\App\ObjectManager;
15+
use Magento\Framework\Exception\LocalizedException;
16+
use Magento\Framework\Stdlib\DateTime;
1417

1518
/**
16-
* Product attribute add/edit form main tab
19+
* Product attribute add/edit advanced form tab
1720
*
1821
* @api
1922
* @since 100.0.2
23+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2024
*/
2125
class Advanced extends Generic
2226
{
@@ -70,7 +74,7 @@ public function __construct(
7074
* Adding product form elements for editing attribute
7175
*
7276
* @return $this
73-
* @throws \Magento\Framework\Exception\LocalizedException
77+
* @throws LocalizedException
7478
* @SuppressWarnings(PHPMD)
7579
*/
7680
protected function _prepareForm()
@@ -139,7 +143,21 @@ protected function _prepareForm()
139143
'label' => __('Default Value'),
140144
'title' => __('Default Value'),
141145
'value' => $attributeObject->getDefaultValue(),
142-
'date_format' => $dateFormat
146+
'date_format' => $dateFormat,
147+
]
148+
);
149+
150+
$timeFormat = $this->_localeDate->getTimeFormat(\IntlDateFormatter::SHORT);
151+
$fieldset->addField(
152+
'default_value_datetime',
153+
'date',
154+
[
155+
'name' => 'default_value_datetime',
156+
'label' => __('Default Value'),
157+
'title' => __('Default Value'),
158+
'value' => $this->getLocalizedDateDefaultValue(),
159+
'date_format' => $dateFormat,
160+
'time_format' => $timeFormat,
143161
]
144162
);
145163

@@ -266,7 +284,7 @@ protected function _initFormValues()
266284
/**
267285
* Retrieve attribute object from registry
268286
*
269-
* @return mixed
287+
* @return Attribute
270288
*/
271289
private function getAttributeObject()
272290
{
@@ -285,4 +303,28 @@ private function getPropertyLocker()
285303
}
286304
return $this->propertyLocker;
287305
}
306+
307+
/**
308+
* Get localized date default value
309+
*
310+
* @return string
311+
* @throws LocalizedException
312+
*/
313+
private function getLocalizedDateDefaultValue(): string
314+
{
315+
$attributeObject = $this->getAttributeObject();
316+
if (empty($attributeObject->getDefaultValue()) || $attributeObject->getFrontendInput() !== 'datetime') {
317+
return (string)$attributeObject->getDefaultValue();
318+
}
319+
320+
try {
321+
$localizedDate = $this->_localeDate->date($attributeObject->getDefaultValue(), null, false);
322+
$localizedDate->setTimezone(new \DateTimeZone($this->_localeDate->getConfigTimezone()));
323+
$localizedDate = $localizedDate->format(DateTime::DATETIME_PHP_FORMAT);
324+
} catch (\Exception $e) {
325+
throw new LocalizedException(__('The default date is invalid.'));
326+
}
327+
328+
return $localizedDate;
329+
}
288330
}

app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Main.php

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,60 @@
77
/**
88
* Product attribute add/edit form main tab
99
*
10-
* @author Magento Core Team <[email protected]>
10+
* @author Magento Core Team <[email protected]>
1111
*/
1212
namespace Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab;
1313

14+
use Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Apply as HelperApply;
1415
use Magento\Eav\Block\Adminhtml\Attribute\Edit\Main\AbstractMain;
16+
use Magento\Framework\Data\Form\Element\AbstractElement;
17+
use Magento\Framework\Data\Form\Element\Fieldset;
18+
use Magento\Framework\DataObject;
1519

1620
/**
21+
* Product attribute add/edit form main tab
22+
*
1723
* @api
18-
* @SuppressWarnings(PHPMD.DepthOfInheritance)
1924
* @since 100.0.2
2025
*/
2126
class Main extends AbstractMain
2227
{
2328
/**
24-
* Adding product form elements for editing attribute
25-
*
26-
* @return $this
27-
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
29+
* @inheritdoc
2830
*/
2931
protected function _prepareForm()
3032
{
3133
parent::_prepareForm();
32-
/** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attributeObject */
33-
$attributeObject = $this->getAttributeObject();
34-
/* @var $form \Magento\Framework\Data\Form */
35-
$form = $this->getForm();
36-
/* @var $fieldset \Magento\Framework\Data\Form\Element\Fieldset */
37-
$fieldset = $form->getElement('base_fieldset');
38-
$fieldsToRemove = ['attribute_code', 'is_unique', 'frontend_class'];
3934

40-
foreach ($fieldset->getElements() as $element) {
41-
/** @var \Magento\Framework\Data\Form\AbstractForm $element */
42-
if (substr($element->getId(), 0, strlen('default_value')) == 'default_value') {
43-
$fieldsToRemove[] = $element->getId();
44-
}
45-
}
46-
foreach ($fieldsToRemove as $id) {
47-
$fieldset->removeField($id);
48-
}
35+
$this->removeUnusedFields();
36+
$this->processFrontendInputTypes();
37+
38+
$this->_eventManager->dispatch('product_attribute_form_build_main_tab', ['form' => $this->getForm()]);
39+
40+
return $this;
41+
}
4942

43+
/**
44+
* @inheritdoc
45+
*/
46+
protected function _getAdditionalElementTypes()
47+
{
48+
return ['apply' => HelperApply::class];
49+
}
50+
51+
/**
52+
* Process frontend input types for product attributes
53+
*
54+
* @return void
55+
*/
56+
private function processFrontendInputTypes(): void
57+
{
58+
$form = $this->getForm();
59+
/** @var AbstractElement $frontendInputElm */
5060
$frontendInputElm = $form->getElement('frontend_input');
51-
$additionalTypes = [
52-
['value' => 'price', 'label' => __('Price')],
53-
['value' => 'media_image', 'label' => __('Media Image')],
54-
];
55-
$additionalReadOnlyTypes = ['gallery' => __('Gallery')];
56-
if (isset($additionalReadOnlyTypes[$attributeObject->getFrontendInput()])) {
57-
$additionalTypes[] = [
58-
'value' => $attributeObject->getFrontendInput(),
59-
'label' => $additionalReadOnlyTypes[$attributeObject->getFrontendInput()],
60-
];
61-
}
61+
$additionalTypes = $this->getAdditionalFrontendInputTypes();
6262

63-
$response = new \Magento\Framework\DataObject();
63+
$response = new DataObject();
6464
$response->setTypes([]);
6565
$this->_eventManager->dispatch('adminhtml_product_attribute_types', ['response' => $response]);
6666
$_hiddenFields = [];
@@ -74,19 +74,51 @@ protected function _prepareForm()
7474

7575
$frontendInputValues = array_merge($frontendInputElm->getValues(), $additionalTypes);
7676
$frontendInputElm->setValues($frontendInputValues);
77+
}
7778

78-
$this->_eventManager->dispatch('product_attribute_form_build_main_tab', ['form' => $form]);
79+
/**
80+
* Get additional Frontend Input Types for product attributes
81+
*
82+
* @return array
83+
*/
84+
private function getAdditionalFrontendInputTypes(): array
85+
{
86+
$additionalTypes = [
87+
['value' => 'price', 'label' => __('Price')],
88+
['value' => 'media_image', 'label' => __('Media Image')],
89+
];
7990

80-
return $this;
91+
$additionalReadOnlyTypes = ['gallery' => __('Gallery')];
92+
$attributeObject = $this->getAttributeObject();
93+
if (isset($additionalReadOnlyTypes[$attributeObject->getFrontendInput()])) {
94+
$additionalTypes[] = [
95+
'value' => $attributeObject->getFrontendInput(),
96+
'label' => $additionalReadOnlyTypes[$attributeObject->getFrontendInput()],
97+
];
98+
}
99+
100+
return $additionalTypes;
81101
}
82102

83103
/**
84-
* Retrieve additional element types for product attributes
104+
* Remove unused form fields
85105
*
86-
* @return array
106+
* @return void
87107
*/
88-
protected function _getAdditionalElementTypes()
108+
private function removeUnusedFields(): void
89109
{
90-
return ['apply' => \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Apply::class];
110+
$form = $this->getForm();
111+
/* @var $fieldset Fieldset */
112+
$fieldset = $form->getElement('base_fieldset');
113+
$fieldsToRemove = ['attribute_code', 'is_unique', 'frontend_class'];
114+
foreach ($fieldset->getElements() as $element) {
115+
/** @var AbstractElement $element */
116+
if (substr($element->getId(), 0, strlen('default_value')) === 'default_value') {
117+
$fieldsToRemove[] = $element->getId();
118+
}
119+
}
120+
foreach ($fieldsToRemove as $id) {
121+
$fieldset->removeField($id);
122+
}
91123
}
92124
}

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
</arguments>
1818

1919
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/>
20+
<conditionalClick selector="{{AdminDataGridHeaderSection.clearFilters}}" dependentSelector="{{AdminDataGridHeaderSection.clearFilters}}" visible="true" stepKey="clearExistingFilters"/>
2021
<fillField selector="{{AdminProductAttributeGridSection.FilterByAttributeCode}}" userInput="{{ProductAttribute.attribute_code}}" stepKey="setAttributeCode"/>
2122
<click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeFromTheGrid"/>
2223
<click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/>
@@ -351,6 +352,23 @@
351352
<fillField stepKey="fillDefaultValue" selector="{{AdvancedAttributePropertiesSection.DefaultValueDate}}" userInput="{{date}}"/>
352353
</actionGroup>
353354

355+
<!-- Inputs datetime default value and attribute code-->
356+
<actionGroup name="CreateProductAttributeWithDatetimeField" extends="createProductAttribute" insertAfter="checkRequired">
357+
<annotations>
358+
<description>EXTENDS: createProductAttribute. Fills in the Attribute Code and Default Value (Attribute Type: Date and Time Field).</description>
359+
</annotations>
360+
<arguments>
361+
<argument name="date" type="string"/>
362+
</arguments>
363+
364+
<scrollTo selector="{{AdvancedAttributePropertiesSection.AdvancedAttributePropertiesSectionToggle}}" stepKey="scrollToAdvancedSection"/>
365+
<conditionalClick selector="{{AdvancedAttributePropertiesSection.AdvancedAttributePropertiesSectionToggle}}" dependentSelector="{{AdvancedAttributePropertiesSection.AttributeCode}}" visible="false" stepKey="openAdvancedSection"/>
366+
<waitForElementVisible selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" stepKey="waitForSlideOutAdvancedSection"/>
367+
<fillField selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" userInput="{{attribute.attribute_code}}" stepKey="fillCode"/>
368+
<scrollTo selector="{{AdvancedAttributePropertiesSection.defaultValueDatetime}}" stepKey="scrollToDefaultField"/>
369+
<fillField selector="{{AdvancedAttributePropertiesSection.defaultValueDatetime}}" userInput="{{date}}" stepKey="fillDefaultValue"/>
370+
</actionGroup>
371+
354372
<!-- Creates dropdown option at row without saving-->
355373
<actionGroup name="createAttributeDropdownNthOption">
356374
<annotations>
@@ -376,4 +394,15 @@
376394

377395
<checkOption selector="{{AttributePropertiesSection.dropdownNthOptionIsDefault(row)}}" stepKey="setAsDefault" after="fillStoreView"/>
378396
</actionGroup>
397+
398+
<!-- Go to advanced attribute properties -->
399+
<actionGroup name="AdminNavigateToProductAttributeAdvancedSection">
400+
<annotations>
401+
<description>Navigate and open Advanced Attribute Properties section on product attribute page</description>
402+
</annotations>
403+
404+
<scrollTo selector="{{AdvancedAttributePropertiesSection.AdvancedAttributePropertiesSectionToggle}}" stepKey="scrollToSection"/>
405+
<conditionalClick selector="{{AdvancedAttributePropertiesSection.AdvancedAttributePropertiesSectionToggle}}" dependentSelector="{{AdvancedAttributePropertiesSection.AttributeCode}}" visible="false" stepKey="openSection"/>
406+
<waitForElementVisible selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" stepKey="waitForSlideOutSection"/>
407+
</actionGroup>
379408
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@
313313
<data key="frontend_input">date</data>
314314
<data key="is_required_admin">No</data>
315315
</entity>
316+
<entity name="DatetimeProductAttribute" extends="productAttributeWysiwyg" type="ProductAttribute">
317+
<data key="frontend_input">datetime</data>
318+
<data key="is_required_admin">No</data>
319+
</entity>
316320
<entity name="priceProductAttribute" extends="productAttributeWysiwyg" type="ProductAttribute">
317321
<data key="frontend_input">date</data>
318322
<data key="is_required_admin">No</data>

app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
<element name="DefaultValueText" type="textarea" selector="#default_value_text"/>
9494
<element name="DefaultValueTextArea" type="textarea" selector="#default_value_textarea"/>
9595
<element name="DefaultValueDate" type="textarea" selector="#default_value_date"/>
96+
<element name="defaultValueDatetime" type="date" selector="#default_value_datetime"/>
9697
<element name="DefaultValueYesNo" type="textarea" selector="#default_value_yesno"/>
9798
<element name="Scope" type="select" selector="#is_global"/>
9899
<element name="UniqueValue" type="select" selector="#is_unique"/>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductGridFilterSection.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,7 @@
3636
<element name="productCount" type="text" selector="#catalog_category_products-total-count"/>
3737
<element name="productPerPage" type="select" selector="#catalog_category_products_page-limit"/>
3838
<element name="storeViewDropdown" type="text" selector="//select[@name='store_id']/option[contains(.,'{{storeView}}')]" parameterized="true"/>
39+
<element name="inputByCodeRangeFrom" type="input" selector="input.admin__control-text[name='{{code}}[from]']" parameterized="true"/>
40+
<element name="inputByCodeRangeTo" type="input" selector="input.admin__control-text[name='{{code}}[to]']" parameterized="true"/>
3941
</section>
4042
</sections>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
9+
<test name="AdminCreateDatetimeProductAttributeTest">
10+
<annotations>
11+
<features value="Catalog"/>
12+
<stories value="Datetime product attributes support"/>
13+
<title value="Datetime product attribute type is supported"/>
14+
<description value="Admin should be able to create datetime product attribute"/>
15+
<severity value="CRITICAL"/>
16+
<testCaseId value="MC-21451"/>
17+
<group value="catalog"/>
18+
</annotations>
19+
<before>
20+
<actionGroup ref="LoginAsAdmin" stepKey="login"/>
21+
</before>
22+
<after>
23+
<actionGroup ref="deleteProductAttribute" stepKey="deleteAttribute">
24+
<argument name="ProductAttribute" value="DatetimeProductAttribute"/>
25+
</actionGroup>
26+
<actionGroup ref="AdminGridFilterResetActionGroup" stepKey="resetGridFilter"/>
27+
<actionGroup ref="logout" stepKey="logout"/>
28+
</after>
29+
<!-- Generate the datetime default value -->
30+
<generateDate date="now" format="m/j/y g:i A" stepKey="generateDefaultValue"/>
31+
<!-- Create new datetime product attribute -->
32+
<amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="goToProductAttributes"/>
33+
<waitForPageLoad stepKey="waitForPageLoadAttributes"/>
34+
<actionGroup ref="CreateProductAttributeWithDatetimeField" stepKey="createAttribute">
35+
<argument name="attribute" value="DatetimeProductAttribute"/>
36+
<argument name="date" value="{$generateDefaultValue}"/>
37+
</actionGroup>
38+
<!-- Navigate to created product attribute -->
39+
<actionGroup ref="navigateToCreatedProductAttribute" stepKey="navigateToAttribute">
40+
<argument name="ProductAttribute" value="DatetimeProductAttribute"/>
41+
</actionGroup>
42+
<!-- Check the saved datetime default value -->
43+
<actionGroup ref="AdminNavigateToProductAttributeAdvancedSection" stepKey="goToAdvancedSection"/>
44+
<scrollTo selector="{{AdvancedAttributePropertiesSection.defaultValueDatetime}}" stepKey="scrollToDefaultValue"/>
45+
<seeInField userInput="{$generateDefaultValue}"
46+
selector="{{AdvancedAttributePropertiesSection.defaultValueDatetime}}"
47+
stepKey="checkDefaultValue"/>
48+
</test>
49+
</tests>

0 commit comments

Comments
 (0)