1<?php 2 3/* 4 * This file is part of Composer. 5 * 6 * (c) Nils Adermann <naderman@naderman.de> 7 * Jordi Boggiano <j.boggiano@seld.be> 8 * 9 * For the full copyright and license information, please view the LICENSE 10 * file that was distributed with this source code. 11 */ 12 13namespace Composer\Repository\Pear; 14 15/** 16 * Read PEAR packages using REST 1.1 interface 17 * 18 * At version 1.1 package descriptions read from: 19 * {baseUrl}/c/categories.xml 20 * {baseUrl}/c/{category}/packagesinfo.xml 21 * 22 * @author Alexey Prilipko <palex@farpost.com> 23 */ 24class ChannelRest11Reader extends BaseChannelReader 25{ 26 private $dependencyReader; 27 28 public function __construct($rfs) 29 { 30 parent::__construct($rfs); 31 32 $this->dependencyReader = new PackageDependencyParser(); 33 } 34 35 /** 36 * Reads package descriptions using PEAR Rest 1.1 interface 37 * 38 * @param $baseUrl string base Url interface 39 * 40 * @return PackageInfo[] 41 */ 42 public function read($baseUrl) 43 { 44 return $this->readChannelPackages($baseUrl); 45 } 46 47 /** 48 * Read list of channel categories from 49 * {baseUrl}/c/categories.xml 50 * 51 * @param $baseUrl string 52 * @return PackageInfo[] 53 */ 54 private function readChannelPackages($baseUrl) 55 { 56 $result = array(); 57 58 $xml = $this->requestXml($baseUrl, "/c/categories.xml"); 59 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS); 60 foreach ($xml->xpath('ns:c') as $node) { 61 $categoryName = (string) $node; 62 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName); 63 $result = array_merge($result, $categoryPackages); 64 } 65 66 return $result; 67 } 68 69 /** 70 * Read packages from 71 * {baseUrl}/c/{category}/packagesinfo.xml 72 * 73 * @param $baseUrl string 74 * @param $categoryName string 75 * @return PackageInfo[] 76 */ 77 private function readCategoryPackages($baseUrl, $categoryName) 78 { 79 $result = array(); 80 81 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml'; 82 $xml = $this->requestXml($baseUrl, $categoryPath); 83 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS); 84 foreach ($xml->xpath('ns:pi') as $node) { 85 $packageInfo = $this->parsePackage($node); 86 $result[] = $packageInfo; 87 } 88 89 return $result; 90 } 91 92 /** 93 * Parses package node. 94 * 95 * @param $packageInfo \SimpleXMLElement xml element describing package 96 * @return PackageInfo 97 */ 98 private function parsePackage($packageInfo) 99 { 100 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS); 101 $channelName = (string) $packageInfo->p->c; 102 $packageName = (string) $packageInfo->p->n; 103 $license = (string) $packageInfo->p->l; 104 $shortDescription = (string) $packageInfo->p->s; 105 $description = (string) $packageInfo->p->d; 106 107 $dependencies = array(); 108 foreach ($packageInfo->xpath('ns:deps') as $node) { 109 $dependencyVersion = (string) $node->v; 110 $dependencyArray = unserialize((string) $node->d); 111 112 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray); 113 114 $dependencies[$dependencyVersion] = $dependencyInfo; 115 } 116 117 $releases = array(); 118 $releasesInfo = $packageInfo->xpath('ns:a/ns:r'); 119 if ($releasesInfo) { 120 foreach ($releasesInfo as $node) { 121 $releaseVersion = (string) $node->v; 122 $releaseStability = (string) $node->s; 123 $releases[$releaseVersion] = new ReleaseInfo( 124 $releaseStability, 125 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array()) 126 ); 127 } 128 } 129 130 return new PackageInfo( 131 $channelName, 132 $packageName, 133 $license, 134 $shortDescription, 135 $description, 136 $releases 137 ); 138 } 139} 140