Skip to content

Commit 1f201ae

Browse files
author
Gabriel da Gama
authored
Merge branch '2.4-develop' into fix-csp-blocked-font-and-image
2 parents 7de93bb + ad29452 commit 1f201ae

File tree

182 files changed

+9144
-3342
lines changed

Some content is hidden

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

182 files changed

+9144
-3342
lines changed

app/code/Magento/Backend/Test/Mftf/Test/AdminExpireCustomerSessionTest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<after>
2323
<!-- 6. Restore default configuration settings. -->
2424
<magentoCLI command="config:set {{DefaultWebCookieLifetimeConfigData.path}} {{DefaultWebCookieLifetimeConfigData.value}}" stepKey="setDefaultCookieLifetime"/>
25+
<!-- Customer Log Out -->
26+
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/>
2527
<!-- Delete data -->
2628
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
2729
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>

app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery/Content.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,15 +209,22 @@ public function getImagesJson()
209209
*/
210210
private function sortImagesByPosition($images)
211211
{
212-
if (is_array($images)) {
212+
$nullPositions = [];
213+
foreach ($images as $index => $image) {
214+
if ($image['position'] === null) {
215+
$nullPositions[] = $image;
216+
unset($images[$index]);
217+
}
218+
}
219+
if (is_array($images) && !empty($images)) {
213220
usort(
214221
$images,
215222
function ($imageA, $imageB) {
216223
return ($imageA['position'] < $imageB['position']) ? -1 : 1;
217224
}
218225
);
219226
}
220-
return $images;
227+
return array_merge($images, $nullPositions);
221228
}
222229

223230
/**

app/code/Magento/Catalog/Block/Product/View/Options/Type/Date.php

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
*/
66
namespace Magento\Catalog\Block\Product\View\Options\Type;
77

8+
use DateTimeZone;
9+
use Magento\Framework\App\ObjectManager;
10+
use Magento\Framework\Data\Form\FilterFactory;
11+
use Magento\Framework\Stdlib\DateTime;
12+
813
/**
914
* Product options text type block
1015
*
@@ -27,22 +32,30 @@ class Date extends \Magento\Catalog\Block\Product\View\Options\AbstractOptions
2732
*/
2833
protected $_catalogProductOptionTypeDate;
2934

35+
/**
36+
* @var FilterFactory
37+
*/
38+
private $filterFactory;
39+
3040
/**
3141
* @param \Magento\Framework\View\Element\Template\Context $context
3242
* @param \Magento\Framework\Pricing\Helper\Data $pricingHelper
3343
* @param \Magento\Catalog\Helper\Data $catalogData
3444
* @param \Magento\Catalog\Model\Product\Option\Type\Date $catalogProductOptionTypeDate
3545
* @param array $data
46+
* @param FilterFactory|null $filterFactory
3647
*/
3748
public function __construct(
3849
\Magento\Framework\View\Element\Template\Context $context,
3950
\Magento\Framework\Pricing\Helper\Data $pricingHelper,
4051
\Magento\Catalog\Helper\Data $catalogData,
4152
\Magento\Catalog\Model\Product\Option\Type\Date $catalogProductOptionTypeDate,
42-
array $data = []
53+
array $data = [],
54+
?FilterFactory $filterFactory = null
4355
) {
4456
$this->_catalogProductOptionTypeDate = $catalogProductOptionTypeDate;
4557
parent::__construct($context, $pricingHelper, $catalogData, $data);
58+
$this->filterFactory = $filterFactory ?? ObjectManager::getInstance()->get(FilterFactory::class);
4659
}
4760

4861
/**
@@ -77,14 +90,24 @@ public function getDateHtml()
7790
public function getCalendarDateHtml()
7891
{
7992
$option = $this->getOption();
80-
$value = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $option->getId() . '/date');
93+
$values = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $option->getId());
8194

8295
$yearStart = $this->_catalogProductOptionTypeDate->getYearStart();
8396
$yearEnd = $this->_catalogProductOptionTypeDate->getYearEnd();
8497

85-
$dateFormat = $this->_localeDate->getDateFormat(\IntlDateFormatter::SHORT);
98+
$dateFormat = $this->_localeDate->getDateFormatWithLongYear();
8699
/** Escape RTL characters which are present in some locales and corrupt formatting */
87100
$escapedDateFormat = preg_replace('/[^MmDdYy\/\.\-]/', '', $dateFormat);
101+
$value = null;
102+
if (is_array($values)) {
103+
$date = $this->getInternalDateString($values);
104+
if ($date !== null) {
105+
$dateFilter = $this->filterFactory->create('date', ['format' => $escapedDateFormat]);
106+
$value = $dateFilter->outputFilter($date);
107+
} elseif (isset($values['date'])) {
108+
$value = $values['date'];
109+
}
110+
}
88111
$calendar = $this->getLayout()->createBlock(
89112
\Magento\Framework\View\Element\Html\Date::class
90113
)->setId(
@@ -158,8 +181,8 @@ public function getTimeHtml()
158181
* Return drop-down html with range of values
159182
*
160183
* @param string $name Id/name of html select element
161-
* @param int $from Start position
162-
* @param int $to End position
184+
* @param int $from Start position
185+
* @param int $to End position
163186
* @param int|null $value Value selected
164187
* @return string Formatted Html
165188
*/
@@ -209,9 +232,8 @@ protected function _getHtmlSelect($name, $value = null)
209232

210233
$select->setExtraParams($extraParams);
211234
if ($value === null) {
212-
$value = $this->getProduct()->getPreconfiguredValues()->getData(
213-
'options/' . $option->getId() . '/' . $name
214-
);
235+
$values = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $option->getId());
236+
$value = is_array($values) ? $this->parseDate($values, $name) : null;
215237
}
216238
if ($value !== null) {
217239
$select->setValue($value);
@@ -233,4 +255,56 @@ protected function _getValueWithLeadingZeros($value)
233255
}
234256
return $value < 10 ? '0' . $value : $value;
235257
}
258+
259+
/**
260+
* Get internal date format of provided value
261+
*
262+
* @param array $value
263+
* @return string|null
264+
*/
265+
private function getInternalDateString(array $value): ?string
266+
{
267+
$result = null;
268+
if (!empty($value['date']) && !empty($value['date_internal'])) {
269+
$dateTimeZone = new DateTimeZone($this->_localeDate->getConfigTimezone());
270+
$dateTimeObject = date_create_from_format(
271+
DateTime::DATETIME_PHP_FORMAT,
272+
$value['date_internal'],
273+
$dateTimeZone
274+
);
275+
if ($dateTimeObject !== false) {
276+
$result = $dateTimeObject->format(DateTime::DATE_PHP_FORMAT);
277+
}
278+
} elseif (!empty($value['day']) && !empty($value['month']) && !empty($value['year'])) {
279+
$dateTimeObject = $this->_localeDate->date();
280+
$dateTimeObject->setDate((int) $value['year'], (int) $value['month'], (int) $value['day']);
281+
$result = $dateTimeObject->format(DateTime::DATE_PHP_FORMAT);
282+
}
283+
return $result;
284+
}
285+
286+
/**
287+
* Parse option value and return the requested part
288+
*
289+
* @param array $value
290+
* @param string $part [year, month, day, hour, minute, day_part]
291+
* @return string|null
292+
*/
293+
private function parseDate(array $value, string $part): ?string
294+
{
295+
$result = null;
296+
if (!empty($value['date']) && !empty($value['date_internal'])) {
297+
$formatDate = explode(' ', $value['date_internal']);
298+
$date = explode('-', $formatDate[0]);
299+
$value['year'] = $date[0];
300+
$value['month'] = $date[1];
301+
$value['day'] = $date[2];
302+
}
303+
304+
if (isset($value[$part])) {
305+
$result = (string) $value[$part];
306+
}
307+
308+
return $result;
309+
}
236310
}

app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,29 +267,50 @@ protected function processNewAndExistingImages($product, array &$images)
267267
{
268268
foreach ($images as &$image) {
269269
if (empty($image['removed'])) {
270+
$isNew = empty($image['value_id']);
270271
$data = $this->processNewImage($product, $image);
271272

272-
if (!$product->isObjectNew()) {
273-
$this->resourceModel->deleteGalleryValueInStore(
274-
$image['value_id'],
275-
$product->getData($this->metadata->getLinkField()),
276-
$product->getStoreId()
277-
);
278-
}
279273
// Add per store labels, position, disabled
280274
$data['value_id'] = $image['value_id'];
281275
$data['label'] = isset($image['label']) ? $image['label'] : '';
282-
$data['position'] = isset($image['position']) ? (int)$image['position'] : 0;
276+
$data['position'] = isset($image['position']) && $image['position'] !== ''
277+
? (int)$image['position']
278+
: null;
283279
$data['disabled'] = isset($image['disabled']) ? (int)$image['disabled'] : 0;
284280
$data['store_id'] = (int)$product->getStoreId();
285281

286282
$data[$this->metadata->getLinkField()] = (int)$product->getData($this->metadata->getLinkField());
287283

288-
$this->resourceModel->insertGalleryValueInStore($data);
284+
$this->saveGalleryStoreValue($product, $data);
285+
if ($isNew && $data['store_id'] !== Store::DEFAULT_STORE_ID) {
286+
$dataForDefaultScope = $data;
287+
$dataForDefaultScope['store_id'] = Store::DEFAULT_STORE_ID;
288+
$dataForDefaultScope['disabled'] = 0;
289+
$dataForDefaultScope['label'] = null;
290+
$this->saveGalleryStoreValue($product, $dataForDefaultScope);
291+
}
289292
}
290293
}
291294
}
292295

296+
/**
297+
* Save media gallery store value
298+
*
299+
* @param Product $product
300+
* @param array $data
301+
*/
302+
private function saveGalleryStoreValue(Product $product, array $data): void
303+
{
304+
if (!$product->isObjectNew()) {
305+
$this->resourceModel->deleteGalleryValueInStore(
306+
$data['value_id'],
307+
$data[$this->metadata->getLinkField()],
308+
$data['store_id']
309+
);
310+
}
311+
$this->resourceModel->insertGalleryValueInStore($data);
312+
}
313+
293314
/**
294315
* Processes image as new.
295316
*

app/code/Magento/Catalog/Model/Product/Gallery/ReadHandler.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ public function execute($entity, $arguments = [])
6464

6565
$this->addMediaDataToProduct(
6666
$entity,
67-
$mediaEntries
67+
$this->sortMediaEntriesByPosition($mediaEntries)
6868
);
69-
69+
7070
return $entity;
7171
}
7272

@@ -108,7 +108,7 @@ public function getAttribute()
108108
* Find default value
109109
*
110110
* @param string $key
111-
* @param string[] &$image
111+
* @param string[] $image
112112
* @return string
113113
* @deprecated 101.0.1
114114
* @since 101.0.0
@@ -121,4 +121,30 @@ protected function findDefaultValue($key, &$image)
121121

122122
return '';
123123
}
124+
125+
/**
126+
* Sort media entries by position
127+
*
128+
* @param array $mediaEntries
129+
* @return array
130+
*/
131+
private function sortMediaEntriesByPosition(array $mediaEntries): array
132+
{
133+
$mediaEntriesWithNullPositions = [];
134+
foreach ($mediaEntries as $index => $mediaEntry) {
135+
if ($mediaEntry['position'] === null) {
136+
$mediaEntriesWithNullPositions[] = $mediaEntry;
137+
unset($mediaEntries[$index]);
138+
}
139+
}
140+
if (!empty($mediaEntries)) {
141+
usort(
142+
$mediaEntries,
143+
function ($entryA, $entryB) {
144+
return ($entryA['position'] < $entryB['position']) ? -1 : 1;
145+
}
146+
);
147+
}
148+
return array_merge($mediaEntries, $mediaEntriesWithNullPositions);
149+
}
124150
}

app/code/Magento/Catalog/Model/Product/Option/Type/File.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
namespace Magento\Catalog\Model\Product\Option\Type;
88

9+
use Magento\Catalog\Model\Product\Exception as ProductException;
10+
use Magento\Catalog\Helper\Product as ProductHelper;
911
use Magento\Framework\App\Filesystem\DirectoryList;
1012
use Magento\Framework\Filesystem;
1113
use Magento\Framework\Exception\LocalizedException;
12-
use Magento\Catalog\Model\Product\Exception as ProductException;
1314
use Magento\Framework\Serialize\Serializer\Json;
1415
use Magento\Framework\App\ObjectManager;
1516

@@ -91,6 +92,11 @@ class File extends \Magento\Catalog\Model\Product\Option\Type\DefaultType
9192
*/
9293
private $filesystem;
9394

95+
/**
96+
* @var ProductHelper
97+
*/
98+
private $productHelper;
99+
94100
/**
95101
* @param \Magento\Checkout\Model\Session $checkoutSession
96102
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -103,6 +109,7 @@ class File extends \Magento\Catalog\Model\Product\Option\Type\DefaultType
103109
* @param array $data
104110
* @param Filesystem $filesystem
105111
* @param Json|null $serializer
112+
* @param ProductHelper|null $productHelper
106113
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
107114
*/
108115
public function __construct(
@@ -116,7 +123,8 @@ public function __construct(
116123
\Magento\Framework\Escaper $escaper,
117124
array $data = [],
118125
Filesystem $filesystem = null,
119-
Json $serializer = null
126+
Json $serializer = null,
127+
ProductHelper $productHelper = null
120128
) {
121129
$this->_itemOptionFactory = $itemOptionFactory;
122130
$this->_urlBuilder = $urlBuilder;
@@ -129,6 +137,7 @@ public function __construct(
129137
$this->validatorInfo = $validatorInfo;
130138
$this->validatorFile = $validatorFile;
131139
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
140+
$this->productHelper = $productHelper ?: ObjectManager::getInstance()->get(ProductHelper::class);
132141
parent::__construct($checkoutSession, $scopeConfig, $data);
133142
}
134143

@@ -223,12 +232,21 @@ public function validateUserValue($values)
223232
$this->setIsValid(true);
224233
$option = $this->getOption();
225234

235+
if (isset($values['files_prefix'])) {
236+
$processingParams = ['files_prefix' => $values['files_prefix']];
237+
$processingParams = array_merge($this->_getProcessingParams()->getData(), $processingParams);
238+
$this->productHelper->addParamsToBuyRequest($this->getRequest(), $processingParams);
239+
}
240+
226241
/*
227242
* Check whether we receive uploaded file or restore file by: reorder/edit configuration or
228243
* previous configuration with no newly uploaded file
229244
*/
230245
$fileInfo = null;
231-
if (isset($values[$option->getId()]) && is_array($values[$option->getId()])) {
246+
if (isset($values[$option->getId()])) {
247+
if (is_string($values[$option->getId()])) {
248+
$values[$option->getId()] = explode(',', $values[$option->getId()]);
249+
}
232250
// Legacy style, file info comes in array with option id index
233251
$fileInfo = $values[$option->getId()];
234252
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminCheckNameToggleOnProductsMassAttributesUpdateActionGroup">
12+
<annotations>
13+
<description>Click the "Change" checkbox for the "Name" field on the Products Masss Attributes Update page.</description>
14+
</annotations>
15+
16+
<click selector="{{AdminEditProductAttributesSection.ChangeAttributeNameToggle}}" stepKey="toggleToChangeName"/>
17+
18+
</actionGroup>
19+
</actionGroups>

0 commit comments

Comments
 (0)