PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/ebay/ebatns/EbatNs_ResponseParser.php

https://gitlab.com/endomorphosis/KindSupply
PHP | 490 lines | 375 code | 72 blank | 43 comment | 83 complexity | abdbf7098aa174e83a1769a7ac8d5488 MD5 | raw file
  1. <?php
  2. // $Id: EbatNs_ResponseParser.php,v 1.1 2007/05/31 11:38:00 michael Exp $
  3. /* $Log: EbatNs_ResponseParser.php,v $
  4. /* Revision 1.1 2007/05/31 11:38:00 michael
  5. /* - initial checkin
  6. /* - version < 513
  7. /*
  8. *
  9. * 5 6.02.06 14:15 Mcoslar
  10. *
  11. * 4 3.02.06 15:47 Mcoslar
  12. *
  13. * 3 3.02.06 10:44 Mcoslar
  14. *
  15. * 2 30.01.06 16:44 Mcoslar
  16. * �nderungen eingef�gt
  17. */
  18. define ('EBATNS_PARSEMODE_CALL', 1);
  19. define ('EBATNS_PARSEMODE_NOTIFICATION', 2);
  20. define ('EBATNS_PARSEMODE_CALLEXTENSION', 3);
  21. define ('EBATNS_PSTATENOT_INITIAL', 0);
  22. define ('EBATNS_PSTATENOT_HAS_SIGNATURE', 1);
  23. define ('EBATNS_PSTATENOT_FOUND_ENVBODY', 2);
  24. define ('EBATNS_PSTATENOT_IN_RESPONSE', 3);
  25. class EbatNs_ResponseParser
  26. {
  27. var $_client;
  28. var $_options;
  29. var $_responseObject = null;
  30. var $_waitForResponseTag = null;
  31. var $_responseTypeName = null;
  32. var $_inResponse = false;
  33. var $_stData = array();
  34. var $_stValue = array();
  35. var $_stMap = array();
  36. var $_depth = 0;
  37. var $_typeNs = null;
  38. var $_typeMap = array();
  39. var $_hasFault = false;
  40. var $_hasError = false;
  41. var $_parseMode = EBATNS_PARSEMODE_CALL;
  42. var $_tmpNotificationSignature = null;
  43. var $_notificationParseState = EBATNS_PSTATENOT_INITIAL;
  44. var $_extensionPrefix = null;
  45. function EbatNs_ResponseParser(& $client, $typeNs, $options = null)
  46. {
  47. $this->_client = & $client;
  48. $this->_typeNs = $typeNs;
  49. $this->setOption('NO_ATTRIBUTES', false);
  50. $this->setOption('NO_UNSET_METADATA', false);
  51. $this->setOption('NO_REDUCE', false);
  52. $this->setOption('NO_EMPTY_ARRAYS');
  53. $this->setOption('NO_EMPTY_VALUES');
  54. $this->setOption('FLATTEN_ON_ARRAYTYPE');
  55. if ($options)
  56. {
  57. $this->_options = array_merge($this->_options, $options);
  58. }
  59. }
  60. function setOption($name, $value = true)
  61. {
  62. $this->_options[$name] = $value;
  63. }
  64. function setMode($newMode)
  65. {
  66. $this->_parseMode = $newMode;
  67. }
  68. function setExtensionPrefix($extensionPrefix)
  69. {
  70. $this->_extensionPrefix = $extensionPrefix;
  71. }
  72. function _reduceElement(& $element)
  73. {
  74. if ($this->_options['NO_REDUCE'])
  75. return true;
  76. if ($this->_options['NO_EMPTY_VALUES'])
  77. {
  78. foreach (get_object_vars($element) as $member => $value)
  79. if ($member[0] == '_' || ($value === null))
  80. unset($element->{$member});
  81. }
  82. else
  83. {
  84. foreach (get_object_vars($element) as $member => $value)
  85. if ($member[0] == '_')
  86. unset($element->{$member});
  87. }
  88. return count(get_object_vars($element)) > 0;
  89. }
  90. function _includeType($typeName)
  91. {
  92. if (!class_exists($typeName)) {
  93. $typeFileName = basename($typeName);
  94. require_once $typeFileName . '.php';
  95. }
  96. return (class_exists($typeName));
  97. }
  98. function & _makeValue($typeName)
  99. {
  100. // if ($this->_parseMode == EBATNS_PARSEMODE_CALLEXTENSION)
  101. // $typeName = $this->_extensionPrefix . $typeName;
  102. if ($this->_includeType($typeName))
  103. {
  104. $t = & new $typeName();
  105. // transfer the typeInfo to the typeMap
  106. $typeInfo['typeName'] = $typeName;
  107. $typeInfo['elements'] = isset($t->_elements) ? $t->_elements : null;
  108. $typeInfo['attributes'] = isset($t->_attributes) ? $t->_attributes : null;
  109. $this->_typeMap[strtolower($typeName)] = $typeInfo;
  110. // unset the type-information from
  111. // the resulting value
  112. if (!$this->_options['NO_UNSET_METADATA'])
  113. {
  114. unset($t->_elements);
  115. unset($t->_attributes);
  116. }
  117. return $t;
  118. }
  119. else
  120. return null;
  121. }
  122. function & decode($responseName, $messageText, $parseMode = EBATNS_PARSEMODE_CALL, $responseTypeName = null)
  123. {
  124. $this->_responseObject = null;
  125. $this->_stValue = array();
  126. $this->_stData = array();
  127. $this->_stMap = array();
  128. $this->_depth = 0;
  129. $this->_hasError = false;
  130. $this->_hasFault = false;
  131. $this->_waitForResponseTag = $responseName;
  132. if ($responseTypeName != null)
  133. $this->_responseTypeName = $responseTypeName;
  134. else
  135. $this->_responseTypeName = $responseName . 'Type';
  136. if ($parseMode != EBATNS_PARSEMODE_CALL)
  137. $this->setMode($parseMode);
  138. $encoding = 'UTF-8';
  139. $parser = xml_parser_create($encoding);
  140. xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
  141. xml_set_object($parser, $this);
  142. xml_set_element_handler($parser, '_startElement', '_endElement');
  143. xml_set_character_data_handler($parser, '_cData');
  144. if (!xml_parse($parser, $messageText, true)) {
  145. $errMsg = sprintf('XML error on line %d col %d byte %d %s',
  146. xml_get_current_line_number($parser),
  147. xml_get_current_column_number($parser),
  148. xml_get_current_byte_index($parser),
  149. xml_error_string(xml_get_error_code($parser)));
  150. // create a error-object
  151. $errResponse = & new EbatNs_ResponseError();
  152. $errResponse->raise($errMsg, 90000 + 1);
  153. return $errResponse;
  154. }
  155. xml_parser_free($parser);
  156. if ($this->_hasFault)
  157. {
  158. return ($t = & $this->_decodeFault($messageText));
  159. }
  160. return ($t = & $this->_responseObject);
  161. }
  162. function _decodeFault($msg)
  163. {
  164. $errResponse = & new EbatNs_ResponseError();
  165. $p = xml_parser_create();
  166. xml_parse_into_struct($p, $msg, $lstValues, $index);
  167. xml_parser_free($p);
  168. foreach ($lstValues as $value)
  169. {
  170. if ($value['type'] == 'complete')
  171. {
  172. switch ($value['tag'])
  173. {
  174. case 'FAULTSTRING':
  175. $errResponse->raise('soap-fault: ' . utf8_decode($value['value']), 90000 + 2);
  176. break;
  177. case 'ERRORCODE':
  178. $code = $value['value'];
  179. break;
  180. case 'SEVERITY':
  181. $severity = $value['value'];
  182. break;
  183. case 'DETAILEDMESSAGE':
  184. $errResponse->raise($value['value'], $code, $severity);
  185. break;
  186. }
  187. }
  188. }
  189. $this->_reduceElement($errResponse);
  190. return $errResponse;
  191. }
  192. function _startElement($parser, $name, $attrs)
  193. {
  194. // wait for the starting-element
  195. if (( ($this->_parseMode == EBATNS_PARSEMODE_CALL ||
  196. $this->_parseMode == EBATNS_PARSEMODE_CALLEXTENSION ) &&
  197. !$this->_inResponse && $name != $this->_waitForResponseTag
  198. )
  199. ||
  200. (
  201. $this->_parseMode == EBATNS_PARSEMODE_NOTIFICATION &&
  202. $this->_notificationParseState < EBATNS_PSTATENOT_IN_RESPONSE
  203. ))
  204. {
  205. if ($this->_parseMode == EBATNS_PARSEMODE_CALL ||
  206. $this->_parseMode == EBATNS_PARSEMODE_CALLEXTENSION )
  207. {
  208. if ($name == 'soapenv:Fault')
  209. $this->_hasFault = true;
  210. return;
  211. }
  212. else
  213. {
  214. if (strstr($name, ':NotificationSignature') !== false)
  215. {
  216. $this->_notificationParseState = EBATNS_PSTATENOT_HAS_SIGNATURE;
  217. return;
  218. }
  219. if ($name == 'soapenv:Body')
  220. {
  221. $this->_notificationParseState = EBATNS_PSTATENOT_FOUND_ENVBODY;
  222. return;
  223. }
  224. if ($this->_notificationParseState == EBATNS_PSTATENOT_FOUND_ENVBODY)
  225. {
  226. // know we will have the name of the response in $name
  227. // so we just set the state and recall the method again !
  228. $this->_notificationParseState = EBATNS_PSTATENOT_IN_RESPONSE;
  229. $this->_waitForResponseTag = $name;
  230. $this->_responseTypeName = $name . 'Type';
  231. $this->_depth = 0;
  232. return $this->_startElement($parser, $name, $attrs);
  233. }
  234. }
  235. }
  236. else
  237. {
  238. // setup the response-object
  239. if (!$this->_inResponse)
  240. {
  241. $parent = null;
  242. $current = & $this->_makeValue($this->_responseTypeName);
  243. $this->_inResponse = true;
  244. $mapName = null;
  245. }
  246. else
  247. {
  248. $mapName = $name;
  249. $parent = & $this->_stValue[$this->_depth];
  250. $typeInfo = $this->_typeMap[strtolower(get_class($parent))];
  251. $elementInfo = $typeInfo['elements'][$name];
  252. // if (!$elementInfo)
  253. // echo "info not found " . get_class($parent) . " $name\n";
  254. if ($elementInfo['nsURI'] == $this->_typeNs)
  255. {
  256. // let CodeTypes (Facets/enums) be result in just
  257. // plain strings but child-objects
  258. if (strpos($elementInfo['type'], 'CodeType') === false)
  259. {
  260. $current = & $this->_makeValue($elementInfo['type']);
  261. if ($attrs)
  262. {
  263. foreach($attrs as $attKey => $attValue)
  264. {
  265. $current->setTypeAttribute($attKey, $attValue);
  266. }
  267. }
  268. }
  269. else
  270. {
  271. // echo "1 no type found $name\n";
  272. $current = null;
  273. }
  274. }
  275. else
  276. {
  277. // echo "xsd-type found " . get_class($parent) . " $name\n";
  278. $current = null;
  279. }
  280. }
  281. }
  282. $this->_depth++;
  283. $this->_stData[$this->_depth] = null;
  284. $this->_stValue[$this->_depth] = & $current;
  285. $this->_stMap[$this->_depth] = $mapName;
  286. }
  287. function _endElement($parser, $name)
  288. {
  289. if ($this->_parseMode == EBATNS_PARSEMODE_NOTIFICATION && $this->_notificationParseState == EBATNS_PSTATENOT_HAS_SIGNATURE)
  290. {
  291. $this->_tmpNotificationSignature = $this->_stData[$this->_depth];
  292. return;
  293. }
  294. if (!$this->_inResponse)
  295. {
  296. return;
  297. }
  298. if ($name == $this->_waitForResponseTag)
  299. {
  300. $this->_responseObject = & $this->_stValue[1];
  301. if ($this->_parseMode == EBATNS_PARSEMODE_NOTIFICATION)
  302. $this->_responseObject->NotificationSignature = $this->_tmpNotificationSignature;
  303. $this->_reduceElement($this->_responseObject);
  304. // switch off the parsing again
  305. $this->_inResponse = false;
  306. return;
  307. }
  308. $current = & $this->_stValue[$this->_depth];
  309. $parent = & $this->_stValue[$this->_depth - 1];
  310. $mapName = $this->_stMap[$this->_depth];
  311. $data = $this->_stData[$this->_depth];
  312. $this->_depth--;
  313. if ($current)
  314. $typeInfoCurrent = $this->_typeMap[strtolower(get_class($current))];
  315. if ($parent)
  316. $typeInfoParent = $this->_typeMap[strtolower(get_class($parent))];
  317. $infoMember = $typeInfoParent['elements'][$mapName];
  318. $data = $this->_decodeData($data, $infoMember['type']);
  319. if ($mapName)
  320. {
  321. if ($current)
  322. {
  323. if (count($typeInfoCurrent['elements']) == 0)
  324. {
  325. $currentIsEmpty = false;
  326. if (count($typeInfoCurrent['attributes']) == 0 || $this->_options['NO_ATTRIBUTES'])
  327. {
  328. // in case there neither child-elements nor attributes
  329. // we reduced the data to a plain-value !
  330. $current = $data;
  331. }
  332. else
  333. {
  334. $current->setTypeValue($data);
  335. }
  336. }
  337. if (is_object($current))
  338. {
  339. $currentIsEmpty = ! $this->_reduceElement($current);
  340. if (!$currentIsEmpty)
  341. {
  342. if ($this->_client->_hasCallbacks)
  343. {
  344. if ($this->_client->_handleDataType($infoMember['type'], $current, $mapName))
  345. return;
  346. }
  347. }
  348. }
  349. }
  350. else
  351. {
  352. $current = $data;
  353. $currentIsEmpty = false;
  354. }
  355. if ($infoMember)
  356. {
  357. list($lower, $upper) = split("\.\.", $infoMember['cardinality']);
  358. if ($upper == '*' || $upper > 1)
  359. {
  360. if ($this->_options['NO_EMPTY_ARRAYS'] && $currentIsEmpty)
  361. {
  362. // do not add an "empty" object
  363. return;
  364. }
  365. else
  366. {
  367. $parent->{$mapName}[] = $current;
  368. return;
  369. }
  370. }
  371. }
  372. // do not set an "empty" value
  373. if ($this->_options['NO_EMPTY_VALUES'] && $currentIsEmpty)
  374. return;
  375. if ($this->_options['FLATTEN_ON_ARRAYTYPE'])
  376. {
  377. // using this option will flatten type that contain "ArrayType"
  378. // so instead of CategoryArray -> Category -> php-array()
  379. // you will just get CategoryArray -> php-array(), so leaving out the
  380. // "Category" - subelement
  381. // check if the parents-element's typename
  382. // contains arraytype
  383. if (strpos($infoMember['type'], 'ArrayType') !== false)
  384. {
  385. $arrayTypeInfo = $this->_typeMap[strtolower($infoMember['type'])];
  386. if (count($arrayTypeInfo['elements']) == 1)
  387. {
  388. $key = array_keys($arrayTypeInfo['elements']);
  389. $current = $current->{$key[0]};
  390. }
  391. }
  392. }
  393. $parent->{$mapName} = $current;
  394. }
  395. }
  396. function _cData($parser, $data)
  397. {
  398. if ($this->_parseMode == EBATNS_PARSEMODE_NOTIFICATION && $this->_notificationParseState == EBATNS_PSTATENOT_HAS_SIGNATURE)
  399. {
  400. $this->_stData[$this->_depth] .= $data;
  401. }
  402. if (!$this->_inResponse)
  403. return;
  404. $this->_stData[$this->_depth] .= $data;
  405. }
  406. function _decodeData($data, $type = 'string')
  407. {
  408. if ($this->_client->_dataConverter != null)
  409. {
  410. return $this->_client->_dataConverter->decodeData($data, $type);
  411. }
  412. else
  413. {
  414. return $data;
  415. }
  416. }
  417. }
  418. ?>