Finding.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service
  17. * @subpackage Ebay
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Finding.php 22824 2010-08-09 18:59:54Z renanbr $
  21. */
  22. /**
  23. * @see Zend_Service_Ebay_Abstract
  24. */
  25. require_once 'Zend/Service/Ebay/Abstract.php';
  26. /** @see Zend_Xml_Security */
  27. require_once 'Zend/Xml/Security.php';
  28. /**
  29. * @category Zend
  30. * @package Zend_Service
  31. * @subpackage Ebay
  32. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. * @uses Zend_Service_Ebay_Abstract
  35. */
  36. class Zend_Service_Ebay_Finding extends Zend_Service_Ebay_Abstract
  37. {
  38. const SERVICE_NAME = 'FindingService';
  39. const SERVICE_VERSION = '1.0.0';
  40. const RESPONSE_DATA_FORMAT = 'XML';
  41. const ENDPOINT_URI = 'http://svcs.ebay.com';
  42. const ENDPOINT_PATH = 'services/search/FindingService/v1';
  43. const XMLNS_FINDING = 'e';
  44. const XMLNS_MS = 'ms';
  45. /**
  46. * @var array
  47. */
  48. protected static $_xmlNamespaces = array(
  49. self::XMLNS_FINDING => 'http://www.ebay.com/marketplace/search/v1/services',
  50. self::XMLNS_MS => 'http://www.ebay.com/marketplace/services'
  51. );
  52. /**
  53. *
  54. * @var array
  55. */
  56. protected $_options = array(
  57. self::OPTION_GLOBAL_ID => 'EBAY-US'
  58. );
  59. /**
  60. * @return array
  61. */
  62. public static function getXmlNamespaces()
  63. {
  64. return self::$_xmlNamespaces;
  65. }
  66. /**
  67. * @param Zend_Config|array|string $options Application Id or array of options
  68. * @throws Zend_Service_Ebay_Finding_Exception When application id is missing
  69. * @return void
  70. */
  71. public function __construct($options)
  72. {
  73. // prepare options
  74. if (is_string($options)) {
  75. // application id was given
  76. $options = array(self::OPTION_APP_ID => $options);
  77. } else {
  78. // check application id
  79. $options = parent::optionsToArray($options);
  80. if (!array_key_exists(self::OPTION_APP_ID, $options)) {
  81. /**
  82. * @see Zend_Service_Ebay_Finding_Exception
  83. */
  84. require_once 'Zend/Service/Ebay/Finding/Exception.php';
  85. throw new Zend_Service_Ebay_Finding_Exception(
  86. 'Application Id is missing.');
  87. }
  88. }
  89. // load options
  90. parent::setOption($options);
  91. }
  92. /**
  93. * @param Zend_Rest_Client $client
  94. * @return Zend_Service_Ebay_Finding Provides a fluent interface
  95. */
  96. public function setClient($client)
  97. {
  98. if (!$client instanceof Zend_Rest_Client) {
  99. /**
  100. * @see Zend_Service_Ebay_Finding_Exception
  101. */
  102. require_once 'Zend/Service/Ebay/Finding/Exception.php';
  103. throw new Zend_Service_Ebay_Finding_Exception(
  104. 'Client object must extend Zend_Rest_Client.');
  105. }
  106. $this->_client = $client;
  107. return $this;
  108. }
  109. /**
  110. * @return Zend_Rest_Client
  111. */
  112. public function getClient()
  113. {
  114. if (!$this->_client instanceof Zend_Rest_Client) {
  115. /**
  116. * @see Zend_Rest_Client
  117. */
  118. require_once 'Zend/Rest/Client.php';
  119. $this->_client = new Zend_Rest_Client();
  120. }
  121. return $this->_client;
  122. }
  123. /**
  124. * Finds items by a keyword query and/or category and allows searching
  125. * within item descriptions.
  126. *
  127. * @param string $keywords
  128. * @param boolean $descriptionSearch
  129. * @param integer $categoryId
  130. * @param Zend_Config|array $options
  131. * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsAdvanced.html
  132. * @return Zend_Service_Ebay_Finding_Response_Items
  133. */
  134. public function findItemsAdvanced($keywords, $descriptionSearch = true, $categoryId = null, $options = null)
  135. {
  136. // prepare options
  137. $options = parent::optionsToArray($options);
  138. $options['keywords'] = $keywords;
  139. $options['descriptionSearch'] = $descriptionSearch;
  140. if (!empty($categoryId)) {
  141. $options['categoryId'] = $categoryId;
  142. }
  143. // do request
  144. return $this->_findItems($options, 'findItemsAdvanced');
  145. }
  146. /**
  147. * Finds items in a specific category. Results can be filtered and sorted.
  148. *
  149. * @param integer $categoryId
  150. * @param Zend_Config|array $options
  151. * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByCategory.html
  152. * @return Zend_Service_Ebay_Finding_Response_Items
  153. */
  154. public function findItemsByCategory($categoryId, $options = null)
  155. {
  156. // prepare options
  157. $options = parent::optionsToArray($options);
  158. $options['categoryId'] = $categoryId;
  159. // do request
  160. return $this->_findItems($options, 'findItemsByCategory');
  161. }
  162. /**
  163. * Finds items on eBay based upon a keyword query and returns details for
  164. * matching items.
  165. *
  166. * @param string $keywords
  167. * @param Zend_Config|array $options
  168. * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByKeywords.html
  169. * @return Zend_Service_Ebay_Finding_Response_Items
  170. */
  171. public function findItemsByKeywords($keywords, $options = null)
  172. {
  173. // prepare options
  174. $options = parent::optionsToArray($options);
  175. $options['keywords'] = $keywords;
  176. // do request
  177. return $this->_findItems($options, 'findItemsByKeywords');
  178. }
  179. /**
  180. * Finds items based upon a product ID, such as an ISBN, UPC, EAN, or ePID.
  181. *
  182. * @param integer $productId
  183. * @param string $productIdType Default value is ReferenceID
  184. * @param Zend_Config|array $options
  185. * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByProduct.html
  186. * @return Zend_Service_Ebay_Finding_Response_Items
  187. */
  188. public function findItemsByProduct($productId, $productIdType = null, $options = null)
  189. {
  190. if (null == $productIdType) {
  191. $productIdType = 'ReferenceID';
  192. }
  193. // prepare options
  194. $options = parent::optionsToArray($options);
  195. $options['productId'] = array('' => $productId,
  196. 'type' => $productIdType);
  197. // do request
  198. return $this->_findItems($options, 'findItemsByProduct');
  199. }
  200. /**
  201. * Finds items in eBay stores. Can search a specific store or can search all
  202. * stores with a keyword query.
  203. *
  204. * @param string $storeName
  205. * @param Zend_Config|array $options
  206. * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsIneBayStores.html
  207. * @return Zend_Service_Ebay_Finding_Response_Items
  208. */
  209. public function findItemsInEbayStores($storeName, $options = null)
  210. {
  211. // prepare options
  212. $options = parent::optionsToArray($options);
  213. $options['storeName'] = $storeName;
  214. // do request
  215. return $this->_findItems($options, 'findItemsIneBayStores');
  216. }
  217. /**
  218. * @param array $options
  219. * @param string $operation
  220. * @return Zend_Service_Ebay_Finding_Response_Items
  221. */
  222. protected function _findItems(array $options, $operation)
  223. {
  224. // set default output selector value
  225. if (!array_key_exists('outputSelector', $options)) {
  226. $options['outputSelector'] = array('AspectHistogram',
  227. 'CategoryHistogram',
  228. 'SellerInfo',
  229. 'StoreInfo');
  230. }
  231. // do request
  232. $dom = $this->_request($operation, $options);
  233. /**
  234. * @see Zend_Service_Ebay_Finding_Response_Items
  235. */
  236. require_once 'Zend/Service/Ebay/Finding/Response/Items.php';
  237. $response = new Zend_Service_Ebay_Finding_Response_Items($dom->firstChild);
  238. return $response->setOperation($operation)
  239. ->setOption($options);
  240. }
  241. /**
  242. * Gets category and/or aspect metadata for the specified category.
  243. *
  244. * @param integer $categoryId
  245. * @param Zend_Config|array $options
  246. * @link http://developer.ebay.com/DevZone/finding/CallRef/getHistograms.html
  247. * @return Zend_Service_Ebay_Finding_Response_Histograms
  248. */
  249. public function getHistograms($categoryId, $options = null)
  250. {
  251. // prepare options
  252. $options = parent::optionsToArray($options);
  253. $options['categoryId'] = $categoryId;
  254. // do request
  255. $operation = 'getHistograms';
  256. $dom = $this->_request($operation, $options);
  257. /**
  258. * @see Zend_Service_Ebay_Finding_Response_Histograms
  259. */
  260. require_once 'Zend/Service/Ebay/Finding/Response/Histograms.php';
  261. $response = new Zend_Service_Ebay_Finding_Response_Histograms($dom->firstChild);
  262. return $response->setOperation($operation)
  263. ->setOption($options);
  264. }
  265. /**
  266. * Checks specified keywords and returns correctly spelled keywords for best
  267. * search results.
  268. *
  269. * @param string $keywords
  270. * @param Zend_Config|array $options
  271. * @link http://developer.ebay.com/DevZone/finding/CallRef/getSearchKeywordsRecommendation.html
  272. * @return Zend_Service_Ebay_Finding_Response_Keywords
  273. */
  274. public function getSearchKeywordsRecommendation($keywords, $options = null)
  275. {
  276. // prepare options
  277. $options = parent::optionsToArray($options);
  278. $options['keywords'] = $keywords;
  279. // do request
  280. $operation = 'getSearchKeywordsRecommendation';
  281. $dom = $this->_request($operation, $options);
  282. /**
  283. * @see Zend_Service_Ebay_Finding_Response_Keywords
  284. */
  285. require_once 'Zend/Service/Ebay/Finding/Response/Keywords.php';
  286. $response = new Zend_Service_Ebay_Finding_Response_Keywords($dom->firstChild);
  287. return $response->setOperation($operation)
  288. ->setOption($options);
  289. }
  290. /**
  291. * @param string $operation
  292. * @param array $options
  293. * @link http://developer.ebay.com/DevZone/finding/Concepts/MakingACall.html#StandardURLParameters
  294. * @return DOMDocument
  295. */
  296. protected function _request($operation, array $options = null)
  297. {
  298. // generate default options
  299. // constructor load global-id and application-id values
  300. $default = array('OPERATION-NAME' => $operation,
  301. 'SERVICE-NAME' => self::SERVICE_NAME,
  302. 'SERVICE-VERSION' => self::SERVICE_VERSION,
  303. 'GLOBAL-ID' => $this->getOption(self::OPTION_GLOBAL_ID),
  304. 'SECURITY-APPNAME' => $this->getOption(self::OPTION_APP_ID),
  305. 'RESPONSE-DATA-FORMAT' => self::RESPONSE_DATA_FORMAT,
  306. 'REST-PAYLOAD' => '');
  307. // prepare options to ebay syntax
  308. $options = $default + $this->_optionsToNameValueSyntax($options);
  309. // do request
  310. $client = $this->getClient();
  311. $client->getHttpClient()->resetParameters();
  312. $response = $client->setUri(self::ENDPOINT_URI)
  313. ->restGet(self::ENDPOINT_PATH, $options);
  314. return $this->_parseResponse($response);
  315. }
  316. /**
  317. * Search for error from request.
  318. *
  319. * If any error is found a DOMDocument is returned, this object contains a
  320. * DOMXPath object as "ebayFindingXPath" attribute.
  321. *
  322. * @param Zend_Http_Response $response
  323. * @link http://developer.ebay.com/DevZone/finding/CallRef/types/ErrorSeverity.html
  324. * @see Zend_Service_Ebay_Finding_Abstract::_initXPath()
  325. * @throws Zend_Service_Ebay_Finding_Exception When any error occurrs during request
  326. * @return DOMDocument
  327. */
  328. protected function _parseResponse(Zend_Http_Response $response)
  329. {
  330. // error message
  331. $message = '';
  332. // first trying, loading XML
  333. $dom = new DOMDocument();
  334. if (!$dom = @Zend_Xml_Security::scan($response->getBody(), $dom)) {
  335. $message = 'It was not possible to load XML returned.';
  336. }
  337. // second trying, check request status
  338. if ($response->isError()) {
  339. $message = $response->getMessage()
  340. . ' (HTTP status code #' . $response->getStatus() . ')';
  341. }
  342. // third trying, search for error message into XML response
  343. // only first error that contains severiry=Error is read
  344. $xpath = new DOMXPath($dom);
  345. foreach (self::$_xmlNamespaces as $alias => $uri) {
  346. $xpath->registerNamespace($alias, $uri);
  347. }
  348. $ns = self::XMLNS_FINDING;
  349. $nsMs = self::XMLNS_MS;
  350. $expression = "//$nsMs:errorMessage[1]/$ns:error/$ns:severity[.='Error']";
  351. $severityNode = $xpath->query($expression)->item(0);
  352. if ($severityNode) {
  353. $errorNode = $severityNode->parentNode;
  354. // ebay message
  355. $messageNode = $xpath->query("//$ns:message[1]", $errorNode)->item(0);
  356. if ($messageNode) {
  357. $message = 'eBay error: ' . $messageNode->nodeValue;
  358. } else {
  359. $message = 'eBay error: unknown';
  360. }
  361. // ebay error id
  362. $errorIdNode = $xpath->query("//$ns:errorId[1]", $errorNode)->item(0);
  363. if ($errorIdNode) {
  364. $message .= ' (#' . $errorIdNode->nodeValue . ')';
  365. }
  366. }
  367. // throw exception when an error was detected
  368. if (strlen($message) > 0) {
  369. /**
  370. * @see Zend_Service_Ebay_Finding_Exception
  371. */
  372. require_once 'Zend/Service/Ebay/Finding/Exception.php';
  373. throw new Zend_Service_Ebay_Finding_Exception($message);
  374. }
  375. // add xpath to dom document
  376. // it allows service_ebay_finding classes use this
  377. $dom->ebayFindingXPath = $xpath;
  378. return $dom;
  379. }
  380. }