Skip to content

Commit 942656c

Browse files
author
Stanislav Idolov
authored
Merge branch '2.4-develop' into ISSUE-30286-widget-remove-layout-update
2 parents c7ee4fb + 285b397 commit 942656c

File tree

241 files changed

+10579
-3462
lines changed

Some content is hidden

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

241 files changed

+10579
-3462
lines changed

app/code/Magento/Backend/App/Area/FrontNameResolver.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ public function isHostBackend()
123123
if ($this->scopeConfig->getValue(self::XML_PATH_USE_CUSTOM_ADMIN_URL, ScopeInterface::SCOPE_STORE)) {
124124
$backendUrl = $this->scopeConfig->getValue(self::XML_PATH_CUSTOM_ADMIN_URL, ScopeInterface::SCOPE_STORE);
125125
} else {
126-
$backendUrl = $this->scopeConfig->getValue(Store::XML_PATH_UNSECURE_BASE_URL, ScopeInterface::SCOPE_STORE);
126+
$backendUrl = $this->config->getValue(Store::XML_PATH_UNSECURE_BASE_URL);
127+
if ($backendUrl === null) {
128+
$backendUrl = $this->scopeConfig->getValue(
129+
Store::XML_PATH_UNSECURE_BASE_URL,
130+
ScopeInterface::SCOPE_STORE
131+
);
132+
}
127133
}
128134
$host = $this->request->getServer('HTTP_HOST', '');
129135
return stripos($this->getHostWithPort($backendUrl), (string) $host) !== false;

app/code/Magento/Backend/Block/Widget/Button.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
*/
66
namespace Magento\Backend\Block\Widget;
77

8+
use Magento\Backend\Block\Template\Context;
89
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\Math\Random;
10-
use Magento\Backend\Block\Template\Context;
1111
use Magento\Framework\View\Helper\SecureHtmlRenderer;
1212

1313
/**
@@ -125,6 +125,9 @@ protected function _prepareAttributes($title, $classes, $disabled)
125125
'value' => $this->getValue(),
126126
'disabled' => $disabled,
127127
];
128+
if ($this->hasData('onclick_attribute')) {
129+
$attributes['onclick'] = $this->getData('onclick_attribute');
130+
}
128131
if ($this->hasData('backend_button_widget_hook_id')) {
129132
$attributes['backend-button-widget-hook-id'] = $this->getData('backend_button_widget_hook_id');
130133
}

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/Backend/Test/Unit/Block/Widget/ButtonTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,16 @@ public function getAttributesHtmlDataProvider()
9494
]
9595
];
9696
}
97+
98+
/**
99+
* Verifies ability of adding button onclick attribute
100+
*
101+
* @return void
102+
*/
103+
public function testOnClickAttribute(): void
104+
{
105+
$this->_blockMock->setData(['onclick_attribute' => 'value']);
106+
$attributes = $this->_blockMock->getAttributesHtml();
107+
$this->assertStringContainsString('onclick', $attributes);
108+
}
97109
}

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
}

0 commit comments

Comments
 (0)