PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/downloader/lib/Mage/Connect/Command/Install.php

https://gitlab.com/blingbang2016/shop
PHP | 568 lines | 441 code | 46 blank | 81 comment | 110 complexity | eb7afec2d9b017c40e02561447180cac 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@magento.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.magento.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Connect
  23. * @copyright Copyright (c) 2006-2016 X.commerce, Inc. and affiliates (http://www.magento.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. final class Mage_Connect_Command_Install extends Mage_Connect_Command
  27. {
  28. /**
  29. * Install action callback
  30. *
  31. * @throws Exception
  32. * @param string $command
  33. * @param array $options
  34. * @param array $params
  35. * @param array $objects
  36. * @return array|null
  37. */
  38. public function doInstall($command, $options, $params, $objects = array())
  39. {
  40. $this->cleanupParams($params);
  41. $installFileMode = $command === 'install-file';
  42. /** @var $ftpObj Mage_Connect_Ftp */
  43. $ftpObj=null;
  44. $ftp = empty($options['ftp']) ? false : $options['ftp'];
  45. /** @var $packager Mage_Connect_Packager */
  46. $packager = $this->getPackager();
  47. /** @var $cache Mage_Connect_Singleconfig */
  48. /** @var $config Mage_Connect_Config */
  49. if ($ftp) {
  50. list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
  51. } else {
  52. $cache = $this->getSconfig();
  53. $config = $this->config();
  54. }
  55. try {
  56. $forceMode = isset($options['force']);
  57. $upgradeAllMode = $command == 'upgrade-all';
  58. $upgradeMode = $command == 'upgrade' || $command == 'upgrade-all';
  59. $noFilesInstall = isset($options['nofiles']);
  60. $withDepsMode = !isset($options['nodeps']);
  61. $ignoreModifiedMode = true || !isset($options['ignorelocalmodification']);
  62. $clearInstallMode = $command == 'install' && !$forceMode;
  63. $installAll = isset($options['install_all']);
  64. $channelAuth = isset($options['auth'])?$options['auth']:array();
  65. $rest = $this->rest();
  66. if (empty($config->magento_root)) {
  67. $config->magento_root=dirname(dirname($_SERVER['SCRIPT_FILENAME']));
  68. }
  69. chdir($config->magento_root);
  70. $dirCache = DIRECTORY_SEPARATOR . $config->downloader_path . DIRECTORY_SEPARATOR
  71. . Mage_Connect_Config::DEFAULT_CACHE_PATH;
  72. $dirTmp = DIRECTORY_SEPARATOR . Mage_Connect_Package_Reader::PATH_TO_TEMPORARY_DIRECTORY;
  73. $dirMedia = DIRECTORY_SEPARATOR . 'media';
  74. $isWritable = true;
  75. if ($ftp) {
  76. $cwd=$ftpObj->getcwd();
  77. $ftpObj->mkdirRecursive($cwd . $dirCache,0777);
  78. $ftpObj->chdir($cwd);
  79. $ftpObj->mkdirRecursive($cwd . $dirTmp,0777);
  80. $ftpObj->chdir($cwd);
  81. $ftpObj->mkdirRecursive($cwd . $dirMedia,0777);
  82. $ftpObj->chdir($cwd);
  83. $err = "Please check for sufficient ftp write file permissions.";
  84. } else {
  85. @mkdir($config->magento_root . $dirCache,0777,true);
  86. @mkdir($config->magento_root . $dirTmp,0777,true);
  87. @mkdir($config->magento_root . $dirMedia,0777,true);
  88. $isWritable = is_writable($config->magento_root)
  89. && is_writable($config->magento_root . DIRECTORY_SEPARATOR . $config->downloader_path)
  90. && is_writable($config->magento_root . $dirCache)
  91. && is_writable($config->magento_root . $dirTmp)
  92. && is_writable($config->magento_root . $dirMedia);
  93. $err = "Please check for sufficient write file permissions.";
  94. }
  95. $isWritable = $isWritable && is_writable($config->magento_root . $dirMedia)
  96. && is_writable($config->magento_root . $dirCache)
  97. && is_writable($config->magento_root . $dirTmp);
  98. if (!$isWritable) {
  99. $this->doError($command, $err);
  100. throw new Exception(
  101. 'Your Magento folder does not have sufficient write permissions, which downloader requires.'
  102. );
  103. }
  104. if (!empty($channelAuth)) {
  105. $rest->getLoader()->setCredentials($channelAuth['username'], $channelAuth['password']);
  106. }
  107. if ($installFileMode) {
  108. if (count($params) < 1) {
  109. throw new Exception("Argument should be: filename");
  110. }
  111. $filename = $params[0];
  112. if (!@file_exists($filename)) {
  113. throw new Exception("File '{$filename}' not found");
  114. }
  115. if (!@is_readable($filename)) {
  116. throw new Exception("File '{$filename}' is not readable");
  117. }
  118. $package = new Mage_Connect_Package($filename);
  119. $package->setConfig($config);
  120. $package->validate();
  121. $errors = $package->getErrors();
  122. if (count($errors)) {
  123. throw new Exception("Package file is invalid\n" . implode("\n", $errors));
  124. }
  125. $pChan = $package->getChannel();
  126. $pName = $package->getName();
  127. $pVer = $package->getVersion();
  128. if (!($cache->isChannelName($pChan) || $cache->isChannelAlias($pChan))) {
  129. throw new Exception("The '{$pChan}' channel is not installed. Please use the MAGE shell "
  130. . "script to install the '{$pChan}' channel.");
  131. }
  132. $conflicts = $cache->hasConflicts($pChan, $pName, $pVer);
  133. if (false !== $conflicts) {
  134. $conflicts = implode(", ",$conflicts);
  135. if ($forceMode) {
  136. $this->doError($command, "Package {$pChan}/{$pName} {$pVer} conflicts with: " . $conflicts);
  137. } else {
  138. throw new Exception("Package {$pChan}/{$pName} {$pVer} conflicts with: " . $conflicts);
  139. }
  140. }
  141. $conflicts = $package->checkPhpDependencies();
  142. if (true !== $conflicts) {
  143. $conflicts = implode(",",$conflicts);
  144. $err = "Package {$pChan}/{$pName} {$pVer} depends on PHP extensions: " . $conflicts;
  145. if ($forceMode) {
  146. $this->doError($command, $err);
  147. } else {
  148. throw new Exception($err);
  149. }
  150. }
  151. $conflicts = $package->checkPhpVersion();
  152. if (true !== $conflicts) {
  153. $err = "Package {$pChan}/{$pName} {$pVer}: " . $conflicts;
  154. if ($forceMode) {
  155. $this->doError($command, $err);
  156. } else {
  157. throw new Exception($err);
  158. }
  159. }
  160. if (!$noFilesInstall) {
  161. if ($ftp) {
  162. $packager->processInstallPackageFtp($package, $filename, $config, $ftpObj);
  163. } else {
  164. $packager->processInstallPackage($package, $filename, $config);
  165. }
  166. }
  167. $cache->addPackage($package);
  168. $installedDeps = array();
  169. $installedDepsAssoc = array();
  170. $installedDepsAssoc[] = array('channel'=>$pChan, 'name'=>$pName, 'version'=>$pVer);
  171. $installedDeps[] = array($pChan, $pName, $pVer);
  172. $title = isset($options['title']) ? $options['title'] : "Package installed: ";
  173. $out = array($command => array('data'=>$installedDeps, 'assoc'=>$installedDepsAssoc, 'title'=>$title));
  174. if ($ftp) {
  175. $packager->writeToRemoteCache($cache, $ftpObj);
  176. @unlink($config->getFilename());
  177. }
  178. $this->ui()->output($out);
  179. return $out[$command]['data'];
  180. }
  181. if (!$upgradeAllMode) {
  182. if (count($params) < 2) {
  183. throw new Exception("Argument should be: channelName packageName");
  184. }
  185. $channel = $params[0];
  186. $package = $params[1];
  187. $argVersionMax = isset($params[2]) ? $params[2]: false;
  188. $argVersionMin = isset($params[3]) ? $params[3]: false;
  189. $cache->checkChannel($channel, $config, $rest);
  190. $channelName = $cache->chanName($channel);
  191. $this->ui()->output("Checking dependencies of packages");
  192. $packagesToInstall = $packager->getDependenciesList($channelName, $package, $cache, $config,
  193. $argVersionMax, $argVersionMin, $withDepsMode, false, $rest
  194. );
  195. /*
  196. * process 'failed' results
  197. */
  198. if (count($packagesToInstall['failed'])) {
  199. $showError=!count($packagesToInstall['result']);
  200. foreach ($packagesToInstall['failed'] as $failed) {
  201. $msg="Package {$failed['channel']}/{$failed['name']} failed: " . $failed['reason'];
  202. if ($showError) {
  203. $this->doError($command, $msg);
  204. } else {
  205. $this->ui()->output($msg);
  206. }
  207. }
  208. }
  209. $packagesToInstall = $packagesToInstall['result'];
  210. } else {
  211. if (empty($params[0])) {
  212. $channels = $cache->getChannelNames();
  213. } else {
  214. $channel = $params[0];
  215. if (!$cache->isChannel($channel)) {
  216. throw new Exception("'{$channel}' is not existant channel name / valid uri");
  217. }
  218. $channels = $cache->chanName($channel);
  219. }
  220. $packagesToInstall = array();
  221. $neededToUpgrade = $packager->getUpgradesList($channels, $cache, $config, $rest);
  222. foreach ($neededToUpgrade as $chan=>$packages) {
  223. foreach ($packages as $name=>$data) {
  224. $versionTo = $data['to'];
  225. $tmp = $packager->getDependenciesList($chan, $name, $cache, $config, $versionTo, $versionTo,
  226. $withDepsMode, false, $rest
  227. );
  228. if (count($tmp['result'])) {
  229. $packagesToInstall = array_merge($packagesToInstall, $tmp['result']);
  230. }
  231. }
  232. }
  233. }
  234. /**
  235. * Make installation
  236. */
  237. $installedDeps = array();
  238. $installedDepsAssoc = array();
  239. foreach ($packagesToInstall as $package) {
  240. try {
  241. $pName = $package['name'];
  242. $pChan = $package['channel'];
  243. $pVer = $package['downloaded_version'];
  244. $pInstallState = $package['install_state'];
  245. $rest->setChannel($cache->chanUrl($pChan));
  246. /**
  247. * Skip existing packages
  248. */
  249. if ($upgradeMode && $cache->hasPackage($pChan, $pName, $pVer, $pVer)
  250. || ('already_installed' == $pInstallState && !$forceMode)
  251. ) {
  252. $this->ui()->output("Already installed: {$pChan}/{$pName} {$pVer}, skipping");
  253. continue;
  254. }
  255. if ('incompartible' == $pInstallState) {
  256. $this->ui()->output(
  257. "Package incompartible with installed Magento: {$pChan}/{$pName} {$pVer}, skipping"
  258. );
  259. continue;
  260. }
  261. $conflicts = $cache->hasConflicts($pChan, $pName, $pVer);
  262. if (false !== $conflicts) {
  263. $conflicts = implode(", ",$conflicts);
  264. if ($forceMode) {
  265. $this->doError($command, "Package {$pChan}/{$pName} {$pVer} conflicts with: " . $conflicts);
  266. } else {
  267. throw new Exception("Package {$pChan}/{$pName} {$pVer} conflicts with: " . $conflicts);
  268. }
  269. }
  270. /**
  271. * Modifications
  272. */
  273. if (($upgradeMode || ($pInstallState == 'upgrade')) && !$ignoreModifiedMode) {
  274. if ($ftp) {
  275. $modifications = $packager->getRemoteModifiedFiles($pChan, $pName, $cache, $config, $ftp);
  276. } else {
  277. $modifications = $packager->getLocalModifiedFiles($pChan, $pName, $cache, $config);
  278. }
  279. if (count($modifications) > 0) {
  280. $this->ui()->output('Changed locally: ');
  281. foreach ($modifications as $row) {
  282. if (!$ftp) {
  283. $this->ui()->output($config->magento_root . DS . $row);
  284. } else {
  285. $this->ui()->output($row);
  286. }
  287. }
  288. }
  289. }
  290. if ($ftp) {
  291. $cwd=$ftpObj->getcwd();
  292. $dir=$cwd . DIRECTORY_SEPARATOR .$config->downloader_path . DIRECTORY_SEPARATOR
  293. . Mage_Connect_Config::DEFAULT_CACHE_PATH . DIRECTORY_SEPARATOR . trim( $pChan, "\\/");
  294. $ftpObj->mkdirRecursive($dir,0777);
  295. $ftpObj->chdir($cwd);
  296. } else {
  297. $dir = $config->getChannelCacheDir($pChan);
  298. @mkdir($dir, 0777, true);
  299. }
  300. $dir = $config->getChannelCacheDir($pChan);
  301. $packageFileName = $pName . "-" . $pVer . ".tgz";
  302. $file = $dir . DIRECTORY_SEPARATOR . $packageFileName;
  303. if (!@file_exists($file)) {
  304. $this->ui()->output("Starting to download $packageFileName ...");
  305. $rest->downloadPackageFileOfRelease($pName, $pVer, $file);
  306. $this->ui()->output(sprintf("...done: %s bytes", number_format(filesize($file))));
  307. }
  308. /**
  309. * Remove old version package before install new
  310. */
  311. if ($cache->hasPackage($pChan, $pName)) {
  312. if ($ftp) {
  313. $packager->processUninstallPackageFtp($pChan, $pName, $cache, $ftpObj);
  314. } else {
  315. $packager->processUninstallPackage($pChan, $pName, $cache, $config);
  316. }
  317. $cache->deletePackage($pChan, $pName);
  318. }
  319. $package = new Mage_Connect_Package($file);
  320. if ($clearInstallMode && $pInstallState != 'upgrade' && !$installAll) {
  321. $contents = $package->getContents();
  322. $this->backup()->setFileTypes(array('csv', 'html'));
  323. $typesToBackup = $this->backup()->getFileTypes();
  324. $this->validator()->validateContents($contents, $config, $typesToBackup);
  325. $errors = $this->validator()->getErrors();
  326. if (count($errors)) {
  327. throw new Exception("Package '{$pName}' is invalid\n" . implode("\n", $errors));
  328. }
  329. $targetPath = rtrim($config->magento_root, "\\/");
  330. foreach ($contents as $filePath) {
  331. $this->backup()->addFile($filePath, $targetPath);
  332. }
  333. if ($this->backup()->getFilesCount() > 0) {
  334. $this->ui()->output('<br/>');
  335. $this->ui()->output('Backup of following files will be created :');
  336. $this->ui()->output('<br/>');
  337. $this->backup()->run();
  338. $this->ui()->output(implode('<br/>', $this->backup()->getAllFiles()));
  339. $this->ui()->output('<br/>');
  340. $this->ui()->output(
  341. $this->backup()->getFilesCount() . ' files was overwritten by installed extension.'
  342. );
  343. $this->ui()->output('<br/>');
  344. $this->backup()->unsetAllFiles();
  345. }
  346. }
  347. $conflicts = $package->checkPhpDependencies();
  348. if (true !== $conflicts) {
  349. $conflicts = implode(",",$conflicts);
  350. $err = "Package {$pChan}/{$pName} {$pVer} depends on PHP extensions: " . $conflicts;
  351. if ($forceMode) {
  352. $this->doError($command, $err);
  353. } else {
  354. throw new Exception($err);
  355. }
  356. }
  357. $conflicts = $package->checkPhpVersion();
  358. if (true !== $conflicts) {
  359. $err = "Package {$pChan}/{$pName} {$pVer}: " . $conflicts;
  360. if ($forceMode) {
  361. $this->doError($command, $err);
  362. } else {
  363. throw new Exception($err);
  364. }
  365. }
  366. if (!$noFilesInstall) {
  367. $this->ui()->output("Installing package {$pChan}/{$pName} {$pVer}");
  368. if ($ftp) {
  369. $packager->processInstallPackageFtp($package, $file, $config, $ftpObj);
  370. } else {
  371. $packager->processInstallPackage($package, $file, $config);
  372. }
  373. $this->ui()->output("Package {$pChan}/{$pName} {$pVer} installed successfully");
  374. }
  375. $cache->addPackage($package);
  376. $installedDepsAssoc[] = array('channel'=>$pChan, 'name'=>$pName, 'version'=>$pVer);
  377. $installedDeps[] = array($pChan, $pName, $pVer);
  378. } catch(Exception $e) {
  379. $this->doError($command, $e->getMessage());
  380. }
  381. }
  382. $title = isset($options['title']) ? $options['title'] : "Package installed: ";
  383. $out = array($command => array('data'=>$installedDeps, 'assoc'=>$installedDepsAssoc, 'title'=>$title));
  384. if ($ftp) {
  385. $packager->writeToRemoteCache($cache, $ftpObj);
  386. @unlink($config->getFilename());
  387. }
  388. $this->ui()->output($out);
  389. return $out[$command]['data'];
  390. } catch (Exception $e) {
  391. if ($ftp) {
  392. $packager->writeToRemoteCache($cache, $ftpObj);
  393. @unlink($config->getFilename());
  394. }
  395. return $this->doError($command, $e->getMessage());
  396. }
  397. }
  398. /**
  399. * Upgrade action callback
  400. *
  401. * @param string $command
  402. * @param array $options
  403. * @param array $params
  404. * @return array|null
  405. */
  406. public function doUpgrade($command, $options, $params)
  407. {
  408. $options['title'] = "Package upgraded: ";
  409. return $this->doInstall($command, $options, $params);
  410. }
  411. /**
  412. * Updgrade action callback
  413. *
  414. * @param string $command
  415. * @param array $options
  416. * @param array $params
  417. * @return array|null
  418. */
  419. public function doUpgradeAll($command, $options, $params)
  420. {
  421. $options['title'] = "Package upgraded: ";
  422. return $this->doInstall($command, $options, $params);
  423. }
  424. /**
  425. * Uninstall package callback
  426. *
  427. * @param string $command
  428. * @param array $options
  429. * @param array $params
  430. * @return array|null
  431. */
  432. public function doUninstall($command, $options, $params)
  433. {
  434. $this->cleanupParams($params);
  435. try {
  436. if (count($params) != 2) {
  437. throw new Exception("Argument count should be = 2");
  438. }
  439. $channel = $params[0];
  440. $package = $params[1];
  441. /** @var $packager Mage_Connect_Packager */
  442. $packager = $this->getPackager();
  443. $withDepsMode = !isset($options['nodeps'])? false : (boolean)$options['nodeps'];
  444. $forceMode = isset($options['force']);
  445. $ftp = empty($options['ftp']) ? false : $options['ftp'];
  446. /** @var $cache Mage_Connect_Singleconfig */
  447. /** @var $config Mage_Connect_Config */
  448. /** @var $ftpObj Mage_Connect_Ftp */
  449. if ($ftp) {
  450. list($cache, $config, $ftpObj) = $packager->getRemoteConf($ftp);
  451. } else {
  452. $cache = $this->getSconfig();
  453. $config = $this->config();
  454. }
  455. $channel = $cache->chanName($channel);
  456. if (!$cache->hasPackage($channel, $package)) {
  457. throw new Exception("Package is not installed");
  458. }
  459. $deletedPackages = array();
  460. $list = $packager->getUninstallList($channel, $package, $cache, $config, $withDepsMode);
  461. foreach ($list['list'] as $packageData) {
  462. try {
  463. $reqd = $cache->requiredByOtherPackages(
  464. $packageData['channel'],
  465. $packageData['name'],
  466. $list['list']
  467. );
  468. if (count($reqd)) {
  469. $errMessage = "{$packageData['channel']}/{$packageData['name']} "
  470. . "{$packageData['version']} is required by: ";
  471. $t = array();
  472. foreach ($reqd as $r) {
  473. $t[] = $r['channel'] . "/" . $r['name'] . " " . $r['version'];
  474. }
  475. $errMessage .= implode(", ", $t);
  476. if ($forceMode) {
  477. $this->ui()->output("Warning: " . $errMessage);
  478. } else {
  479. throw new Exception($errMessage);
  480. }
  481. }
  482. } catch(Exception $e) {
  483. if ($forceMode) {
  484. $this->doError($command, $e->getMessage());
  485. } else {
  486. throw new Exception($e->getMessage());
  487. }
  488. }
  489. }
  490. foreach ($list['list'] as $packageData) {
  491. try {
  492. list($chan, $pack) = array($packageData['channel'], $packageData['name']);
  493. $packageName = $packageData['channel'] . "/" . $packageData['name'];
  494. $this->ui()->output("Starting to uninstall $packageName ");
  495. if ($ftp) {
  496. $packager->processUninstallPackageFtp($chan, $pack, $cache, $ftpObj);
  497. } else {
  498. $packager->processUninstallPackage($chan, $pack, $cache, $config);
  499. }
  500. $cache->deletePackage($chan, $pack);
  501. $deletedPackages[] = array($chan, $pack);
  502. $this->ui()->output("Package {$packageName} uninstalled");
  503. } catch(Exception $e) {
  504. if ($forceMode) {
  505. $this->doError($command, $e->getMessage());
  506. } else {
  507. throw new Exception($e->getMessage());
  508. }
  509. }
  510. }
  511. if ($ftp) {
  512. $packager->writeToRemoteCache($cache, $ftpObj);
  513. @unlink($config->getFilename());
  514. }
  515. $out = array($command=>array('data'=>$deletedPackages, 'title'=>'Package deleted: '));
  516. $this->ui()->output($out);
  517. return $out[$command]['data'];
  518. } catch (Exception $e) {
  519. return $this->doError($command, $e->getMessage());
  520. }
  521. }
  522. }