Skip to content

Commit c4a7d77

Browse files
authored
Merge pull request #5580 from magento-tsg-csl3/2.4-develop-pr22
[TSG-CSL3] For 2.4 (pr22)
2 parents ee78423 + d3adb66 commit c4a7d77

File tree

31 files changed

+567
-385
lines changed

31 files changed

+567
-385
lines changed

app/code/Magento/Config/App/Config/Source/RuntimeConfigSource.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
use Magento\Framework\App\Config\ConfigSourceInterface;
99
use Magento\Framework\App\Config\ScopeCodeResolver;
1010
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\App\DeploymentConfig;
12+
use Magento\Framework\App\ObjectManager;
1113
use Magento\Framework\DataObject;
1214
use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory;
1315
use Magento\Framework\App\Config\Scope\Converter;
16+
use Magento\Framework\DB\Adapter\TableNotFoundException;
1417

1518
/**
1619
* Class for retrieving runtime configuration from database.
@@ -34,20 +37,27 @@ class RuntimeConfigSource implements ConfigSourceInterface
3437
* @var ScopeCodeResolver
3538
*/
3639
private $scopeCodeResolver;
40+
/**
41+
* @var DeploymentConfig
42+
*/
43+
private $deploymentConfig;
3744

3845
/**
3946
* @param CollectionFactory $collectionFactory
4047
* @param ScopeCodeResolver $scopeCodeResolver
4148
* @param Converter $converter
49+
* @param DeploymentConfig|null $deploymentConfig
4250
*/
4351
public function __construct(
4452
CollectionFactory $collectionFactory,
4553
ScopeCodeResolver $scopeCodeResolver,
46-
Converter $converter
54+
Converter $converter,
55+
?DeploymentConfig $deploymentConfig = null
4756
) {
4857
$this->collectionFactory = $collectionFactory;
4958
$this->converter = $converter;
5059
$this->scopeCodeResolver = $scopeCodeResolver;
60+
$this->deploymentConfig = $deploymentConfig ?? ObjectManager::getInstance()->get(DeploymentConfig::class);
5161
}
5262

5363
/**
@@ -59,7 +69,7 @@ public function __construct(
5969
*/
6070
public function get($path = '')
6171
{
62-
$data = new DataObject($this->loadConfig());
72+
$data = new DataObject($this->deploymentConfig->isDbAvailable() ? $this->loadConfig() : []);
6373
return $data->getData($path) ?: [];
6474
}
6575

@@ -75,8 +85,12 @@ private function loadConfig()
7585
{
7686
try {
7787
$collection = $this->collectionFactory->create();
88+
$collection->load();
7889
} catch (\DomainException $e) {
7990
$collection = [];
91+
} catch (TableNotFoundException $exception) {
92+
// database is empty or not setup
93+
$collection = [];
8094
}
8195
$config = [];
8296
foreach ($collection as $item) {

app/code/Magento/Config/Test/Unit/App/Config/Source/RuntimeConfigSourceTest.php

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,57 @@
55
*/
66
namespace Magento\Config\Test\Unit\App\Config\Source;
77

8+
use ArrayIterator;
89
use Magento\Config\App\Config\Source\RuntimeConfigSource;
10+
use Magento\Config\Model\ResourceModel\Config\Data\Collection;
911
use Magento\Config\Model\ResourceModel\Config\Data\CollectionFactory;
1012
use Magento\Framework\App\Config\Scope\Converter;
1113
use Magento\Framework\App\Config\ScopeCodeResolver;
1214
use Magento\Framework\App\Config\ScopeConfigInterface;
1315
use Magento\Framework\App\Config\Value;
16+
use Magento\Framework\App\DeploymentConfig;
17+
use Magento\Framework\DB\Adapter\TableNotFoundException;
18+
use PHPUnit\Framework\MockObject\MockObject;
19+
use PHPUnit\Framework\TestCase;
1420

1521
/**
1622
* Test Class for retrieving runtime configuration from database.
17-
* @package Magento\Config\Test\Unit\App\Config\Source
1823
*/
19-
class RuntimeConfigSourceTest extends \PHPUnit\Framework\TestCase
24+
class RuntimeConfigSourceTest extends TestCase
2025
{
2126
/**
22-
* @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
27+
* @var CollectionFactory|MockObject
2328
*/
2429
private $collectionFactory;
2530

2631
/**
27-
* @var ScopeCodeResolver|\PHPUnit_Framework_MockObject_MockObject
32+
* @var ScopeCodeResolver|MockObject
2833
*/
2934
private $scopeCodeResolver;
3035

3136
/**
32-
* @var Converter|\PHPUnit_Framework_MockObject_MockObject
37+
* @var Converter|MockObject
3338
*/
3439
private $converter;
3540

3641
/**
37-
* @var Value|\PHPUnit_Framework_MockObject_MockObject
42+
* @var Value|MockObject
3843
*/
3944
private $configItem;
4045

4146
/**
42-
* @var Value|\PHPUnit_Framework_MockObject_MockObject
47+
* @var Value|MockObject
4348
*/
4449
private $configItemTwo;
4550

4651
/**
4752
* @var RuntimeConfigSource
4853
*/
4954
private $configSource;
55+
/**
56+
* @var DeploymentConfig|MockObject
57+
*/
58+
private $deploymentConfig;
5059

5160
public function setUp()
5261
{
@@ -68,20 +77,29 @@ public function setUp()
6877
->disableOriginalConstructor()
6978
->setMethods(['getScope', 'getPath', 'getValue', 'getScopeId'])
7079
->getMock();
80+
$this->deploymentConfig = $this->createPartialMock(DeploymentConfig::class, ['isDbAvailable']);
7181
$this->configSource = new RuntimeConfigSource(
7282
$this->collectionFactory,
7383
$this->scopeCodeResolver,
74-
$this->converter
84+
$this->converter,
85+
$this->deploymentConfig
7586
);
7687
}
7788

7889
public function testGet()
7990
{
91+
$this->deploymentConfig->method('isDbAvailable')
92+
->willReturn(true);
93+
$collection = $this->createPartialMock(Collection::class, ['load', 'getIterator']);
94+
$collection->method('load')
95+
->willReturn($collection);
96+
$collection->method('getIterator')
97+
->willReturn(new ArrayIterator([$this->configItem, $this->configItemTwo]));
8098
$scope = 'websites';
8199
$scopeCode = 'myWebsites';
82100
$this->collectionFactory->expects($this->once())
83101
->method('create')
84-
->willReturn([$this->configItem, $this->configItemTwo]);
102+
->willReturn($collection);
85103
$this->configItem->expects($this->exactly(2))
86104
->method('getScope')
87105
->willReturn(ScopeConfigInterface::SCOPE_TYPE_DEFAULT);
@@ -133,4 +151,22 @@ public function testGet()
133151
$this->configSource->get()
134152
);
135153
}
154+
155+
public function testGetWhenDbIsNotAvailable()
156+
{
157+
$this->deploymentConfig->method('isDbAvailable')->willReturn(false);
158+
$this->assertEquals([], $this->configSource->get());
159+
}
160+
161+
public function testGetWhenDbIsEmpty()
162+
{
163+
$this->deploymentConfig->method('isDbAvailable')
164+
->willReturn(true);
165+
$collection = $this->createPartialMock(Collection::class, ['load']);
166+
$collection->method('load')
167+
->willThrowException($this->createMock(TableNotFoundException::class));
168+
$this->collectionFactory->method('create')
169+
->willReturn($collection);
170+
$this->assertEquals([], $this->configSource->get());
171+
}
136172
}

app/code/Magento/Paypal/Model/Payflow/Transparent.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Transparent extends Payflowpro implements TransparentInterface
6161
*
6262
* @var bool
6363
*/
64-
protected $_canFetchTransactionInfo = false;
64+
protected $_canFetchTransactionInfo = true;
6565

6666
/**
6767
* @var ResponseValidator
@@ -355,11 +355,11 @@ public function capture(InfoInterface $payment, $amount)
355355
*
356356
* @param InfoInterface $payment
357357
* @return bool
358-
* @throws InvalidTransitionException
359358
* @throws LocalizedException
360359
*/
361360
public function acceptPayment(InfoInterface $payment)
362361
{
362+
$this->validatePaymentTransaction($payment);
363363
if ($this->getConfigPaymentAction() === MethodInterface::ACTION_AUTHORIZE_CAPTURE) {
364364
$invoices = iterator_to_array($payment->getOrder()->getInvoiceCollection());
365365
$invoice = count($invoices) ? reset($invoices) : null;
@@ -387,6 +387,20 @@ public function denyPayment(InfoInterface $payment)
387387
return true;
388388
}
389389

390+
/**
391+
* @inheritDoc
392+
*/
393+
public function fetchTransactionInfo(InfoInterface $payment, $transactionId)
394+
{
395+
$result = parent::fetchTransactionInfo($payment, $transactionId);
396+
$this->_canFetchTransactionInfo = false;
397+
if ($payment->getIsTransactionApproved()) {
398+
$this->acceptPayment($payment);
399+
}
400+
401+
return $result;
402+
}
403+
390404
/**
391405
* Marks payment as fraudulent.
392406
*
@@ -444,4 +458,24 @@ private function getZeroAmountAuthorizationId(InfoInterface $payment): string
444458
{
445459
return (string)$payment->getAdditionalInformation(self::PNREF);
446460
}
461+
462+
/**
463+
* Validates payment transaction status on PayPal.
464+
*
465+
* @param InfoInterface $payment
466+
* @throws LocalizedException
467+
*/
468+
private function validatePaymentTransaction(InfoInterface $payment): void
469+
{
470+
if ($payment->canFetchTransactionInfo()) {
471+
$transactionId = $payment->getLastTransId();
472+
parent::fetchTransactionInfo($payment, $transactionId);
473+
$this->_canFetchTransactionInfo = false;
474+
if ($payment->getIsTransactionDenied()) {
475+
throw new LocalizedException(
476+
__('Payment can\'t be accepted since transaction was rejected by merchant.')
477+
);
478+
}
479+
}
480+
}
447481
}

app/code/Magento/Paypal/Model/SmartButtonConfig.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use Magento\Store\Model\ScopeInterface;
1414

1515
/**
16-
* Smart button config
16+
* Smart button configuration.
1717
*/
1818
class SmartButtonConfig
1919
{
@@ -96,7 +96,14 @@ public function getConfig(string $page): array
9696
private function getDisallowedFunding(): array
9797
{
9898
$disallowedFunding = $this->config->getValue('disable_funding_options');
99-
return $disallowedFunding ? explode(',', $disallowedFunding) : [];
99+
$result = $disallowedFunding ? explode(',', $disallowedFunding) : [];
100+
101+
// PayPal Guest Checkout Credit Card Icons only available when Guest Checkout option is enabled
102+
if ($this->isPaypalGuestCheckoutAllowed() === false && !in_array('CARD', $result)) {
103+
array_push($result, 'CARD');
104+
}
105+
106+
return $result;
100107
}
101108

102109
/**
@@ -168,4 +175,14 @@ private function updateStyles(array $styles, string $page): array
168175

169176
return $styles;
170177
}
178+
179+
/**
180+
* Returns if is allowed PayPal Guest Checkout.
181+
*
182+
* @return bool
183+
*/
184+
private function isPaypalGuestCheckoutAllowed(): bool
185+
{
186+
return $this->config->getValue('solution_type') === Config::EC_SOLUTION_TYPE_SOLE;
187+
}
171188
}

0 commit comments

Comments
 (0)