2011-04-17 22:14:44 +00:00
< ? 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 ;
2011-09-20 21:34:06 +00:00
use Composer\Package\Loader\ArrayLoader ;
2012-04-13 00:58:40 +00:00
use Composer\Package\PackageInterface ;
2012-10-13 16:54:48 +00:00
use Composer\Package\AliasPackage ;
2012-08-20 13:44:45 +00:00
use Composer\Package\Version\VersionParser ;
2012-10-13 16:54:48 +00:00
use Composer\DependencyResolver\Pool ;
2011-10-01 13:01:33 +00:00
use Composer\Json\JsonFile ;
2012-04-06 20:39:43 +00:00
use Composer\Cache ;
2012-04-09 14:36:06 +00:00
use Composer\Config ;
2012-03-18 20:04:15 +00:00
use Composer\IO\IOInterface ;
use Composer\Util\RemoteFilesystem ;
2013-11-19 16:45:28 +00:00
use Composer\Plugin\PluginEvents ;
use Composer\Plugin\PreFileDownloadEvent ;
use Composer\EventDispatcher\EventDispatcher ;
2015-06-18 16:44:58 +00:00
use Composer\Package\LinkConstraint\LinkConstraintInterface ;
use Composer\Package\LinkConstraint\VersionConstraint ;
2011-04-17 22:14:44 +00:00
/**
* @ author Jordi Boggiano < j . boggiano @ seld . be >
*/
2014-11-20 16:23:51 +00:00
class ComposerRepository extends ArrayRepository
2011-04-17 22:14:44 +00:00
{
2012-04-13 00:58:40 +00:00
protected $config ;
2012-10-03 09:56:31 +00:00
protected $options ;
2011-09-20 21:34:06 +00:00
protected $url ;
2012-10-14 14:33:53 +00:00
protected $baseUrl ;
2012-03-18 20:04:15 +00:00
protected $io ;
2013-02-21 15:50:04 +00:00
protected $rfs ;
2012-04-06 20:39:43 +00:00
protected $cache ;
2012-04-13 00:58:40 +00:00
protected $notifyUrl ;
2013-03-10 12:27:49 +00:00
protected $searchUrl ;
2012-10-14 14:33:53 +00:00
protected $hasProviders = false ;
2013-02-21 15:50:04 +00:00
protected $providersUrl ;
2013-07-01 23:46:20 +00:00
protected $lazyProvidersUrl ;
2012-10-14 14:33:53 +00:00
protected $providerListing ;
2015-06-18 13:40:27 +00:00
protected $providers = array ();
protected $providersByUid = array ();
2012-08-20 13:44:45 +00:00
protected $loader ;
2012-10-24 14:11:32 +00:00
protected $rootAliases ;
2013-02-21 16:37:18 +00:00
protected $allowSslDowngrade = false ;
2013-11-19 16:45:28 +00:00
protected $eventDispatcher ;
2013-07-01 23:45:43 +00:00
protected $sourceMirrors ;
protected $distMirrors ;
2012-10-11 19:26:11 +00:00
private $degradedMode = false ;
2012-10-01 11:58:01 +00:00
private $rootData ;
2011-04-17 22:14:44 +00:00
2013-11-19 16:45:28 +00:00
public function __construct ( array $repoConfig , IOInterface $io , Config $config , EventDispatcher $eventDispatcher = null )
2011-04-17 22:14:44 +00:00
{
2012-10-11 18:54:59 +00:00
if ( ! preg_match ( '{^[\w.]+\??://}' , $repoConfig [ 'url' ])) {
2011-12-12 09:57:57 +00:00
// assume http as the default protocol
2012-04-09 14:36:06 +00:00
$repoConfig [ 'url' ] = 'http://' . $repoConfig [ 'url' ];
2011-12-03 11:43:38 +00:00
}
2012-04-09 14:36:06 +00:00
$repoConfig [ 'url' ] = rtrim ( $repoConfig [ 'url' ], '/' );
2012-10-11 18:54:59 +00:00
if ( 'https?' === substr ( $repoConfig [ 'url' ], 0 , 6 )) {
$repoConfig [ 'url' ] = ( extension_loaded ( 'openssl' ) ? 'https' : 'http' ) . substr ( $repoConfig [ 'url' ], 6 );
}
2012-11-05 14:39:43 +00:00
$urlBits = parse_url ( $repoConfig [ 'url' ]);
2013-10-30 16:46:35 +00:00
if ( $urlBits === false || empty ( $urlBits [ 'scheme' ])) {
2012-04-09 14:36:06 +00:00
throw new \UnexpectedValueException ( 'Invalid url given for Composer repository: ' . $repoConfig [ 'url' ]);
2011-09-20 21:34:06 +00:00
}
2012-10-03 09:56:31 +00:00
if ( ! isset ( $repoConfig [ 'options' ])) {
$repoConfig [ 'options' ] = array ();
}
2013-02-21 16:37:18 +00:00
if ( isset ( $repoConfig [ 'allow_ssl_downgrade' ]) && true === $repoConfig [ 'allow_ssl_downgrade' ]) {
$this -> allowSslDowngrade = true ;
}
2012-10-03 09:56:31 +00:00
2012-04-13 00:58:40 +00:00
$this -> config = $config ;
2012-10-03 09:56:31 +00:00
$this -> options = $repoConfig [ 'options' ];
2012-04-09 14:36:06 +00:00
$this -> url = $repoConfig [ 'url' ];
2014-12-08 22:04:10 +00:00
$this -> baseUrl = rtrim ( preg_replace ( '{^(.*)(?:/[^/\\]+.json)?(?:[?#].*)?$}' , '$1' , $this -> url ), '/' );
2012-03-18 20:04:15 +00:00
$this -> io = $io ;
2013-02-21 15:50:04 +00:00
$this -> cache = new Cache ( $io , $config -> get ( 'cache-repo-dir' ) . '/' . preg_replace ( '{[^a-z0-9.]}i' , '-' , $this -> url ), 'a-z0-9.$' );
2012-08-20 13:44:45 +00:00
$this -> loader = new ArrayLoader ();
2014-04-11 12:27:14 +00:00
$this -> rfs = new RemoteFilesystem ( $this -> io , $this -> config , $this -> options );
2013-11-19 16:45:28 +00:00
$this -> eventDispatcher = $eventDispatcher ;
2011-04-17 22:14:44 +00:00
}
2012-10-24 14:11:32 +00:00
public function setRootAliases ( array $rootAliases )
{
$this -> rootAliases = $rootAliases ;
}
2014-05-13 21:54:48 +00:00
/**
* { @ inheritDoc }
*/
2015-06-18 16:44:58 +00:00
public function findPackage ( $name , $constraint )
2014-05-13 21:54:48 +00:00
{
2014-10-17 07:10:47 +00:00
if ( ! $this -> hasProviders ()) {
2015-06-18 16:44:58 +00:00
return parent :: findPackage ( $name , $constraint );
2014-10-17 07:10:47 +00:00
}
2015-06-18 16:44:58 +00:00
2014-05-13 21:54:48 +00:00
$name = strtolower ( $name );
2015-06-18 16:44:58 +00:00
if ( ! $constraint instanceof LinkConstraintInterface ) {
$versionParser = new VersionParser ();
$constraint = $versionParser -> parseConstraints ( $constraint );
}
2014-05-13 21:54:48 +00:00
foreach ( $this -> getProviderNames () as $providerName ) {
if ( $name === $providerName ) {
2015-06-18 13:40:27 +00:00
$packages = $this -> whatProvides ( new Pool ( 'dev' ), $providerName );
2014-05-13 21:54:48 +00:00
foreach ( $packages as $package ) {
2015-06-18 16:44:58 +00:00
if ( $name === $package -> getName ()) {
$pkgConstraint = new VersionConstraint ( '==' , $package -> getVersion ());
if ( $constraint -> matches ( $pkgConstraint )) {
return $package ;
}
2014-05-13 21:54:48 +00:00
}
}
}
}
}
/**
* { @ inheritDoc }
*/
2015-06-18 16:44:58 +00:00
public function findPackages ( $name , $constraint = null )
2014-05-13 21:54:48 +00:00
{
2014-10-17 07:10:47 +00:00
if ( ! $this -> hasProviders ()) {
2015-06-18 16:44:58 +00:00
return parent :: findPackages ( $name , $constraint );
2014-10-17 07:10:47 +00:00
}
2014-05-13 21:54:48 +00:00
// normalize name
$name = strtolower ( $name );
2015-06-18 16:44:58 +00:00
if ( null !== $constraint && ! $constraint instanceof LinkConstraintInterface ) {
2014-05-13 21:54:48 +00:00
$versionParser = new VersionParser ();
2015-06-18 16:44:58 +00:00
$constraint = $versionParser -> parseConstraints ( $constraint );
2014-05-13 21:54:48 +00:00
}
$packages = array ();
foreach ( $this -> getProviderNames () as $providerName ) {
if ( $name === $providerName ) {
2015-06-18 16:44:58 +00:00
$candidates = $this -> whatProvides ( new Pool ( 'dev' ), $providerName );
foreach ( $candidates as $package ) {
if ( $name === $package -> getName ()) {
$pkgConstraint = new VersionConstraint ( '==' , $package -> getVersion ());
if ( null === $constraint || $constraint -> matches ( $pkgConstraint )) {
$packages [] = $package ;
}
2014-05-13 21:54:48 +00:00
}
}
}
}
return $packages ;
}
2013-03-10 12:33:41 +00:00
public function getPackages ()
{
if ( $this -> hasProviders ()) {
throw new \LogicException ( 'Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.' );
}
return parent :: getPackages ();
}
2012-08-23 17:16:23 +00:00
/**
* { @ inheritDoc }
*/
2013-03-10 12:32:59 +00:00
public function search ( $query , $mode = 0 )
2012-08-23 17:16:23 +00:00
{
2013-03-10 12:32:59 +00:00
$this -> loadRootServerFile ();
if ( $this -> searchUrl && $mode === self :: SEARCH_FULLTEXT ) {
$url = str_replace ( '%query%' , $query , $this -> searchUrl );
2014-05-07 16:38:58 +00:00
$hostname = parse_url ( $url , PHP_URL_HOST ) ? : $url ;
$json = $this -> rfs -> getContents ( $hostname , $url , false );
2013-03-10 12:32:59 +00:00
$results = JsonFile :: parseJson ( $json , $url );
return $results [ 'results' ];
2012-08-24 00:29:03 +00:00
}
2012-08-23 17:16:23 +00:00
2013-03-10 12:32:59 +00:00
if ( $this -> hasProviders ()) {
$results = array ();
$regex = '{(?:' . implode ( '|' , preg_split ( '{\s+}' , $query )) . ')}i' ;
foreach ( $this -> getProviderNames () as $name ) {
if ( preg_match ( $regex , $name )) {
$results [] = array ( 'name' => $name );
2012-08-23 17:16:23 +00:00
}
}
2013-03-10 12:32:59 +00:00
return $results ;
}
return parent :: search ( $query , $mode );
}
public function getProviderNames ()
{
$this -> loadRootServerFile ();
if ( null === $this -> providerListing ) {
$this -> loadProviderListings ( $this -> loadRootServerFile ());
}
2015-01-31 21:24:33 +00:00
if ( $this -> lazyProvidersUrl ) {
// Can not determine list of provided packages for lazy repositories
return array ();
}
2013-03-10 12:32:59 +00:00
if ( $this -> providersUrl ) {
return array_keys ( $this -> providerListing );
}
// BC handling for old providers-includes
$providers = array ();
foreach ( array_keys ( $this -> providerListing ) as $provider ) {
$providers [] = substr ( $provider , 2 , - 5 );
2012-08-23 17:16:23 +00:00
}
2013-03-10 12:32:59 +00:00
return $providers ;
2012-08-23 17:16:23 +00:00
}
2014-05-07 17:10:55 +00:00
protected function configurePackageTransportOptions ( PackageInterface $package )
2013-08-19 07:40:54 +00:00
{
2014-05-07 17:12:58 +00:00
foreach ( $package -> getDistUrls () as $url ) {
if ( strpos ( $url , $this -> baseUrl ) === 0 ) {
$package -> setTransportOptions ( $this -> options );
2014-06-10 14:02:44 +00:00
2014-05-07 17:12:58 +00:00
return ;
}
2013-08-19 07:40:54 +00:00
}
}
2012-10-01 11:58:01 +00:00
public function hasProviders ()
{
$this -> loadRootServerFile ();
2012-10-14 14:33:53 +00:00
return $this -> hasProviders ;
2012-10-01 11:58:01 +00:00
}
2015-06-18 13:40:27 +00:00
public function resetPackageIds ()
{
foreach ( $this -> providersByUid as $package ) {
if ( $package instanceof AliasPackage ) {
$package -> getAliasOf () -> setId ( - 1 );
}
$package -> setId ( - 1 );
}
}
public function whatProvides ( Pool $pool , $name )
2012-10-01 11:58:01 +00:00
{
2015-06-18 13:40:27 +00:00
if ( isset ( $this -> providers [ $name ])) {
return $this -> providers [ $name ];
}
2013-03-10 12:32:59 +00:00
// skip platform packages
2013-04-06 20:26:10 +00:00
if ( preg_match ( PlatformRepository :: PLATFORM_PACKAGE_REGEX , $name ) || '__root__' === $name ) {
2013-03-10 12:32:59 +00:00
return array ();
}
2012-10-14 14:33:53 +00:00
if ( null === $this -> providerListing ) {
$this -> loadProviderListings ( $this -> loadRootServerFile ());
}
2012-10-01 11:58:01 +00:00
2013-07-01 23:46:20 +00:00
if ( $this -> lazyProvidersUrl && ! isset ( $this -> providerListing [ $name ])) {
2014-05-14 09:25:20 +00:00
$hash = null ;
2013-07-01 23:46:20 +00:00
$url = str_replace ( '%package%' , $name , $this -> lazyProvidersUrl );
$cacheKey = false ;
} elseif ( $this -> providersUrl ) {
2013-02-21 15:50:04 +00:00
// package does not exist in this repo
if ( ! isset ( $this -> providerListing [ $name ])) {
return array ();
}
2012-10-14 14:33:53 +00:00
2013-02-21 15:50:04 +00:00
$hash = $this -> providerListing [ $name ][ 'sha256' ];
$url = str_replace ( array ( '%package%' , '%hash%' ), array ( $name , $hash ), $this -> providersUrl );
$cacheKey = 'provider-' . strtr ( $name , '/' , '$' ) . '.json' ;
} else {
// BC handling for old providers-includes
$url = 'p/' . $name . '.json' ;
// package does not exist in this repo
if ( ! isset ( $this -> providerListing [ $url ])) {
return array ();
}
$hash = $this -> providerListing [ $url ][ 'sha256' ];
$cacheKey = null ;
2012-10-14 14:33:53 +00:00
}
2013-07-01 23:46:20 +00:00
if ( $cacheKey && $this -> cache -> sha256 ( $cacheKey ) === $hash ) {
2013-02-21 15:50:04 +00:00
$packages = json_decode ( $this -> cache -> read ( $cacheKey ), true );
2012-10-14 14:33:53 +00:00
} else {
2013-02-21 15:50:04 +00:00
$packages = $this -> fetchFile ( $url , $cacheKey , $hash );
2012-10-01 11:58:01 +00:00
}
2015-06-18 13:40:27 +00:00
$this -> providers [ $name ] = array ();
foreach ( $packages [ 'packages' ] as $versions ) {
2015-06-08 16:50:15 +00:00
foreach ( $versions as $version ) {
2015-06-18 13:40:27 +00:00
// avoid loading the same objects twice
if ( isset ( $this -> providersByUid [ $version [ 'uid' ]])) {
// skip if already assigned
if ( ! isset ( $this -> providers [ $name ][ $version [ 'uid' ]])) {
// expand alias in two packages
if ( $this -> providersByUid [ $version [ 'uid' ]] instanceof AliasPackage ) {
$this -> providers [ $name ][ $version [ 'uid' ]] = $this -> providersByUid [ $version [ 'uid' ]] -> getAliasOf ();
$this -> providers [ $name ][ $version [ 'uid' ] . '-alias' ] = $this -> providersByUid [ $version [ 'uid' ]];
} else {
$this -> providers [ $name ][ $version [ 'uid' ]] = $this -> providersByUid [ $version [ 'uid' ]];
}
// check for root aliases
if ( isset ( $this -> providersByUid [ $version [ 'uid' ] . '-root' ])) {
$this -> providers [ $name ][ $version [ 'uid' ] . '-root' ] = $this -> providersByUid [ $version [ 'uid' ] . '-root' ];
}
}
} else {
if ( ! $pool -> isPackageAcceptable ( strtolower ( $version [ 'name' ]), VersionParser :: parseStability ( $version [ 'version' ]))) {
continue ;
}
2012-10-24 14:11:32 +00:00
2015-06-18 13:40:27 +00:00
// load acceptable packages in the providers
$package = $this -> createPackage ( $version , 'Composer\Package\Package' );
$package -> setRepository ( $this );
2012-10-24 14:11:32 +00:00
2015-06-18 13:40:27 +00:00
if ( $package instanceof AliasPackage ) {
$aliased = $package -> getAliasOf ();
$aliased -> setRepository ( $this );
$this -> providers [ $name ][ $version [ 'uid' ]] = $aliased ;
$this -> providers [ $name ][ $version [ 'uid' ] . '-alias' ] = $package ;
// override provider with its alias so it can be expanded in the if block above
$this -> providersByUid [ $version [ 'uid' ]] = $package ;
} else {
$this -> providers [ $name ][ $version [ 'uid' ]] = $package ;
$this -> providersByUid [ $version [ 'uid' ]] = $package ;
}
2012-10-24 14:11:32 +00:00
2015-06-18 13:40:27 +00:00
// handle root package aliases
unset ( $rootAliasData );
if ( isset ( $this -> rootAliases [ $package -> getName ()][ $package -> getVersion ()])) {
$rootAliasData = $this -> rootAliases [ $package -> getName ()][ $package -> getVersion ()];
} elseif ( $package instanceof AliasPackage && isset ( $this -> rootAliases [ $package -> getName ()][ $package -> getAliasOf () -> getVersion ()])) {
$rootAliasData = $this -> rootAliases [ $package -> getName ()][ $package -> getAliasOf () -> getVersion ()];
}
if ( isset ( $rootAliasData )) {
$alias = $this -> createAliasPackage ( $package , $rootAliasData [ 'alias_normalized' ], $rootAliasData [ 'alias' ]);
$alias -> setRepository ( $this );
$this -> providers [ $name ][ $version [ 'uid' ] . '-root' ] = $alias ;
$this -> providersByUid [ $version [ 'uid' ] . '-root' ] = $alias ;
}
2012-10-01 11:58:01 +00:00
}
}
}
2015-06-18 13:40:27 +00:00
return $this -> providers [ $name ];
2012-10-01 11:58:01 +00:00
}
2012-08-22 15:47:05 +00:00
/**
* { @ inheritDoc }
*/
2011-04-17 22:14:44 +00:00
protected function initialize ()
{
parent :: initialize ();
2012-04-06 20:39:43 +00:00
2012-08-20 13:44:45 +00:00
$repoData = $this -> loadDataFromServer ();
foreach ( $repoData as $package ) {
2012-09-08 00:00:02 +00:00
$this -> addPackage ( $this -> createPackage ( $package , 'Composer\Package\CompletePackage' ));
2012-08-20 13:44:45 +00:00
}
}
2013-08-19 07:40:54 +00:00
/**
* Adds a new package to the repository
*
* @ param PackageInterface $package
*/
public function addPackage ( PackageInterface $package )
{
parent :: addPackage ( $package );
2014-05-07 17:10:55 +00:00
$this -> configurePackageTransportOptions ( $package );
2013-08-19 07:40:54 +00:00
}
2012-10-01 11:58:01 +00:00
protected function loadRootServerFile ()
2012-08-20 13:44:45 +00:00
{
2012-10-01 11:58:01 +00:00
if ( null !== $this -> rootData ) {
return $this -> rootData ;
}
2012-07-20 08:27:02 +00:00
if ( ! extension_loaded ( 'openssl' ) && 'https' === substr ( $this -> url , 0 , 5 )) {
throw new \RuntimeException ( 'You must enable the openssl extension in your php.ini to load information from ' . $this -> url );
}
2012-10-11 19:26:11 +00:00
$jsonUrlParts = parse_url ( $this -> url );
2012-08-29 13:12:08 +00:00
2014-12-08 22:04:10 +00:00
if ( isset ( $jsonUrlParts [ 'path' ]) && false !== strpos ( $jsonUrlParts [ 'path' ], '.json' )) {
2012-10-11 19:26:11 +00:00
$jsonUrl = $this -> url ;
} else {
$jsonUrl = $this -> url . '/packages.json' ;
}
2012-04-13 00:58:40 +00:00
2012-10-11 19:26:11 +00:00
$data = $this -> fetchFile ( $jsonUrl , 'packages.json' );
2012-04-13 00:58:40 +00:00
2013-02-21 15:50:04 +00:00
if ( ! empty ( $data [ 'notify-batch' ])) {
2013-03-10 12:27:49 +00:00
$this -> notifyUrl = $this -> canonicalizeUrl ( $data [ 'notify-batch' ]);
} elseif ( ! empty ( $data [ 'notify_batch' ])) {
// TODO remove this BC notify_batch support
$this -> notifyUrl = $this -> canonicalizeUrl ( $data [ 'notify_batch' ]);
} elseif ( ! empty ( $data [ 'notify' ])) {
$this -> notifyUrl = $this -> canonicalizeUrl ( $data [ 'notify' ]);
2012-11-28 17:44:49 +00:00
}
2013-03-10 12:27:49 +00:00
if ( ! empty ( $data [ 'search' ])) {
$this -> searchUrl = $this -> canonicalizeUrl ( $data [ 'search' ]);
2012-04-06 20:39:43 +00:00
}
2012-04-06 18:40:31 +00:00
2013-07-01 23:45:43 +00:00
if ( ! empty ( $data [ 'mirrors' ])) {
foreach ( $data [ 'mirrors' ] as $mirror ) {
2013-10-19 15:41:29 +00:00
if ( ! empty ( $mirror [ 'git-url' ])) {
$this -> sourceMirrors [ 'git' ][] = array ( 'url' => $mirror [ 'git-url' ], 'preferred' => ! empty ( $mirror [ 'preferred' ]));
}
if ( ! empty ( $mirror [ 'hg-url' ])) {
$this -> sourceMirrors [ 'hg' ][] = array ( 'url' => $mirror [ 'hg-url' ], 'preferred' => ! empty ( $mirror [ 'preferred' ]));
2013-07-01 23:45:43 +00:00
}
if ( ! empty ( $mirror [ 'dist-url' ])) {
$this -> distMirrors [] = array ( 'url' => $mirror [ 'dist-url' ], 'preferred' => ! empty ( $mirror [ 'preferred' ]));
}
}
}
2013-10-19 15:41:29 +00:00
if ( ! empty ( $data [ 'warning' ])) {
2015-02-06 12:52:44 +00:00
$this -> io -> writeError ( '<warning>Warning from ' . $this -> url . ': ' . $data [ 'warning' ] . '</warning>' );
2013-10-19 15:41:29 +00:00
}
2013-07-01 23:46:20 +00:00
if ( ! empty ( $data [ 'providers-lazy-url' ])) {
$this -> lazyProvidersUrl = $this -> canonicalizeUrl ( $data [ 'providers-lazy-url' ]);
$this -> hasProviders = true ;
}
2013-02-27 12:32:21 +00:00
if ( $this -> allowSslDowngrade ) {
$this -> url = str_replace ( 'https://' , 'http://' , $this -> url );
2015-06-10 16:13:56 +00:00
$this -> baseUrl = str_replace ( 'https://' , 'http://' , $this -> baseUrl );
2013-02-27 12:32:21 +00:00
}
2013-02-21 15:50:04 +00:00
if ( ! empty ( $data [ 'providers-url' ])) {
2013-03-10 12:27:49 +00:00
$this -> providersUrl = $this -> canonicalizeUrl ( $data [ 'providers-url' ]);
2013-02-21 15:50:04 +00:00
$this -> hasProviders = true ;
}
2012-10-14 14:33:53 +00:00
if ( ! empty ( $data [ 'providers' ]) || ! empty ( $data [ 'providers-includes' ])) {
$this -> hasProviders = true ;
2012-10-01 11:58:01 +00:00
}
return $this -> rootData = $data ;
}
2013-03-10 12:27:49 +00:00
protected function canonicalizeUrl ( $url )
{
if ( '/' === $url [ 0 ]) {
return preg_replace ( '{(https?://[^/]+).*}i' , '$1' . $url , $this -> url );
}
return $url ;
}
2012-10-01 11:58:01 +00:00
protected function loadDataFromServer ()
{
$data = $this -> loadRootServerFile ();
2012-08-20 13:44:45 +00:00
return $this -> loadIncludes ( $data );
2012-04-06 18:40:31 +00:00
}
2012-10-14 14:33:53 +00:00
protected function loadProviderListings ( $data )
{
if ( isset ( $data [ 'providers' ])) {
if ( ! is_array ( $this -> providerListing )) {
$this -> providerListing = array ();
}
$this -> providerListing = array_merge ( $this -> providerListing , $data [ 'providers' ]);
}
2013-02-21 15:50:04 +00:00
if ( $this -> providersUrl && isset ( $data [ 'provider-includes' ])) {
$includes = $data [ 'provider-includes' ];
2013-02-21 17:51:22 +00:00
foreach ( $includes as $include => $metadata ) {
$url = $this -> baseUrl . '/' . str_replace ( '%hash%' , $metadata [ 'sha256' ], $include );
$cacheKey = str_replace ( array ( '%hash%' , '$' ), '' , $include );
if ( $this -> cache -> sha256 ( $cacheKey ) === $metadata [ 'sha256' ]) {
$includedData = json_decode ( $this -> cache -> read ( $cacheKey ), true );
} else {
$includedData = $this -> fetchFile ( $url , $cacheKey , $metadata [ 'sha256' ]);
}
$this -> loadProviderListings ( $includedData );
}
2013-02-21 15:50:04 +00:00
} elseif ( isset ( $data [ 'providers-includes' ])) {
// BC layer for old-style providers-includes
$includes = $data [ 'providers-includes' ];
foreach ( $includes as $include => $metadata ) {
2012-10-14 14:33:53 +00:00
if ( $this -> cache -> sha256 ( $include ) === $metadata [ 'sha256' ]) {
$includedData = json_decode ( $this -> cache -> read ( $include ), true );
} else {
2012-10-15 12:37:27 +00:00
$includedData = $this -> fetchFile ( $include , null , $metadata [ 'sha256' ]);
2012-10-14 14:33:53 +00:00
}
$this -> loadProviderListings ( $includedData );
}
}
}
2012-08-20 13:44:45 +00:00
protected function loadIncludes ( $data )
2012-04-06 18:40:31 +00:00
{
2012-08-20 13:44:45 +00:00
$packages = array ();
2012-04-06 18:40:31 +00:00
// legacy repo handling
if ( ! isset ( $data [ 'packages' ]) && ! isset ( $data [ 'includes' ])) {
foreach ( $data as $pkg ) {
foreach ( $pkg [ 'versions' ] as $metadata ) {
2012-08-20 13:44:45 +00:00
$packages [] = $metadata ;
2012-04-06 18:40:31 +00:00
}
}
2012-10-22 20:40:32 +00:00
return $packages ;
2011-04-17 22:14:44 +00:00
}
2012-04-06 18:40:31 +00:00
if ( isset ( $data [ 'packages' ])) {
foreach ( $data [ 'packages' ] as $package => $versions ) {
foreach ( $versions as $version => $metadata ) {
2012-08-20 13:44:45 +00:00
$packages [] = $metadata ;
2012-04-06 18:40:31 +00:00
}
}
2012-04-06 17:56:34 +00:00
}
2012-04-06 18:40:31 +00:00
if ( isset ( $data [ 'includes' ])) {
foreach ( $data [ 'includes' ] as $include => $metadata ) {
2012-04-06 20:39:43 +00:00
if ( $this -> cache -> sha1 ( $include ) === $metadata [ 'sha1' ]) {
$includedData = json_decode ( $this -> cache -> read ( $include ), true );
} else {
2012-10-11 19:26:11 +00:00
$includedData = $this -> fetchFile ( $include );
2012-04-06 20:39:43 +00:00
}
2012-08-20 13:44:45 +00:00
$packages = array_merge ( $packages , $this -> loadIncludes ( $includedData ));
2011-10-29 05:43:26 +00:00
}
2011-04-23 18:52:37 +00:00
}
2012-08-20 13:44:45 +00:00
return $packages ;
2011-04-23 18:52:37 +00:00
}
2012-09-08 00:00:02 +00:00
protected function createPackage ( array $data , $class )
{
try {
2013-05-14 13:24:18 +00:00
if ( ! isset ( $data [ 'notification-url' ])) {
$data [ 'notification-url' ] = $this -> notifyUrl ;
}
2012-11-29 08:24:28 +00:00
2014-05-07 17:10:55 +00:00
$package = $this -> loader -> load ( $data , 'Composer\Package\CompletePackage' );
2013-10-19 15:41:29 +00:00
if ( isset ( $this -> sourceMirrors [ $package -> getSourceType ()])) {
$package -> setSourceMirrors ( $this -> sourceMirrors [ $package -> getSourceType ()]);
}
2013-07-01 23:45:43 +00:00
$package -> setDistMirrors ( $this -> distMirrors );
2014-05-07 17:10:55 +00:00
$this -> configurePackageTransportOptions ( $package );
return $package ;
2012-09-08 00:00:02 +00:00
} catch ( \Exception $e ) {
2012-09-08 11:49:37 +00:00
throw new \RuntimeException ( 'Could not load package ' . ( isset ( $data [ 'name' ]) ? $data [ 'name' ] : json_encode ( $data )) . ' in ' . $this -> url . ': [' . get_class ( $e ) . '] ' . $e -> getMessage (), 0 , $e );
2012-09-08 00:00:02 +00:00
}
}
2012-10-11 19:26:11 +00:00
2012-10-15 12:37:27 +00:00
protected function fetchFile ( $filename , $cacheKey = null , $sha256 = null )
2012-10-11 19:26:11 +00:00
{
2013-07-01 23:46:20 +00:00
if ( null === $cacheKey ) {
2012-10-11 19:26:11 +00:00
$cacheKey = $filename ;
2012-10-14 14:33:53 +00:00
$filename = $this -> baseUrl . '/' . $filename ;
2012-10-11 19:26:11 +00:00
}
2015-09-20 17:26:23 +00:00
// url-encode $ signs in URLs as bad proxies choke on them
if ( $pos = strpos ( $filename , '$' )) {
$filename = substr ( $filename , 0 , $pos ) . '%24' . substr ( $filename , $pos + 1 );
}
2012-10-11 19:26:11 +00:00
$retries = 3 ;
while ( $retries -- ) {
try {
2013-11-19 16:45:28 +00:00
$preFileDownloadEvent = new PreFileDownloadEvent ( PluginEvents :: PRE_FILE_DOWNLOAD , $this -> rfs , $filename );
if ( $this -> eventDispatcher ) {
$this -> eventDispatcher -> dispatch ( $preFileDownloadEvent -> getName (), $preFileDownloadEvent );
}
2014-05-07 16:38:58 +00:00
$hostname = parse_url ( $filename , PHP_URL_HOST ) ? : $filename ;
$json = $preFileDownloadEvent -> getRemoteFilesystem () -> getContents ( $hostname , $filename , false );
2013-02-21 15:50:04 +00:00
if ( $sha256 && $sha256 !== hash ( 'sha256' , $json )) {
2012-10-21 14:10:47 +00:00
if ( $retries ) {
2013-05-03 10:29:18 +00:00
usleep ( 100000 );
2012-10-21 14:10:47 +00:00
continue ;
}
2013-02-21 16:07:53 +00:00
// TODO use scarier wording once we know for sure it doesn't do false positives anymore
throw new RepositorySecurityException ( 'The contents of ' . $filename . ' do not match its signature. This should indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.' );
2012-10-15 12:37:27 +00:00
}
2013-02-21 15:50:04 +00:00
$data = JsonFile :: parseJson ( $json , $filename );
2013-07-01 23:46:20 +00:00
if ( $cacheKey ) {
$this -> cache -> write ( $cacheKey , $json );
}
2012-10-11 19:26:11 +00:00
break ;
} catch ( \Exception $e ) {
2013-02-21 17:16:54 +00:00
if ( $retries ) {
2013-05-03 10:29:18 +00:00
usleep ( 100000 );
2013-02-21 17:16:54 +00:00
continue ;
}
2013-02-21 16:41:38 +00:00
if ( $e instanceof RepositorySecurityException ) {
throw $e ;
}
2013-07-01 23:46:20 +00:00
if ( $cacheKey && ( $contents = $this -> cache -> read ( $cacheKey ))) {
2013-02-21 17:16:54 +00:00
if ( ! $this -> degradedMode ) {
2015-02-06 12:52:44 +00:00
$this -> io -> writeError ( '<warning>' . $e -> getMessage () . '</warning>' );
$this -> io -> writeError ( '<warning>' . $this -> url . ' could not be fully loaded, package information was loaded from the local cache and may be out of date</warning>' );
2012-10-11 19:26:11 +00:00
}
2013-02-21 17:16:54 +00:00
$this -> degradedMode = true ;
$data = JsonFile :: parseJson ( $contents , $this -> cache -> getRoot () . $cacheKey );
2012-10-11 19:35:51 +00:00
2013-02-21 17:16:54 +00:00
break ;
2012-10-11 19:26:11 +00:00
}
2013-02-21 17:16:54 +00:00
throw $e ;
2012-10-11 19:26:11 +00:00
}
}
return $data ;
}
2011-09-17 11:39:37 +00:00
}