Skip to content

Commit 1871319

Browse files
committed
Merge branch 'ACP2E-2679' of https://github.com/magento-l3/magento2ce into 2.4-develop
2 parents 2161e5c + a72edc6 commit 1871319

File tree

13 files changed

+336
-37
lines changed

13 files changed

+336
-37
lines changed

app/code/Magento/CatalogImportExport/Model/Export/Product.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
368368
*/
369369
private $stockConfiguration;
370370

371+
/**
372+
* @var array
373+
*/
374+
private array $attributeFrontendTypes = [];
375+
371376
/**
372377
* Product constructor.
373378
*
@@ -1062,7 +1067,7 @@ protected function collectRawData()
10621067

10631068
if ($this->_attributeTypes[$code] == 'datetime') {
10641069
if (in_array($code, $this->dateAttrCodes)
1065-
|| in_array($code, $this->userDefinedAttributes)
1070+
|| $this->attributeFrontendTypes[$code] === 'date'
10661071
) {
10671072
$attrValue = $this->_localeDate->formatDateTime(
10681073
new \DateTime($attrValue),
@@ -1657,6 +1662,7 @@ protected function initAttributes()
16571662
$this->_attributeValues[$attribute->getAttributeCode()] = $this->getAttributeOptions($attribute);
16581663
$this->_attributeTypes[$attribute->getAttributeCode()] =
16591664
\Magento\ImportExport\Model\Import::getAttributeType($attribute);
1665+
$this->attributeFrontendTypes[$attribute->getAttributeCode()] = $attribute->getFrontendInput();
16601666
if ($attribute->getIsUserDefined()) {
16611667
$this->userDefinedAttributes[] = $attribute->getAttributeCode();
16621668
}

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,18 +2054,26 @@ private function saveProductAttributesPhase(
20542054
$backModel = $attribute->getBackendModel();
20552055
$attrTable = $attribute->getBackend()->getTable();
20562056
$storeIds = [0];
2057-
if ('datetime' == $attribute->getBackendType()
2058-
&& (
2059-
in_array($attribute->getAttributeCode(), $this->dateAttrCodes)
2060-
|| $attribute->getIsUserDefined()
2061-
)
2062-
) {
2063-
$attrValue = $this->dateTime->formatDate($attrValue, false);
2064-
} elseif ('datetime' == $attribute->getBackendType() && strtotime($attrValue)) {
2065-
$attrValue = gmdate(
2066-
'Y-m-d H:i:s',
2067-
$this->_localeDate->date($attrValue)->getTimestamp()
2068-
);
2057+
if ('datetime' == $attribute->getBackendType()) {
2058+
$attrValue = trim((string) $attrValue);
2059+
if (!empty($attrValue)) {
2060+
$timezone = new \DateTimeZone($this->_localeDate->getConfigTimezone());
2061+
// Parse date from format Y-m-d[ H:i:s]
2062+
$date = date_create_from_format(DateTime::DATETIME_PHP_FORMAT, $attrValue, $timezone)
2063+
?: date_create_from_format(DateTime::DATE_PHP_FORMAT, $attrValue, $timezone);
2064+
// Perhaps, date is formatted according to user locale. For example, dates in exported csv file
2065+
$date = $date ?: $this->_localeDate->date($attrValue);
2066+
if ($attribute->getFrontendInput() === 'date'
2067+
|| in_array($attribute->getAttributeCode(), $this->dateAttrCodes)
2068+
) {
2069+
$date->setTime(0, 0);
2070+
} else {
2071+
$date->setTimezone(new \DateTimeZone($this->_localeDate->getDefaultTimezone()));
2072+
}
2073+
$attrValue = $date->format(DateTime::DATETIME_PHP_FORMAT);
2074+
} else {
2075+
$attrValue = null;
2076+
}
20692077
} elseif ($backModel) {
20702078
$attribute->getBackend()->beforeSave($product);
20712079
$attrValue = $product->getData($attribute->getAttributeCode());

app/code/Magento/CatalogImportExport/Model/Import/Product/Validator.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
namespace Magento\CatalogImportExport\Model\Import\Product;
77

88
use Magento\CatalogImportExport\Model\Import\Product;
9+
use Magento\Framework\App\ObjectManager;
10+
use Magento\Framework\Stdlib\DateTime;
11+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
912
use Magento\Framework\Validator\AbstractValidator;
1013
use Magento\Catalog\Model\Product\Attribute\Backend\Sku;
1114

@@ -49,15 +52,24 @@ class Validator extends AbstractValidator implements RowValidatorInterface
4952
protected $invalidAttribute;
5053

5154
/**
52-
* @param \Magento\Framework\Stdlib\StringUtils $string
55+
* @var TimezoneInterface
56+
*/
57+
private $localeDate;
58+
59+
/**
60+
* @param StringUtils $string
5361
* @param RowValidatorInterface[] $validators
62+
* @param TimezoneInterface|null $localeDate
5463
*/
5564
public function __construct(
5665
\Magento\Framework\Stdlib\StringUtils $string,
57-
$validators = []
66+
$validators = [],
67+
?TimezoneInterface $localeDate = null
5868
) {
5969
$this->string = $string;
6070
$this->validators = $validators;
71+
$this->localeDate = $localeDate ?: ObjectManager::getInstance()
72+
->get(TimezoneInterface::class);
6173
}
6274

6375
/**
@@ -302,7 +314,16 @@ private function validateMultiselect(string $attrCode, array $options, array|str
302314
private function validateDateTime(string $rowData): bool
303315
{
304316
$val = trim($rowData);
305-
$valid = strtotime($val) !== false;
317+
try {
318+
if (!date_create_from_format(DateTime::DATETIME_PHP_FORMAT, $val)
319+
&& !date_create_from_format(DateTime::DATE_PHP_FORMAT, $val)
320+
) {
321+
$this->localeDate->date($val);
322+
}
323+
$valid = true;
324+
} catch (\Exception $e) {
325+
$valid = false;
326+
}
306327
if (!$valid) {
307328
$this->_addMessages([RowValidatorInterface::ERROR_INVALID_ATTRIBUTE_TYPE]);
308329
}

app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
use PHPUnit\Framework\MockObject\MockObject;
1919
use PHPUnit\Framework\TestCase;
2020

21+
/**
22+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
23+
*/
2124
class ValidatorTest extends TestCase
2225
{
2326
/** @var Validator */
@@ -62,13 +65,19 @@ protected function setUp(): void
6265
);
6366

6467
$this->validators = [$this->validatorOne, $this->validatorTwo];
65-
$this->objectManagerHelper = new ObjectManagerHelper($this);
66-
$this->validator = $this->objectManagerHelper->getObject(
67-
Validator::class,
68-
[
69-
'string' => new StringUtils(),
70-
'validators' => $this->validators
71-
]
68+
$timezone = $this->createMock(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class);
69+
$timezone->expects($this->any())
70+
->method('date')
71+
->willReturnCallback(
72+
function ($date = null) {
73+
return new \DateTime($date);
74+
}
75+
);
76+
77+
$this->validator = new Validator(
78+
new StringUtils(),
79+
$this->validators,
80+
$timezone
7281
);
7382
$this->validator->init($this->context);
7483
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\ImportExport\Api\Data;
20+
21+
interface FieldsEnclosureAwareExportInfoInterface extends LocalizedExportInfoInterface
22+
{
23+
/**
24+
* Returns whether fields enclosure is enabled
25+
*
26+
* @return bool|null
27+
*/
28+
public function getFieldsEnclosure(): ?bool;
29+
30+
/**
31+
* Set whether fields enclosure is enabled
32+
*
33+
* @param bool $fieldsEnclosure
34+
* @return void
35+
*/
36+
public function setFieldsEnclosure(bool $fieldsEnclosure): void;
37+
}

app/code/Magento/ImportExport/Controller/Adminhtml/Export/Export.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ public function execute()
9999
$params['entity'],
100100
$params['export_filter'],
101101
$params['skip_attr'],
102-
$this->localeResolver->getLocale()
102+
$this->localeResolver->getLocale(),
103+
isset($params['fields_enclosure']) ? (bool) $params['fields_enclosure'] : null
103104
);
104105

105106
$this->messagePublisher->publish('import_export.export', $dataObject);

app/code/Magento/ImportExport/Model/Export/Entity/ExportInfo.php

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
namespace Magento\ImportExport\Model\Export\Entity;
99

10-
use Magento\ImportExport\Api\Data\LocalizedExportInfoInterface;
10+
use Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface;
1111

1212
/**
1313
* Class ExportInfo implementation for ExportInfoInterface.
1414
*/
15-
class ExportInfo implements LocalizedExportInfoInterface
15+
class ExportInfo implements FieldsEnclosureAwareExportInfoInterface
1616
{
1717
/**
1818
* @var string
@@ -49,6 +49,11 @@ class ExportInfo implements LocalizedExportInfoInterface
4949
*/
5050
private $locale;
5151

52+
/**
53+
* @var bool
54+
*/
55+
private $fieldsEnclosure;
56+
5257
/**
5358
* @inheritdoc
5459
*/
@@ -163,4 +168,20 @@ public function setLocale(string $locale): void
163168
{
164169
$this->locale = $locale;
165170
}
171+
172+
/**
173+
* @inheritDoc
174+
*/
175+
public function getFieldsEnclosure(): ?bool
176+
{
177+
return $this->fieldsEnclosure;
178+
}
179+
180+
/**
181+
* @inheritDoc
182+
*/
183+
public function setFieldsEnclosure(bool $fieldsEnclosure): void
184+
{
185+
$this->fieldsEnclosure = $fieldsEnclosure;
186+
}
166187
}

app/code/Magento/ImportExport/Model/Export/Entity/ExportInfoFactory.php

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\Serialize\SerializerInterface;
1111
use Magento\ImportExport\Api\Data\ExportInfoInterface;
1212
use Magento\Framework\ObjectManagerInterface;
13+
use Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface;
1314
use \Psr\Log\LoggerInterface;
1415
use Magento\ImportExport\Model\Export\ConfigInterface;
1516
use Magento\ImportExport\Model\Export\Entity\Factory as EntityFactory;
@@ -18,6 +19,8 @@
1819

1920
/**
2021
* Factory for Export Info
22+
*
23+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2124
*/
2225
class ExportInfoFactory
2326
{
@@ -83,11 +86,18 @@ public function __construct(
8386
* @param string $exportFilter
8487
* @param array $skipAttr
8588
* @param string|null $locale
89+
* @param bool|null $fieldsEnclosure
8690
* @return ExportInfoInterface
8791
* @throws \Magento\Framework\Exception\LocalizedException
8892
*/
89-
public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?string $locale = null)
90-
{
93+
public function create(
94+
$fileFormat,
95+
$entity,
96+
$exportFilter,
97+
$skipAttr = [],
98+
?string $locale = null,
99+
?bool $fieldsEnclosure = null
100+
) {
91101
$writer = $this->getWriter($fileFormat);
92102
$entityAdapter = $this->getEntityAdapter(
93103
$entity,
@@ -97,8 +107,8 @@ public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?str
97107
$writer->getContentType()
98108
);
99109
$fileName = $this->generateFileName($entity, $entityAdapter, $writer->getFileExtension());
100-
/** @var ExportInfoInterface $exportInfo */
101-
$exportInfo = $this->objectManager->create(ExportInfoInterface::class);
110+
/** @var FieldsEnclosureAwareExportInfoInterface $exportInfo */
111+
$exportInfo = $this->objectManager->create(FieldsEnclosureAwareExportInfoInterface::class);
102112
$exportInfo->setExportFilter($this->serializer->serialize($exportFilter));
103113
$exportInfo->setSkipAttr($skipAttr);
104114
$exportInfo->setFileName($fileName);
@@ -108,6 +118,9 @@ public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?str
108118
if ($locale) {
109119
$exportInfo->setLocale($locale);
110120
}
121+
if ($fieldsEnclosure !== null) {
122+
$exportInfo->setFieldsEnclosure($fieldsEnclosure);
123+
}
111124

112125
return $exportInfo;
113126
}

app/code/Magento/ImportExport/etc/communication.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Communication/etc/communication.xsd">
9-
<topic name="import_export.export" request="Magento\ImportExport\Api\Data\LocalizedExportInfoInterface">
9+
<topic name="import_export.export" request="Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface">
1010
<handler name="exportProcessor" type="Magento\ImportExport\Model\Export\Consumer" method="process" />
1111
</topic>
1212
</config>

app/code/Magento/ImportExport/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<preference for="Magento\ImportExport\Model\Report\ReportProcessorInterface" type="Magento\ImportExport\Model\Report\Csv" />
1313
<preference for="Magento\ImportExport\Api\Data\ExportInfoInterface" type="Magento\ImportExport\Model\Export\Entity\ExportInfo" />
1414
<preference for="Magento\ImportExport\Api\Data\LocalizedExportInfoInterface" type="Magento\ImportExport\Model\Export\Entity\ExportInfo" />
15+
<preference for="Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface" type="Magento\ImportExport\Model\Export\Entity\ExportInfo" />
1516
<preference for="Magento\ImportExport\Api\ExportManagementInterface" type="Magento\ImportExport\Model\Export\ExportManagement" />
1617
<preference for="Magento\ImportExport\Model\LocaleEmulatorInterface" type="Magento\ImportExport\Model\LocaleEmulator\Proxy" />
1718
<type name="Magento\Framework\Module\Setup\Migration">

0 commit comments

Comments
 (0)