DataObjectProcessor.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Reflection;
  7. use Magento\Framework\Api\CustomAttributesDataInterface;
  8. use Magento\Framework\Phrase;
  9. /**
  10. * Data object processor for array serialization using class reflection
  11. *
  12. * @api
  13. * @since 100.0.2
  14. */
  15. class DataObjectProcessor
  16. {
  17. /**
  18. * @var MethodsMap
  19. */
  20. private $methodsMapProcessor;
  21. /**
  22. * @var TypeCaster
  23. */
  24. private $typeCaster;
  25. /**
  26. * @var FieldNamer
  27. */
  28. private $fieldNamer;
  29. /**
  30. * @var ExtensionAttributesProcessor
  31. */
  32. private $extensionAttributesProcessor;
  33. /**
  34. * @var CustomAttributesProcessor
  35. */
  36. private $customAttributesProcessor;
  37. /**
  38. * @var array
  39. */
  40. private $processors;
  41. /**
  42. * @param MethodsMap $methodsMapProcessor
  43. * @param TypeCaster $typeCaster
  44. * @param FieldNamer $fieldNamer
  45. * @param CustomAttributesProcessor $customAttributesProcessor
  46. * @param ExtensionAttributesProcessor $extensionAttributesProcessor
  47. * @param array $processors
  48. */
  49. public function __construct(
  50. MethodsMap $methodsMapProcessor,
  51. TypeCaster $typeCaster,
  52. FieldNamer $fieldNamer,
  53. CustomAttributesProcessor $customAttributesProcessor,
  54. ExtensionAttributesProcessor $extensionAttributesProcessor,
  55. array $processors = []
  56. ) {
  57. $this->methodsMapProcessor = $methodsMapProcessor;
  58. $this->typeCaster = $typeCaster;
  59. $this->fieldNamer = $fieldNamer;
  60. $this->extensionAttributesProcessor = $extensionAttributesProcessor;
  61. $this->customAttributesProcessor = $customAttributesProcessor;
  62. $this->processors = $processors;
  63. }
  64. /**
  65. * Use class reflection on given data interface to build output data array
  66. *
  67. * @param mixed $dataObject
  68. * @param string $dataObjectType
  69. * @return array
  70. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  71. */
  72. public function buildOutputDataArray($dataObject, $dataObjectType)
  73. {
  74. $methods = $this->methodsMapProcessor->getMethodsMap($dataObjectType);
  75. $outputData = [];
  76. foreach (array_keys($methods) as $methodName) {
  77. if (!$this->methodsMapProcessor->isMethodValidForDataField($dataObjectType, $methodName)) {
  78. continue;
  79. }
  80. $value = $dataObject->{$methodName}();
  81. $isMethodReturnValueRequired = $this->methodsMapProcessor->isMethodReturnValueRequired(
  82. $dataObjectType,
  83. $methodName
  84. );
  85. if ($value === null && !$isMethodReturnValueRequired) {
  86. continue;
  87. }
  88. $returnType = $this->methodsMapProcessor->getMethodReturnType($dataObjectType, $methodName);
  89. $key = $this->fieldNamer->getFieldNameForMethodName($methodName);
  90. if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES && $value === []) {
  91. continue;
  92. }
  93. if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES) {
  94. $value = $this->customAttributesProcessor->buildOutputDataArray($dataObject, $dataObjectType);
  95. } elseif ($key === "extension_attributes") {
  96. $value = $this->extensionAttributesProcessor->buildOutputDataArray($value, $returnType);
  97. if (empty($value)) {
  98. continue;
  99. }
  100. } else {
  101. if (is_object($value) && !($value instanceof Phrase)) {
  102. $value = $this->buildOutputDataArray($value, $returnType);
  103. } elseif (is_array($value)) {
  104. $valueResult = [];
  105. $arrayElementType = substr($returnType, 0, -2);
  106. foreach ($value as $singleValue) {
  107. if (is_object($singleValue) && !($singleValue instanceof Phrase)) {
  108. $singleValue = $this->buildOutputDataArray($singleValue, $arrayElementType);
  109. }
  110. $valueResult[] = $this->typeCaster->castValueToType($singleValue, $arrayElementType);
  111. }
  112. $value = $valueResult;
  113. } else {
  114. $value = $this->typeCaster->castValueToType($value, $returnType);
  115. }
  116. }
  117. $outputData[$key] = $value;
  118. }
  119. $outputData = $this->changeOutputArray($dataObject, $outputData);
  120. return $outputData;
  121. }
  122. /**
  123. * Change output array if needed.
  124. *
  125. * @param mixed $dataObject
  126. * @param array $outputData
  127. * @return array
  128. */
  129. private function changeOutputArray($dataObject, array $outputData): array
  130. {
  131. foreach ($this->processors as $dataObjectClassName => $processor) {
  132. if ($dataObject instanceof $dataObjectClassName) {
  133. $outputData = $processor->execute($dataObject, $outputData);
  134. }
  135. }
  136. return $outputData;
  137. }
  138. }