From d715b1a779e3e890dee1e02469be0794a214f8d3 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Mon, 12 Sep 2016 17:37:50 +1200 Subject: [PATCH] proof of concept --- .editorconfig | 15 +++++++ src/RecipeInstaller.php | 90 +++++++++++++++++++++++++++++++++++------ 2 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..aa9a047 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +# PHP PSR-2 Coding Standards +# http://www.php-fig.org/psr/psr-2/ + +root = true + +[*.php] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 diff --git a/src/RecipeInstaller.php b/src/RecipeInstaller.php index b1fb84f..c171908 100644 --- a/src/RecipeInstaller.php +++ b/src/RecipeInstaller.php @@ -9,6 +9,11 @@ use Composer\IO\IOInterface; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; +use FilesystemIterator; +use Iterator; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RegexIterator; class RecipeInstaller extends LibraryInstaller { public function __construct( @@ -25,19 +30,80 @@ class RecipeInstaller extends LibraryInstaller { { parent::install($repo, $package); - // Install recipe skeleton - var_dump("Package info:\n"); - var_dump($package); - var_dump($this->getInstallPath($package)); - var_dump($package->getExtra()); - - var_dump("Repo info:\n"); - var_dump($repo); - if(file_exists('composer.json')) { - var_dump(file_get_contents('composer.json')); + // Copy project files to root + $destinationPath = getcwd(); + $name = $package->getName(); + $extra = $package->getExtra(); + if (isset($extra['project-files'])) { + $this->installProjectFiles($name, $this->getInstallPath($package), $destinationPath, $extra['project-files']); } + } - var_dump("Installer info:\n"); - var_dump($this); + /** + * Install project files in the specified directory + * + * @param string $recipe Recipe name + * @param string $sourceRoot Base of source files (no trailing slash) + * @param string $destinationRoot Base of destination directory (no trailing slash) + * @param array $filePatterns List of file patterns in wildcard format (e.g. `code/My*.php`) + */ + public function installProjectFiles($recipe, $sourceRoot, $destinationRoot, $filePatterns) + { + $fileIterator = $this->getFileIterator($sourceRoot, $filePatterns); + foreach($fileIterator as $path => $info) { + $relativePath = substr($path, strlen($sourceRoot)); + $destination = $destinationRoot . $relativePath; + + // Only copy non-existent files + if (file_exists($destination)) { + continue; + } + $this->io->write("Installing recipe $recipe file $relativePath"); + $this->filesystem->ensureDirectoryExists(dirname($destination)); + file_put_contents($destination, file_get_contents($path)); + } + } + + /** + * Get iterator of matching source files to copy + * + * @param string $sourceRoot Root directory of sources (no trailing slash) + * @param array $patterns List of wildcard patterns to match + * @return Iterator File iterator, where key is path and value is file info object + */ + public function getFileIterator($sourceRoot, $patterns) { + // Build regexp pattern + $expressions = []; + foreach($patterns as $pattern) { + $expressions[] = $this->globToRegexp($pattern); + } + $regExp = '#' . $this->globToRegexp($sourceRoot . '/').'(('.implode(')|(', $expressions).'))#'; + + // Build directory iterator + $directoryIterator = new RecursiveDirectoryIterator( + $sourceRoot, + FilesystemIterator::SKIP_DOTS + | FilesystemIterator::UNIX_PATHS + | FilesystemIterator::KEY_AS_PATHNAME + | FilesystemIterator::CURRENT_AS_FILEINFO + ); + + // Return filtered iterator + $iterator = new RecursiveIteratorIterator($directoryIterator); + return new RegexIterator($iterator, $regExp); + } + + /** + * Convert glob pattern to regexp + * + * @param string $glob + * @return string + */ + protected function globToRegexp($glob) { + $sourceParts = explode('*', $glob); + $regexParts = array_map(function($part) { + return preg_quote($part, '#'); + }, $sourceParts); + return implode('(.+)', $regexParts); } }