diff --git a/vendor/magento/module-catalog-import-export/Model/Export/Product.php b/vendor/magento/module-catalog-import-export/Model/Export/Product.php
index 505dafc27ab14..79fe54430bdd2 100644
--- a/vendor/magento/module-catalog-import-export/Model/Export/Product.php
+++ b/vendor/magento/module-catalog-import-export/Model/Export/Product.php
@@ -368,6 +368,11 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
*/
private $stockConfiguration;
+ /**
+ * @var array
+ */
+ private array $attributeFrontendTypes = [];
+
/**
* Product constructor.
*
@@ -1062,7 +1067,7 @@ protected function collectRawData()
if ($this->_attributeTypes[$code] == 'datetime') {
if (in_array($code, $this->dateAttrCodes)
- || in_array($code, $this->userDefinedAttributes)
+ || $this->attributeFrontendTypes[$code] === 'date'
) {
$attrValue = $this->_localeDate->formatDateTime(
new \DateTime($attrValue),
@@ -1657,6 +1662,7 @@ protected function initAttributes()
$this->_attributeValues[$attribute->getAttributeCode()] = $this->getAttributeOptions($attribute);
$this->_attributeTypes[$attribute->getAttributeCode()] =
\Magento\ImportExport\Model\Import::getAttributeType($attribute);
+ $this->attributeFrontendTypes[$attribute->getAttributeCode()] = $attribute->getFrontendInput();
if ($attribute->getIsUserDefined()) {
$this->userDefinedAttributes[] = $attribute->getAttributeCode();
}
diff --git a/vendor/magento/module-catalog-import-export/Model/Import/Product.php b/vendor/magento/module-catalog-import-export/Model/Import/Product.php
index 129151261b3a3..a7003c4b56c6a 100644
--- a/vendor/magento/module-catalog-import-export/Model/Import/Product.php
+++ b/vendor/magento/module-catalog-import-export/Model/Import/Product.php
@@ -2055,18 +2055,26 @@ private function saveProductAttributesPhase(
$backModel = $attribute->getBackendModel();
$attrTable = $attribute->getBackend()->getTable();
$storeIds = [0];
- if ('datetime' == $attribute->getBackendType()
- && (
- in_array($attribute->getAttributeCode(), $this->dateAttrCodes)
- || $attribute->getIsUserDefined()
- )
- ) {
- $attrValue = $this->dateTime->formatDate($attrValue, false);
- } elseif ('datetime' == $attribute->getBackendType() && strtotime($attrValue)) {
- $attrValue = gmdate(
- 'Y-m-d H:i:s',
- $this->_localeDate->date($attrValue)->getTimestamp()
- );
+ if ('datetime' == $attribute->getBackendType()) {
+ $attrValue = trim((string) $attrValue);
+ if (!empty($attrValue)) {
+ $timezone = new \DateTimeZone($this->_localeDate->getConfigTimezone());
+ // Parse date from format Y-m-d[ H:i:s]
+ $date = date_create_from_format(DateTime::DATETIME_PHP_FORMAT, $attrValue, $timezone)
+ ?: date_create_from_format(DateTime::DATE_PHP_FORMAT, $attrValue, $timezone);
+ // Perhaps, date is formatted according to user locale. For example, dates in exported csv file
+ $date = $date ?: $this->_localeDate->date($attrValue);
+ if ($attribute->getFrontendInput() === 'date'
+ || in_array($attribute->getAttributeCode(), $this->dateAttrCodes)
+ ) {
+ $date->setTime(0, 0);
+ } else {
+ $date->setTimezone(new \DateTimeZone($this->_localeDate->getDefaultTimezone()));
+ }
+ $attrValue = $date->format(DateTime::DATETIME_PHP_FORMAT);
+ } else {
+ $attrValue = null;
+ }
} elseif ($backModel) {
$attribute->getBackend()->beforeSave($product);
$attrValue = $product->getData($attribute->getAttributeCode());
diff --git a/vendor/magento/module-catalog-import-export/Model/Import/Product/Validator.php b/vendor/magento/module-catalog-import-export/Model/Import/Product/Validator.php
index f74886069d501..24d8b6ae2593e 100644
--- a/vendor/magento/module-catalog-import-export/Model/Import/Product/Validator.php
+++ b/vendor/magento/module-catalog-import-export/Model/Import/Product/Validator.php
@@ -6,6 +6,9 @@
namespace Magento\CatalogImportExport\Model\Import\Product;
use Magento\CatalogImportExport\Model\Import\Product;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Stdlib\DateTime;
+use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\Framework\Validator\AbstractValidator;
use Magento\Catalog\Model\Product\Attribute\Backend\Sku;
@@ -49,15 +52,24 @@ class Validator extends AbstractValidator implements RowValidatorInterface
protected $invalidAttribute;
/**
- * @param \Magento\Framework\Stdlib\StringUtils $string
+ * @var TimezoneInterface
+ */
+ private $localeDate;
+
+ /**
+ * @param StringUtils $string
* @param RowValidatorInterface[] $validators
+ * @param TimezoneInterface|null $localeDate
*/
public function __construct(
\Magento\Framework\Stdlib\StringUtils $string,
- $validators = []
+ $validators = [],
+ ?TimezoneInterface $localeDate = null
) {
$this->string = $string;
$this->validators = $validators;
+ $this->localeDate = $localeDate ?: ObjectManager::getInstance()
+ ->get(TimezoneInterface::class);
}
/**
@@ -302,7 +314,16 @@ private function validateMultiselect(string $attrCode, array $options, array|str
private function validateDateTime(string $rowData): bool
{
$val = trim($rowData);
- $valid = strtotime($val) !== false;
+ try {
+ if (!date_create_from_format(DateTime::DATETIME_PHP_FORMAT, $val)
+ && !date_create_from_format(DateTime::DATE_PHP_FORMAT, $val)
+ ) {
+ $this->localeDate->date($val);
+ }
+ $valid = true;
+ } catch (\Exception $e) {
+ $valid = false;
+ }
if (!$valid) {
$this->_addMessages([RowValidatorInterface::ERROR_INVALID_ATTRIBUTE_TYPE]);
}
diff --git a/vendor/magento/module-import-export/Api/Data/FieldsEnclosureAwareExportInfoInterface.php b/vendor/magento/module-import-export/Api/Data/FieldsEnclosureAwareExportInfoInterface.php
new file mode 100644
index 0000000000000..af1efa3fbd3bb
--- /dev/null
+++ b/vendor/magento/module-import-export/Api/Data/FieldsEnclosureAwareExportInfoInterface.php
@@ -0,0 +1,37 @@
+localeResolver->getLocale()
+ $this->localeResolver->getLocale(),
+ isset($params['fields_enclosure']) ? (bool) $params['fields_enclosure'] : null
);
$this->messagePublisher->publish('import_export.export', $dataObject);
diff --git a/vendor/magento/module-import-export/Model/Export/Entity/ExportInfo.php b/vendor/magento/module-import-export/Model/Export/Entity/ExportInfo.php
index b2b6fe01dc1be..772659a95d3b7 100644
--- a/vendor/magento/module-import-export/Model/Export/Entity/ExportInfo.php
+++ b/vendor/magento/module-import-export/Model/Export/Entity/ExportInfo.php
@@ -7,12 +7,12 @@
namespace Magento\ImportExport\Model\Export\Entity;
-use Magento\ImportExport\Api\Data\LocalizedExportInfoInterface;
+use Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface;
/**
* Class ExportInfo implementation for ExportInfoInterface.
*/
-class ExportInfo implements LocalizedExportInfoInterface
+class ExportInfo implements FieldsEnclosureAwareExportInfoInterface
{
/**
* @var string
@@ -49,6 +49,11 @@ class ExportInfo implements LocalizedExportInfoInterface
*/
private $locale;
+ /**
+ * @var bool
+ */
+ private $fieldsEnclosure;
+
/**
* @inheritdoc
*/
@@ -163,4 +168,20 @@ public function setLocale(string $locale): void
{
$this->locale = $locale;
}
+
+ /**
+ * @inheritDoc
+ */
+ public function getFieldsEnclosure(): ?bool
+ {
+ return $this->fieldsEnclosure;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function setFieldsEnclosure(bool $fieldsEnclosure): void
+ {
+ $this->fieldsEnclosure = $fieldsEnclosure;
+ }
}
diff --git a/vendor/magento/module-import-export/Model/Export/Entity/ExportInfoFactory.php b/vendor/magento/module-import-export/Model/Export/Entity/ExportInfoFactory.php
index 93251136f7510..c2813e1759f96 100644
--- a/vendor/magento/module-import-export/Model/Export/Entity/ExportInfoFactory.php
+++ b/vendor/magento/module-import-export/Model/Export/Entity/ExportInfoFactory.php
@@ -10,6 +10,7 @@
use Magento\Framework\Serialize\SerializerInterface;
use Magento\ImportExport\Api\Data\ExportInfoInterface;
use Magento\Framework\ObjectManagerInterface;
+use Magento\ImportExport\Api\Data\FieldsEnclosureAwareExportInfoInterface;
use \Psr\Log\LoggerInterface;
use Magento\ImportExport\Model\Export\ConfigInterface;
use Magento\ImportExport\Model\Export\Entity\Factory as EntityFactory;
@@ -18,6 +19,8 @@
/**
* Factory for Export Info
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ExportInfoFactory
{
@@ -83,11 +86,18 @@ public function __construct(
* @param string $exportFilter
* @param array $skipAttr
* @param string|null $locale
+ * @param bool|null $fieldsEnclosure
* @return ExportInfoInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
- public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?string $locale = null)
- {
+ public function create(
+ $fileFormat,
+ $entity,
+ $exportFilter,
+ $skipAttr = [],
+ ?string $locale = null,
+ ?bool $fieldsEnclosure = null
+ ) {
$writer = $this->getWriter($fileFormat);
$entityAdapter = $this->getEntityAdapter(
$entity,
@@ -97,8 +107,8 @@ public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?str
$writer->getContentType()
);
$fileName = $this->generateFileName($entity, $entityAdapter, $writer->getFileExtension());
- /** @var ExportInfoInterface $exportInfo */
- $exportInfo = $this->objectManager->create(ExportInfoInterface::class);
+ /** @var FieldsEnclosureAwareExportInfoInterface $exportInfo */
+ $exportInfo = $this->objectManager->create(FieldsEnclosureAwareExportInfoInterface::class);
$exportInfo->setExportFilter($this->serializer->serialize($exportFilter));
$exportInfo->setSkipAttr($skipAttr);
$exportInfo->setFileName($fileName);
@@ -108,6 +118,9 @@ public function create($fileFormat, $entity, $exportFilter, $skipAttr = [], ?str
if ($locale) {
$exportInfo->setLocale($locale);
}
+ if ($fieldsEnclosure !== null) {
+ $exportInfo->setFieldsEnclosure($fieldsEnclosure);
+ }
return $exportInfo;
}
diff --git a/vendor/magento/module-import-export/etc/communication.xml b/vendor/magento/module-import-export/etc/communication.xml
index de0907f3831fc..c850b53cea7e9 100644
--- a/vendor/magento/module-import-export/etc/communication.xml
+++ b/vendor/magento/module-import-export/etc/communication.xml
@@ -6,7 +6,7 @@
*/
-->
-
+
diff --git a/vendor/magento/module-import-export/etc/di.xml b/vendor/magento/module-import-export/etc/di.xml
index 66930b2127d52..a579087ec45ea 100644
--- a/vendor/magento/module-import-export/etc/di.xml
+++ b/vendor/magento/module-import-export/etc/di.xml
@@ -12,6 +12,7 @@
+