diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 7725a8b31..7b1ab4d21 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -26,6 +26,7 @@ class Config 'process-timeout' => 300, 'vendor-dir' => 'vendor', 'bin-dir' => '{$vendor-dir}/bin', + 'notify-on-install' => true, ); } diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index c99dad571..6f397b358 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\Package\PackageInterface; use Composer\Package\AliasPackage; +use Composer\Repository\NotifiableRepositoryInterface; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UpdateOperation; @@ -128,6 +129,7 @@ class InstallationManager } $installer = $this->getInstaller($package->getType()); $installer->install($package); + $this->notifyInstall($package); } /** @@ -153,6 +155,7 @@ class InstallationManager if ($initialType === $targetType) { $installer = $this->getInstaller($initialType); $installer->update($initial, $target); + $this->notifyInstall($target); } else { $this->getInstaller($initialType)->uninstall($initial); $this->getInstaller($targetType)->install($target); @@ -200,4 +203,11 @@ class InstallationManager return getcwd().DIRECTORY_SEPARATOR.$this->vendorPath; } + + protected function notifyInstall(PackageInterface $package) + { + if ($package->getRepository() instanceof NotifiableRepositoryInterface) { + $package->getRepository()->notifyInstall($package); + } + } } diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 9778f294b..9bdd9f05d 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -14,6 +14,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Package\LinkConstraint\VersionConstraint; +use Composer\Package\PackageInterface; use Composer\Json\JsonFile; use Composer\Cache; use Composer\Config; @@ -23,12 +24,14 @@ use Composer\Util\RemoteFilesystem; /** * @author Jordi Boggiano */ -class ComposerRepository extends ArrayRepository +class ComposerRepository extends ArrayRepository implements NotifiableRepositoryInterface { + protected $config; protected $url; protected $io; protected $packages; protected $cache; + protected $notifyUrl; public function __construct(array $repoConfig, IOInterface $io, Config $config) { @@ -41,11 +44,41 @@ class ComposerRepository extends ArrayRepository throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']); } + $this->config = $config; $this->url = $repoConfig['url']; $this->io = $io; $this->cache = new Cache($io, $config->get('home').'/cache/'.preg_replace('{[^a-z0-9.]}', '-', $this->url)); } + /** + * {@inheritDoc} + */ + public function notifyInstall(PackageInterface $package) + { + if (!$this->notifyUrl || !$this->config->get('notify-on-install')) { + return; + } + + // TODO use an optional curl_multi pool for all the notifications + $url = str_replace('%package%', $package->getPrettyName(), $this->notifyUrl); + + $params = array( + 'version' => $package->getPrettyVersion(), + 'version_normalized' => $package->getVersion(), + ); + $opts = array('http' => + array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => http_build_query($params), + 'timeout' => 3, + ) + ); + + $context = stream_context_create($opts); + @file_get_contents($url, false, $context); + } + protected function initialize() { parent::initialize(); @@ -53,6 +86,11 @@ class ComposerRepository extends ArrayRepository try { $json = new JsonFile($this->url.'/packages.json', new RemoteFilesystem($this->io)); $data = $json->read(); + + if (!empty($data['notify'])) { + $this->notifyUrl = preg_replace('{(https?://[^/]+).*}i', '$1' . $data['notify'], $this->url); + } + $this->cache->write('packages.json', json_encode($data)); } catch (\Exception $e) { if ($contents = $this->cache->read('packages.json')) { diff --git a/src/Composer/Repository/NotifiableRepositoryInterface.php b/src/Composer/Repository/NotifiableRepositoryInterface.php new file mode 100644 index 000000000..68fa76055 --- /dev/null +++ b/src/Composer/Repository/NotifiableRepositoryInterface.php @@ -0,0 +1,28 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\Package\PackageInterface; + +/** + * @author Jordi Boggiano + */ +interface NotifiableRepositoryInterface extends RepositoryInterface +{ + /** + * Notify this repository about the installation of a package + * + * @param PackageInterface $package Package that is installed + */ + function notifyInstall(PackageInterface $package); +}