DownloadManager.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Downloader;
  12. use Composer\Package\PackageInterface;
  13. use Composer\Downloader\DownloaderInterface;
  14. /**
  15. * Downloaders manager.
  16. *
  17. * @author Konstantin Kudryashov <ever.zet@gmail.com>
  18. */
  19. class DownloadManager
  20. {
  21. private $preferSource = false;
  22. private $downloaders = array();
  23. /**
  24. * Initializes download manager.
  25. *
  26. * @param Boolean $preferSource prefer downloading from source
  27. */
  28. public function __construct($preferSource = false)
  29. {
  30. $this->preferSource = $preferSource;
  31. }
  32. /**
  33. * Makes downloader prefer source installation over the dist.
  34. *
  35. * @param Boolean $preferSource prefer downloading from source
  36. */
  37. public function setPreferSource($preferSource)
  38. {
  39. $this->preferSource = $preferSource;
  40. }
  41. /**
  42. * Sets installer downloader for a specific installation type.
  43. *
  44. * @param string $type installation type
  45. * @param DownloaderInterface $downloader downloader instance
  46. */
  47. public function setDownloader($type, DownloaderInterface $downloader)
  48. {
  49. $this->downloaders[$type] = $downloader;
  50. }
  51. /**
  52. * Returns downloader for a specific installation type.
  53. *
  54. * @param string $type installation type
  55. *
  56. * @return DownloaderInterface
  57. *
  58. * @throws UnexpectedValueException if downloader for provided type is not registeterd
  59. */
  60. public function getDownloader($type)
  61. {
  62. if (!isset($this->downloaders[$type])) {
  63. throw new \InvalidArgumentException('Unknown downloader type: '.$type);
  64. }
  65. return $this->downloaders[$type];
  66. }
  67. /**
  68. * Returns downloader for already installed package.
  69. *
  70. * @param PackageInterface $package package instance
  71. *
  72. * @return DownloaderInterface
  73. *
  74. * @throws InvalidArgumentException if package has no installation source specified
  75. * @throws LogicException if specific downloader used to load package with
  76. * wrong type
  77. */
  78. public function getDownloaderForInstalledPackage(PackageInterface $package)
  79. {
  80. $installationSource = $package->getInstallationSource();
  81. if ('dist' === $installationSource) {
  82. $downloader = $this->getDownloader($package->getDistType());
  83. } elseif ('source' === $installationSource) {
  84. $downloader = $this->getDownloader($package->getSourceType());
  85. } else {
  86. throw new \InvalidArgumentException(
  87. 'Package '.$package.' seems not been installed properly'
  88. );
  89. }
  90. if ($installationSource !== $downloader->getInstallationSource()) {
  91. throw new \LogicException(sprintf(
  92. 'Downloader "%s" is a %s type downloader and can not be used to download %s',
  93. get_class($downloader), $downloader->getInstallationSource(), $installationSource
  94. ));
  95. }
  96. return $downloader;
  97. }
  98. /**
  99. * Downloads package into target dir.
  100. *
  101. * @param PackageInterface $package package instance
  102. * @param string $targetDir target dir
  103. * @param Boolean $preferSource prefer installation from source
  104. *
  105. * @throws InvalidArgumentException if package have no urls to download from
  106. */
  107. public function download(PackageInterface $package, $targetDir, $preferSource = null)
  108. {
  109. $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
  110. $sourceType = $package->getSourceType();
  111. $distType = $package->getDistType();
  112. if (!($preferSource && $sourceType) && $distType) {
  113. $package->setInstallationSource('dist');
  114. } elseif ($sourceType) {
  115. $package->setInstallationSource('source');
  116. } else {
  117. throw new \InvalidArgumentException(
  118. 'Package '.$package.' should have source or dist specified'
  119. );
  120. }
  121. $fs = new Util\Filesystem();
  122. $fs->ensureDirectoryExists($targetDir);
  123. $downloader = $this->getDownloaderForInstalledPackage($package);
  124. $downloader->download($package, $targetDir);
  125. }
  126. /**
  127. * Updates package from initial to target version.
  128. *
  129. * @param PackageInterface $initial initial package version
  130. * @param PackageInterface $target target package version
  131. * @param string $targetDir target dir
  132. *
  133. * @throws InvalidArgumentException if initial package is not installed
  134. */
  135. public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
  136. {
  137. $downloader = $this->getDownloaderForInstalledPackage($initial);
  138. $installationSource = $initial->getInstallationSource();
  139. if ('dist' === $installationSource) {
  140. $initialType = $initial->getDistType();
  141. $targetType = $target->getDistType();
  142. } else {
  143. $initialType = $initial->getSourceType();
  144. $targetType = $target->getSourceType();
  145. }
  146. if ($initialType === $targetType) {
  147. $target->setInstallationSource($installationSource);
  148. $downloader->update($initial, $target, $targetDir);
  149. } else {
  150. $downloader->remove($initial, $targetDir);
  151. $this->download($target, $targetDir, 'source' === $installationSource);
  152. }
  153. }
  154. /**
  155. * Removes package from target dir.
  156. *
  157. * @param PackageInterface $package package instance
  158. * @param string $targetDir target dir
  159. */
  160. public function remove(PackageInterface $package, $targetDir)
  161. {
  162. $downloader = $this->getDownloaderForInstalledPackage($package);
  163. $downloader->remove($package, $targetDir);
  164. }
  165. }