Add PEAR channel reader & Update PearRepository to use it.
parent
ee2834a169
commit
e173f11b37
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Util\RemoteFilesystem;
|
||||
|
||||
/**
|
||||
* Base PEAR Channel reader.
|
||||
*
|
||||
* Provides xml namespaces and red
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
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';
|
||||
|
||||
/** @var RemoteFilesystem */
|
||||
private $rfs;
|
||||
|
||||
protected function __construct($rfs)
|
||||
{
|
||||
$this->rfs = $rfs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read content from remote filesystem.
|
||||
*
|
||||
* @param $origin string server
|
||||
* @param $path string relative path to content
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
protected function requestContent($origin, $path)
|
||||
{
|
||||
$url = rtrim($origin, '/') . '/' . ltrim($path, '/');
|
||||
$content = $this->rfs->getContents($origin, $url, false);
|
||||
if (!$content) {
|
||||
throw new \UnexpectedValueException('The PEAR channel at '.$url.' did not respond.');
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read xml content from remote filesystem
|
||||
*
|
||||
* @param $origin string server
|
||||
* @param $path string relative path to content
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
protected function requestXml($origin, $path)
|
||||
{
|
||||
// http://components.ez.no/p/packages.xml is malformed. to read it we must ignore parsing errors.
|
||||
$xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
|
||||
|
||||
if (false == $xml) {
|
||||
$url = rtrim($origin, '/') . '/' . ltrim($path, '/');
|
||||
throw new \UnexpectedValueException('The PEAR channel at '.$origin.' is broken.');
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* PEAR channel info
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class ChannelInfo
|
||||
{
|
||||
private $name;
|
||||
private $alias;
|
||||
private $packages;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $alias
|
||||
* @param PackageInfo[] $packages
|
||||
*/
|
||||
public function __construct($name, $alias, array $packages)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->alias = $alias;
|
||||
$this->packages = $packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the channel
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of the channel
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of channel packages
|
||||
*
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
public function getPackages()
|
||||
{
|
||||
return $this->packages;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Util\RemoteFilesystem;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\Link;
|
||||
|
||||
/**
|
||||
* PEAR Channel package reader.
|
||||
*
|
||||
* Reads channel packages info from and builds MemoryPackage's
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class ChannelReader extends BaseChannelReader
|
||||
{
|
||||
/** @var array of ('xpath test' => 'rest implementation') */
|
||||
private $readerMap;
|
||||
|
||||
public function __construct(RemoteFilesystem $rfs)
|
||||
{
|
||||
parent::__construct($rfs);
|
||||
|
||||
$rest10reader = new ChannelRest10Reader($rfs);
|
||||
$rest11reader = new ChannelRest11Reader($rfs);
|
||||
|
||||
$this->readerMap = array(
|
||||
'REST1.3' => $rest11reader,
|
||||
'REST1.2' => $rest11reader,
|
||||
'REST1.1' => $rest11reader,
|
||||
'REST1.0' => $rest10reader,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param $url string PEAR Channel url
|
||||
* @return ChannelInfo
|
||||
*/
|
||||
public function read($url)
|
||||
{
|
||||
$xml = $this->requestXml($url, "/channel.xml");
|
||||
|
||||
$channelName = (string) $xml->name;
|
||||
$channelSummary = (string) $xml->summary;
|
||||
$channelAlias = (string) $xml->suggestedalias;
|
||||
|
||||
$supportedVersions = array_keys($this->readerMap);
|
||||
$selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
|
||||
if (false === $selectedRestVersion) {
|
||||
throw new \UnexpectedValueException(sprintf('PEAR repository $s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
|
||||
}
|
||||
|
||||
$reader = $this->readerMap[$selectedRestVersion['version']];
|
||||
$packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
|
||||
|
||||
return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds MemoryPackages from PEAR package definition data.
|
||||
*
|
||||
* @param $channelName string channel name
|
||||
* @param $channelAlias string channel alias
|
||||
* @param $packageDefinitions PackageInfo[] package definition
|
||||
* @return array
|
||||
*/
|
||||
private function buildComposerPackages($channelName, $channelAlias, $packageDefinitions)
|
||||
{
|
||||
$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
|
||||
}
|
||||
|
||||
$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 ($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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Downloader\TransportException;
|
||||
|
||||
/**
|
||||
* Read PEAR packages using REST 1.0 interface
|
||||
*
|
||||
* At version 1.0 package descriptions read from:
|
||||
* {baseUrl}/p/packages.xml
|
||||
* {baseUrl}/p/{package}/info.xml
|
||||
* {baseUrl}/p/{package}/allreleases.xml
|
||||
* {baseUrl}/p/{package}/deps.{version}.txt
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class ChannelRest10Reader extends BaseChannelReader
|
||||
{
|
||||
private $dependencyReader;
|
||||
|
||||
public function __construct($rfs)
|
||||
{
|
||||
parent::__construct($rfs);
|
||||
|
||||
$this->dependencyReader = new PackageDependencyParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads package descriptions using PEAR Rest 1.0 interface
|
||||
*
|
||||
* @param $baseUrl string base Url interface
|
||||
*
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
public function read($baseUrl)
|
||||
{
|
||||
return $this->readPackages($baseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read list of packages from
|
||||
* {baseUrl}/p/packages.xml
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
private function readPackages($baseUrl)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$xmlPath = '/p/packages.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::allPackagesNS);
|
||||
foreach ($xml->xpath('ns:p') as $node) {
|
||||
$packageName = (string) $node;
|
||||
$packageInfo = $this->readPackage($baseUrl, $packageName);
|
||||
$result[] = $packageInfo;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package info from
|
||||
* {baseUrl}/p/{package}/info.xml
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @param $packageName string
|
||||
* @return PackageInfo
|
||||
*/
|
||||
private function readPackage($baseUrl, $packageName)
|
||||
{
|
||||
$xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::packageInfoNS);
|
||||
|
||||
$channelName = (string) $xml->c;
|
||||
$packageName = (string) $xml->n;
|
||||
$license = (string) $xml->l;
|
||||
$shortDescription = (string) $xml->s;
|
||||
$description = (string) $xml->d;
|
||||
|
||||
return new PackageInfo(
|
||||
$channelName,
|
||||
$packageName,
|
||||
$license,
|
||||
$shortDescription,
|
||||
$description,
|
||||
$this->readPackageReleases($baseUrl, $packageName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package releases from
|
||||
* {baseUrl}/p/{package}/allreleases.xml
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @param $packageName string
|
||||
* @return ReleaseInfo[] hash array with keys as version numbers
|
||||
*/
|
||||
private function readPackageReleases($baseUrl, $packageName)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
try {
|
||||
$xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
|
||||
$xml = $this->requestXml($baseUrl, $xmlPath);
|
||||
$xml->registerXPathNamespace('ns', self::allReleasesNS);
|
||||
foreach ($xml->xpath('ns:r') as $node) {
|
||||
$releaseVersion = (string) $node->v;
|
||||
$releaseStability = (string) $node->s;
|
||||
|
||||
try {
|
||||
$result[$releaseVersion] = new ReleaseInfo(
|
||||
$releaseStability,
|
||||
$this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
|
||||
);
|
||||
} catch (TransportException $exception) {
|
||||
if ($exception->getCode() != 404) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TransportException $exception) {
|
||||
if ($exception->getCode() != 404) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read package dependencies from
|
||||
* {baseUrl}/p/{package}/deps.{version}.txt
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @param $packageName string
|
||||
* @param $version string
|
||||
* @return DependencyInfo[]
|
||||
*/
|
||||
private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
|
||||
{
|
||||
$dependencyReader = new PackageDependencyParser();
|
||||
|
||||
$depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
|
||||
$content = $this->requestContent($baseUrl, $depthPath);
|
||||
$dependencyArray = unserialize($content);
|
||||
$result = $dependencyReader->buildDependencyInfo($dependencyArray);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* Read PEAR packages using REST 1.1 interface
|
||||
*
|
||||
* At version 1.1 package descriptions read from:
|
||||
* {baseUrl}/c/categories.xml
|
||||
* {baseUrl}/c/{category}/packagesinfo.xml
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class ChannelRest11Reader extends BaseChannelReader
|
||||
{
|
||||
private $dependencyReader;
|
||||
|
||||
public function __construct($rfs)
|
||||
{
|
||||
parent::__construct($rfs);
|
||||
|
||||
$this->dependencyReader = new PackageDependencyParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads package descriptions using PEAR Rest 1.1 interface
|
||||
*
|
||||
* @param $baseUrl string base Url interface
|
||||
*
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
public function read($baseUrl)
|
||||
{
|
||||
return $this->readChannelPackages($baseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read list of channel categories from
|
||||
* {baseUrl}/c/categories.xml
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
private function readChannelPackages($baseUrl)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$xml = $this->requestXml($baseUrl, "/c/categories.xml");
|
||||
$xml->registerXPathNamespace('ns', self::allCategoriesNS);
|
||||
foreach ($xml->xpath('ns:c') as $node) {
|
||||
$categoryName = (string) $node;
|
||||
$categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
|
||||
$result = array_merge($result, $categoryPackages);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read packages from
|
||||
* {baseUrl}/c/{category}/packagesinfo.xml
|
||||
*
|
||||
* @param $baseUrl string
|
||||
* @param $categoryName string
|
||||
* @return PackageInfo[]
|
||||
*/
|
||||
private function readCategoryPackages($baseUrl, $categoryName)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
|
||||
$xml = $this->requestXml($baseUrl, $categoryPath);
|
||||
$xml->registerXPathNamespace('ns', self::categoryPackagesInfoNS);
|
||||
foreach ($xml->xpath('ns:pi') as $node) {
|
||||
$packageInfo = $this->parsePackage($node);
|
||||
$result[] = $packageInfo;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses package node.
|
||||
*
|
||||
* @param $packageInfo \SimpleXMLElement xml element describing package
|
||||
* @return PackageInfo
|
||||
*/
|
||||
private function parsePackage($packageInfo)
|
||||
{
|
||||
$packageInfo->registerXPathNamespace('ns', self::categoryPackagesInfoNS);
|
||||
$channelName = (string) $packageInfo->p->c;
|
||||
$packageName = (string) $packageInfo->p->n;
|
||||
$license = (string) $packageInfo->p->l;
|
||||
$shortDescription = (string) $packageInfo->p->s;
|
||||
$description = (string) $packageInfo->p->d;
|
||||
|
||||
$dependencies = array();
|
||||
foreach ($packageInfo->xpath('ns:deps') as $node) {
|
||||
$dependencyVersion = (string) $node->v;
|
||||
$dependencyArray = unserialize((string) $node->d);
|
||||
|
||||
$dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
|
||||
|
||||
$dependencies[$dependencyVersion] = $dependencyInfo;
|
||||
}
|
||||
|
||||
$releases = array();
|
||||
foreach ($packageInfo->xpath('ns:a/ns:r') as $node) {
|
||||
$releaseVersion = (string) $node->v;
|
||||
$releaseStability = (string) $node->s;
|
||||
$releases[$releaseVersion] = new ReleaseInfo(
|
||||
$releaseStability,
|
||||
isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
|
||||
);
|
||||
}
|
||||
|
||||
return new PackageInfo(
|
||||
$channelName,
|
||||
$packageName,
|
||||
$license,
|
||||
$shortDescription,
|
||||
$description,
|
||||
$releases
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* PEAR package release dependency info
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class DependencyConstraint
|
||||
{
|
||||
private $type;
|
||||
private $constraint;
|
||||
private $channelName;
|
||||
private $packageName;
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $constraint
|
||||
* @param string $channelName
|
||||
* @param string $packageName
|
||||
*/
|
||||
public function __construct($type, $constraint, $channelName, $packageName)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->constraint = $constraint;
|
||||
$this->channelName = $channelName;
|
||||
$this->packageName = $packageName;
|
||||
}
|
||||
|
||||
public function getChannelName()
|
||||
{
|
||||
return $this->channelName;
|
||||
}
|
||||
|
||||
public function getConstraint()
|
||||
{
|
||||
return $this->constraint;
|
||||
}
|
||||
|
||||
public function getPackageName()
|
||||
{
|
||||
return $this->packageName;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* PEAR package release dependency info
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class DependencyInfo
|
||||
{
|
||||
private $requires;
|
||||
private $optionals;
|
||||
|
||||
/**
|
||||
* @param DependencyConstraint[] $requires list of requires/conflicts/replaces
|
||||
* @param array $optionals [groupName => DependencyConstraint[]] list of optional groups
|
||||
*/
|
||||
public function __construct($requires, $optionals)
|
||||
{
|
||||
$this->requires = $requires;
|
||||
$this->optionals = $optionals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DependencyConstraint[] list of requires/conflicts/replaces
|
||||
*/
|
||||
public function getRequires()
|
||||
{
|
||||
return $this->requires;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array [groupName => DependencyConstraint[]] list of optional groups
|
||||
*/
|
||||
public function getOptionals()
|
||||
{
|
||||
return $this->optionals;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* Read PEAR packages using REST 1.0 interface
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class PackageDependencyParser
|
||||
{
|
||||
/**
|
||||
* Builds dependency information from package.xml 1.0 format
|
||||
*
|
||||
* http://pear.php.net/manual/en/guide.developers.package2.dependencies.php
|
||||
*
|
||||
* package.xml 1.0 format consists of array of
|
||||
* { type="php|os|sapi|ext|pkg" rel="has|not|eq|ge|gt|le|lt" optional="yes"
|
||||
* channel="channelName" name="extName|packageName" }
|
||||
*
|
||||
* @param $depArray array Dependency data in package.xml 1.0 format
|
||||
* @return DependencyConstraint[]
|
||||
*/
|
||||
private function buildDependency10Info($depArray)
|
||||
{
|
||||
static $dep10toOperatorMap = array('has'=>'==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
|
||||
|
||||
$result = array();
|
||||
|
||||
foreach ($depArray as $depItem) {
|
||||
if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
|
||||
// 'unknown rel type:' . $depItem['rel'];
|
||||
continue;
|
||||
}
|
||||
|
||||
$depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
|
||||
? 'optional'
|
||||
: 'required';
|
||||
$depType = 'not' == $depItem['rel']
|
||||
? 'conflicts'
|
||||
: $depType;
|
||||
|
||||
$depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
|
||||
|
||||
// has & not are special operators that does not requires version
|
||||
$depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
|
||||
? '*'
|
||||
: $dep10toOperatorMap[$depItem['rel']] . $depVersion;
|
||||
|
||||
switch ($depItem['type']) {
|
||||
case 'php':
|
||||
$depChannelName = 'php';
|
||||
$depPackageName = '';
|
||||
break;
|
||||
case 'pkg':
|
||||
$depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
|
||||
$depPackageName = $depItem['name'];
|
||||
break;
|
||||
case 'ext':
|
||||
$depChannelName = 'ext';
|
||||
$depPackageName = $depItem['name'];
|
||||
break;
|
||||
case 'os':
|
||||
case 'sapi':
|
||||
$depChannelName = '';
|
||||
$depPackageName = '';
|
||||
break;
|
||||
default:
|
||||
$depChannelName = '';
|
||||
$depPackageName = '';
|
||||
break;
|
||||
}
|
||||
|
||||
if ('' != $depChannelName) {
|
||||
$result[] = new DependencyConstraint(
|
||||
$depType,
|
||||
$depVersionConstraint,
|
||||
$depChannelName,
|
||||
$depPackageName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dependency information from package.xml 2.0 format
|
||||
*
|
||||
* @param $depArray array Dependency data in package.xml 1.0 format
|
||||
* @return DependencyInfo
|
||||
*/
|
||||
private function buildDependency20Info($depArray)
|
||||
{
|
||||
$result = array();
|
||||
$optionals = array();
|
||||
$defaultOptionals = array();
|
||||
foreach ($depArray as $depType => $depTypeGroup) {
|
||||
if (!is_array($depTypeGroup)) {
|
||||
continue;
|
||||
}
|
||||
if ('required' == $depType || 'optional' == $depType) {
|
||||
foreach ($depTypeGroup as $depItemType => $depItem) {
|
||||
switch ($depItemType) {
|
||||
case 'php':
|
||||
$result[] = new DependencyConstraint(
|
||||
$depType,
|
||||
$this->parse20VersionConstraint($depItem),
|
||||
'php',
|
||||
''
|
||||
);
|
||||
break;
|
||||
case 'package':
|
||||
$deps = $this->buildDepPackageConstraints($depItem, $depType);
|
||||
$result = array_merge($result, $deps);
|
||||
break;
|
||||
case 'extension':
|
||||
$deps = $this->buildDepExtensionConstraints($depItem, $depType);
|
||||
$result = array_merge($result, $deps);
|
||||
break;
|
||||
case 'subpackage':
|
||||
$deps = $this->buildDepPackageConstraints($depItem, 'replaces');
|
||||
$defaultOptionals += $deps;
|
||||
break;
|
||||
case 'os':
|
||||
case 'pearinstaller':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif ('group' == $depType) {
|
||||
if ($this->isHash($depTypeGroup)) {
|
||||
$depTypeGroup = array($depTypeGroup);
|
||||
}
|
||||
|
||||
foreach ($depTypeGroup as $depItem) {
|
||||
$groupName = $depItem['attribs']['name'];
|
||||
if (!isset($optionals[$groupName])) {
|
||||
$optionals[$groupName] = array();
|
||||
}
|
||||
|
||||
if (isset($depItem['subpackage'])) {
|
||||
$optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
|
||||
} else {
|
||||
$result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($defaultOptionals) > 0) {
|
||||
$optionals['*'] = $defaultOptionals;
|
||||
}
|
||||
|
||||
return new DependencyInfo($result, $optionals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dependency constraint of 'extension' type
|
||||
*
|
||||
* @param $depItem array dependency constraint or array of dependency constraints
|
||||
* @param $depType string target type of building constraint.
|
||||
* @return DependencyConstraint[]
|
||||
*/
|
||||
private function buildDepExtensionConstraints($depItem, $depType)
|
||||
{
|
||||
if ($this->isHash($depItem)) {
|
||||
$depItem = array($depItem);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($depItem as $subDepItem) {
|
||||
$depChannelName = 'ext';
|
||||
$depPackageName = $subDepItem['name'];
|
||||
$depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
|
||||
|
||||
$result[] = new DependencyConstraint(
|
||||
$depType,
|
||||
$depVersionConstraint,
|
||||
$depChannelName,
|
||||
$depPackageName
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds dependency constraint of 'package' type
|
||||
*
|
||||
* @param $depItem array dependency constraint or array of dependency constraints
|
||||
* @param $depType string target type of building constraint.
|
||||
* @return DependencyConstraint[]
|
||||
*/
|
||||
private function buildDepPackageConstraints($depItem, $depType)
|
||||
{
|
||||
if ($this->isHash($depItem)) {
|
||||
$depItem = array($depItem);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($depItem as $subDepItem) {
|
||||
$depChannelName = $subDepItem['channel'];
|
||||
$depPackageName = $subDepItem['name'];
|
||||
$depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
|
||||
if (isset($subDepItem['conflicts'])) {
|
||||
$depType = 'conflicts';
|
||||
}
|
||||
|
||||
$result[] = new DependencyConstraint(
|
||||
$depType,
|
||||
$depVersionConstraint,
|
||||
$depChannelName,
|
||||
$depPackageName
|
||||
);
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* @param array $data array containing serveral 'min', 'max', 'has', 'exclude' and other keys.
|
||||
* @return string
|
||||
*/
|
||||
private function parse20VersionConstraint(array $data)
|
||||
{
|
||||
static $dep20toOperatorMap = array('has'=>'==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
|
||||
|
||||
$versions = array();
|
||||
$values = array_intersect_key($data, $dep20toOperatorMap);
|
||||
if (0 == count($values)) {
|
||||
return '*';
|
||||
} elseif (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']);
|
||||
} else {
|
||||
foreach ($values as $op => $version) {
|
||||
if ('exclude' == $op && is_array($version)) {
|
||||
foreach ($version as $versionPart) {
|
||||
$versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
|
||||
}
|
||||
} else {
|
||||
$versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return implode(',', $versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Softened version parser
|
||||
*
|
||||
* @param $version
|
||||
* @return bool|string
|
||||
*/
|
||||
private 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if array is associative or hash type
|
||||
*
|
||||
* @param array $array
|
||||
* @return bool
|
||||
*/
|
||||
private function isHash(array $array)
|
||||
{
|
||||
return !array_key_exists(1, $array) && !array_key_exists(0, $array);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* PEAR Package info
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class PackageInfo
|
||||
{
|
||||
private $channelName;
|
||||
private $packageName;
|
||||
private $license;
|
||||
private $shortDescription;
|
||||
private $description;
|
||||
private $releases;
|
||||
|
||||
/**
|
||||
* @param string $channelName
|
||||
* @param string $packageName
|
||||
* @param string $license
|
||||
* @param string $shortDescription
|
||||
* @param string $description
|
||||
* @param ReleaseInfo[] $releases associative array maps release version to release info
|
||||
*/
|
||||
public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
|
||||
{
|
||||
$this->channelName = $channelName;
|
||||
$this->packageName = $packageName;
|
||||
$this->license = $license;
|
||||
$this->shortDescription = $shortDescription;
|
||||
$this->description = $description;
|
||||
$this->releases = $releases;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the package channel name
|
||||
*/
|
||||
public function getChannelName()
|
||||
{
|
||||
return $this->channelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the package name
|
||||
*/
|
||||
public function getPackageName()
|
||||
{
|
||||
return $this->packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the package description
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the package short escription
|
||||
*/
|
||||
public function getShortDescription()
|
||||
{
|
||||
return $this->shortDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the package licence
|
||||
*/
|
||||
public function getLicense()
|
||||
{
|
||||
return $this->license;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ReleaseInfo[]
|
||||
*/
|
||||
public function getReleases()
|
||||
{
|
||||
return $this->releases;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
/**
|
||||
* PEAR package release info
|
||||
*
|
||||
* @author Alexey Prilipko <palex@farpost.com>
|
||||
*/
|
||||
class ReleaseInfo
|
||||
{
|
||||
private $stability;
|
||||
private $dependencyInfo;
|
||||
|
||||
/**
|
||||
* @param string $stability
|
||||
* @param DependencyInfo $dependencies
|
||||
*/
|
||||
public function __construct($stability, $dependencyInfo)
|
||||
{
|
||||
$this->stability = $stability;
|
||||
$this->dependencyInfo = $dependencyInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DependencyInfo release dependencies
|
||||
*/
|
||||
public function getDependencyInfo()
|
||||
{
|
||||
return $this->dependencyInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string release stability
|
||||
*/
|
||||
public function getStability()
|
||||
{
|
||||
return $this->stability;
|
||||
}
|
||||
}
|
|
@ -13,26 +13,33 @@
|
|||
namespace Composer\Repository;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Repository\Pear\ChannelInfo;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Util\RemoteFilesystem;
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Config;
|
||||
use Composer\Downloader\TransportException;
|
||||
|
||||
/**
|
||||
* Builds list of package from PEAR channel.
|
||||
*
|
||||
* Packages read from channel are named as 'pear-{channelName}/{packageName}'
|
||||
* and has aliased as 'pear-{channelAlias}/{packageName}'
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class PearRepository extends ArrayRepository
|
||||
{
|
||||
private static $channelNames = array();
|
||||
|
||||
private $url;
|
||||
private $baseUrl;
|
||||
private $channel;
|
||||
private $io;
|
||||
private $rfs;
|
||||
|
||||
/** @var string vendor makes additional alias for each channel as {prefix}/{packagename}. It allows smoother
|
||||
* package transition to composer-like repositories.
|
||||
*/
|
||||
private $vendorAlias;
|
||||
|
||||
public function __construct(array $repoConfig, IOInterface $io, Config $config, RemoteFilesystem $rfs = null)
|
||||
{
|
||||
if (!preg_match('{^https?://}', $repoConfig['url'])) {
|
||||
|
@ -44,9 +51,9 @@ class PearRepository extends ArrayRepository
|
|||
}
|
||||
|
||||
$this->url = rtrim($repoConfig['url'], '/');
|
||||
$this->channel = !empty($repoConfig['channel']) ? $repoConfig['channel'] : null;
|
||||
$this->io = $io;
|
||||
$this->rfs = $rfs ?: new RemoteFilesystem($this->io);
|
||||
$this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
|
@ -54,341 +61,127 @@ class PearRepository extends ArrayRepository
|
|||
parent::initialize();
|
||||
|
||||
$this->io->write('Initializing PEAR repository '.$this->url);
|
||||
$this->initializeChannel();
|
||||
$this->io->write('Packages names will be prefixed with: pear-'.$this->channel.'/');
|
||||
|
||||
// try to load as a composer repo
|
||||
$reader = new \Composer\Repository\Pear\ChannelReader($this->rfs);
|
||||
try {
|
||||
$json = new JsonFile($this->url.'/packages.json', new RemoteFilesystem($this->io));
|
||||
$packages = $json->read();
|
||||
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Repository is Composer-compatible, loading via packages.json instead of PEAR protocol');
|
||||
}
|
||||
|
||||
$loader = new ArrayLoader();
|
||||
foreach ($packages as $data) {
|
||||
foreach ($data['versions'] as $rev) {
|
||||
if (strpos($rev['name'], 'pear-'.$this->channel) !== 0) {
|
||||
$rev['name'] = 'pear-'.$this->channel.'/'.$rev['name'];
|
||||
}
|
||||
$this->addPackage($loader->load($rev));
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Loaded '.$rev['name'].' '.$rev['version']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
$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;
|
||||
}
|
||||
|
||||
$this->fetchFromServer();
|
||||
}
|
||||
|
||||
protected function initializeChannel()
|
||||
{
|
||||
$channelXML = $this->requestXml($this->url . "/channel.xml");
|
||||
if (!$this->channel) {
|
||||
$this->channel = $channelXML->getElementsByTagName("suggestedalias")->item(0)->nodeValue
|
||||
?: $channelXML->getElementsByTagName("name")->item(0)->nodeValue;
|
||||
}
|
||||
if (!$this->baseUrl) {
|
||||
$this->baseUrl = $channelXML->getElementsByTagName("baseurl")->item(0)->nodeValue
|
||||
? trim($channelXML->getElementsByTagName("baseurl")->item(0)->nodeValue, '/')
|
||||
: $this->url . '/rest';
|
||||
}
|
||||
|
||||
self::$channelNames[$channelXML->getElementsByTagName("name")->item(0)->nodeValue] = $this->channel;
|
||||
}
|
||||
|
||||
protected function fetchFromServer()
|
||||
{
|
||||
$categoryXML = $this->requestXml($this->baseUrl . "/c/categories.xml");
|
||||
$categories = $categoryXML->getElementsByTagName("c");
|
||||
|
||||
foreach ($categories as $category) {
|
||||
$link = $this->baseUrl . '/c/' . str_replace(' ', '+', $category->nodeValue);
|
||||
try {
|
||||
$packagesLink = $link . "/packagesinfo.xml";
|
||||
$this->fetchPear2Packages($packagesLink);
|
||||
} catch (TransportException $e) {
|
||||
if (false === strpos($e->getMessage(), '404')) {
|
||||
throw $e;
|
||||
}
|
||||
$categoryLink = $link . "/packages.xml";
|
||||
$this->fetchPearPackages($categoryLink);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $categoryLink
|
||||
* @throws TransportException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function fetchPearPackages($categoryLink)
|
||||
{
|
||||
$packagesXML = $this->requestXml($categoryLink);
|
||||
$packages = $packagesXML->getElementsByTagName('p');
|
||||
$loader = new ArrayLoader();
|
||||
$packages = $this->buildComposerPackages($channelInfo);
|
||||
foreach ($packages as $package) {
|
||||
$packageName = $package->nodeValue;
|
||||
$fullName = 'pear-'.$this->channel.'/'.$packageName;
|
||||
|
||||
$releaseLink = $this->baseUrl . "/r/" . $packageName;
|
||||
$allReleasesLink = $releaseLink . "/allreleases2.xml";
|
||||
|
||||
try {
|
||||
$releasesXML = $this->requestXml($allReleasesLink);
|
||||
} catch (TransportException $e) {
|
||||
if (strpos($e->getMessage(), '404')) {
|
||||
continue;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$releases = $releasesXML->getElementsByTagName('r');
|
||||
|
||||
foreach ($releases as $release) {
|
||||
/* @var $release \DOMElement */
|
||||
$pearVersion = $release->getElementsByTagName('v')->item(0)->nodeValue;
|
||||
|
||||
$packageData = array(
|
||||
'name' => $fullName,
|
||||
'type' => 'library',
|
||||
'dist' => array('type' => 'pear', 'url' => $this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz"),
|
||||
'version' => $pearVersion,
|
||||
'autoload' => array(
|
||||
'classmap' => array(''),
|
||||
),
|
||||
'include-path' => array('/'),
|
||||
);
|
||||
|
||||
try {
|
||||
$deps = $this->rfs->getContents($this->url, $releaseLink . "/deps.".$pearVersion.".txt", false);
|
||||
} catch (TransportException $e) {
|
||||
if (strpos($e->getMessage(), '404')) {
|
||||
continue;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$packageData += $this->parseDependencies($deps);
|
||||
|
||||
try {
|
||||
$this->addPackage($loader->load($packageData));
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Loaded '.$packageData['name'].' '.$packageData['version']);
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Could not load '.$packageData['name'].' '.$packageData['version'].': '.$e->getMessage());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$this->addPackage($package);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return string
|
||||
* Builds MemoryPackages from PEAR package definition data.
|
||||
*
|
||||
* @param ChannelInfo $channelInfo
|
||||
* @return MemoryPackage
|
||||
*/
|
||||
private function parseVersion(array $data)
|
||||
private function buildComposerPackages(ChannelInfo $channelInfo)
|
||||
{
|
||||
if (!isset($data['min']) && !isset($data['max'])) {
|
||||
return '*';
|
||||
}
|
||||
$versions = array();
|
||||
if (isset($data['min'])) {
|
||||
$versions[] = '>=' . $data['min'];
|
||||
}
|
||||
if (isset($data['max'])) {
|
||||
$versions[] = '<=' . $data['max'];
|
||||
$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) {
|
||||
continue; // skip packages with unparsable versions
|
||||
}
|
||||
|
||||
$composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
|
||||
|
||||
// distribution url must be read from /r/{packageName}/{version}.xml::/r/g:text()
|
||||
// but this location is 'de-facto' standard
|
||||
$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 ($channelInfo->getName() == $packageDefinition->getChannelName()) {
|
||||
$composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
|
||||
$aliasConstraint = new VersionConstraint('==', $normalizedVersion);
|
||||
$replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
|
||||
}
|
||||
|
||||
// alias package with user-specified prefix. it makes private pear channels looks like composer's.
|
||||
if (!empty($this->vendorAlias)) {
|
||||
$composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
|
||||
$aliasConstraint = new VersionConstraint('==', $normalizedVersion);
|
||||
$replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
|
||||
}
|
||||
|
||||
foreach ($releaseInfo->getDependencyInfo()->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 ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
|
||||
foreach ($dependencyConstraints as $dependencyConstraint) {
|
||||
$dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
|
||||
$suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
|
||||
}
|
||||
}
|
||||
|
||||
$package = new 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 implode(',', $versions);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Improve dependencies resolution of pear packages.
|
||||
* @param array $depsOptions
|
||||
* @return array
|
||||
*/
|
||||
private function parseDependenciesOptions(array $depsOptions)
|
||||
private function buildComposerPackageName($pearChannelName, $pearPackageName)
|
||||
{
|
||||
$data = array();
|
||||
foreach ($depsOptions as $name => $options) {
|
||||
// make sure single deps are wrapped in an array
|
||||
if (isset($options['name'])) {
|
||||
$options = array($options);
|
||||
}
|
||||
if ('php' == $name) {
|
||||
$data[$name] = $this->parseVersion($options);
|
||||
} elseif ('package' == $name) {
|
||||
foreach ($options as $key => $value) {
|
||||
if (isset($value['providesextension'])) {
|
||||
// skip PECL dependencies
|
||||
continue;
|
||||
}
|
||||
if (isset($value['uri'])) {
|
||||
// skip uri-based dependencies
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$dataKey = $value['name'];
|
||||
if (false === strpos($dataKey, '/')) {
|
||||
$dataKey = $this->getChannelShorthand($value['channel']).'/'.$dataKey;
|
||||
}
|
||||
$data['pear-'.$dataKey] = $this->parseVersion($value);
|
||||
}
|
||||
}
|
||||
} elseif ('extension' == $name) {
|
||||
foreach ($options as $key => $value) {
|
||||
$dataKey = 'ext-' . $value['name'];
|
||||
$data[$dataKey] = $this->parseVersion($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $deps
|
||||
* @return array
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function parseDependencies($deps)
|
||||
{
|
||||
if (preg_match('((O:([0-9])+:"([^"]+)"))', $deps, $matches)) {
|
||||
if (strlen($matches[3]) == $matches[2]) {
|
||||
throw new \InvalidArgumentException("Invalid dependency data, it contains serialized objects.");
|
||||
}
|
||||
}
|
||||
$deps = (array) @unserialize($deps);
|
||||
unset($deps['required']['pearinstaller']);
|
||||
|
||||
$depsData = array();
|
||||
if (!empty($deps['required'])) {
|
||||
$depsData['require'] = $this->parseDependenciesOptions($deps['required']);
|
||||
}
|
||||
|
||||
if (!empty($deps['optional'])) {
|
||||
$depsData['suggest'] = $this->parseDependenciesOptions($deps['optional']);
|
||||
}
|
||||
|
||||
return $depsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $packagesLink
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private function fetchPear2Packages($packagesLink)
|
||||
{
|
||||
$loader = new ArrayLoader();
|
||||
$packagesXml = $this->requestXml($packagesLink);
|
||||
|
||||
$informations = $packagesXml->getElementsByTagName('pi');
|
||||
foreach ($informations as $information) {
|
||||
$package = $information->getElementsByTagName('p')->item(0);
|
||||
|
||||
$packageName = $package->getElementsByTagName('n')->item(0)->nodeValue;
|
||||
$fullName = 'pear-'.$this->channel.'/'.$packageName;
|
||||
$packageData = array(
|
||||
'name' => $fullName,
|
||||
'type' => 'library',
|
||||
'autoload' => array(
|
||||
'classmap' => array(''),
|
||||
),
|
||||
'include-path' => array('/'),
|
||||
);
|
||||
$packageKeys = array('l' => 'license', 'd' => 'description');
|
||||
foreach ($packageKeys as $pear => $composer) {
|
||||
if ($package->getElementsByTagName($pear)->length > 0
|
||||
&& ($pear = $package->getElementsByTagName($pear)->item(0)->nodeValue)) {
|
||||
$packageData[$composer] = $pear;
|
||||
}
|
||||
}
|
||||
|
||||
$depsData = array();
|
||||
foreach ($information->getElementsByTagName('deps') as $depElement) {
|
||||
$depsVersion = $depElement->getElementsByTagName('v')->item(0)->nodeValue;
|
||||
$depsData[$depsVersion] = $this->parseDependencies(
|
||||
$depElement->getElementsByTagName('d')->item(0)->nodeValue
|
||||
);
|
||||
}
|
||||
|
||||
$releases = $information->getElementsByTagName('a')->item(0);
|
||||
if (!$releases) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$releases = $releases->getElementsByTagName('r');
|
||||
$packageUrl = $this->url . '/get/' . $packageName;
|
||||
foreach ($releases as $release) {
|
||||
$version = $release->getElementsByTagName('v')->item(0)->nodeValue;
|
||||
$releaseData = array(
|
||||
'dist' => array(
|
||||
'type' => 'pear',
|
||||
'url' => $packageUrl . '-' . $version . '.tgz'
|
||||
),
|
||||
'version' => $version
|
||||
);
|
||||
if (isset($depsData[$version])) {
|
||||
$releaseData += $depsData[$version];
|
||||
}
|
||||
|
||||
$package = $packageData + $releaseData;
|
||||
try {
|
||||
$this->addPackage($loader->load($package));
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Loaded '.$package['name'].' '.$package['version']);
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
if ($this->io->isVerbose()) {
|
||||
$this->io->write('Could not load '.$package['name'].' '.$package['version'].': '.$e->getMessage());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($pearChannelName == 'php') {
|
||||
return "php";
|
||||
} elseif ($pearChannelName == 'ext') {
|
||||
return "ext-{$pearPackageName}";
|
||||
} else {
|
||||
return "pear-{$pearChannelName}/{$pearPackageName}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function requestXml($url)
|
||||
protected function parseVersion($version)
|
||||
{
|
||||
$content = $this->rfs->getContents($this->url, $url, false);
|
||||
if (!$content) {
|
||||
throw new \UnexpectedValueException('The PEAR channel at '.$url.' did not respond.');
|
||||
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;
|
||||
}
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->loadXML($content);
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
private function getChannelShorthand($url)
|
||||
{
|
||||
if (!isset(self::$channelNames[$url])) {
|
||||
try {
|
||||
$channelXML = $this->requestXml('http://'.$url."/channel.xml");
|
||||
$shorthand = $channelXML->getElementsByTagName("suggestedalias")->item(0)->nodeValue
|
||||
?: $channelXML->getElementsByTagName("name")->item(0)->nodeValue;
|
||||
self::$channelNames[$url] = $shorthand;
|
||||
} catch (\Exception $e) {
|
||||
self::$channelNames[$url] = substr($url, 0, strpos($url, '.'));
|
||||
}
|
||||
}
|
||||
|
||||
return self::$channelNames[$url];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Test\Mock;
|
||||
|
||||
use Composer\Util\RemoteFilesystem;
|
||||
use Composer\Downloader\TransportException;
|
||||
|
||||
/**
|
||||
* Remote filesystem mock
|
||||
|
@ -29,10 +30,11 @@ class RemoteFilesystemMock extends RemoteFilesystem
|
|||
|
||||
public function getContents($originUrl, $fileUrl, $progress = true)
|
||||
{
|
||||
if(!empty($this->contentMap[$fileUrl]))
|
||||
if (!empty($this->contentMap[$fileUrl])) {
|
||||
return $this->contentMap[$fileUrl];
|
||||
}
|
||||
|
||||
throw new \Composer\Downloader\TransportException('The "'.$fileUrl.'" file could not be downloaded (NOT FOUND)', 404);
|
||||
throw new TransportException('The "'.$fileUrl.'" file could not be downloaded (NOT FOUND)', 404);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Test\TestCase;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Test\Mock\RemoteFilesystemMock;
|
||||
|
||||
class ChannelReaderTest extends TestCase
|
||||
{
|
||||
public function testShouldBuildPackagesFromPearSchema()
|
||||
{
|
||||
$rfs = new RemoteFilesystemMock(array(
|
||||
'http://pear.net/channel.xml' => file_get_contents(__DIR__ . '/Fixtures/channel.1.1.xml'),
|
||||
'http://test.loc/rest11/c/categories.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/categories.xml'),
|
||||
'http://test.loc/rest11/c/Default/packagesinfo.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/packagesinfo.xml'),
|
||||
));
|
||||
|
||||
$reader = new \Composer\Repository\Pear\ChannelReader($rfs);
|
||||
|
||||
$channelInfo = $reader->read('http://pear.net/');
|
||||
$packages = $channelInfo->getPackages();
|
||||
|
||||
$this->assertCount(3, $packages);
|
||||
$this->assertEquals('HTTP_Client', $packages[0]->getPackageName());
|
||||
$this->assertEquals('HTTP_Request', $packages[1]->getPackageName());
|
||||
$this->assertEquals('MDB2', $packages[2]->getPackageName());
|
||||
|
||||
$mdb2releases = $packages[2]->getReleases();
|
||||
$this->assertEquals(9, count($mdb2releases['2.4.0']->getDependencyInfo()->getOptionals()));
|
||||
}
|
||||
|
||||
public function testShouldSelectCorrectReader()
|
||||
{
|
||||
$rfs = new RemoteFilesystemMock(array(
|
||||
'http://pear.1.0.net/channel.xml' => file_get_contents(__DIR__ . '/Fixtures/channel.1.0.xml'),
|
||||
'http://test.loc/rest10/p/packages.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/packages.xml'),
|
||||
'http://test.loc/rest10/p/http_client/info.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_client_info.xml'),
|
||||
'http://test.loc/rest10/p/http_request/info.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_request_info.xml'),
|
||||
'http://pear.1.1.net/channel.xml' => file_get_contents(__DIR__ . '/Fixtures/channel.1.1.xml'),
|
||||
'http://test.loc/rest11/c/categories.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/categories.xml'),
|
||||
'http://test.loc/rest11/c/Default/packagesinfo.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/packagesinfo.xml'),
|
||||
));
|
||||
|
||||
$reader = new \Composer\Repository\Pear\ChannelReader($rfs);
|
||||
|
||||
$reader->read('http://pear.1.0.net/');
|
||||
$reader->read('http://pear.1.1.net/');
|
||||
}
|
||||
|
||||
public function testShouldCreatePackages()
|
||||
{
|
||||
$reader = $this->getMockBuilder('\Composer\Repository\Pear\ChannelReader')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$ref = new \ReflectionMethod($reader, 'buildComposerPackages');
|
||||
$ref->setAccessible(true);
|
||||
|
||||
$packageInfo = new PackageInfo(
|
||||
'test.loc',
|
||||
'sample',
|
||||
'license',
|
||||
'shortDescription',
|
||||
'description',
|
||||
array(
|
||||
'1.0.0.1' => new ReleaseInfo(
|
||||
'stable',
|
||||
new DependencyInfo(
|
||||
array(
|
||||
new DependencyConstraint(
|
||||
'required',
|
||||
'> 5.2.0.0',
|
||||
'php',
|
||||
''
|
||||
),
|
||||
new DependencyConstraint(
|
||||
'conflicts',
|
||||
'== 2.5.6.0',
|
||||
'pear.php.net',
|
||||
'broken'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'*' => array(
|
||||
new DependencyConstraint(
|
||||
'optional',
|
||||
'*',
|
||||
'ext',
|
||||
'xml'
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$packages = $ref->invoke($reader, 'test.loc', 'test', array($packageInfo));
|
||||
|
||||
$expectedPackage = new MemoryPackage('pear-test.loc/sample', '1.0.0.1' , '1.0.0.1');
|
||||
$expectedPackage->setType('library');
|
||||
$expectedPackage->setDistType('pear');
|
||||
$expectedPackage->setDescription('description');
|
||||
$expectedPackage->setDistUrl("http://test.loc/get/sample-1.0.0.1.tgz");
|
||||
$expectedPackage->setAutoload(array('classmap' => array('')));
|
||||
$expectedPackage->setIncludePaths(array('/'));
|
||||
$expectedPackage->setRequires(array(
|
||||
new Link('pear-test.loc/sample', 'php', $this->createConstraint('>', '5.2.0.0'), 'required', '> 5.2.0.0'),
|
||||
));
|
||||
$expectedPackage->setConflicts(array(
|
||||
new Link('pear-test.loc/sample', 'pear-pear.php.net/broken', $this->createConstraint('==', '2.5.6.0'), 'conflicts', '== 2.5.6.0'),
|
||||
));
|
||||
$expectedPackage->setSuggests(array(
|
||||
'*-ext-xml' => '*',
|
||||
));
|
||||
$expectedPackage->setReplaces(array(
|
||||
new Link('pear-test.loc/sample', 'pear-test/sample', new VersionConstraint('==', '1.0.0.1'), 'replaces', '== 1.0.0.1'),
|
||||
));
|
||||
|
||||
$this->assertCount(1, $packages);
|
||||
$this->assertEquals($expectedPackage, $packages[0], 0, 1);
|
||||
}
|
||||
|
||||
private function createConstraint($operator, $version)
|
||||
{
|
||||
$constraint = new VersionConstraint($operator, $version);
|
||||
$constraint->setPrettyString($operator.' '.$version);
|
||||
|
||||
return $constraint;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Test\TestCase;
|
||||
use Composer\Test\Mock\RemoteFilesystemMock;
|
||||
|
||||
class ChannelRest10ReaderTest extends TestCase
|
||||
{
|
||||
public function testShouldBuildPackagesFromPearSchema()
|
||||
{
|
||||
$rfs = new RemoteFilesystemMock(array(
|
||||
'http://test.loc/rest10/p/packages.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/packages.xml'),
|
||||
'http://test.loc/rest10/p/http_client/info.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_client_info.xml'),
|
||||
'http://test.loc/rest10/r/http_client/allreleases.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_client_allreleases.xml'),
|
||||
'http://test.loc/rest10/r/http_client/deps.1.2.1.txt' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_client_deps.1.2.1.txt'),
|
||||
'http://test.loc/rest10/p/http_request/info.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_request_info.xml'),
|
||||
'http://test.loc/rest10/r/http_request/allreleases.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_request_allreleases.xml'),
|
||||
'http://test.loc/rest10/r/http_request/deps.1.4.0.txt' => file_get_contents(__DIR__ . '/Fixtures/Rest1.0/http_request_deps.1.4.0.txt'),
|
||||
));
|
||||
|
||||
$reader = new \Composer\Repository\Pear\ChannelRest10Reader($rfs);
|
||||
|
||||
/** @var $packages \Composer\Package\PackageInterface[] */
|
||||
$packages = $reader->read('http://test.loc/rest10');
|
||||
|
||||
$this->assertCount(2, $packages);
|
||||
$this->assertEquals('HTTP_Client', $packages[0]->getPackageName());
|
||||
$this->assertEquals('HTTP_Request', $packages[1]->getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Test\TestCase;
|
||||
use Composer\Test\Mock\RemoteFilesystemMock;
|
||||
|
||||
class ChannelRest11ReaderTest extends TestCase
|
||||
{
|
||||
public function testShouldBuildPackagesFromPearSchema()
|
||||
{
|
||||
$rfs = new RemoteFilesystemMock(array(
|
||||
'http://pear.1.1.net/channel.xml' => file_get_contents(__DIR__ . '/Fixtures/channel.1.1.xml'),
|
||||
'http://test.loc/rest11/c/categories.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/categories.xml'),
|
||||
'http://test.loc/rest11/c/Default/packagesinfo.xml' => file_get_contents(__DIR__ . '/Fixtures/Rest1.1/packagesinfo.xml'),
|
||||
));
|
||||
|
||||
$reader = new \Composer\Repository\Pear\ChannelRest11Reader($rfs);
|
||||
|
||||
/** @var $packages \Composer\Package\PackageInterface[] */
|
||||
$packages = $reader->read('http://test.loc/rest11');
|
||||
|
||||
$this->assertCount(3, $packages);
|
||||
$this->assertEquals('HTTP_Client', $packages[0]->getPackageName());
|
||||
$this->assertEquals('HTTP_Request', $packages[1]->getPackageName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
[
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : "*",
|
||||
"channel" : "pear.php.net",
|
||||
"name" : "Foo"
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "pkg", "rel": "has", "name": "Foo" }
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"package": {
|
||||
"name": "Foo",
|
||||
"channel": "pear.php.net"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : ">1.0.0.0",
|
||||
"channel" : "pear.php.net",
|
||||
"name" : "Foo"
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "pkg", "rel": "gt", "version": "1.0.0", "name": "Foo" }
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"package": {
|
||||
"name": "Foo",
|
||||
"channel": "pear.php.net",
|
||||
"min": "1.0.0",
|
||||
"exclude": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "conflicts",
|
||||
"constraint" : "*",
|
||||
"channel" : "pear.php.net",
|
||||
"name" : "Foo"
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "pkg", "rel": "not", "name": "Foo" }
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"package": {
|
||||
"name": "Foo",
|
||||
"channel": "pear.php.net",
|
||||
"conflicts": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : ">=1.0.0.0",
|
||||
"channel" : "pear.php.net",
|
||||
"name" : "Foo"
|
||||
},
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : "<2.0.0.0",
|
||||
"channel" : "pear.php.net",
|
||||
"name" : "Foo"
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "pkg", "rel": "ge", "version": "1.0.0", "name": "Foo" },
|
||||
{ "type": "pkg", "rel": "lt", "version": "2.0.0", "name": "Foo" }
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"package": [
|
||||
{
|
||||
"name": "Foo",
|
||||
"channel": "pear.php.net",
|
||||
"min": "1.0.0"
|
||||
},
|
||||
{
|
||||
"name": "Foo",
|
||||
"channel": "pear.php.net",
|
||||
"max": "2.0.0",
|
||||
"exclude": "2.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : ">=5.3.0.0",
|
||||
"channel" : "php",
|
||||
"name" : ""
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "php", "rel": "ge", "version": "5.3"}
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"php": {
|
||||
"min": "5.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "required",
|
||||
"constraint" : "*",
|
||||
"channel" : "ext",
|
||||
"name" : "xmllib"
|
||||
}
|
||||
],
|
||||
"1.0": [
|
||||
{ "type": "ext", "rel": "has", "name": "xmllib"}
|
||||
],
|
||||
"2.0": {
|
||||
"required": {
|
||||
"extension": [
|
||||
{
|
||||
"name": "xmllib"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"expected": [
|
||||
{
|
||||
"type" : "optional",
|
||||
"constraint" : "*",
|
||||
"channel" : "ext",
|
||||
"name" : "xmllib"
|
||||
}
|
||||
],
|
||||
"1.0": false,
|
||||
"2.0": {
|
||||
"optional": {
|
||||
"extension": [
|
||||
{
|
||||
"name": "xmllib"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<a xmlns="http://pear.php.net/dtd/rest.allreleases" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.allreleases http://pear.php.net/dtd/rest.allreleases.xsd">
|
||||
<p>HTTP_Client</p>
|
||||
<c>pear.net</c>
|
||||
<r>
|
||||
<v>1.2.1</v>
|
||||
<s>stable</s>
|
||||
</r>
|
||||
</a>
|
|
@ -0,0 +1 @@
|
|||
a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}s:7:"package";a:3:{s:4:"name";s:12:"HTTP_Request";s:7:"channel";s:8:"pear.net";s:3:"min";s:5:"1.4.0";}}}
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<p xmlns="http://pear.php.net/dtd/rest.package" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.package http://pear.php.net/dtd/rest.package.xsd">
|
||||
<n>HTTP_Client</n>
|
||||
<c>pear.net</c>
|
||||
<ca xlink:href="/rest/c/Default">Default</ca>
|
||||
<l>BSD</l>
|
||||
<s>
|
||||
Easy way to perform multiple HTTP requests and process their results
|
||||
</s>
|
||||
<d>
|
||||
The HTTP_Client class wraps around HTTP_Request and provides a higher level interface for performing multiple HTTP requests. Features: * Manages cookies and referrers between requests * Handles HTTP redirection * Has methods to set default headers and request parameters * Implements the Subject-Observer design pattern: the base class sends events to listeners that do the response processing.
|
||||
</d>
|
||||
<r xlink:href="/rest/r/http_client"/>
|
||||
</p>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<a xmlns="http://pear.php.net/dtd/rest.allreleases" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.allreleases http://pear.php.net/dtd/rest.allreleases.xsd">
|
||||
<p>HTTP_Request</p>
|
||||
<c>pear.net</c>
|
||||
<r>
|
||||
<v>1.4.0</v>
|
||||
<s>stable</s>
|
||||
</r>
|
||||
</a>
|
|
@ -0,0 +1 @@
|
|||
a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.0.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}s:7:"package";a:2:{i:0;a:3:{s:4:"name";s:7:"Net_URL";s:7:"channel";s:12:"pear.dev.loc";s:3:"min";s:6:"1.0.12";}i:1;a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:8:"pear.net";s:3:"min";s:5:"1.0.2";}}}}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<p xmlns="http://pear.php.net/dtd/rest.package" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.package http://pear.php.net/dtd/rest.package.xsd">
|
||||
<n>HTTP_Request</n>
|
||||
<c>pear.net</c>
|
||||
<ca xlink:href="/rest/c/Default">Default</ca>
|
||||
<l>BSD</l>
|
||||
<s>Provides an easy way to perform HTTP requests</s>
|
||||
<d>
|
||||
Supports GET/POST/HEAD/TRACE/PUT/DELETE, Basic authentication, Proxy, Proxy Authentication, SSL, file uploads etc.
|
||||
</d>
|
||||
<r xlink:href="/rest/r/http_request"/>
|
||||
</p>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<a xmlns="http://pear.php.net/dtd/rest.allpackages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.allpackages http://pear.php.net/dtd/rest.allpackages.xsd">
|
||||
<c>pear.net</c>
|
||||
<p>HTTP_Client</p>
|
||||
<p>HTTP_Request</p>
|
||||
</a>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<a xmlns="http://pear.php.net/dtd/rest.allcategories" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.allcategories http://pear.php.net/dtd/rest.allcategories.xsd">
|
||||
<ch>pear.net</ch>
|
||||
<c xlink:href="/rest/c/Default/info.xml">Default</c>
|
||||
</a>
|
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<f xmlns="http://pear.php.net/dtd/rest.categorypackageinfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://pear.php.net/dtd/rest.categorypackageinfo http://pear.php.net/dtd/rest.categorypackageinfo.xsd">
|
||||
<pi>
|
||||
<p>
|
||||
<n>HTTP_Client</n>
|
||||
<c>pear.net</c>
|
||||
<ca xlink:href="/rest/c/Default">Default</ca>
|
||||
<l>BSD</l>
|
||||
<s>
|
||||
Easy way to perform multiple HTTP requests and process their results
|
||||
</s>
|
||||
<d>
|
||||
The HTTP_Client class wraps around HTTP_Request and provides a higher level interface for performing multiple HTTP requests. Features: * Manages cookies and referrers between requests * Handles HTTP redirection * Has methods to set default headers and request parameters * Implements the Subject-Observer design pattern: the base class sends events to listeners that do the response processing.
|
||||
</d>
|
||||
<r xlink:href="/rest/r/http_client"/>
|
||||
</p>
|
||||
<a>
|
||||
<r>
|
||||
<v>1.2.1</v>
|
||||
<s>stable</s>
|
||||
</r>
|
||||
</a>
|
||||
<deps>
|
||||
<v>1.2.1</v>
|
||||
<d>a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:5:"1.4.3";}s:7:"package";a:3:{s:4:"name";s:12:"HTTP_Request";s:7:"channel";s:8:"pear.net";s:3:"min";s:5:"1.4.0";}}}</d>
|
||||
</deps>
|
||||
</pi>
|
||||
<pi>
|
||||
<p>
|
||||
<n>HTTP_Request</n>
|
||||
<c>pear.net</c>
|
||||
<ca xlink:href="/rest/c/Default">Default</ca>
|
||||
<l>BSD</l>
|
||||
<s>Provides an easy way to perform HTTP requests</s>
|
||||
<d>
|
||||
Supports GET/POST/HEAD/TRACE/PUT/DELETE, Basic authentication, Proxy, Proxy Authentication, SSL, file uploads etc.
|
||||
</d>
|
||||
<r xlink:href="/rest/r/http_request"/>
|
||||
</p>
|
||||
<a>
|
||||
<r>
|
||||
<v>1.4.0</v>
|
||||
<s>stable</s>
|
||||
</r>
|
||||
</a>
|
||||
<deps>
|
||||
<v>1.4.0</v>
|
||||
<d>a:1:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.0.0";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}s:7:"package";a:2:{i:0;a:3:{s:4:"name";s:7:"Net_URL";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:6:"1.0.12";}i:1;a:3:{s:4:"name";s:10:"Net_Socket";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.0.2";}}}}</d>
|
||||
</deps>
|
||||
</pi>
|
||||
<pi>
|
||||
<p><n>MDB2</n>
|
||||
<c>pear.net</c>
|
||||
<ca xlink:href="/rest/c/Database">Database</ca>
|
||||
<l>BSD License</l>
|
||||
<s>database abstraction layer</s>
|
||||
<d>PEAR MDB2 is a merge of the PEAR DB and Metabase php database abstraction layers.
|
||||
|
||||
It provides a common API for all supported RDBMS. The main difference to most
|
||||
other DB abstraction packages is that MDB2 goes much further to ensure
|
||||
portability. MDB2 provides most of its many features optionally that
|
||||
can be used to construct portable SQL statements:
|
||||
* Object-Oriented API
|
||||
* A DSN (data source name) or array format for specifying database servers
|
||||
* Datatype abstraction and on demand datatype conversion
|
||||
* Various optional fetch modes to fix portability issues
|
||||
* Portable error codes
|
||||
* Sequential and non sequential row fetching as well as bulk fetching
|
||||
* Ability to make buffered and unbuffered queries
|
||||
* Ordered array and associative array for the fetched rows
|
||||
* Prepare/execute (bind) named and unnamed placeholder emulation
|
||||
* Sequence/autoincrement emulation
|
||||
* Replace emulation
|
||||
* Limited sub select emulation
|
||||
* Row limit emulation
|
||||
* Transactions/savepoint support
|
||||
* Large Object support
|
||||
* Index/Unique Key/Primary Key support
|
||||
* Pattern matching abstraction
|
||||
* Module framework to load advanced functionality on demand
|
||||
* Ability to read the information schema
|
||||
* RDBMS management methods (creating, dropping, altering)
|
||||
* Reverse engineering schemas from an existing database
|
||||
* SQL function call abstraction
|
||||
* Full integration into the PEAR Framework
|
||||
* PHPDoc API documentation</d>
|
||||
<r xlink:href="/rest/r/mdb2"/>
|
||||
</p>
|
||||
<a>
|
||||
<r><v>2.4.0</v><s>stable</s></r>
|
||||
</a>
|
||||
<deps>
|
||||
<v>2.4.0</v>
|
||||
<d>a:2:{s:8:"required";a:3:{s:3:"php";a:1:{s:3:"min";s:5:"4.3.2";}s:13:"pearinstaller";a:1:{s:3:"min";s:7:"1.4.0b1";}s:7:"package";a:3:{s:4:"name";s:4:"PEAR";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.3.6";}}s:5:"group";a:9:{i:0;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:29:"Frontbase SQL driver for MDB2";s:4:"name";s:5:"fbsql";}s:10:"subpackage";a:3:{s:4:"name";s:17:"MDB2_Driver_fbsql";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.3.0";}}i:1;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:34:"Interbase/Firebird driver for MDB2";s:4:"name";s:5:"ibase";}s:10:"subpackage";a:3:{s:4:"name";s:17:"MDB2_Driver_ibase";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}i:2;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:21:"MySQL driver for MDB2";s:4:"name";s:5:"mysql";}s:10:"subpackage";a:3:{s:4:"name";s:17:"MDB2_Driver_mysql";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}i:3;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:22:"MySQLi driver for MDB2";s:4:"name";s:6:"mysqli";}s:10:"subpackage";a:3:{s:4:"name";s:18:"MDB2_Driver_mysqli";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}i:4;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:29:"MS SQL Server driver for MDB2";s:4:"name";s:5:"mssql";}s:10:"subpackage";a:3:{s:4:"name";s:17:"MDB2_Driver_mssql";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.2.0";}}i:5;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:22:"Oracle driver for MDB2";s:4:"name";s:4:"oci8";}s:10:"subpackage";a:3:{s:4:"name";s:16:"MDB2_Driver_oci8";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}i:6;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:26:"PostgreSQL driver for MDB2";s:4:"name";s:5:"pgsql";}s:10:"subpackage";a:3:{s:4:"name";s:17:"MDB2_Driver_pgsql";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}i:7;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:24:"Querysim driver for MDB2";s:4:"name";s:8:"querysim";}s:10:"subpackage";a:3:{s:4:"name";s:20:"MDB2_Driver_querysim";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"0.6.0";}}i:8;a:2:{s:7:"attribs";a:2:{s:4:"hint";s:23:"SQLite2 driver for MDB2";s:4:"name";s:6:"sqlite";}s:10:"subpackage";a:3:{s:4:"name";s:18:"MDB2_Driver_sqlite";s:7:"channel";s:12:"pear.php.net";s:3:"min";s:5:"1.4.0";}}}}</d>
|
||||
</deps>
|
||||
</pi>
|
||||
</f>
|
|
@ -0,0 +1,12 @@
|
|||
<channel xmlns="http://pear.php.net/channel-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd">
|
||||
<name>pear.net</name>
|
||||
<summary>Test PEAR channel</summary>
|
||||
<suggestedalias>test_alias</suggestedalias>
|
||||
<servers>
|
||||
<primary>
|
||||
<rest>
|
||||
<baseurl type="REST1.0">http://test.loc/rest10/</baseurl>
|
||||
</rest>
|
||||
</primary>
|
||||
</servers>
|
||||
</channel>
|
|
@ -0,0 +1,12 @@
|
|||
<channel xmlns="http://pear.php.net/channel-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd">
|
||||
<name>pear.net</name>
|
||||
<summary>Test PEAR channel</summary>
|
||||
<suggestedalias>test_alias</suggestedalias>
|
||||
<servers>
|
||||
<primary>
|
||||
<rest>
|
||||
<baseurl type="REST1.1">http://test.loc/rest11/</baseurl>
|
||||
</rest>
|
||||
</primary>
|
||||
</servers>
|
||||
</channel>
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Repository\Pear;
|
||||
|
||||
use Composer\Test\TestCase;
|
||||
|
||||
class PackageDependencyParserTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider dataProvider10
|
||||
* @param $expected
|
||||
* @param $data
|
||||
*/
|
||||
public function testShouldParseDependencies($expected, $data10, $data20)
|
||||
{
|
||||
$expectedDependencies = array();
|
||||
foreach ($expected as $expectedItem) {
|
||||
$expectedDependencies[] = new DependencyConstraint(
|
||||
$expectedItem['type'],
|
||||
$expectedItem['constraint'],
|
||||
$expectedItem['channel'],
|
||||
$expectedItem['name']
|
||||
);
|
||||
}
|
||||
|
||||
$parser = new PackageDependencyParser();
|
||||
|
||||
if (false !== $data10) {
|
||||
$result = $parser->buildDependencyInfo($data10);
|
||||
$this->assertEquals($expectedDependencies, $result->getRequires() + $result->getOptionals(), "Failed for package.xml 1.0 format");
|
||||
}
|
||||
|
||||
if (false !== $data20) {
|
||||
$result = $parser->buildDependencyInfo($data20);
|
||||
$this->assertEquals($expectedDependencies, $result->getRequires() + $result->getOptionals(), "Failed for package.xml 2.0 format");
|
||||
}
|
||||
}
|
||||
|
||||
public function dataProvider10()
|
||||
{
|
||||
$data = json_decode(file_get_contents(__DIR__.'/Fixtures/DependencyParserTestData.json'), true);
|
||||
if (0 !== json_last_error()) {
|
||||
throw new \PHPUnit_Framework_Exception('Invalid json file.');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -29,11 +29,11 @@ class PearRepositoryTest extends TestCase
|
|||
*/
|
||||
private $remoteFilesystem;
|
||||
|
||||
public function testComposerNonCompatibleRepositoryShouldSetIncludePath()
|
||||
public function testComposerShouldSetIncludePath()
|
||||
{
|
||||
$url = 'pear.phpmd.org';
|
||||
$expectedPackages = array(
|
||||
array('name' => 'pear-phpmd/PHP_PMD', 'version' => '1.3.3'),
|
||||
array('name' => 'pear-pear.phpmd.org/PHP_PMD', 'version' => '1.3.3'),
|
||||
);
|
||||
|
||||
$repoConfig = array(
|
||||
|
@ -78,53 +78,47 @@ class PearRepositoryTest extends TestCase
|
|||
public function repositoryDataProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'pear.phpunit.de',
|
||||
array(
|
||||
array('name' => 'pear-phpunit/PHPUnit_MockObject', 'version' => '1.1.1'),
|
||||
array('name' => 'pear-phpunit/PHPUnit', 'version' => '3.6.10'),
|
||||
array('name' => 'pear-pear.phpunit.de/PHPUnit_MockObject', 'version' => '1.1.1'),
|
||||
array('name' => 'pear-pear.phpunit.de/PHPUnit', 'version' => '3.6.10'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.php.net',
|
||||
array(
|
||||
array('name' => 'pear-pear/PEAR', 'version' => '1.9.4'),
|
||||
array('name' => 'pear-pear.php.net/PEAR', 'version' => '1.9.4'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.pdepend.org',
|
||||
array(
|
||||
array('name' => 'pear-pdepend/PHP_Depend', 'version' => '1.0.5'),
|
||||
array('name' => 'pear-pear.pdepend.org/PHP_Depend', 'version' => '1.0.5'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.phpmd.org',
|
||||
array(
|
||||
array('name' => 'pear-phpmd/PHP_PMD', 'version' => '1.3.3'),
|
||||
array('name' => 'pear-pear.phpmd.org/PHP_PMD', 'version' => '1.3.3'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.doctrine-project.org',
|
||||
array(
|
||||
array('name' => 'pear-doctrine/DoctrineORM', 'version' => '2.2.2'),
|
||||
array('name' => 'pear-pear.doctrine-project.org/DoctrineORM', 'version' => '2.2.2'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.symfony-project.com',
|
||||
array(
|
||||
array('name' => 'pear-symfony/YAML', 'version' => '1.0.6'),
|
||||
array('name' => 'pear-pear.symfony-project.com/YAML', 'version' => '1.0.6'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'pear.pirum-project.org',
|
||||
array(
|
||||
array('name' => 'pear-pirum/Pirum', 'version' => '1.1.4'),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'packages.zendframework.com',
|
||||
array(
|
||||
array('name' => 'pear-zf2/Zend_Code', 'version' => '2.0.0.0-beta3'),
|
||||
array('name' => 'pear-pear.pirum-project.org/Pirum', 'version' => '1.1.4'),
|
||||
)
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue