PageRenderTime 33ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/downloader/lib/Mage/Connect/Rest.php

https://bitbucket.org/acidel/buykoala
PHP | 366 lines | 208 code | 41 blank | 117 comment | 34 complexity | 55c7edc14ba36f3cae047d152fd639a1 MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  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@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Connect
  23. * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Class to work with remote REST interface
  28. *
  29. * @category Mage
  30. * @package Mage_Connect
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Connect_Rest
  34. {
  35. const CHANNELS_XML = "channels.xml";
  36. const CHANNEL_XML = "channel.xml";
  37. const PACKAGES_XML = "packages.xml";
  38. const RELEASES_XML = "releases.xml";
  39. const PACKAGE_XML = "package.xml";
  40. const EXT = "tgz";
  41. /**
  42. * HTTP Loader
  43. * @var Mage_HTTP_IClient
  44. */
  45. protected $_loader = null;
  46. /**
  47. * XML parser
  48. * @var Mage_Xml_Parser
  49. */
  50. protected $_parser = null;
  51. /**
  52. * Channel URI
  53. * @var string
  54. */
  55. protected $_chanUri = '';
  56. /**
  57. * Protocol HTTP or FTP
  58. *
  59. * @var string http or ftp
  60. */
  61. protected $_protocol = '';
  62. /**
  63. * Constructor
  64. */
  65. public function __construct($protocol="http")
  66. {
  67. switch ($protocol) {
  68. case 'ftp':
  69. $this->_protocol = 'ftp';
  70. break;
  71. case 'http':
  72. $this->_protocol = 'http';
  73. break;
  74. default:
  75. $this->_protocol = 'http';
  76. break;
  77. }
  78. }
  79. /**
  80. * Set channel info
  81. *
  82. * @param string $uri
  83. * @param sting $name
  84. */
  85. public function setChannel($uri)
  86. {
  87. $this->_chanUri = $uri;
  88. }
  89. /**
  90. * Get HTTP loader
  91. * @return Mage_Connect_Loader
  92. */
  93. public function getLoader()
  94. {
  95. if(is_null($this->_loader)) {
  96. $this->_loader = Mage_Connect_Loader::getInstance($this->_protocol);
  97. }
  98. return $this->_loader;
  99. }
  100. /**
  101. * Get parser
  102. *
  103. * @return Mage_Xml_Parser
  104. */
  105. protected function getParser()
  106. {
  107. if(is_null($this->_parser)) {
  108. $this->_parser = new Mage_Xml_Parser();
  109. }
  110. return $this->_parser;
  111. }
  112. /**
  113. * Load URI response
  114. * @param string $uri
  115. */
  116. protected function loadChannelUri($uriSuffix)
  117. {
  118. $url = $this->_chanUri."/".$uriSuffix;
  119. //print $url."\n";
  120. $this->getLoader()->get($url);
  121. $statusCode = $this->getLoader()->getStatus();
  122. if($statusCode != 200) {
  123. return false;
  124. }
  125. return $this->getLoader()->getBody();
  126. }
  127. /**
  128. * Get channels list of URI
  129. * @return array
  130. */
  131. public function getChannelInfo()
  132. {
  133. $out = $this->loadChannelUri(self::CHANNEL_XML);
  134. $statusCode = $this->getLoader()->getStatus();
  135. if($statusCode != 200) {
  136. throw new Exception("Invalid server response for {$this->_chanUri}");
  137. }
  138. $parser = $this->getParser();
  139. $out = $parser->loadXML($out)->xmlToArray();
  140. // TODO: add channel validator
  141. $vo = new Mage_Connect_Channel_VO();
  142. $vo->fromArray($out['channel']);
  143. if(!$vo->validate()) {
  144. throw new Exception("Invalid channel.xml file");
  145. }
  146. return $vo;
  147. }
  148. /**
  149. * Get packages list of channel
  150. * @return array
  151. */
  152. public function getPackages()
  153. {
  154. $out = $this->loadChannelUri(self::PACKAGES_XML);
  155. $statusCode = $this->getLoader()->getStatus();
  156. if($statusCode != 200) {
  157. return false;
  158. }
  159. $parser = $this->getParser();
  160. $out = $parser->loadXML($out)->xmlToArray();
  161. if(!isset($out['data']['p'])) {
  162. return array();
  163. }
  164. if(isset($out['data']['p'][0])) {
  165. return $out['data']['p'];
  166. }
  167. if(is_array($out['data']['p'])) {
  168. return array($out['data']['p']);
  169. }
  170. return array();
  171. }
  172. public function getPackagesHashed()
  173. {
  174. $out = $this->loadChannelUri(self::PACKAGES_XML);
  175. $statusCode = $this->getLoader()->getStatus();
  176. if($statusCode != 200) {
  177. return false;
  178. }
  179. $parser = $this->getParser();
  180. $out = $parser->loadXML($out)->xmlToArray();
  181. $return = array();
  182. if(!isset($out['data']['p'])) {
  183. return $return;
  184. }
  185. if(isset($out['data']['p'][0])) {
  186. $return = $out['data']['p'];
  187. }elseif(is_array($out['data']['p'])) {
  188. $return = array($out['data']['p']);
  189. }
  190. $c = count($return);
  191. if($c) {
  192. $output = array();
  193. for($i=0; $i<$c; $i++) {
  194. $element = $return[$i];
  195. $output[$element['n']] = $element['r'];
  196. }
  197. $return = $output;
  198. }
  199. $out = array();
  200. foreach($return as $name=>$package) {
  201. $stabilities = array_map(array($this, 'shortStateToLong'), array_keys($package));
  202. $versions = array_map('trim', array_values($package));
  203. $package = array_combine($versions, $stabilities);
  204. ksort($package);
  205. $out[$name] = $package;
  206. }
  207. return $out;
  208. }
  209. /**
  210. * Stub
  211. * @param $n
  212. * @return unknown_type
  213. */
  214. public function escapePackageName($n)
  215. {
  216. return $n;
  217. }
  218. /**
  219. * Get releases list of package on current channel
  220. * @param string $package package name
  221. */
  222. public function getReleases($package)
  223. {
  224. $out = $this->loadChannelUri($this->escapePackageName($package)."/".self::RELEASES_XML);
  225. $statusCode = $this->getLoader()->getStatus();
  226. if($statusCode != 200) {
  227. return false;
  228. }
  229. $parser = $this->getParser();
  230. $out = $parser->loadXML($out)->xmlToArray();
  231. if(!isset($out['releases']['r'])) {
  232. return array();
  233. }
  234. $src = $out['releases']['r'];
  235. if(!array_key_exists(0, $src)) {
  236. return array($src);
  237. }
  238. $this->sortReleases($src);
  239. return $src;
  240. }
  241. /**
  242. * Sort releases
  243. * @param array $releases
  244. * @return void
  245. */
  246. public function sortReleases(array &$releases)
  247. {
  248. usort($releases, array($this, 'sortReleasesCallback'));
  249. $releases = array_reverse($releases);
  250. }
  251. /**
  252. * Sort releases callback
  253. * @param string $a
  254. * @param srting $b
  255. * @return int
  256. */
  257. protected function sortReleasesCallback($a, $b)
  258. {
  259. return version_compare($a['v'],$b['v']);
  260. }
  261. /**
  262. * Get package info (package.xml)
  263. *
  264. * @param $package
  265. * @return unknown_type
  266. */
  267. public function getPackageInfo($package)
  268. {
  269. $out = $this->loadChannelUri($this->escapePackageName($package)."/".self::PACKAGE_XML);
  270. if(false === $out) {
  271. return false;
  272. }
  273. return new Mage_Connect_Package($out);
  274. }
  275. /**
  276. *
  277. * @param $package
  278. * @param $version
  279. * @return Mage_Connect_Package
  280. */
  281. public function getPackageReleaseInfo($package, $version)
  282. {
  283. $out = $this->loadChannelUri($this->escapePackageName($package)."/".$version."/".self::PACKAGE_XML);
  284. if(false === $out) {
  285. return false;
  286. }
  287. return new Mage_Connect_Package($out);
  288. }
  289. /**
  290. * Get package archive file of release
  291. * @param string $package package name
  292. * @param string $version version
  293. */
  294. public function downloadPackageFileOfRelease($package, $version, $targetFile)
  295. {
  296. $package = $this->escapePackageName($package);
  297. $version = $this->escapePackageName($version);
  298. if(file_exists($targetFile)) {
  299. $chksum = $this->loadChannelUri($package."/".$version."/checksum");
  300. $statusCode = $this->getLoader()->getStatus();
  301. if($statusCode == 200) {
  302. if(md5_file($targetFile) == $chksum) {
  303. return true;
  304. }
  305. }
  306. }
  307. $out = $this->loadChannelUri($package."/".$version."/".$package."-".$version.".".self::EXT);
  308. $statusCode = $this->getLoader()->getStatus();
  309. if($statusCode != 200) {
  310. throw new Exception("Package not found: {$package} {$version}");
  311. }
  312. $dir = dirname($targetFile);
  313. @mkdir($dir, 0777, true);
  314. $result = @file_put_contents($targetFile, $out);
  315. if(false === $result) {
  316. throw new Exception("Cannot write to file {$targetFile}");
  317. }
  318. return true;
  319. }
  320. protected $states = array('b'=>'beta', 'd'=>'dev', 's'=>'stable', 'a'=>'alpha');
  321. public function shortStateToLong($s)
  322. {
  323. return isset($this->states[$s]) ? $this->states[$s] : 'dev';
  324. }
  325. }