Xml.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. /**
  3. * XML deserializer of REST request content.
  4. *
  5. * Copyright © Magento, Inc. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\Framework\Webapi\Rest\Request\Deserializer;
  9. use Magento\Framework\App\State;
  10. use Magento\Framework\Phrase;
  11. class Xml implements \Magento\Framework\Webapi\Rest\Request\DeserializerInterface
  12. {
  13. /**
  14. * @var \Magento\Framework\Xml\Parser
  15. */
  16. protected $_xmlParser;
  17. /**
  18. * @var \Magento\Framework\App\State
  19. */
  20. protected $_appState;
  21. /**
  22. * @param \Magento\Framework\Xml\Parser $xmlParser
  23. * @param State $appState
  24. */
  25. public function __construct(\Magento\Framework\Xml\Parser $xmlParser, State $appState)
  26. {
  27. $this->_xmlParser = $xmlParser;
  28. $this->_appState = $appState;
  29. }
  30. /**
  31. * Load error string.
  32. *
  33. * Is null if there was no error while loading
  34. *
  35. * @var string
  36. */
  37. protected $_errorMessage = null;
  38. /**
  39. * Convert XML document into array.
  40. *
  41. * @param string $xmlRequestBody XML document
  42. * @return array Data converted from XML document to array. Root node is excluded from response.
  43. * @throws \InvalidArgumentException In case of invalid argument type.
  44. * @throws \Magento\Framework\Webapi\Exception If decoding error occurs.
  45. */
  46. public function deserialize($xmlRequestBody)
  47. {
  48. if (!is_string($xmlRequestBody)) {
  49. throw new \InvalidArgumentException(
  50. sprintf('"%s" data type is invalid. String is expected.', gettype($xmlRequestBody))
  51. );
  52. }
  53. /** Disable external entity loading to prevent possible vulnerability */
  54. $previousLoaderState = libxml_disable_entity_loader(true);
  55. set_error_handler([$this, 'handleErrors']);
  56. $this->_xmlParser->loadXML($xmlRequestBody);
  57. restore_error_handler();
  58. libxml_disable_entity_loader($previousLoaderState);
  59. /** Process errors during XML parsing. */
  60. if ($this->_errorMessage !== null) {
  61. if ($this->_appState->getMode() !== State::MODE_DEVELOPER) {
  62. $exceptionMessage = new Phrase('Decoding error.');
  63. } else {
  64. $exceptionMessage = new Phrase('Decoding Error: %1', [$this->_errorMessage]);
  65. }
  66. throw new \Magento\Framework\Webapi\Exception($exceptionMessage);
  67. }
  68. $data = $this->_xmlParser->xmlToArray();
  69. /** Data will always have exactly one element so it is safe to call reset here. */
  70. return reset($data);
  71. }
  72. /**
  73. * Handle any errors during XML loading.
  74. *
  75. * @param integer $errorNumber
  76. * @param string $errorMessage
  77. * @param string $errorFile
  78. * @param integer $errorLine
  79. * @return void
  80. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  81. */
  82. public function handleErrors($errorNumber, $errorMessage, $errorFile, $errorLine)
  83. {
  84. if ($this->_errorMessage === null) {
  85. $this->_errorMessage = $errorMessage;
  86. } else {
  87. $this->_errorMessage .= $errorMessage;
  88. }
  89. }
  90. }