Your IP : 127.0.0.1
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Magento\Framework\DataObject;
use Magento\Framework\Api\AbstractSimpleObject;
use Magento\Framework\Api\ExtensibleDataInterface;
use Magento\Framework\Api\ExtensionAttributesFactory;
use Magento\Framework\DataObject;
use Magento\Framework\DataObject\Copy\Config;
use Magento\Framework\Event\ManagerInterface;
/**
* Utility class for copying data sets between objects
*/
class Copy
{
/**
* @var Config
*/
protected $fieldsetConfig;
/**
* Core event manager proxy
*
* @var ManagerInterface
*/
protected $eventManager = null;
/**
* @var ExtensionAttributesFactory
*/
protected $extensionAttributesFactory;
/**
* @param ManagerInterface $eventManager
* @param Config $fieldsetConfig
* @param ExtensionAttributesFactory $extensionAttributesFactory
*/
public function __construct(
ManagerInterface $eventManager,
Config $fieldsetConfig,
ExtensionAttributesFactory $extensionAttributesFactory
) {
$this->eventManager = $eventManager;
$this->fieldsetConfig = $fieldsetConfig;
$this->extensionAttributesFactory = $extensionAttributesFactory;
}
/**
* Copy data from object|array to object|array containing fields from fieldset matching an aspect.
*
* Contents of $aspect are a field name in target object or array.
* If targetField attribute is not provided - will be used the same name as in the source object or array.
*
* @param string $fieldset
* @param string $aspect
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $source
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $target
* @param string $root
*
* @return array|DataObject|null the value of $target
* @throws \InvalidArgumentException
*
* @api
*/
public function copyFieldsetToTarget($fieldset, $aspect, $source, $target, $root = 'global')
{
if (!$this->_isFieldsetInputValid($source, $target)) {
return null;
}
$fields = $this->fieldsetConfig->getFieldset($fieldset, $root);
if ($fields === null) {
return $target;
}
$targetIsArray = is_array($target);
foreach ($fields as $code => $node) {
if (empty($node[$aspect])) {
continue;
}
$value = $this->_getFieldsetFieldValue($source, $code);
$targetCode = (string)$node[$aspect];
$targetCode = $targetCode == '*' ? $code : $targetCode;
$target = $this->_setFieldsetFieldValue($target, $targetCode, $value);
}
$target = $this->dispatchCopyFieldSetEvent($fieldset, $aspect, $source, $target, $root, $targetIsArray);
return $target;
}
/**
* Dispatch copy fieldset event
*
* @param string $fieldset
* @param string $aspect
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $source
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $target
* @param string $root
* @param bool $targetIsArray
*
* @return DataObject|mixed
*/
protected function dispatchCopyFieldSetEvent($fieldset, $aspect, $source, $target, $root, $targetIsArray)
{
$eventName = sprintf('core_copy_fieldset_%s_%s', $fieldset, $aspect);
if ($targetIsArray) {
$target = new DataObject($target);
}
$this->eventManager->dispatch(
$eventName,
['target' => $target, 'source' => $source, 'root' => $root]
);
if ($targetIsArray) {
$target = $target->getData();
}
return $target;
}
/**
* Get data from object|array to object|array containing fields from fieldset matching an aspect.
*
* @param string $fieldset
* @param string $aspect a field name
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $source
* @param string $root
*
* @return array
*
* @api
*/
public function getDataFromFieldset($fieldset, $aspect, $source, $root = 'global')
{
if ((!$this->isInputArgumentValid($source))) {
return null;
}
$fields = $this->fieldsetConfig->getFieldset($fieldset, $root);
if ($fields === null) {
return null;
}
$data = [];
foreach ($fields as $code => $node) {
if (empty($node[$aspect])) {
continue;
}
$value = $this->_getFieldsetFieldValue($source, $code);
$targetCode = (string)$node[$aspect];
$targetCode = $targetCode == '*' ? $code : $targetCode;
$data[$targetCode] = $value;
}
return $data;
}
/**
* Check if source and target are valid input for converting using fieldset
*
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $source
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $target
*
* @return bool
*/
protected function _isFieldsetInputValid($source, $target)
{
return $this->isInputArgumentValid($source) && $this->isInputArgumentValid($target);
}
/**
* Verify that we can access data from input object.
*
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $object
*
* @return bool
*/
private function isInputArgumentValid($object): bool
{
return (is_array($object) || $object instanceof DataObject ||
$object instanceof ExtensibleDataInterface ||
$object instanceof AbstractSimpleObject);
}
/**
* Get value of source by code
*
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $source
* @param string $code
*
* @return mixed
* @throws \InvalidArgumentException
*/
protected function _getFieldsetFieldValue($source, $code)
{
switch (true) {
case is_array($source):
$value = isset($source[$code]) ? $source[$code] : null;
break;
case $source instanceof ExtensibleDataInterface:
$value = $this->getAttributeValueFromExtensibleObject($source, $code);
break;
case $source instanceof DataObject:
$value = $source->getDataUsingMethod($code);
break;
case $source instanceof AbstractSimpleObject:
$sourceArray = $source->__toArray();
$value = isset($sourceArray[$code]) ? $sourceArray[$code] : null;
break;
default:
throw new \InvalidArgumentException(
'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject'
);
}
return $value;
}
/**
* Set value of target by code
*
* @param array|DataObject|ExtensibleDataInterface|AbstractSimpleObject $target
* @param string $targetCode
* @param mixed $value
*
* @return array|DataObject|ExtensibleDataInterface|AbstractSimpleObject
* @throws \InvalidArgumentException
*/
protected function _setFieldsetFieldValue($target, $targetCode, $value)
{
switch (true) {
case is_array($target):
$target[$targetCode] = $value;
break;
case $target instanceof ExtensibleDataInterface:
$this->setAttributeValueFromExtensibleObject($target, $targetCode, $value);
break;
case $target instanceof DataObject:
$target->setDataUsingMethod($targetCode, $value);
break;
case $target instanceof AbstractSimpleObject:
$target->setData($targetCode, $value);
break;
default:
throw new \InvalidArgumentException(
'Source should be array, Magento Object, ExtensibleDataInterface, or AbstractSimpleObject'
);
}
return $target;
}
/**
* Access the extension get method
*
* @param ExtensibleDataInterface $source
* @param string $code
*
* @return mixed
* @throws \InvalidArgumentException
*
* @deprecated 102.0.3
* @see \Magento\Framework\DataObject\Copy::getAttributeValueFromExtensibleObject
*/
protected function getAttributeValueFromExtensibleDataObject($source, $code)
{
return $this->getAttributeValueFromExtensibleObject($source, $code);
}
/**
* Get Attribute Value from Extensible Object Data with fallback to DataObject or AbstractSimpleObject.
*
* @param ExtensibleDataInterface $source
* @param string $code
*
* @return mixed|null
*/
private function getAttributeValueFromExtensibleObject(ExtensibleDataInterface $source, string $code)
{
$method = 'get' . str_replace('_', '', ucwords($code, '_'));
$methodExists = method_exists($source, $method);
if ($methodExists === true) {
return $source->{$method}();
}
$extensionAttributes = $source->getExtensionAttributes();
if ($extensionAttributes) {
$methodExists = method_exists($extensionAttributes, $method);
if ($methodExists) {
return $extensionAttributes->{$method}();
}
}
if ($source instanceof DataObject) {
return $source->getDataUsingMethod($code);
}
if ($source instanceof AbstractSimpleObject) {
$sourceArray = $source->__toArray();
return isset($sourceArray[$code]) ? $sourceArray[$code] : null;
}
throw new \InvalidArgumentException('Attribute in object does not exist.');
}
/**
* Access the extension set method
*
* @param ExtensibleDataInterface $target
* @param string $code
* @param mixed $value
*
* @return void
* @throws \InvalidArgumentException
*
* @deprecated 102.0.3
* @see \Magento\Framework\DataObject\Copy::setAttributeValueFromExtensibleObject
*/
protected function setAttributeValueFromExtensibleDataObject(ExtensibleDataInterface $target, $code, $value)
{
$this->setAttributeValueFromExtensibleObject($target, $code, $value);
}
/**
* Set Attribute Value for Extensible Object Data with fallback to DataObject or AbstractSimpleObject.
*
* @param ExtensibleDataInterface $target
* @param string $code
* @param mixed $value
*
* @return void
* @throws \InvalidArgumentException
*/
private function setAttributeValueFromExtensibleObject(ExtensibleDataInterface $target, string $code, $value): void
{
$method = 'set' . str_replace('_', '', ucwords($code, '_'));
$methodExists = method_exists($target, $method);
if ($methodExists) {
$target->{$method}($value);
return;
}
$extensionAttributes = $target->getExtensionAttributes();
if ($extensionAttributes === null) {
$extensionAttributes = $this->extensionAttributesFactory->create(get_class($target));
}
if (method_exists($extensionAttributes, $method)) {
$extensionAttributes->{$method}($value);
$target->setExtensionAttributes($extensionAttributes);
return;
}
if ($target instanceof DataObject) {
$target->setDataUsingMethod($code, $value);
return;
}
if ($target instanceof AbstractSimpleObject) {
$target->setData($code, $value);
return;
}
throw new \InvalidArgumentException('Attribute in object does not exist.');
}
}