<?php namespace LakeDrops\DorgFlow; use Composer\Composer; use Composer\IO\IOInterface; use Composer\Script\Event; use GitElephant\Repository; use LakeDrops\Component\Dotenv\Dotenv; use Symfony\Component\Filesystem\Filesystem; /** * Class Handler. * * @package LakeDrops\DorgFlow */ class Handler { /** * The composer object of this session. * * @var \Composer\Composer */ protected $composer; /** * The input-output object of the composer session. * * @var \Composer\IO\IOInterface */ protected $io; /** * Handler constructor. * * @param \Composer\Composer $composer * The composer object of this session. * @param \Composer\IO\IOInterface $io * The input-output object of the composer session. */ public function __construct(Composer $composer, IOInterface $io) { $this->composer = $composer; $this->io = $io; } /** * Retrieve a package from the current composer process. * * @param string $name * Name of the package to get from the current composer installation. * * @return \Composer\Package\PackageInterface * The package. */ protected function getPackage($name) { return $this->composer->getRepositoryManager()->getLocalRepository()->findPackage($name, '*'); } /** * Post install/update event to prepare projects for development. * * @param \Composer\Script\Event $event * The event that triggered the call of this function. */ public function prepareDevProjects(Event $event) { // We only do the fancy stuff for developers. if (!$event->isDevMode()) { return; } $options = $this->getOptions(); if (empty($options['projects'])) { return; } $this->io->write('Dorgflow: Preparing drupol.org packages for development', TRUE); $installationManager = $this->composer->getInstallationManager(); foreach ($options['projects'] as $project => $version) { $package = $this->getPackage($project); if (empty($package)) { continue; } $path = $installationManager->getInstallPath($package); $this->io->write("- $project => $path", TRUE); $this->prepareWorkingDirectory($path, $project, $version, $options['username']); } } /** * Retrieve options from composer.json "extra" configuration. * * @return array * The options. */ protected function getOptions() { $env = new Dotenv('dorgflow', $this->io); $extra = $this->composer->getPackage()->getExtra() + ['dorgflow' => []]; $options = $extra['dorgflow'] + [ 'projects' => [], 'username' => $env->receive('drupal_org_username', 'Drupal.org username', getenv('USER')), ]; return $options; } /** * Prepare the working directory of a git based package for dorgflow. * * @param string $path * Name of the working directory. * @param string $project * Name of the project. * @param string $version * Version to checkout. * @param string $username * Username on drupal.org. */ protected function prepareWorkingDirectory($path, $project, $version, $username) { list(, $projectname) = explode('/', $project); $uri = $username . '@git.drupal.org:project/' . $projectname . '.git'; // Git Clone the repository into the working directory. $repository = Repository::open($path); $repository->init(); try { $origin = $repository->getRemote('origin', FALSE); if ($origin && $origin->getFetchURL() == $uri) { // Already setup correctly. return; } } catch (\Exception $ex) { // Ignore the exception and conitue setup. } $fs = new Filesystem(); $fs->remove($path); $fs->mkdir($path); $repository->init(); $repository->addRemote('origin', $uri); $repository->fetch(); $repository->checkout($version); $repository->getCaller()->execute('branch --set-upstream-to origin/' . $version . ' ' . $version); $this->io->write(" - completed", TRUE); } }