Review fixes
parent
e173f11b37
commit
f2853c842b
|
@ -26,17 +26,17 @@ abstract class BaseChannelReader
|
|||
/**
|
||||
* PEAR REST Interface namespaces
|
||||
*/
|
||||
const channelNS = 'http://pear.php.net/channel-1.0';
|
||||
const allCategoriesNS = 'http://pear.php.net/dtd/rest.allcategories';
|
||||
const categoryPackagesInfoNS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
|
||||
const allPackagesNS = 'http://pear.php.net/dtd/rest.allpackages';
|
||||
const allReleasesNS = 'http://pear.php.net/dtd/rest.allreleases';
|
||||
const packageInfoNS = 'http://pear.php.net/dtd/rest.package';
|
||||
const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
|
||||
const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
|
||||
const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
|
||||
const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
|
||||
const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
|
||||
const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
|
||||
|
||||
/** @var RemoteFilesystem */
|
||||
private $rfs;
|
||||
|
||||
protected function __construct($rfs)
|
||||
protected function __construct(RemoteFilesystem $rfs)
|
||||
{
|
||||
$this->rfs = $rfs;
|
||||
}
|
||||
|
|
|
@ -43,28 +43,6 @@ class ChannelReader extends BaseChannelReader
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads channel supported REST interfaces and selects one of them
|
||||
*
|
||||
* @param $channelXml \SimpleXMLElement
|
||||
* @param $supportedVersions string[] supported PEAR REST protocols
|
||||
* @return array|bool hash with selected version and baseUrl
|
||||
*/
|
||||
private function selectRestVersion($channelXml, $supportedVersions)
|
||||
{
|
||||
$channelXml->registerXPathNamespace('ns', self::channelNS);
|
||||
|
||||
foreach ($supportedVersions as $version) {
|
||||
$xpathTest = "ns:servers/ns:primary/ns:rest/ns:baseurl[@type='{$version}']";
|
||||
$testResult = $channelXml->xpath($xpathTest);
|
||||
if (count($testResult) > 0) {
|
||||
return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads PEAR channel through REST interface and builds list of packages
|
||||
*
|
||||
|
@ -81,7 +59,7 @@ class ChannelReader extends BaseChannelReader
|
|||
|
||||
$supportedVersions = array_keys($this->readerMap);
|
||||
$selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
|
||||
if (false === $selectedRestVersion) {
|
||||
if (!$selectedRestVersion) {
|
||||
throw new \UnexpectedValueException(sprintf('PEAR repository $s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
|
||||
}
|
||||
|
||||
|
@ -92,109 +70,24 @@ class ChannelReader extends BaseChannelReader
|
|||
}
|
||||
|
||||
/**
|
||||
* Builds MemoryPackages from PEAR package definition data.
|
||||
* Reads channel supported REST interfaces and selects one of them
|
||||
*
|
||||
* @param $channelName string channel name
|
||||
* @param $channelAlias string channel alias
|
||||
* @param $packageDefinitions PackageInfo[] package definition
|
||||
* @return array
|
||||
* @param $channelXml \SimpleXMLElement
|
||||
* @param $supportedVersions string[] supported PEAR REST protocols
|
||||
* @return array|null hash with selected version and baseUrl
|
||||
*/
|
||||
private function buildComposerPackages($channelName, $channelAlias, $packageDefinitions)
|
||||
private function selectRestVersion($channelXml, $supportedVersions)
|
||||
{
|
||||
$versionParser = new \Composer\Package\Version\VersionParser();
|
||||
$result = array();
|
||||
foreach ($packageDefinitions as $packageDefinition) {
|
||||
foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
|
||||
$normalizedVersion = $this->parseVersion($version);
|
||||
if (false === $normalizedVersion) {
|
||||
continue; // skip packages with unparsable versions
|
||||
}
|
||||
$channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
|
||||
|
||||
$composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
|
||||
|
||||
// distribution url must be read from /r/{packageName}/{version}.xml::/r/g:text()
|
||||
$distUrl = "http://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
|
||||
|
||||
$requires = array();
|
||||
$suggests = array();
|
||||
$conflicts = array();
|
||||
$replaces = array();
|
||||
|
||||
// alias package only when its channel matches repository channel,
|
||||
// cause we've know only repository channel alias
|
||||
if ($channelName == $packageDefinition->getChannelName()) {
|
||||
$composerPackageAlias = $this->buildComposerPackageName($channelAlias, $packageDefinition->getPackageName());
|
||||
$aliasConstraint = new VersionConstraint('==', $normalizedVersion);
|
||||
$aliasLink = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
|
||||
$replaces[] = $aliasLink;
|
||||
}
|
||||
|
||||
$dependencyInfo = $releaseInfo->getDependencyInfo();
|
||||
foreach ($dependencyInfo->getRequires() as $dependencyConstraint) {
|
||||
$dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
|
||||
$constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
|
||||
$link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
|
||||
switch ($dependencyConstraint->getType()) {
|
||||
case 'required':
|
||||
$requires[] = $link;
|
||||
break;
|
||||
case 'conflicts':
|
||||
$conflicts[] = $link;
|
||||
break;
|
||||
case 'replaces':
|
||||
$replaces[] = $link;
|
||||
break;
|
||||
foreach ($supportedVersions as $version) {
|
||||
$xpathTest = "ns:servers/ns:primary/ns:rest/ns:baseurl[@type='{$version}']";
|
||||
$testResult = $channelXml->xpath($xpathTest);
|
||||
if (count($testResult) > 0) {
|
||||
return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($dependencyInfo->getOptionals() as $groupName => $dependencyConstraints) {
|
||||
foreach ($dependencyConstraints as $dependencyConstraint) {
|
||||
$dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
|
||||
$suggests[$groupName.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
|
||||
}
|
||||
}
|
||||
|
||||
$package = new \Composer\Package\MemoryPackage($composerPackageName, $normalizedVersion, $version);
|
||||
$package->setType('library');
|
||||
$package->setDescription($packageDefinition->getDescription());
|
||||
$package->setDistType('pear');
|
||||
$package->setDistUrl($distUrl);
|
||||
$package->setAutoload(array('classmap' => array('')));
|
||||
$package->setIncludePaths(array('/'));
|
||||
$package->setRequires($requires);
|
||||
$package->setConflicts($conflicts);
|
||||
$package->setSuggests($suggests);
|
||||
$package->setReplaces($replaces);
|
||||
$result[] = $package;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function buildComposerPackageName($pearChannelName, $pearPackageName)
|
||||
{
|
||||
if ($pearChannelName == 'php') {
|
||||
return "php";
|
||||
}
|
||||
if ($pearChannelName == 'ext') {
|
||||
return "ext-{$pearPackageName}";
|
||||
}
|
||||
|
||||
return "pear-{$pearChannelName}/{$pearPackageName}";
|
||||
}
|
||||
|
||||
protected function parseVersion($version)
|
||||
{
|
||||
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
|
||||
$version = $matches[1]
|
||||
.(!empty($matches[2]) ? $matches[2] : '.0')
|
||||
.(!empty($matches[3]) ? $matches[3] : '.0')
|
||||
.(!empty($matches[4]) ? $matches[4] : '.0');
|
||||
|
||||
return $version;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class ChannelRest10Reader extends BaseChannelReader
|
|||
|
||||
$xmlPath = '/p/packages.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::allPackagesNS);
|
||||
$xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
|
||||
foreach ($xml->xpath('ns:p') as $node) {
|
||||
$packageName = (string) $node;
|
||||
$packageInfo = $this->readPackage($baseUrl, $packageName);
|
||||
|
@ -83,7 +83,7 @@ class ChannelRest10Reader extends BaseChannelReader
|
|||
{
|
||||
$xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::packageInfoNS);
|
||||
$xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
|
||||
|
||||
$channelName = (string) $xml->c;
|
||||
$packageName = (string) $xml->n;
|
||||
|
@ -116,7 +116,7 @@ class ChannelRest10Reader extends BaseChannelReader
|
|||
try {
|
||||
$xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::allReleasesNS);
|
||||
$xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
|
||||
foreach ($xml->xpath('ns:r') as $node) {
|
||||
$releaseVersion = (string) $node->v;
|
||||
$releaseStability = (string) $node->s;
|
||||
|
|
|
@ -56,7 +56,7 @@ class ChannelRest11Reader extends BaseChannelReader
|
|||
$result = array();
|
||||
|
||||
$xml = $this->requestXml($baseUrl, "/c/categories.xml");
|
||||
$xml->registerXPathNamespace('ns', self::allCategoriesNS);
|
||||
$xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
|
||||
foreach ($xml->xpath('ns:c') as $node) {
|
||||
$categoryName = (string) $node;
|
||||
$categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
|
||||
|
@ -80,7 +80,7 @@ class ChannelRest11Reader extends BaseChannelReader
|
|||
|
||||
$categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
|
||||
$xml = $this->requestXml($baseUrl, $categoryPath);
|
||||
$xml->registerXPathNamespace('ns', self::categoryPackagesInfoNS);
|
||||
$xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
|
||||
foreach ($xml->xpath('ns:pi') as $node) {
|
||||
$packageInfo = $this->parsePackage($node);
|
||||
$result[] = $packageInfo;
|
||||
|
@ -97,7 +97,7 @@ class ChannelRest11Reader extends BaseChannelReader
|
|||
*/
|
||||
private function parsePackage($packageInfo)
|
||||
{
|
||||
$packageInfo->registerXPathNamespace('ns', self::categoryPackagesInfoNS);
|
||||
$packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
|
||||
$channelName = (string) $packageInfo->p->c;
|
||||
$packageName = (string) $packageInfo->p->n;
|
||||
$license = (string) $packageInfo->p->l;
|
||||
|
|
|
@ -19,6 +19,23 @@ namespace Composer\Repository\Pear;
|
|||
*/
|
||||
class PackageDependencyParser
|
||||
{
|
||||
/**
|
||||
* Builds dependency information. It detects used package.xml format.
|
||||
*
|
||||
* @param $depArray array
|
||||
* @return DependencyInfo
|
||||
*/
|
||||
public function buildDependencyInfo($depArray)
|
||||
{
|
||||
if (!is_array($depArray)) {
|
||||
return new DependencyInfo(array(), array());
|
||||
}
|
||||
if (!$this->isHash($depArray)) {
|
||||
return new DependencyInfo($this->buildDependency10Info($depArray), array());
|
||||
}
|
||||
return $this->buildDependency20Info($depArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dependency information from package.xml 1.0 format
|
||||
*
|
||||
|
@ -229,23 +246,6 @@ class PackageDependencyParser
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dependency information. It detects used package.xml format.
|
||||
*
|
||||
* @param $depArray array
|
||||
* @return DependencyInfo
|
||||
*/
|
||||
public function buildDependencyInfo($depArray)
|
||||
{
|
||||
if (!is_array($depArray)) {
|
||||
return new DependencyInfo(array(), array());
|
||||
} elseif (!$this->isHash($depArray)) {
|
||||
return new DependencyInfo($this->buildDependency10Info($depArray), array());
|
||||
} else {
|
||||
return $this->buildDependency20Info($depArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses version constraint
|
||||
*
|
||||
|
@ -260,7 +260,8 @@ class PackageDependencyParser
|
|||
$values = array_intersect_key($data, $dep20toOperatorMap);
|
||||
if (0 == count($values)) {
|
||||
return '*';
|
||||
} elseif (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
|
||||
}
|
||||
if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
|
||||
$versions[] = '>' . $this->parseVersion($values['min']);
|
||||
} elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
|
||||
$versions[] = '<' . $this->parseVersion($values['max']);
|
||||
|
@ -283,7 +284,7 @@ class PackageDependencyParser
|
|||
* Softened version parser
|
||||
*
|
||||
* @param $version
|
||||
* @return bool|string
|
||||
* @return null|string
|
||||
*/
|
||||
private function parseVersion($version)
|
||||
{
|
||||
|
@ -294,9 +295,9 @@ class PackageDependencyParser
|
|||
.(!empty($matches[4]) ? $matches[4] : '.0');
|
||||
|
||||
return $version;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
namespace Composer\Repository;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Repository\Pear\ChannelReader;
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Repository\Pear\ChannelInfo;
|
||||
use Composer\Package\Link;
|
||||
|
@ -34,6 +36,7 @@ class PearRepository extends ArrayRepository
|
|||
private $url;
|
||||
private $io;
|
||||
private $rfs;
|
||||
private $versionParser;
|
||||
|
||||
/** @var string vendor makes additional alias for each channel as {prefix}/{packagename}. It allows smoother
|
||||
* package transition to composer-like repositories.
|
||||
|
@ -54,6 +57,7 @@ class PearRepository extends ArrayRepository
|
|||
$this->io = $io;
|
||||
$this->rfs = $rfs ?: new RemoteFilesystem($this->io);
|
||||
$this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
|
||||
$this->versionParser = new VersionParser();
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
|
@ -62,14 +66,14 @@ class PearRepository extends ArrayRepository
|
|||
|
||||
$this->io->write('Initializing PEAR repository '.$this->url);
|
||||
|
||||
$reader = new \Composer\Repository\Pear\ChannelReader($this->rfs);
|
||||
$reader = new ChannelReader($this->rfs);
|
||||
try {
|
||||
$channelInfo = $reader->read($this->url);
|
||||
} catch (\Exception $e) {
|
||||
$this->io->write('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
|
||||
return;
|
||||
}
|
||||
$packages = $this->buildComposerPackages($channelInfo);
|
||||
$packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
|
||||
foreach ($packages as $package) {
|
||||
$this->addPackage($package);
|
||||
}
|
||||
|
@ -81,14 +85,13 @@ class PearRepository extends ArrayRepository
|
|||
* @param ChannelInfo $channelInfo
|
||||
* @return MemoryPackage
|
||||
*/
|
||||
private function buildComposerPackages(ChannelInfo $channelInfo)
|
||||
private function buildComposerPackages(ChannelInfo $channelInfo, VersionParser $versionParser)
|
||||
{
|
||||
$versionParser = new \Composer\Package\Version\VersionParser();
|
||||
$result = array();
|
||||
foreach ($channelInfo->getPackages() as $packageDefinition) {
|
||||
foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
|
||||
$normalizedVersion = $this->parseVersion($version);
|
||||
if (false === $normalizedVersion) {
|
||||
if (!$normalizedVersion) {
|
||||
continue; // skip packages with unparsable versions
|
||||
}
|
||||
|
||||
|
@ -160,18 +163,25 @@ class PearRepository extends ArrayRepository
|
|||
return $result;
|
||||
}
|
||||
|
||||
private function buildComposerPackageName($pearChannelName, $pearPackageName)
|
||||
private function buildComposerPackageName($channelName, $packageName)
|
||||
{
|
||||
if ($pearChannelName == 'php') {
|
||||
if ('php' === $channelName) {
|
||||
return "php";
|
||||
} elseif ($pearChannelName == 'ext') {
|
||||
return "ext-{$pearPackageName}";
|
||||
} else {
|
||||
return "pear-{$pearChannelName}/{$pearPackageName}";
|
||||
}
|
||||
if ('ext' === $channelName) {
|
||||
return "ext-{$packageName}";
|
||||
}
|
||||
|
||||
protected function parseVersion($version)
|
||||
return "pear-{$channelName}/{$packageName}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Softened version parser.
|
||||
*
|
||||
* @param string $version
|
||||
* @return null|string
|
||||
*/
|
||||
private function parseVersion($version)
|
||||
{
|
||||
if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
|
||||
$version = $matches[1]
|
||||
|
@ -180,8 +190,8 @@ class PearRepository extends ArrayRepository
|
|||
.(!empty($matches[4]) ? $matches[4] : '.0');
|
||||
|
||||
return $version;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Test\TestCase;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\MemoryPackage;
|
||||
|
@ -62,14 +63,18 @@ class ChannelReaderTest extends TestCase
|
|||
|
||||
public function testShouldCreatePackages()
|
||||
{
|
||||
$reader = $this->getMockBuilder('\Composer\Repository\Pear\ChannelReader')
|
||||
$reader = $this->getMockBuilder('\Composer\Repository\PearRepository')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$ref = new \ReflectionMethod($reader, 'buildComposerPackages');
|
||||
$ref->setAccessible(true);
|
||||
|
||||
$packageInfo = new PackageInfo(
|
||||
$channelInfo = new ChannelInfo(
|
||||
'test.loc',
|
||||
'test',
|
||||
array(
|
||||
new PackageInfo(
|
||||
'test.loc',
|
||||
'sample',
|
||||
'license',
|
||||
|
@ -106,9 +111,11 @@ class ChannelReaderTest extends TestCase
|
|||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$packages = $ref->invoke($reader, 'test.loc', 'test', array($packageInfo));
|
||||
$packages = $ref->invoke($reader, $channelInfo, new VersionParser());
|
||||
|
||||
$expectedPackage = new MemoryPackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1');
|
||||
$expectedPackage->setType('library');
|
||||
|
|
Loading…
Reference in New Issue