Skip to content

Commit 81d4361

Browse files
authored
Merge branch '2.4-develop' into gl_pr_paypal_nov11_2021
2 parents 2f8d769 + 40ceb70 commit 81d4361

File tree

9 files changed

+192
-44
lines changed

9 files changed

+192
-44
lines changed

app/code/Magento/Sales/Model/Order/Payment.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,21 @@ public function setCcLast4($ccLast4)
22722272
return $this->setData(OrderPaymentInterface::CC_LAST_4, $ccLast4);
22732273
}
22742274

2275+
/**
2276+
* @inheritDoc
2277+
*
2278+
* Because cc_last_4 data attribute violates data contract (use underscore (_) between alphanumerical characters),
2279+
* this ad hoc method is for setting cc_last_4 data value in \Magento\Framework\Api\DataObjectHelper::_setDataValues
2280+
*/
2281+
public function setCustomAttribute($attributeCode, $attributeValue)
2282+
{
2283+
if ($attributeCode === OrderPaymentInterface::CC_LAST_4) {
2284+
return parent::setData(OrderPaymentInterface::CC_LAST_4, $attributeValue);
2285+
}
2286+
2287+
return parent::setCustomAttribute($attributeCode, $attributeValue);
2288+
}
2289+
22752290
/**
22762291
* @inheritdoc
22772292
*/

dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/fixture/declarative_installer/constraint_modification.mysql8.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
`int_auto_increment_with_nullable` int unsigned NOT NULL AUTO_INCREMENT,
1010
`int_disabled_auto_increment` smallint unsigned DEFAULT \'0\',
1111
UNIQUE KEY `AUTO_INCREMENT_TEST_INT_AUTO_INCREMENT_WITH_NULLABLE` (`int_auto_increment_with_nullable`)
12-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
12+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
1313
'reference_table' => 'CREATE TABLE `reference_table` (
1414
`tinyint_ref` tinyint NOT NULL AUTO_INCREMENT,
1515
`tinyint_without_padding` tinyint NOT NULL DEFAULT \'0\',
@@ -25,7 +25,7 @@
2525
`smallint_ref` smallint NOT NULL DEFAULT \'0\',
2626
PRIMARY KEY (`tinyint_ref`,`smallint_ref`),
2727
UNIQUE KEY `REFERENCE_TABLE_SMALLINT_REF` (`smallint_ref`)
28-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
28+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
2929
'test_table' => 'CREATE TABLE `test_table` (
3030
`smallint` smallint DEFAULT NULL,
3131
`tinyint` tinyint DEFAULT NULL,
@@ -53,5 +53,5 @@
5353
CONSTRAINT `FK_FB77604C299EB8612D01E4AF8D9931F2` FOREIGN KEY (`integer_main`) REFERENCES `auto_increment_test` (`int_auto_increment_with_nullable`) ON DELETE CASCADE,
5454
CONSTRAINT `TEST_TABLE_SMALLINT_MAIN_REFERENCE_TABLE_SMALLINT_REF` FOREIGN KEY (`smallint_main`) REFERENCES `reference_table` (`smallint_ref`) ON DELETE CASCADE,
5555
CONSTRAINT `TEST_TABLE_TINYINT_REFERENCE_TABLE_TINYINT_REF` FOREIGN KEY (`tinyint`) REFERENCES `reference_table` (`tinyint_ref`) ON DELETE SET NULL
56-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
56+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
5757
];

dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/fixture/declarative_installer/rollback.mysql8.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
`store_owner_id` smallint DEFAULT NULL COMMENT \'Store Owner Reference\',
1313
KEY `STORE_STORE_OWNER_ID_STORE_OWNER_OWNER_ID` (`store_owner_id`),
1414
CONSTRAINT `STORE_STORE_OWNER_ID_STORE_OWNER_OWNER_ID` FOREIGN KEY (`store_owner_id`) REFERENCES `store_owner` (`owner_id`) ON DELETE SET NULL
15-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
15+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
1616
'store_owner' => 'CREATE TABLE `store_owner` (
1717
`owner_id` smallint NOT NULL AUTO_INCREMENT,
1818
`store_owner_name` varchar(255) DEFAULT NULL COMMENT \'Store Owner Name\',
1919
PRIMARY KEY (`owner_id`)
20-
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=\'Store owner information\''
20+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT=\'Store owner information\''
2121
],
2222
'after' => [
2323
'store' => 'CREATE TABLE `store` (
2424
`store_owner` varchar(255) DEFAULT NULL COMMENT \'Store Owner Name\'
25-
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
25+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3'
2626
]
2727
];

dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule1/fixture/declarative_installer/table_removal.mysql8.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
`int_auto_increment_with_nullable` int unsigned NOT NULL AUTO_INCREMENT,
99
`int_disabled_auto_increment` smallint unsigned DEFAULT \'0\',
1010
UNIQUE KEY `AUTO_INCREMENT_TEST_INT_AUTO_INCREMENT_WITH_NULLABLE` (`int_auto_increment_with_nullable`)
11-
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
11+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3'
1212
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
return [
9+
'before' => 'CREATE TABLE `some_table` (
10+
`some_column` varchar(255) DEFAULT NULL COMMENT \'Some Column Name\'
11+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
12+
'after' => 'CREATE TABLE `some_table_renamed` (
13+
`some_column` varchar(255) DEFAULT NULL COMMENT \'Some Column Name\'
14+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
15+
];

dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule2/fixture/shards.mysql8.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
`smallint` smallint NOT NULL AUTO_INCREMENT,
99
`varchar` varchar(254) DEFAULT NULL,
1010
PRIMARY KEY (`smallint`)
11-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
11+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
1212
'test_table_two' => 'CREATE TABLE `test_table_two` (
1313
`smallint` smallint NOT NULL AUTO_INCREMENT,
1414
`varchar` varchar(254) DEFAULT NULL,
1515
PRIMARY KEY (`smallint`)
16-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
16+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
1717
'reference_table' => 'CREATE TABLE `reference_table` (
1818
`tinyint_ref` tinyint NOT NULL AUTO_INCREMENT,
1919
`tinyint_without_padding` tinyint NOT NULL DEFAULT \'0\',
@@ -27,10 +27,10 @@
2727
`bigint_default_nullable` bigint unsigned DEFAULT \'1\',
2828
`bigint_not_default_not_nullable` bigint unsigned NOT NULL,
2929
PRIMARY KEY (`tinyint_ref`)
30-
) ENGINE=InnoDB DEFAULT CHARSET=utf8',
30+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3',
3131
'auto_increment_test' => 'CREATE TABLE `auto_increment_test` (
3232
`int_auto_increment_with_nullable` int unsigned NOT NULL AUTO_INCREMENT,
3333
`int_disabled_auto_increment` smallint unsigned DEFAULT \'0\',
3434
UNIQUE KEY `AUTO_INCREMENT_TEST_INT_AUTO_INCREMENT_WITH_NULLABLE` (`int_auto_increment_with_nullable`)
35-
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
35+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3'
3636
];

dev/tests/setup-integration/_files/Magento/TestSetupDeclarationModule9/fixture/declarative_installer/disabling_tables.mysql8.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
`int_auto_increment_with_nullable` int unsigned NOT NULL AUTO_INCREMENT,
1111
`int_disabled_auto_increment` smallint unsigned DEFAULT \'0\',
1212
UNIQUE KEY `AUTO_INCREMENT_TEST_INT_AUTO_INCREMENT_WITH_NULLABLE` (`int_auto_increment_with_nullable`)
13-
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
13+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3'
1414
];

lib/internal/Magento/Framework/Api/DataObjectHelper.php

Lines changed: 88 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use Magento\Framework\Reflection\MethodsMap;
1010

1111
/**
12-
* Data object helper.
12+
* Service class allow populating object from array data
1313
*
1414
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1515
*/
@@ -94,49 +94,69 @@ public function populateWithArray($dataObject, array $data, $interfaceName)
9494
* @param string $interfaceName
9595
* @return $this
9696
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
97+
* @SuppressWarnings(PHPMD.NPathComplexity)
9798
*/
9899
protected function _setDataValues($dataObject, array $data, $interfaceName)
99100
{
100-
$dataObjectMethods = get_class_methods(get_class($dataObject));
101-
foreach ($data as $key => $value) {
102-
/* First, verify is there any setter for the key on the Service Data Object */
103-
$camelCaseKey = \Magento\Framework\Api\SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key);
104-
$possibleMethods = [
105-
'set' . $camelCaseKey,
106-
'setIs' . $camelCaseKey,
107-
];
108-
if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES
109-
&& ($dataObject instanceof ExtensibleDataInterface)
110-
&& is_array($data[$key])
111-
&& !empty($data[$key])
112-
) {
113-
foreach ($data[$key] as $customAttribute) {
114-
$dataObject->setCustomAttribute(
115-
$customAttribute[AttributeInterface::ATTRIBUTE_CODE],
116-
$customAttribute[AttributeInterface::VALUE]
117-
);
118-
}
119-
} elseif ($methodNames = array_intersect($possibleMethods, $dataObjectMethods)) {
120-
$methodName = array_values($methodNames)[0];
121-
if (!is_array($value)) {
122-
if ($methodName === 'setExtensionAttributes' && $value === null) {
123-
// Cannot pass a null value to a method with a typed parameter
101+
if (empty($data)) {
102+
return $this;
103+
}
104+
$setMethods = $this->getSetters($dataObject);
105+
if ($dataObject instanceof ExtensibleDataInterface
106+
&& !empty($data[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES])
107+
) {
108+
foreach ($data[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES] as $customAttribute) {
109+
$dataObject->setCustomAttribute(
110+
$customAttribute[AttributeInterface::ATTRIBUTE_CODE],
111+
$customAttribute[AttributeInterface::VALUE]
112+
);
113+
}
114+
unset($data[CustomAttributesDataInterface::CUSTOM_ATTRIBUTES]);
115+
}
116+
if ($dataObject instanceof \Magento\Framework\Model\AbstractModel) {
117+
$simpleData = array_filter($data, static function ($e) {
118+
return is_scalar($e) || is_null($e);
119+
});
120+
if (isset($simpleData['id'])) {
121+
$dataObject->setId($simpleData['id']);
122+
unset($simpleData['id']);
123+
}
124+
$simpleData = array_intersect_key($simpleData, $setMethods);
125+
$dataObject->addData($simpleData);
126+
$data = array_diff_key($data, $simpleData);
127+
if (\count($data) === 0) {
128+
return $this;
129+
}
130+
}
131+
foreach (array_intersect_key($data, $setMethods) as $key => $value) {
132+
$methodName = SimpleDataObjectConverter::snakeCaseToUpperCamelCase($key);
133+
134+
if (!is_array($value)) {
135+
if ($methodName !== 'ExtensionAttributes' || $value !== null) {
136+
if (method_exists($dataObject, 'set' . $methodName)) {
137+
$dataObject->{'set' . $methodName}($value);
124138
} else {
125-
$dataObject->$methodName($value);
139+
$dataObject->{'setIs' . $methodName}($value);
126140
}
127-
} else {
128-
$getterMethodName = 'get' . $camelCaseKey;
129-
$this->setComplexValue($dataObject, $getterMethodName, $methodName, $value, $interfaceName);
130141
}
131-
} elseif ($dataObject instanceof CustomAttributesDataInterface) {
132-
$dataObject->setCustomAttribute($key, $value);
142+
} else {
143+
$getterMethodName = 'get' . $methodName;
144+
$this->setComplexValue($dataObject, $getterMethodName, 'set' . $methodName, $value, $interfaceName);
133145
}
146+
unset($data[$key]);
134147
}
135148

149+
if ($dataObject instanceof CustomAttributesDataInterface) {
150+
foreach ($data as $key => $value) {
151+
$dataObject->setCustomAttribute($key, $value);
152+
}
153+
}
136154
return $this;
137155
}
138156

139157
/**
158+
* Set complex (like object) value using $methodName based on return type of $getterMethodName
159+
*
140160
* @param mixed $dataObject
141161
* @param string $getterMethodName
142162
* @param string $methodName
@@ -179,7 +199,7 @@ protected function setComplexValue(
179199
} elseif (is_subclass_of($returnType, \Magento\Framework\Api\ExtensionAttributesInterface::class)) {
180200
foreach ($value as $extensionAttributeKey => $extensionAttributeValue) {
181201
$extensionAttributeGetterMethodName
182-
= 'get' . \Magento\Framework\Api\SimpleDataObjectConverter::snakeCaseToUpperCamelCase(
202+
= 'get' . SimpleDataObjectConverter::snakeCaseToUpperCamelCase(
183203
$extensionAttributeKey
184204
);
185205
$methodReturnType = $this->methodsMapProcessor->getMethodReturnType(
@@ -260,4 +280,40 @@ public function getCustomAttributeValueByType(array $attributeValues, $type)
260280
}
261281
return $attributeValueArray;
262282
}
283+
284+
/** @var array */
285+
private array $settersCache = [];
286+
287+
/**
288+
* Get list of setters for object
289+
*
290+
* @param object $dataObject
291+
* @return array
292+
*/
293+
private function getSetters(object $dataObject): array
294+
{
295+
$class = get_class($dataObject);
296+
if (!isset($this->settersCache[$class])) {
297+
$dataObjectMethods = get_class_methods($class);
298+
// use regexp to manipulate with method list as it use jit starting with PHP 7.3
299+
$setters = array_filter(
300+
explode(
301+
',',
302+
strtolower(
303+
// (0) remove all not setter
304+
// (1) add _ before upper letter
305+
// (2) remove set_ in start of name
306+
// (3) add name without is_ prefix
307+
preg_replace(
308+
['/(^|,)(?!set)[^,]*/S','/(.)([A-Z])/S', '/(^|,)set_/iS', '/(^|,)is_([^,]+)/is'],
309+
['', '$1_$2', '$1', '$1$2,is_$2'],
310+
implode(',', $dataObjectMethods)
311+
)
312+
)
313+
)
314+
);
315+
$this->settersCache[$class] = array_flip($setters);
316+
}
317+
return $this->settersCache[$class];
318+
}
263319
}

lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
use Magento\Framework\Reflection\MethodsMap;
2525
use Magento\Framework\Reflection\TypeProcessor;
2626
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
27+
use Magento\Sales\Api\Data\OrderPaymentInterface;
28+
use Magento\Sales\Model\Order\Payment;
2729
use PHPUnit\Framework\MockObject\MockObject;
2830
use PHPUnit\Framework\TestCase;
2931

@@ -297,6 +299,66 @@ public function testPopulateWithArrayWithCustomAttributes(): void
297299
);
298300
}
299301

302+
/**
303+
* @return void
304+
*/
305+
public function testPopulateWithArrayWithOrderPaymentAttributes(): void
306+
{
307+
$method = 'companycredit';
308+
$customerPaymentId = null;
309+
$additionalData = null;
310+
$poNumber = 'ReferenceNumber934829dek2';
311+
$cc_type = "Debit";
312+
$cc_number_enc = "393993138";
313+
$cc_last_4 = "3982";
314+
$cc_owner = "John Doe";
315+
$cc_exp_month = "05";
316+
$cc_exp_year = "24";
317+
$cc_number = '1234567890';
318+
$cc_cid = null;
319+
$cc_ss_issue = null;
320+
$cc_ss_start_month = "0";
321+
$cc_ss_start_year = "0";
322+
323+
/** @var OrderPaymentInterface $orderPaymentObject */
324+
$orderPaymentObject = $this->objectManager->getObject(
325+
Payment::class,
326+
['dataObjectHelper' => $this->dataObjectHelper]
327+
);
328+
329+
$data = [
330+
'method' => $method,
331+
'customer_payment_id' => $customerPaymentId,
332+
'additionalData' => $additionalData,
333+
'additionalInformation' => [],
334+
'po_number' => $poNumber,
335+
'cc_type' => $cc_type,
336+
'cc_number_enc' => $cc_number_enc,
337+
'cc_last_4' => $cc_last_4,
338+
'cc_owner' => $cc_owner,
339+
'cc_exp_month' => $cc_exp_month,
340+
'cc_exp_year' => $cc_exp_year,
341+
'cc_number' => $cc_number,
342+
'cc_cid' => $cc_cid,
343+
'cc_ss_issue' => $cc_ss_issue,
344+
'cc_ss_start_month' => $cc_ss_start_month,
345+
'cc_ss_start_year' => $cc_ss_start_year
346+
];
347+
$this->dataObjectHelper->populateWithArray(
348+
$orderPaymentObject,
349+
$data,
350+
OrderPaymentInterface::class
351+
);
352+
$this->assertEquals($method, $orderPaymentObject->getMethod());
353+
$this->assertEquals($cc_exp_month, $orderPaymentObject->getCcExpMonth());
354+
$this->assertEquals($cc_exp_year, $orderPaymentObject->getCcExpYear());
355+
$this->assertEquals($cc_last_4, $orderPaymentObject->getCcLast4());
356+
$this->assertEquals($cc_owner, $orderPaymentObject->getCcOwner());
357+
$this->assertEquals($cc_number_enc, $orderPaymentObject->getCcNumberEnc());
358+
$this->assertEquals($poNumber, $orderPaymentObject->getPoNumber());
359+
$this->assertEquals($cc_type, $orderPaymentObject->getCcType());
360+
}
361+
300362
/**
301363
* @param array $data1
302364
* @param array $data2

0 commit comments

Comments
 (0)