Skip to content

Commit 800ff38

Browse files
committed
Merge remote-tracking branch 'tier4/ACP2E-2855' into PR_10_JAN_2024
2 parents 7df9337 + 3b8ff8f commit 800ff38

File tree

2 files changed

+126
-42
lines changed

2 files changed

+126
-42
lines changed

lib/internal/Magento/Framework/Model/AbstractModel.php

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,24 @@
55
*/
66
namespace Magento\Framework\Model;
77

8+
use Exception;
89
use Laminas\Validator\ValidatorChain;
910
use Laminas\Validator\ValidatorInterface;
11+
use Magento\Framework\App\CacheInterface;
12+
use Magento\Framework\App\ObjectManager;
13+
use Magento\Framework\App\State;
1014
use Magento\Framework\DataObject;
15+
use Magento\Framework\Event\ManagerInterface;
1116
use Magento\Framework\Exception\LocalizedException;
17+
use Magento\Framework\Message\Error;
18+
use Magento\Framework\Model\ActionValidator\RemoveAction;
19+
use Magento\Framework\Model\ResourceModel\AbstractResource;
20+
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
21+
use Magento\Framework\Data\Collection\AbstractDb as AbstractDbCollection;
22+
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
1223
use Magento\Framework\Phrase;
24+
use Magento\Framework\Registry;
25+
use Psr\Log\LoggerInterface;
1326

1427
/**
1528
* Abstract model class
@@ -71,12 +84,12 @@ abstract class AbstractModel extends DataObject
7184
/**
7285
* Resource model instance
7386
*
74-
* @var \Magento\Framework\Model\ResourceModel\Db\AbstractDb
87+
* @var AbstractDb
7588
*/
7689
protected $_resource;
7790

7891
/**
79-
* @var \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
92+
* @var AbstractCollection
8093
*/
8194
protected $_resourceCollection;
8295

@@ -129,34 +142,34 @@ abstract class AbstractModel extends DataObject
129142
/**
130143
* Application Event Dispatcher
131144
*
132-
* @var \Magento\Framework\Event\ManagerInterface
145+
* @var ManagerInterface
133146
*/
134147
protected $_eventManager;
135148

136149
/**
137150
* Application Cache Manager
138151
*
139-
* @var \Magento\Framework\App\CacheInterface
152+
* @var CacheInterface
140153
*/
141154
protected $_cacheManager;
142155

143156
/**
144-
* @var \Magento\Framework\Registry
157+
* @var Registry
145158
*/
146159
protected $_registry;
147160

148161
/**
149-
* @var \Psr\Log\LoggerInterface
162+
* @var LoggerInterface
150163
*/
151164
protected $_logger;
152165

153166
/**
154-
* @var \Magento\Framework\App\State
167+
* @var State
155168
*/
156169
protected $_appState;
157170

158171
/**
159-
* @var \Magento\Framework\Model\ActionValidator\RemoveAction
172+
* @var RemoveAction
160173
*/
161174
protected $_actionValidator;
162175

@@ -168,18 +181,19 @@ abstract class AbstractModel extends DataObject
168181
protected $storedData = [];
169182

170183
/**
171-
* @param \Magento\Framework\Model\Context $context
172-
* @param \Magento\Framework\Registry $registry
173-
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
174-
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
184+
* @param Context $context
185+
* @param Registry $registry
186+
* @param AbstractResource|null $resource
187+
* @param AbstractDbCollection|null $resourceCollection
175188
* @param array $data
189+
* @throws LocalizedException
176190
*/
177191
public function __construct(
178-
\Magento\Framework\Model\Context $context,
179-
\Magento\Framework\Registry $registry,
180-
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
181-
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
182-
array $data = []
192+
Context $context,
193+
Registry $registry,
194+
AbstractResource $resource = null,
195+
AbstractDbCollection $resourceCollection = null,
196+
array $data = []
183197
) {
184198
$this->_registry = $registry;
185199
$this->_appState = $context->getAppState();
@@ -214,6 +228,7 @@ protected function _construct() //phpcs:ignore Magento2.CodeAnalysis.EmptyBlock
214228
*
215229
* @param string $resourceModel
216230
* @return void
231+
* @throws LocalizedException
217232
*/
218233
protected function _init($resourceModel)
219234
{
@@ -252,11 +267,11 @@ public function __sleep()
252267
*/
253268
public function __wakeup()
254269
{
255-
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
256-
$this->_registry = $objectManager->get(\Magento\Framework\Registry::class);
270+
$objectManager = ObjectManager::getInstance();
271+
$this->_registry = $objectManager->get(Registry::class);
257272

258-
$context = $objectManager->get(\Magento\Framework\Model\Context::class);
259-
if ($context instanceof \Magento\Framework\Model\Context) {
273+
$context = $objectManager->get(Context::class);
274+
if ($context instanceof Context) {
260275
$this->_appState = $context->getAppState();
261276
$this->_eventManager = $context->getEventDispatcher();
262277
$this->_cacheManager = $context->getCacheManager();
@@ -357,6 +372,7 @@ public function setData($key, $value = null)
357372
}
358373
$this->_data = $key;
359374
} else {
375+
$this->checkAndConvertNumericValue($key, $value);
360376
if (!array_key_exists($key, $this->_data) || $this->_data[$key] !== $value) {
361377
$this->_hasDataChanges = true;
362378
}
@@ -470,19 +486,19 @@ protected function _setResourceModel($resourceName, $collectionName = null)
470486
/**
471487
* Get resource instance
472488
*
473-
* @throws \Magento\Framework\Exception\LocalizedException
474-
* @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
489+
* @return AbstractDb
490+
* @throws LocalizedException
475491
* @deprecated 101.0.0 because resource models should be used directly
476492
* @see we don't recommend this approach anymore
477493
*/
478494
protected function _getResource()
479495
{
480496
if (empty($this->_resourceName) && empty($this->_resource)) {
481-
throw new \Magento\Framework\Exception\LocalizedException(
482-
new \Magento\Framework\Phrase('The resource isn\'t set.')
497+
throw new LocalizedException(
498+
new Phrase('The resource isn\'t set.')
483499
);
484500
}
485-
return $this->_resource ?: \Magento\Framework\App\ObjectManager::getInstance()->get($this->_resourceName);
501+
return $this->_resource ?: ObjectManager::getInstance()->get($this->_resourceName);
486502
}
487503

488504
/**
@@ -499,20 +515,20 @@ public function getResourceName()
499515
* Get collection instance
500516
*
501517
* @TODO MAGETWO-23541: Incorrect dependencies between Model\AbstractModel and Data\Collection\Db from Framework
502-
* @throws \Magento\Framework\Exception\LocalizedException
503-
* @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
518+
* @throws LocalizedException
519+
* @return AbstractCollection
504520
* @deprecated 101.0.0 because collections should be used directly via factory
505521
* @see we don't recommend this approach anymore
506522
*/
507523
public function getResourceCollection()
508524
{
509525
if (empty($this->_resourceCollection) && empty($this->_collectionName)) {
510-
throw new \Magento\Framework\Exception\LocalizedException(
511-
new \Magento\Framework\Phrase('Model collection resource name is not defined.')
526+
throw new LocalizedException(
527+
new Phrase('Model collection resource name is not defined.')
512528
);
513529
}
514530
return !$this->_collectionName ? clone $this
515-
->_resourceCollection : \Magento\Framework\App\ObjectManager::getInstance()
531+
->_resourceCollection : ObjectManager::getInstance()
516532
->create(
517533
$this->_collectionName
518534
);
@@ -522,9 +538,10 @@ public function getResourceCollection()
522538
* Retrieve collection instance
523539
*
524540
* @TODO MAGETWO-23541: Incorrect dependencies between Model\AbstractModel and Data\Collection\Db from Framework
525-
* @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
526-
* @deprecated 101.0.0 because collections should be used directly via factory
541+
* @return AbstractCollection
542+
* @throws LocalizedException
527543
* @see we don't recommend this approach anymore
544+
* @deprecated 101.0.0 because collections should be used directly via factory
528545
*/
529546
public function getCollection()
530547
{
@@ -537,10 +554,11 @@ public function getCollection()
537554
* @param integer $modelId
538555
* @param null|string $field
539556
* @return $this
557+
* @throws LocalizedException
558+
* @see we don't recommend this approach anymore
540559
* @deprecated 100.1.0 because entities must not be responsible for their own loading.
541560
* Service contracts should persist entities. Use resource model "load" or collections to implement
542561
* service contract model loading operations.
543-
* @see we don't recommend this approach anymore
544562
*/
545563
public function load($modelId, $field = null)
546564
{
@@ -651,7 +669,7 @@ public function setHasDataChanges($flag)
651669
* Save object data
652670
*
653671
* @return $this
654-
* @throws \Exception
672+
* @throws Exception
655673
*
656674
* @deprecated 100.1.0 because entities must not be responsible for their own persistence.
657675
* Service contracts should persist entities. Use resource model "save" to implement
@@ -726,7 +744,7 @@ public function validateBeforeSave()
726744
new Phrase(implode(PHP_EOL, $errors))
727745
);
728746
foreach ($errors as $errorMessage) {
729-
$exception->addMessage(new \Magento\Framework\Message\Error($errorMessage));
747+
$exception->addMessage(new Error($errorMessage));
730748
}
731749
throw $exception;
732750
}
@@ -739,6 +757,7 @@ public function validateBeforeSave()
739757
* Returns FALSE, if no validation rules exist.
740758
*
741759
* @return ValidatorInterface|false
760+
* @throws LocalizedException
742761
*/
743762
protected function _getValidatorBeforeSave()
744763
{
@@ -782,7 +801,7 @@ protected function _createValidatorBeforeSave()
782801
*/
783802
private function getValidator(): ValidatorChain
784803
{
785-
return \Magento\Framework\App\ObjectManager::getInstance()->create(ValidatorChain::class);
804+
return ObjectManager::getInstance()->create(ValidatorChain::class);
786805
}
787806

788807
/**
@@ -852,7 +871,7 @@ public function afterSave()
852871
* Delete object from database
853872
*
854873
* @return $this
855-
* @throws \Exception
874+
* @throws Exception
856875
* @deprecated 100.1.0 because entities must not be responsible for their own deletion.
857876
* Service contracts should delete entities. Use resource model "delete" method to implement
858877
* service contract persistence operations.
@@ -868,13 +887,13 @@ public function delete()
868887
* Processing object before delete data
869888
*
870889
* @return $this
871-
* @throws \Magento\Framework\Exception\LocalizedException
890+
* @throws LocalizedException
872891
*/
873892
public function beforeDelete()
874893
{
875894
if (!$this->_actionValidator->isAllowed($this)) {
876-
throw new \Magento\Framework\Exception\LocalizedException(
877-
new \Magento\Framework\Phrase('Delete operation is forbidden for current area')
895+
throw new LocalizedException(
896+
new Phrase('Delete operation is forbidden for current area')
878897
);
879898
}
880899

@@ -913,7 +932,7 @@ public function afterDeleteCommit()
913932
/**
914933
* Retrieve model resource
915934
*
916-
* @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
935+
* @return AbstractDb
917936
* @deprecated 101.0.0 because resource models should be used directly
918937
* @see we don't recommend this approach anymore
919938
*/
@@ -1010,4 +1029,24 @@ public function getEventPrefix()
10101029
{
10111030
return $this->_eventPrefix;
10121031
}
1032+
1033+
/**
1034+
* Check and Convert Numeric Value for Proper Type Matching
1035+
*
1036+
* @param mixed $key
1037+
* @param mixed $value
1038+
* @return void
1039+
*/
1040+
private function checkAndConvertNumericValue(mixed $key, mixed $value): void
1041+
{
1042+
if (array_key_exists($key, $this->_data) && is_numeric($this->_data[$key])
1043+
&& $value != null
1044+
) {
1045+
if (is_int($value)) {
1046+
$this->_data[$key] = (int) $this->_data[$key];
1047+
} elseif (is_float($value)) {
1048+
$this->_data[$key] = (float) $this->_data[$key];
1049+
}
1050+
}
1051+
}
10131052
}

lib/internal/Magento/Framework/Model/Test/Unit/AbstractModelTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,49 @@ public function testSetDataChanges()
190190
$this->model->setDataChanges(true);
191191
$this->assertTrue($this->model->hasDataChanges());
192192
}
193+
194+
/**
195+
* Test case for checking setData function is working for all possible key value pairs
196+
*
197+
* @dataProvider getKeyValueDataPairs
198+
*/
199+
public function testSetDataWithDifferentKeyValuePairs(
200+
array $data,
201+
mixed $testKey,
202+
mixed $testValue,
203+
bool $hasDataChangedFor
204+
): void {
205+
$this->model->setData($data);
206+
$this->model->setOrigData();
207+
$this->model->setData($testKey, $testValue);
208+
$this->assertEquals($data, $this->model->getOrigData());
209+
$this->assertEquals($hasDataChangedFor, $this->model->dataHasChangedFor($testKey));
210+
}
211+
212+
/**
213+
* Data provider for testSetDataWithDifferentKeyValuePairs
214+
*
215+
* @return array
216+
*/
217+
public function getKeyValueDataPairs(): array
218+
{
219+
return [
220+
'when test data and compare data are string' => [['key' => 'value'], 'key', 'value', false],
221+
'when test data and compare data are different' => [['key' => 'value'], 'key', 10, true],
222+
'when test data string and compare data is null' => [['key' => 'value'], 'key', null, true],
223+
'when test data and compare data both null' => [['key' => null], 'key', null, false],
224+
'when test data empty string and compare data is null' => [['key' => ''], 'key', null, false],
225+
'when test data and compare data are empty string' => [['key' => ''], 'key', '', false],
226+
'when test data is null and compare data is empty string' => [['key' => null], 'key', '', false],
227+
'when test data and compare data are int' => [['key' => 1], 'key', 1, false],
228+
'when test data is int and compare data is float' => [['key' => 1.0], 'key', 1, false],
229+
'when test data is string and compare data is float' => [['key' => '1.0'], 'key', 1.0, false],
230+
'when test data is string and compare data is int' => [['key' => '1'], 'key', 1, false],
231+
'when test data is float and compare data is string' => [['key' => 1.0], 'key', '1.0', false],
232+
'when test data is int and compare data is string' => [['key' => 1], 'key', '1', false],
233+
'when test data and compare data are float' => [['key' => 1.0], 'key', 1.0, false],
234+
'when test data is 0 and compare data is null' => [['key' => 0], 'key', null, false],
235+
'when test data is null and compare data is 0' => [['key' => null], 'key', 0, false],
236+
];
237+
}
193238
}

0 commit comments

Comments
 (0)