Skip to content

Commit 555a57d

Browse files
committed
Merge remote-tracking branch 'upstream/2.4-develop' into phpcs-installer
2 parents 7e80263 + aab3ee6 commit 555a57d

File tree

454 files changed

+17284
-1597
lines changed

Some content is hidden

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

454 files changed

+17284
-1597
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Authorization\Model;
10+
11+
use Magento\Framework\App\Backpressure\ContextInterface;
12+
use Magento\Framework\App\Backpressure\IdentityProviderInterface;
13+
use Magento\Framework\Exception\RuntimeException;
14+
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
15+
16+
/**
17+
* Utilizes UserContext for backpressure identity
18+
*/
19+
class IdentityProvider implements IdentityProviderInterface
20+
{
21+
/**
22+
* User context identity type map
23+
*/
24+
private const USER_CONTEXT_IDENTITY_TYPE_MAP = [
25+
UserContextInterface::USER_TYPE_CUSTOMER => ContextInterface::IDENTITY_TYPE_CUSTOMER,
26+
UserContextInterface::USER_TYPE_ADMIN => ContextInterface::IDENTITY_TYPE_ADMIN
27+
];
28+
29+
/**
30+
* @var UserContextInterface
31+
*/
32+
private UserContextInterface $userContext;
33+
34+
/**
35+
* @var RemoteAddress
36+
*/
37+
private RemoteAddress $remoteAddress;
38+
39+
/**
40+
* @param UserContextInterface $userContext
41+
* @param RemoteAddress $remoteAddress
42+
*/
43+
public function __construct(UserContextInterface $userContext, RemoteAddress $remoteAddress)
44+
{
45+
$this->userContext = $userContext;
46+
$this->remoteAddress = $remoteAddress;
47+
}
48+
49+
/**
50+
* @inheritDoc
51+
*
52+
* @throws RuntimeException
53+
*/
54+
public function fetchIdentityType(): int
55+
{
56+
if (!$this->userContext->getUserId()) {
57+
return ContextInterface::IDENTITY_TYPE_IP;
58+
}
59+
60+
$userType = $this->userContext->getUserType();
61+
if (isset(self::USER_CONTEXT_IDENTITY_TYPE_MAP[$userType])) {
62+
return self::USER_CONTEXT_IDENTITY_TYPE_MAP[$userType];
63+
}
64+
65+
throw new RuntimeException(__('User type not defined'));
66+
}
67+
68+
/**
69+
* @inheritDoc
70+
*
71+
* @throws RuntimeException
72+
*/
73+
public function fetchIdentity(): string
74+
{
75+
$userId = $this->userContext->getUserId();
76+
if ($userId) {
77+
return (string)$userId;
78+
}
79+
80+
$address = $this->remoteAddress->getRemoteAddress();
81+
if (!$address) {
82+
throw new RuntimeException(__('Failed to extract remote address'));
83+
}
84+
85+
return $address;
86+
}
87+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Authorization\Test\Unit\Model;
10+
11+
use Magento\Authorization\Model\IdentityProvider;
12+
use Magento\Authorization\Model\UserContextInterface;
13+
use Magento\Framework\App\Backpressure\ContextInterface;
14+
use Magento\Framework\Exception\RuntimeException;
15+
use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress;
16+
use PHPUnit\Framework\MockObject\MockObject;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Tests the IdentityProvider class
21+
*/
22+
class IdentityProviderTest extends TestCase
23+
{
24+
/**
25+
* @var UserContextInterface|MockObject
26+
*/
27+
private $userContext;
28+
29+
/**
30+
* @var RemoteAddress|MockObject
31+
*/
32+
private $remoteAddress;
33+
34+
/**
35+
* @var IdentityProvider
36+
*/
37+
private $model;
38+
39+
/**
40+
* @inheritDoc
41+
*/
42+
protected function setUp(): void
43+
{
44+
parent::setUp();
45+
46+
$this->userContext = $this->createMock(UserContextInterface::class);
47+
$this->remoteAddress = $this->createMock(RemoteAddress::class);
48+
$this->model = new IdentityProvider($this->userContext, $this->remoteAddress);
49+
}
50+
51+
/**
52+
* Cases for identity provider.
53+
*
54+
* @return array
55+
*/
56+
public function getIdentityCases(): array
57+
{
58+
return [
59+
'empty-user-context' => [null, null, '127.0.0.1', ContextInterface::IDENTITY_TYPE_IP, '127.0.0.1'],
60+
'guest-user-context' => [
61+
UserContextInterface::USER_TYPE_GUEST,
62+
null,
63+
'127.0.0.1',
64+
ContextInterface::IDENTITY_TYPE_IP,
65+
'127.0.0.1'
66+
],
67+
'admin-user-context' => [
68+
UserContextInterface::USER_TYPE_ADMIN,
69+
42,
70+
'127.0.0.1',
71+
ContextInterface::IDENTITY_TYPE_ADMIN,
72+
'42'
73+
],
74+
'customer-user-context' => [
75+
UserContextInterface::USER_TYPE_CUSTOMER,
76+
42,
77+
'127.0.0.1',
78+
ContextInterface::IDENTITY_TYPE_CUSTOMER,
79+
'42'
80+
],
81+
];
82+
}
83+
84+
/**
85+
* Verify identity provider.
86+
*
87+
* @param int|null $userType
88+
* @param int|null $userId
89+
* @param string $remoteAddr
90+
* @param int $expectedType
91+
* @param string $expectedIdentity
92+
* @return void
93+
* @dataProvider getIdentityCases
94+
*/
95+
public function testFetchIdentity(
96+
?int $userType,
97+
?int $userId,
98+
string $remoteAddr,
99+
int $expectedType,
100+
string $expectedIdentity
101+
): void {
102+
$this->userContext->method('getUserType')->willReturn($userType);
103+
$this->userContext->method('getUserId')->willReturn($userId);
104+
$this->remoteAddress->method('getRemoteAddress')->willReturn($remoteAddr);
105+
106+
$this->assertEquals($expectedType, $this->model->fetchIdentityType());
107+
$this->assertEquals($expectedIdentity, $this->model->fetchIdentity());
108+
}
109+
110+
/**
111+
* Tests fetching an identity type when user type can't be defined
112+
*/
113+
public function testFetchIdentityTypeUserTypeNotDefined()
114+
{
115+
$this->userContext->method('getUserId')->willReturn(2);
116+
$this->userContext->method('getUserType')->willReturn(null);
117+
$this->expectException(RuntimeException::class);
118+
$this->expectExceptionMessage(__('User type not defined')->getText());
119+
$this->model->fetchIdentityType();
120+
}
121+
122+
/**
123+
* Tests fetching an identity when user address can't be extracted
124+
*/
125+
public function testFetchIdentityFailedToExtractRemoteAddress()
126+
{
127+
$this->userContext->method('getUserId')->willReturn(null);
128+
$this->remoteAddress->method('getRemoteAddress')->willReturn(false);
129+
$this->expectException(RuntimeException::class);
130+
$this->expectExceptionMessage(__('Failed to extract remote address')->getText());
131+
$this->model->fetchIdentity();
132+
}
133+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@
2424
</arguments>
2525
</type>
2626
<preference for="Magento\Authorization\Model\UserContextInterface" type="Magento\Authorization\Model\CompositeUserContext"/>
27+
<preference for="Magento\Framework\App\Backpressure\IdentityProviderInterface"
28+
type="Magento\Authorization\Model\IdentityProvider"/>
2729
</config>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
"We can't find the role for the user you wanted.","We can't find the role for the user you wanted."
22
"Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log.","Something went wrong while compiling a list of allowed resources. You can find out more in the exceptions log."
3+
"User type not defined","User type not defined"
4+
"Failed to extract remote address","Failed to extract remote address"

app/code/Magento/Backend/Block/Dashboard/Totals.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Reports\Model\ResourceModel\Order\Collection;
1414
use Magento\Reports\Model\ResourceModel\Order\CollectionFactory;
1515
use Magento\Store\Model\Store;
16+
use Magento\Framework\App\ObjectManager;
1617

1718
/**
1819
* Adminhtml dashboard totals bar
@@ -31,19 +32,27 @@ class Totals extends Bar
3132
*/
3233
protected $_moduleManager;
3334

35+
/**
36+
* @var Period
37+
*/
38+
private $period;
39+
3440
/**
3541
* @param Context $context
3642
* @param CollectionFactory $collectionFactory
3743
* @param Manager $moduleManager
3844
* @param array $data
45+
* @param Period|null $period
3946
*/
4047
public function __construct(
4148
Context $context,
4249
CollectionFactory $collectionFactory,
4350
Manager $moduleManager,
44-
array $data = []
51+
array $data = [],
52+
?Period $period = null
4553
) {
4654
$this->_moduleManager = $moduleManager;
55+
$this->period = $period ?? ObjectManager::getInstance()->get(Period::class);
4756
parent::__construct($context, $collectionFactory, $data);
4857
}
4958

@@ -63,7 +72,8 @@ protected function _prepareLayout()
6372
) || $this->getRequest()->getParam(
6473
'group'
6574
);
66-
$period = $this->getRequest()->getParam('period', Period::PERIOD_24_HOURS);
75+
$firstPeriod = array_key_first($this->period->getDatePeriods());
76+
$period = $this->getRequest()->getParam('period', $firstPeriod);
6777

6878
/* @var $collection Collection */
6979
$collection = $this->_collectionFactory->create()->addCreateAtPeriodFilter(

app/code/Magento/Backend/Model/Dashboard/Chart/Date.php

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

88
namespace Magento\Backend\Model\Dashboard\Chart;
99

10+
use DateTimeZone;
1011
use Magento\Backend\Model\Dashboard\Period;
1112
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
1213
use Magento\Reports\Model\ResourceModel\Order\CollectionFactory;
@@ -54,40 +55,32 @@ public function getByPeriod(string $period): array
5455
'',
5556
true
5657
);
57-
5858
$timezoneLocal = $this->localeDate->getConfigTimezone();
59-
$localStartDate = new \DateTime($dateStart->format('Y-m-d H:i:s'), new \DateTimeZone($timezoneLocal));
60-
$localEndDate = new \DateTime($dateEnd->format('Y-m-d H:i:s'), new \DateTimeZone($timezoneLocal));
59+
60+
$dateStart->setTimezone(new DateTimeZone($timezoneLocal));
61+
$dateEnd->setTimezone(new DateTimeZone($timezoneLocal));
6162

6263
if ($period === Period::PERIOD_24_HOURS) {
63-
$localEndDate = new \DateTime('now', new \DateTimeZone($timezoneLocal));
64-
$localStartDate = clone $localEndDate;
65-
$localStartDate->modify('-1 day');
66-
$localStartDate->modify('+1 hour');
67-
} elseif ($period === Period::PERIOD_TODAY) {
68-
$localEndDate->modify('now');
69-
} else {
70-
$localEndDate->setTime(23, 59, 59);
71-
$localStartDate->setTime(0, 0, 0);
64+
$dateEnd->modify('-1 hour');
7265
}
7366

7467
$dates = [];
7568

76-
while ($localStartDate <= $localEndDate) {
69+
while ($dateStart <= $dateEnd) {
7770
switch ($period) {
7871
case Period::PERIOD_7_DAYS:
7972
case Period::PERIOD_1_MONTH:
80-
$d = $localStartDate->format('Y-m-d');
81-
$localStartDate->modify('+1 day');
73+
$d = $dateStart->format('Y-m-d');
74+
$dateStart->modify('+1 day');
8275
break;
8376
case Period::PERIOD_1_YEAR:
8477
case Period::PERIOD_2_YEARS:
85-
$d = $localStartDate->format('Y-m');
86-
$localStartDate->modify('first day of next month');
78+
$d = $dateStart->format('Y-m');
79+
$dateStart->modify('first day of next month');
8780
break;
8881
default:
89-
$d = $localStartDate->format('Y-m-d H:00');
90-
$localStartDate->modify('+1 hour');
82+
$d = $dateStart->format('Y-m-d H:00');
83+
$dateStart->modify('+1 hour');
9184
}
9285

9386
$dates[] = $d;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminDashboardTotalsBlockTest" extends="AdminCheckDashboardWithChartsTest">
12+
<annotations>
13+
<features value="Backend"/>
14+
<stories value="Order Totals on Magento dashboard"/>
15+
<title value="Dashboard First Shows Wrong Information about Revenue"/>
16+
<description value="Revenue on Magento dashboard page is displaying properly"/>
17+
<severity value="AVERAGE"/>
18+
<testCaseId value="ACP2E-1294"/>
19+
<useCaseId value="ACSD-46523"/>
20+
<group value="backend"/>
21+
</annotations>
22+
<remove keyForRemoval="checkQuantityWasChanged"/>
23+
<waitForElementVisible selector="{{AdminDashboardSection.dashboardTotals('Revenue')}}" stepKey="waitForRevenueAfter"/>
24+
<grabTextFrom selector="{{AdminDashboardSection.dashboardTotals('Revenue')}}" stepKey="grabRevenueAfter"/>
25+
<selectOption userInput="1m" selector="select#dashboard_chart_period" stepKey="selectOneMonthPeriod"/>
26+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappear"/>
27+
<selectOption userInput="today" selector="select#dashboard_chart_period" stepKey="selectTodayPeriod"/>
28+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskToDisappearAfterSelectTodayPeriod"/>
29+
<waitForElementVisible selector="{{AdminDashboardSection.dashboardTotals('Revenue')}}" stepKey="waitForRevenueAfterSelectTodayPeriod"/>
30+
<waitForElementVisible selector="{{AdminDashboardSection.dashboardTotals('Quantity')}}" stepKey="waitForQuantityAfterSelectTodayPeriod"/>
31+
<grabTextFrom selector="{{AdminDashboardSection.dashboardTotals('Revenue')}}" stepKey="grabRevenueAfterSelectTodayPeriod"/>
32+
<grabTextFrom selector="{{AdminDashboardSection.dashboardTotals('Quantity')}}" stepKey="grabQuantityAfterSelectTodayPeriod"/>
33+
<assertEquals stepKey="checkTodayRevenue">
34+
<actualResult type="const">$grabRevenueAfter</actualResult>
35+
<expectedResult type="const">$grabRevenueAfterSelectTodayPeriod</expectedResult>
36+
</assertEquals>
37+
<assertEquals stepKey="checkTodayQuantity">
38+
<actualResult type="const">$grabQuantityAfter</actualResult>
39+
<expectedResult type="const">$grabQuantityAfterSelectTodayPeriod</expectedResult>
40+
</assertEquals>
41+
</test>
42+
</tests>

0 commit comments

Comments
 (0)