diff --git a/src/Composer/Package.php b/src/Composer/Package.php index 3d392c75..b92285d5 100644 --- a/src/Composer/Package.php +++ b/src/Composer/Package.php @@ -15,6 +15,12 @@ class Package /** @var array */ public $autoloaders = []; + /** @var array */ + public $dependencies = []; + + /** @var array */ + public $suggested_dependencies = []; + public function __construct($path) { $this->path = $path; @@ -47,4 +53,12 @@ public function findAutoloaders() array_push($this->autoloaders, $autoloader); } } + + public function findDependencies() + { + $this->dependencies = array_keys((array)$this->config->require); + if (isset($this->config->suggest) && $this->config->suggest) { + $this->suggested_dependencies = array_keys((array)$this->config->suggest); + } + } } diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index fab03a02..2298ab48 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -4,8 +4,10 @@ use CoenJacobs\Mozart\Composer\Package; use CoenJacobs\Mozart\Mover; +use CoenJacobs\Mozart\Synchronizer; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class Compose extends Command @@ -13,12 +15,20 @@ class Compose extends Command protected function configure() { $this->setName('compose'); + $this->addOption( + 'skip_dependencies', + null, + InputOption::VALUE_OPTIONAL, + 'Skip processing of package sub-dependencies.', + false + ); $this->setDescription('Composes all dependencies as a package inside a WordPress plugin.'); $this->setHelp(''); } protected function execute(InputInterface $input, OutputInterface $output) { + $skip_dependencies = $input->getOption('skip_dependencies') !== false; $workingDir = getcwd(); $config = json_decode(file_get_contents($workingDir . '/composer.json')); @@ -27,12 +37,54 @@ protected function execute(InputInterface $input, OutputInterface $output) $mover = new Mover($workingDir, $config); $mover->deleteTargetDirs(); - foreach ($config->packages as $package_slug) { + $packages = new \ArrayIterator($config->packages); + $processed_packages = []; + + foreach ($packages as $package_slug) { $package = new Package($workingDir . '/vendor/' . $package_slug); $package->findAutoloaders(); $mover->movePackage($package); + if ($skip_dependencies) { + continue; + } + $package->findDependencies(); + $processed_packages[] = $package; + foreach ($package->dependencies as $dependency) { + if (file_exists($workingDir . '/vendor/' . $dependency) && + !in_array($dependency, $packages->getArrayCopy()) + ) { + $packages->append($dependency); + }; + } } $mover->replaceClassmapNames(); + + if ($skip_dependencies) { + return; + } + + $synchronizer = new Synchronizer($workingDir, $config); + + foreach ($processed_packages as $package) { + if (!$package->dependencies) { + continue; + } + $dependencies = array_unique(array_merge($package->dependencies, $package->suggested_dependencies)); + foreach ($dependencies as $dependency_name) { + $matching_packages = array_filter( + $processed_packages, + function (Package $pack) use ($dependency_name) { + return $pack->config->name === $dependency_name; + } + ); + $dependent_package = reset($matching_packages); + // Suggested dependency might not be installed + if (!$dependent_package) { + continue; + } + $synchronizer->syncMovedPackageWithDependency($package, $dependent_package); + } + } } } diff --git a/src/Mover.php b/src/Mover.php index dee0a100..d7c8a663 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -89,7 +89,8 @@ public function movePackage(Package $package) * @param $path * @return mixed */ - public function moveFile(Package $package, $autoloader, $file, $path = '') { + public function moveFile(Package $package, $autoloader, $file, $path = '') + { if ($autoloader instanceof NamespaceAutoloader) { $namespacePath = $autoloader->getNamespacePath(); $replaceWith = $this->config->dep_directory . $namespacePath; diff --git a/src/Synchronizer.php b/src/Synchronizer.php new file mode 100644 index 00000000..0d6fc56e --- /dev/null +++ b/src/Synchronizer.php @@ -0,0 +1,95 @@ +workingDir = $workingDir; + $this->targetDir = $config->dep_directory; + $this->config = $config; + + $this->filesystem = new Filesystem(new Local($this->workingDir)); + } + + + public function syncMovedPackageWithDependency(Package $package, Package $dependency) + { + $finder = new Finder(); + + foreach ($package->autoloaders as $autoloader) { + if ($autoloader instanceof NamespaceAutoloader) { + $source_path = $this->workingDir . $this->targetDir . $autoloader->getNamespacePath(); + $finder->files()->in($source_path); + + foreach ($finder as $file) { + if ('.php' == substr($file, '-4', 4)) { + foreach ($dependency->autoloaders as $dep_autoloader) { + $targetFile = str_replace($this->workingDir, '', $file->getRealPath()); + $this->replaceInFile($targetFile, $dep_autoloader); + } + } + } + } + + if ($autoloader instanceof Classmap) { + $finder = new Finder(); + $source_path = $this->workingDir . $this->config->classmap_directory . $package->config->name; + $finder->files()->in($source_path); + + foreach ($finder as $foundFile) { + if ('.php' == substr($foundFile, '-4', 4)) { + foreach ($dependency->autoloaders as $dep_autoloader) { + $targetFile = str_replace($this->workingDir, '', $foundFile->getRealPath()); + $this->replaceInFile($targetFile, $dep_autoloader); + } + } + } + } + } + } + + /** + * @param $targetFile + * @param $autoloader + */ + public function replaceInFile($targetFile, $autoloader) + { + $contents = $this->filesystem->read($targetFile); + + if ($autoloader instanceof NamespaceAutoloader) { + $replacer = new NamespaceReplacer(); + $replacer->dep_namespace = $this->config->dep_namespace; + } else { + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = $this->config->classmap_prefix; + } + + $replacer->setAutoloader($autoloader); + $contents = $replacer->replace($contents); + + $this->filesystem->put($targetFile, $contents); + } +}