ServiceOutputProcessor.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Webapi;
  7. use Magento\Framework\Api\AbstractExtensibleObject;
  8. use Magento\Framework\Api\ExtensibleDataObjectConverter;
  9. use Magento\Framework\App\ObjectManager;
  10. use Magento\Framework\Reflection\DataObjectProcessor;
  11. use Magento\Framework\Reflection\MethodsMap;
  12. use Magento\Framework\Reflection\TypeProcessor;
  13. use Zend\Code\Reflection\ClassReflection;
  14. /**
  15. * Data object converter
  16. *
  17. * @api
  18. * @since 100.0.2
  19. */
  20. class ServiceOutputProcessor implements ServicePayloadConverterInterface
  21. {
  22. /**
  23. * @var DataObjectProcessor
  24. */
  25. protected $dataObjectProcessor;
  26. /**
  27. * @var MethodsMap
  28. */
  29. protected $methodsMapProcessor;
  30. /**
  31. * @var TypeProcessor|null
  32. */
  33. private $typeProcessor;
  34. /**
  35. * @param DataObjectProcessor $dataObjectProcessor
  36. * @param MethodsMap $methodsMapProcessor
  37. * @param TypeProcessor|null $typeProcessor
  38. */
  39. public function __construct(
  40. DataObjectProcessor $dataObjectProcessor,
  41. MethodsMap $methodsMapProcessor,
  42. TypeProcessor $typeProcessor = null
  43. ) {
  44. $this->dataObjectProcessor = $dataObjectProcessor;
  45. $this->methodsMapProcessor = $methodsMapProcessor;
  46. $this->typeProcessor = $typeProcessor ?: ObjectManager::getInstance()->get(TypeProcessor::class);
  47. }
  48. /**
  49. * Converts the incoming data into scalar or an array of scalars format.
  50. *
  51. * If the data provided is null, then an empty array is returned. Otherwise, if the data is an object, it is
  52. * assumed to be a Data Object and converted to an associative array with keys representing the properties of the
  53. * Data Object.
  54. * Nested Data Objects are also converted. If the data provided is itself an array, then we iterate through the
  55. * contents and convert each piece individually.
  56. *
  57. * @param mixed $data
  58. * @param string $serviceClassName
  59. * @param string $serviceMethodName
  60. * @return array|int|string|bool|float Scalar or array of scalars
  61. */
  62. public function process($data, $serviceClassName, $serviceMethodName)
  63. {
  64. /** @var string $dataType */
  65. $dataType = $this->methodsMapProcessor->getMethodReturnType($serviceClassName, $serviceMethodName);
  66. if (class_exists($serviceClassName) || interface_exists($serviceClassName)) {
  67. $sourceClass = new ClassReflection($serviceClassName);
  68. $dataType = $this->typeProcessor->resolveFullyQualifiedClassName($sourceClass, $dataType);
  69. }
  70. return $this->convertValue($data, $dataType);
  71. }
  72. /**
  73. * Convert data object to array and process available custom attributes
  74. *
  75. * @param array $dataObjectArray
  76. * @return array
  77. */
  78. protected function processDataObject($dataObjectArray)
  79. {
  80. if (isset($dataObjectArray[AbstractExtensibleObject::CUSTOM_ATTRIBUTES_KEY])) {
  81. $dataObjectArray = ExtensibleDataObjectConverter::convertCustomAttributesToSequentialArray(
  82. $dataObjectArray
  83. );
  84. }
  85. //Check for nested custom_attributes
  86. foreach ($dataObjectArray as $key => $value) {
  87. if (is_array($value)) {
  88. $dataObjectArray[$key] = $this->processDataObject($value);
  89. }
  90. }
  91. return $dataObjectArray;
  92. }
  93. /**
  94. * Convert associative array into proper data object.
  95. *
  96. * @param array $data
  97. * @param string $type
  98. * @return array|object
  99. */
  100. public function convertValue($data, $type)
  101. {
  102. if (is_array($data)) {
  103. $result = [];
  104. $arrayElementType = substr($type, 0, -2);
  105. foreach ($data as $datum) {
  106. if (is_object($datum)) {
  107. $datum = $this->processDataObject(
  108. $this->dataObjectProcessor->buildOutputDataArray($datum, $arrayElementType)
  109. );
  110. }
  111. $result[] = $datum;
  112. }
  113. return $result;
  114. } elseif (is_object($data)) {
  115. return $this->processDataObject(
  116. $this->dataObjectProcessor->buildOutputDataArray($data, $type)
  117. );
  118. } elseif ($data === null) {
  119. return [];
  120. } else {
  121. /** No processing is required for scalar types */
  122. return $data;
  123. }
  124. }
  125. }