PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/downloader/Maged/Model/Connect.php

https://bitbucket.org/andrewjleavitt/magestudy
PHP | 477 lines | 336 code | 48 blank | 93 comment | 62 complexity | d74b1c342eb129c73d9654f29c3f2fbd MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
  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) 2010 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. include_once "Maged/Connect.php";
  27. /**
  28. * Class for initialize Mage_Connect lib
  29. *
  30. * @category Mage
  31. * @package Mage_Connect
  32. * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
  33. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  34. */
  35. class Maged_Model_Connect extends Maged_Model
  36. {
  37. /**
  38. * Constructor
  39. */
  40. protected function _construct()
  41. {
  42. parent::_construct();
  43. }
  44. /**
  45. * Retrive object of Maged_Connect
  46. *
  47. * @return Maged_Connect
  48. */
  49. public function connect()
  50. {
  51. return Maged_Connect::getInstance();
  52. }
  53. /**
  54. * Install All Magento
  55. *
  56. * @param boolean $force
  57. */
  58. public function installAll($force=false, $chanName='')
  59. {
  60. $options = array('install_all'=>true);
  61. if ($force) {
  62. $this->connect()->cleanSconfig();
  63. $options['force'] = 1;
  64. }
  65. $packages = array(
  66. 'Mage_All_Latest',
  67. );
  68. $connectConfig = $this->connect()->getConfig();
  69. $ftp = $connectConfig->remote_config;
  70. if (!empty($ftp)) {
  71. $options['ftp'] = $ftp;
  72. }
  73. $params = array();
  74. $uri = $this->controller()->channelConfig()->getRootChannelUri();
  75. $this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
  76. $connectConfig->root_channel = $chanName;
  77. foreach ($packages as $package) {
  78. $params[] = $uri;
  79. $params[] = $package;
  80. }
  81. $this->connect()->runHtmlConsole(array('command'=>'install', 'options'=>$options, 'params'=>$params));
  82. }
  83. /**
  84. * Prepare to install package
  85. *
  86. * @param string $id
  87. * @return array
  88. */
  89. public function prepareToInstall($id)
  90. {
  91. if (!preg_match('#^([^ ]+)\/([^-]+)(-[^-]+)?$#', $id, $match)) {
  92. echo('Invalid package identifier provided: '.$id);
  93. exit;
  94. }
  95. $channel = $match[1];
  96. $package = $match[2];
  97. $version = (!empty($match[3]) ? trim($match[3],'/\-') : '');
  98. $connect = $this->connect();
  99. $sconfig = $connect->getSingleConfig();
  100. $options = array();
  101. $params = array($channel, $package, $version);
  102. $this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
  103. $connect->run('package-prepare', $options, $params);
  104. $output = $connect->getOutput();
  105. $errors = $connect->getFrontend()->getErrors();
  106. $package_error = array();
  107. foreach ($errors as $error){
  108. if (isset($error[1])){
  109. $package_error[] = $error[1];
  110. }
  111. }
  112. $packages = array();
  113. if (is_array($output) && isset($output['package-prepare'])){
  114. $packages = array_merge($output['package-prepare'], array('errors'=>array('error'=>$package_error)));
  115. } elseif (is_array($output) && !empty($package_error)) {
  116. $packages = array('errors'=>array('error'=>$package_error));
  117. }
  118. return $packages;
  119. }
  120. /**
  121. * Retrieve all installed packages
  122. *
  123. * @return array
  124. */
  125. public function getAllInstalledPackages()
  126. {
  127. $connect = $this->connect();
  128. $sconfig = $connect->getSingleConfig(true);
  129. $connect->run('list-installed');
  130. $output = $connect->getOutput();
  131. $packages = array();
  132. if (is_array($output) && isset($output['list-installed']['data'])){
  133. $packages = $output['list-installed']['data'];
  134. } else {
  135. }
  136. foreach ($packages as $channel=>$package) {
  137. foreach ($package as $name=>$data) {
  138. $summary = $sconfig->getPackageObject($channel, $name)->getSummary();
  139. $addition = array('summary'=>$summary, 'upgrade_versions'=>array(), 'upgrade_latest'=>'');
  140. $packages[$channel][$name] = array_merge($data, $addition);
  141. }
  142. }
  143. if (!empty($_GET['updates'])) {
  144. $options = array();
  145. $this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
  146. $result = $connect->run('list-upgrades', $options);
  147. $output = $connect->getOutput();
  148. if (is_array($output)) {
  149. $channelData = $output;
  150. if (!empty($channelData['list-upgrades']['data']) && is_array($channelData['list-upgrades']['data'])) {
  151. foreach ($channelData['list-upgrades']['data'] as $channel=>$package) {
  152. foreach ($package as $name=>$data) {
  153. if (!isset($packages[$channel][$name])) {
  154. continue;
  155. }
  156. $packages[$channel][$name]['upgrade_latest'] = $data['to'].' ('.$data['from'].')';
  157. }
  158. }
  159. }
  160. }
  161. }
  162. $states = array('snapshot'=>0, 'devel'=>1, 'alpha'=>2, 'beta'=>3, 'stable'=>4);
  163. $preferredState = $states[$this->getPreferredState()];
  164. foreach ($packages as $channel=>&$package) {
  165. foreach ($package as $name=>&$data) {
  166. $actions = array();
  167. $systemPkg = $name==='Mage_Downloader';
  168. if (!empty($data['upgrade_latest'])) {
  169. $status = 'upgrade-available';
  170. $releases = array();
  171. $connect->run('info', array(), array($channel, $name));
  172. $output = $connect->getOutput();
  173. if (!empty($output['info']['releases'])) {
  174. foreach ($output['info']['releases'] as $release) {
  175. $stability = $packages[$channel][$name]['stability'];
  176. if ($states[$release['s']] < min($preferredState, $states[$stability])) {
  177. continue;
  178. }
  179. if (version_compare($release['v'], $packages[$channel][$name]['version']) < 1) {
  180. continue;
  181. }
  182. $releases[$release['v']] = $release['v'].' ('.$release['s'].')';
  183. }
  184. }
  185. if ($releases) {
  186. uksort($releases, 'version_compare');
  187. foreach ($releases as $version => $release) {
  188. $actions['upgrade|'.$version] = 'Upgrade to '.$release;
  189. }
  190. } else {
  191. $a = explode(' ', $data['upgrade_latest'], 2);
  192. $actions['upgrade|'.$a[0]] = 'Upgrade';
  193. }
  194. if (!$systemPkg) {
  195. $actions['uninstall'] = 'Uninstall';
  196. }
  197. } else {
  198. $status = 'installed';
  199. $actions['reinstall'] = 'Reinstall';
  200. if (!$systemPkg) {
  201. $actions['uninstall'] = 'Uninstall';
  202. }
  203. }
  204. $packages[$channel][$name]['actions'] = $actions;
  205. $packages[$channel][$name]['status'] = $status;
  206. }
  207. }
  208. return $packages;
  209. }
  210. /**
  211. * Run packages action
  212. *
  213. * @param mixed $packages
  214. */
  215. public function applyPackagesActions($packages, $ignoreLocalModification='')
  216. {
  217. $actions = array();
  218. foreach ($packages as $package=>$action) {
  219. if ($action) {
  220. $a = explode('|', $package);
  221. $b = explode('|', $action);
  222. $package = $a[1];
  223. $channel = $a[0];
  224. $version = '';
  225. if ($b[0]=='upgrade') {
  226. $version = $b[1];
  227. }
  228. $actions[$b[0]][] = array($channel, $package, $version, $version);
  229. }
  230. }
  231. if (empty($actions)) {
  232. $this->connect()->runHtmlConsole('No actions selected');
  233. exit;
  234. }
  235. $this->controller()->startInstall();
  236. $options = array();
  237. if (!empty($ignoreLocalModification)) {
  238. $options = array('ignorelocalmodification'=>1);
  239. }
  240. if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
  241. $options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
  242. }
  243. $this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
  244. foreach ($actions as $action=>$packages) {
  245. foreach ($packages as $package) {
  246. switch ($action) {
  247. case 'install': case 'uninstall': case 'upgrade':
  248. $this->connect()->runHtmlConsole(array(
  249. 'command'=>$action,
  250. 'options'=>$options,
  251. 'params'=>$package
  252. ));
  253. break;
  254. case 'reinstall':
  255. $package_info = $this->connect()->getSingleConfig()->getPackage($package[0], $package[1]);
  256. if (isset($package_info['version'])) {
  257. $package[2] = $package_info['version'];
  258. $package[3] = $package_info['version'];
  259. }
  260. $this->connect()->runHtmlConsole(array(
  261. 'command'=>'install',
  262. 'options'=>array_merge($options, array('force'=>1, 'nodeps'=>1)),
  263. 'params'=>$package
  264. ));
  265. break;
  266. }
  267. }
  268. }
  269. $this->controller()->endInstall();
  270. }
  271. public function installUploadedPackage($file)
  272. {
  273. $this->controller()->startInstall();
  274. $options = array();
  275. if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
  276. $options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
  277. }
  278. $this->connect()->runHtmlConsole(array(
  279. 'command'=>'install-file',
  280. 'options'=>$options,
  281. 'params'=>array($file),
  282. ));
  283. $this->controller()->endInstall();
  284. }
  285. /**
  286. * Install package by id
  287. *
  288. * @param string $id
  289. * @param boolean $force
  290. */
  291. public function installPackage($id, $force=false)
  292. {
  293. $match = array();
  294. //if (!preg_match('#^([^ ]+) ([^-]+)(-[^-]+)?$#', $id, $match)) {// there is bug? space not used as separator "/" must be there. Version number part (-[^-]+) may be optional?
  295. //if (!preg_match('#^([^\/]+)\/([^-]+)?$#', $id, $match)&&!preg_match('#^([^ ]+)\/([^-]+)(-[^-]+)?$#', $id, $match)&&!preg_match('#^([^ ]+) ([^-]+)(-[^-]+)?$#', $id, $match)) {
  296. if (!preg_match('#^([^ ]+)\/([^-]+)(-[^-]+)?$#', $id, $match)) {
  297. $this->connect()->runHtmlConsole('Invalid package identifier provided: '.$id);
  298. exit;
  299. }
  300. $channel = $match[1];
  301. $package = $match[2];//.(!empty($match[3]) ? $match[3] : '');
  302. $version = (!empty($match[3]) ? trim($match[3],'/\-') : '');
  303. $this->controller()->startInstall();
  304. $options = array();
  305. if ($force) {
  306. $options['force'] = 1;
  307. }
  308. if(!$this->controller()->isWritable()||strlen($this->connect()->getConfig()->__get('remote_config'))>0){
  309. $options['ftp'] = $this->connect()->getConfig()->__get('remote_config');
  310. }
  311. $this->controller()->channelConfig()->setCommandOptions($this->controller()->session(), $options);
  312. $this->connect()->runHtmlConsole(array(
  313. 'command'=>'install',
  314. 'options'=>$options,
  315. 'params'=>array(0=>$channel, 1=>$package, 2=>$version),
  316. ));
  317. $this->controller()->endInstall();
  318. }
  319. /**
  320. * Retrieve stability choosen client
  321. *
  322. * @return string alpha, beta, ...
  323. */
  324. public function getPreferredState()
  325. {
  326. if (is_null($this->get('preferred_state'))) {
  327. $connectConfig = $this->connect()->getConfig();
  328. $this->set('preferred_state', $connectConfig->__get('preferred_state'));
  329. }
  330. return $this->get('preferred_state');
  331. }
  332. /**
  333. * Retrieve protocol choosen client
  334. *
  335. * @return string http, ftp
  336. */
  337. public function getProtocol()
  338. {
  339. if (is_null($this->get('protocol'))) {
  340. $connectConfig = $this->connect()->getConfig();
  341. $this->set('protocol', $connectConfig->__get('protocol'));
  342. }
  343. return $this->get('protocol');
  344. }
  345. /**
  346. * Validate settings post data.
  347. *
  348. * @param array $p
  349. */
  350. public function validateConfigPost($p)
  351. {
  352. $errors = array();
  353. $configTestFile = 'connect.cfgt';
  354. $configObj = $this->connect()->getConfig();
  355. if ('ftp' == $p['deployment_type'] || '1' == $p['inst_protocol']) {
  356. /*check ftp*/
  357. $confFile = $configObj->downloader_path.DIRECTORY_SEPARATOR.$configTestFile;
  358. try {
  359. $ftpObj = new Mage_Connect_Ftp();
  360. $ftpObj->connect($p['ftp']);
  361. $tempFile = tempnam(sys_get_temp_dir(),'config');
  362. $serial = md5('config test file');
  363. $f = @fopen($tempFile, "w+");
  364. @fwrite($f, $serial);
  365. @fclose($f);
  366. $ret=$ftpObj->upload($confFile, $tempFile);
  367. //read file
  368. if (!$errors && is_file($configTestFile)) {
  369. $size = filesize($configTestFile);
  370. if(!$size) {
  371. $errors[]='Unable to read saved settings. Please check Installation Path of FTP Connection.';
  372. }
  373. if (!$errors) {
  374. $f = @fopen($configTestFile, "r");
  375. @fseek($f, 0, SEEK_SET);
  376. $contents = @fread($f, strlen($serial));
  377. if ($serial != $contents) {
  378. $errors[]='Wrong Installation Path of FTP Connection.';
  379. }
  380. fclose($f);
  381. }
  382. } else {
  383. $errors[] = 'Unable to read saved settings. Please check Installation Path of FTP Connection.';
  384. }
  385. $ftpObj->delete($confFile);
  386. $ftpObj->close();
  387. } catch (Exception $e) {
  388. $errors[] = 'Deployment FTP Error. ' . $e->getMessage();
  389. }
  390. } else {
  391. $p['ftp'] = '';
  392. }
  393. if ('1' == $p['use_custom_permissions_mode']) {
  394. /*check permissions*/
  395. if (octdec(intval($p['mkdir_mode'])) < 73 || octdec(intval($p['mkdir_mode'])) > 511) {
  396. $errors[]='Folders permissions not valid. ';
  397. }
  398. if (octdec(intval($p['chmod_file_mode'])) < 73 || octdec(intval($p['chmod_file_mode'])) > 511) {
  399. $errors[]='Files permissions not valid. ';
  400. }
  401. }
  402. //$this->controller()->session()->addMessage('success', 'Settings has been successfully saved');
  403. return $errors;
  404. }
  405. /**
  406. * Save settings.
  407. *
  408. * @param array $p
  409. */
  410. public function saveConfigPost($p)
  411. {
  412. $configObj = $this->connect()->getConfig();
  413. if ('ftp' == $p['deployment_type'] || '1' == $p['inst_protocol']){
  414. $this->set('ftp',$p['ftp']);
  415. } else {
  416. $p['ftp'] = '';
  417. }
  418. $configObj->remote_config = $p['ftp'];
  419. $configObj->preferred_state = $p['preferred_state'];
  420. $configObj->protocol = $p['protocol'];
  421. $configObj->use_custom_permissions_mode = $p['use_custom_permissions_mode'];
  422. if ('1' == $p['use_custom_permissions_mode']) {
  423. $configObj->global_dir_mode = octdec(intval($p['mkdir_mode']));
  424. $configObj->global_file_mode = octdec(intval($p['chmod_file_mode']));
  425. }
  426. $this->controller()->session()->addMessage('success', 'Settings has been successfully saved');
  427. return $this;
  428. }
  429. }