Json.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. /**
  3. * Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
  4. */
  5. namespace Temando\Shipping\Rest\SchemaMapper;
  6. use Temando\Shipping\Rest\Response\DataObject\AbstractResource;
  7. use Temando\Shipping\Rest\SchemaMapper\JsonApi\RelationshipHandler;
  8. use Temando\Shipping\Rest\SchemaMapper\JsonApi\ResourceContainerInterface;
  9. use Temando\Shipping\Rest\SchemaMapper\JsonApi\TypeMapInterface;
  10. use Temando\Shipping\Rest\SchemaMapper\Reflection\PropertyHandlerInterface;
  11. use Temando\Shipping\Rest\SchemaMapper\Reflection\TypeHandlerInterface;
  12. /**
  13. * Temando REST API JSON API Parser
  14. *
  15. * This deserializer introduces very minimal JSON API support as required for handling
  16. * Temando platform responses:
  17. * - use type property to determine the deserialized type via type map
  18. * - resolve relationships (only if contained in message, no fetching of additional resource)
  19. *
  20. * @package Temando\Shipping\Rest
  21. * @author Christoph Aßmann <christoph.assmann@netresearch.de>
  22. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  23. * @link http://www.temando.com/
  24. */
  25. class Json extends AbstractParser implements ParserInterface
  26. {
  27. /**
  28. * @var ResourceContainerInterface
  29. */
  30. private $resourceContainer;
  31. /**
  32. * @var TypeMapInterface
  33. */
  34. private $typeMap;
  35. /**
  36. * @var RelationshipHandler
  37. */
  38. private $relationshipHandler;
  39. /**
  40. * JsonApi constructor.
  41. * @param PropertyHandlerInterface $propertyHandler
  42. * @param TypeHandlerInterface $typeHandler
  43. * @param ResourceContainerInterface $resourceContainer
  44. * @param TypeMapInterface $typeMap
  45. * @param RelationshipHandler $relationshipHandler
  46. */
  47. public function __construct(
  48. PropertyHandlerInterface $propertyHandler,
  49. TypeHandlerInterface $typeHandler,
  50. ResourceContainerInterface $resourceContainer,
  51. TypeMapInterface $typeMap,
  52. RelationshipHandler $relationshipHandler
  53. ) {
  54. $this->resourceContainer = $resourceContainer;
  55. $this->typeMap = $typeMap;
  56. $this->relationshipHandler = $relationshipHandler;
  57. parent::__construct($propertyHandler, $typeHandler);
  58. }
  59. /**
  60. * Copy the properties to an object of the given type.
  61. *
  62. * @param mixed[] $properties Associated array of property keys and values.
  63. * @param string $type The type of the target object.
  64. * @return object The target object with all properties set.
  65. */
  66. public function parseProperties(array $properties, $type)
  67. {
  68. if (isset($properties['type']) && isset($properties['id'])) {
  69. // target type can be overridden via type map
  70. $type = $this->typeMap->getClass($properties['type']) ?: $type;
  71. }
  72. if (ltrim($type, '\\') === \Temando\Shipping\Rest\Response\Fields\Relationship::class) {
  73. // normalize relationship data to array
  74. $properties['data'] = [$properties['data']];
  75. }
  76. $result = parent::parseProperties($properties, $type);
  77. if ($result instanceof AbstractResource) {
  78. $this->resourceContainer->addResource($result);
  79. }
  80. return $result;
  81. }
  82. /**
  83. * Convert JSON document into internal types.
  84. *
  85. * Relationships are resolved: related resource gets added as property to
  86. * the parent resource, e.g. resource.relationships.fooRelationship => resource.fooResource
  87. *
  88. * @param string $data The data to be parsed
  89. * @param string $type The type (interface) to map the data to
  90. * @return mixed The object with populated properties
  91. */
  92. public function parse($data, $type)
  93. {
  94. $properties = json_decode($data, true);
  95. $result = $this->parseProperties($properties, $type);
  96. // iterate over all resources within the response
  97. foreach ($this->resourceContainer->getResources() as $resource) {
  98. $this->relationshipHandler->addRelationships($resource, $this->resourceContainer);
  99. }
  100. return $result;
  101. }
  102. }