PearRepository.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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\Repository;
  12. use Composer\Package\Loader\ArrayLoader;
  13. /**
  14. * @author Benjamin Eberlei <kontakt@beberlei.de>
  15. * @author Jordi Boggiano <j.boggiano@seld.be>
  16. */
  17. class PearRepository extends ArrayRepository
  18. {
  19. protected $url;
  20. public function __construct(array $config)
  21. {
  22. if (!preg_match('{^https?://}', $config['url'])) {
  23. $config['url'] = 'http://'.$config['url'];
  24. }
  25. if (!filter_var($config['url'], FILTER_VALIDATE_URL)) {
  26. throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$config['url']);
  27. }
  28. $this->url = $config['url'];
  29. }
  30. protected function initialize()
  31. {
  32. parent::initialize();
  33. set_error_handler(function($severity, $message, $file, $line) {
  34. throw new \ErrorException($message, $severity, $severity, $file, $line);
  35. });
  36. $this->fetchFromServer();
  37. restore_error_handler();
  38. }
  39. protected function fetchFromServer()
  40. {
  41. $categoryXML = $this->requestXml($this->url . "/rest/c/categories.xml");
  42. $categories = $categoryXML->getElementsByTagName("c");
  43. foreach ($categories as $category) {
  44. $categoryLink = $category->getAttribute("xlink:href");
  45. $categoryLink = str_replace("info.xml", "packages.xml", $categoryLink);
  46. $packagesXML = $this->requestXml($this->url . $categoryLink);
  47. $packages = $packagesXML->getElementsByTagName('p');
  48. $loader = new ArrayLoader();
  49. foreach ($packages as $package) {
  50. $packageName = $package->nodeValue;
  51. $packageLink = $package->getAttribute('xlink:href');
  52. $releaseLink = $this->url . str_replace("/rest/p/", "/rest/r/", $packageLink);
  53. $allReleasesLink = $releaseLink . "/allreleases2.xml";
  54. try {
  55. $releasesXML = $this->requestXml($allReleasesLink);
  56. } catch (\ErrorException $e) {
  57. if (strpos($e->getMessage(), '404')) {
  58. continue;
  59. }
  60. throw $e;
  61. }
  62. $releases = $releasesXML->getElementsByTagName('r');
  63. foreach ($releases as $release) {
  64. /* @var $release DOMElement */
  65. $pearVersion = $release->getElementsByTagName('v')->item(0)->nodeValue;
  66. $packageData = array(
  67. 'name' => $packageName,
  68. 'type' => 'library',
  69. 'dist' => array('type' => 'pear', 'url' => $this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz"),
  70. 'version' => $pearVersion,
  71. );
  72. try {
  73. $deps = file_get_contents($releaseLink . "/deps.".$pearVersion.".txt");
  74. } catch (\ErrorException $e) {
  75. if (strpos($e->getMessage(), '404')) {
  76. continue;
  77. }
  78. throw $e;
  79. }
  80. if (preg_match('((O:([0-9])+:"([^"]+)"))', $deps, $matches)) {
  81. if (strlen($matches[3]) == $matches[2]) {
  82. throw new \InvalidArgumentException("Invalid dependency data, it contains serialized objects.");
  83. }
  84. }
  85. $deps = unserialize($deps);
  86. if (isset($deps['required']['package'])) {
  87. $requires = array();
  88. if (isset($deps['required']['package']['name'])) {
  89. $deps['required']['package'] = array($deps['required']['package']);
  90. }
  91. foreach ($deps['required']['package'] as $dependency) {
  92. if (isset($dependency['min'])) {
  93. $packageData['require'][$dependency['name']] = '>='.$dependency['min'];
  94. } else {
  95. $packageData['require'][$dependency['name']] = '>=0.0.0';
  96. }
  97. }
  98. }
  99. try {
  100. $this->addPackage($loader->load($packageData));
  101. } catch (\UnexpectedValueException $e) {
  102. continue;
  103. }
  104. }
  105. }
  106. }
  107. }
  108. /**
  109. * @param string $url
  110. * @return DOMDocument
  111. */
  112. private function requestXml($url)
  113. {
  114. $content = file_get_contents($url);
  115. if (!$content) {
  116. throw new \UnexpectedValueException('The PEAR channel at '.$url.' did not respond.');
  117. }
  118. $dom = new \DOMDocument('1.0', 'UTF-8');
  119. $dom->loadXML($content);
  120. return $dom;
  121. }
  122. }