From 7bc393e259a6897c4b5b9afc4110f35e10854734 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 12 Sep 2024 17:42:12 +0200 Subject: [PATCH 01/15] Installed phpmd and basic configuration file --- composer.json | 3 ++- phpmd.xml.dist | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 phpmd.xml.dist diff --git a/composer.json b/composer.json index 05f06aa5..6f0af7e6 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,8 @@ "symfony/console": "^5.4", "symfony/finder": "^5.4", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "phpcompatibility/php-compatibility": "dev-develop" + "phpcompatibility/php-compatibility": "dev-develop", + "phpmd/phpmd": "^2.15" }, "scripts": { "test": [ diff --git a/phpmd.xml.dist b/phpmd.xml.dist new file mode 100644 index 00000000..185b7f28 --- /dev/null +++ b/phpmd.xml.dist @@ -0,0 +1,16 @@ + + + + + + + + + + From 45f76f578cac687f06817f6eb1f00627429cae75 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 12 Sep 2024 17:42:32 +0200 Subject: [PATCH 02/15] Fixed all code smells in main replacer class --- src/FilesHandler.php | 50 ++++++++++++++++++++ src/Replacer.php | 108 ++++++++++++++++++++----------------------- 2 files changed, 99 insertions(+), 59 deletions(-) create mode 100644 src/FilesHandler.php diff --git a/src/FilesHandler.php b/src/FilesHandler.php new file mode 100644 index 00000000..a1d21b2e --- /dev/null +++ b/src/FilesHandler.php @@ -0,0 +1,50 @@ +config = $config; + + $adapter = new LocalFilesystemAdapter( + $this->config->getWorkingDir() + ); + + // The FilesystemOperator + $this->filesystem = new Filesystem($adapter); + } + + public function readFile(string $path): string + { + try { + $contents = $this->filesystem->read($path); + } catch (UnableToReadFile $e) { + $contents = ''; + } + + return $contents; + } + + public function writeFile(string $path, string $contents): void + { + $this->filesystem->write($path, $contents); + } + + public function getFilesFromPath(string $path): Iterator + { + $finder = new Finder(); + return $finder->files()->in($path)->getIterator(); + } +} diff --git a/src/Replacer.php b/src/Replacer.php index c092bcf9..2da61921 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -9,11 +9,8 @@ use CoenJacobs\Mozart\Config\Package; use CoenJacobs\Mozart\Replace\ClassmapReplacer; use CoenJacobs\Mozart\Replace\NamespaceReplacer; +use CoenJacobs\Mozart\Replace\Replacer as ReplacerInterface; use Exception; -use League\Flysystem\Local\LocalFilesystemAdapter; -use League\Flysystem\UnableToReadFile; -use League\Flysystem\Filesystem; -use Symfony\Component\Finder\Finder; class Replacer { @@ -29,21 +26,15 @@ class Replacer /** @var array */ protected $replacedClasses = []; - /** @var Filesystem */ - protected $filesystem; + /** @var FilesHandler */ + protected $files; public function __construct(string $workingDir, Mozart $config) { $this->workingDir = $workingDir; $this->config = $config; $this->targetDir = $this->config->getDepDirectory(); - - $adapter = new LocalFilesystemAdapter( - $this->workingDir - ); - - // The FilesystemOperator - $this->filesystem = new Filesystem($adapter); + $this->files = new FilesHandler($config); } /** @@ -67,32 +58,35 @@ public function replacePackage(Package $package): void public function replaceInFile(string $targetFile, Autoloader $autoloader): void { $targetFile = str_replace($this->workingDir, '', $targetFile); - try { - $contents = $this->filesystem->read($targetFile); - } catch (UnableToReadFile $e) { - return; - } + $contents = $this->files->readFile($targetFile); if (!$contents) { return; } - if ($autoloader instanceof NamespaceAutoloader) { - $replacer = new NamespaceReplacer(); - $replacer->dep_namespace = $this->config->getDependencyNamespace(); - } else { - $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = $this->config->getClassmapPrefix(); - } - - $replacer->setAutoloader($autoloader); + $replacer = $this->getReplacerByAutoloader($autoloader); $contents = $replacer->replace($contents); if ($replacer instanceof ClassmapReplacer) { $this->replacedClasses = array_merge($this->replacedClasses, $replacer->replacedClasses); } - $this->filesystem->write($targetFile, $contents); + $this->files->writeFile($targetFile, $contents); + } + + public function getReplacerByAutoloader(Autoloader $autoloader): ReplacerInterface + { + if ($autoloader instanceof NamespaceAutoloader) { + $replacer = new NamespaceReplacer(); + $replacer->dep_namespace = $this->config->getDependencyNamespace(); + $replacer->setAutoloader($autoloader); + return $replacer; + } + + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = $this->config->getClassmapPrefix(); + $replacer->setAutoloader($autoloader); + return $replacer; } public function replacePackageByAutoloader(Package $package, Autoloader $autoloader): void @@ -102,15 +96,14 @@ public function replacePackageByAutoloader(Package $package, Autoloader $autoloa } if ($autoloader instanceof NamespaceAutoloader) { - $source_path = $this->workingDir . $this->targetDir + $sourcePath = $this->workingDir . $this->targetDir . str_replace('\\', DIRECTORY_SEPARATOR, $autoloader->getNamespace()); - $this->replaceInDirectory($autoloader, $source_path); + $this->replaceInDirectory($autoloader, $sourcePath); } elseif ($autoloader instanceof Classmap) { - $finder = new Finder(); - $source_path = $this->workingDir . $this->config->getClassmapDirectory() . $package->getName(); - $finder->files()->in($source_path); + $sourcePath = $this->workingDir . $this->config->getClassmapDirectory() . $package->getName(); + $files = $this->files->getFilesFromPath($sourcePath); - foreach ($finder as $foundFile) { + foreach ($files as $foundFile) { $targetFile = $foundFile->getRealPath(); if ('.php' == substr($targetFile, -4, 4)) { @@ -127,26 +120,21 @@ public function replaceParentClassesInDirectory(string $directory): void } $directory = trim($directory, '//'); - $finder = new Finder(); - $finder->files()->in($directory); + $files = $this->files->getFilesFromPath($directory); $replacedClasses = $this->replacedClasses; - foreach ($finder as $file) { + foreach ($files as $file) { $targetFile = $file->getPathName(); if ('.php' == substr($targetFile, -4, 4)) { - try { - $contents = $this->filesystem->read($targetFile); - } catch (UnableToReadFile $e) { - continue; - } + $contents = $this->files->readFile($targetFile); foreach ($replacedClasses as $original => $replacement) { $contents = preg_replace_callback( '/(.*)([^a-zA-Z0-9_\x7f-\xff])'. $original . '([^a-zA-Z0-9_\x7f-\xff])/U', function ($matches) use ($replacement) { - if (preg_match('/(include|require)/', $matches[0], $output_array)) { + if (preg_match('/(include|require)/', $matches[0])) { return $matches[0]; } return $matches[1] . $matches[2] . $replacement . $matches[3]; @@ -159,17 +147,16 @@ function ($matches) use ($replacement) { } } - $this->filesystem->write($targetFile, $contents); + $this->files->writeFile($targetFile, $contents); } } } public function replaceInDirectory(NamespaceAutoloader $autoloader, string $directory): void { - $finder = new Finder(); - $finder->files()->in($directory); + $files = $this->files->getFilesFromPath($directory); - foreach ($finder as $file) { + foreach ($files as $file) { $targetFile = $file->getPathName(); if ('.php' == substr($targetFile, -4, 4)) { @@ -198,21 +185,24 @@ public function replaceParentPackage(Package $package, Package $parent): void if ($autoloader instanceof NamespaceAutoloader) { $this->replaceInDirectory($autoloader, $directory); - } else { - $directory = str_replace($this->workingDir, '', $directory); - $this->replaceParentClassesInDirectory($directory); + return; } - } else { - $directory = $this->workingDir . - $this->config->getClassmapDirectory() . $parent->getName(); - if ($autoloader instanceof NamespaceAutoloader) { - $this->replaceInDirectory($autoloader, $directory); - } else { - $directory = str_replace($this->workingDir, '', $directory); - $this->replaceParentClassesInDirectory($directory); - } + $directory = str_replace($this->workingDir, '', $directory); + $this->replaceParentClassesInDirectory($directory); + return; + } + + $directory = $this->workingDir . + $this->config->getClassmapDirectory() . $parent->getName(); + + if ($autoloader instanceof NamespaceAutoloader) { + $this->replaceInDirectory($autoloader, $directory); + return; } + + $directory = str_replace($this->workingDir, '', $directory); + $this->replaceParentClassesInDirectory($directory); } } } From 707f808eb177a477be1ad41394b6d00073de3298 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 12 Sep 2024 17:47:55 +0200 Subject: [PATCH 03/15] Change boolean load dependencies flag to separate method --- src/Console/Commands/Compose.php | 2 +- src/PackageFactory.php | 11 ++--------- src/PackageFinder.php | 4 +++- tests/Config/ConfigMapperTest.php | 1 + tests/MoverTest.php | 1 + 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index 2a9b762d..c74a82d1 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -48,7 +48,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $composerFile = $this->workingDir . DIRECTORY_SEPARATOR. 'composer.json'; try { - $package = PackageFactory::createPackage($composerFile, null, false); + $package = PackageFactory::createPackage($composerFile); } catch (Exception $e) { $output->write('Unable to read the composer.json file'); return 1; diff --git a/src/PackageFactory.php b/src/PackageFactory.php index da67d61e..fcf4cb59 100644 --- a/src/PackageFactory.php +++ b/src/PackageFactory.php @@ -10,11 +10,8 @@ class PackageFactory /** @var array */ public static array $cache = []; - public static function createPackage( - string $path, - stdClass $overrideAutoload = null, - bool $loadDependencies = true - ): Package { + public static function createPackage(string $path, stdClass $overrideAutoload = null): Package + { if (isset(self::$cache[$path])) { return self::$cache[$path]; } @@ -25,10 +22,6 @@ public static function createPackage( $package->setAutoload($overrideAutoload); } - if ($loadDependencies) { - $package->loadDependencies(); - } - self::$cache[$path] = $package; return $package; } diff --git a/src/PackageFinder.php b/src/PackageFinder.php index 9f162c63..d0470fa3 100644 --- a/src/PackageFinder.php +++ b/src/PackageFinder.php @@ -53,7 +53,9 @@ public function getPackageBySlug(string $slug): ?Package $autoloaders = $override_autoload->$slug; } - return PackageFactory::createPackage($packageDir . 'composer.json', $autoloaders, true); + $package = PackageFactory::createPackage($packageDir . 'composer.json', $autoloaders); + $package->loadDependencies(); + return $package; } /** diff --git a/tests/Config/ConfigMapperTest.php b/tests/Config/ConfigMapperTest.php index 42e1ed7a..433ae202 100644 --- a/tests/Config/ConfigMapperTest.php +++ b/tests/Config/ConfigMapperTest.php @@ -16,6 +16,7 @@ class ConfigMapperTest extends TestCase public function it_creates_a_valid_config_object_based_on_composer_file() { $package = PackageFactory::createPackage(__DIR__ . '/config-mapper-test.json'); + $package->loadDependencies(); $this->assertInstanceOf(Package::class, $package); $this->assertInstanceOf(Mozart::class, $package->getExtra()->getMozart()); $this->assertCount(4, $package->autoload->getAutoloaders()); diff --git a/tests/MoverTest.php b/tests/MoverTest.php index 8945f49e..d5de5d94 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -138,6 +138,7 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void $overrideAutoload = $overrideAutoload->getByKey( $packageString ); } $parsedPackage = PackageFactory::createPackage($testDummyComposerPath, $overrideAutoload); + $parsedPackage->loadDependencies(); $packages[] = $parsedPackage; } From 716cb13626016653f0baa8bdb7d8509795051f10 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 12 Sep 2024 17:54:28 +0200 Subject: [PATCH 04/15] CamelCasing all the things --- src/PackageFinder.php | 6 +++--- src/Replace/ClassmapReplacer.php | 4 ++-- src/Replace/NamespaceReplacer.php | 6 +++--- src/Replacer.php | 4 ++-- tests/replacers/ClassMapReplacerTest.php | 22 +++++++++++----------- tests/replacers/NamespaceReplacerTest.php | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/PackageFinder.php b/src/PackageFinder.php index d0470fa3..df5b210a 100644 --- a/src/PackageFinder.php +++ b/src/PackageFinder.php @@ -48,9 +48,9 @@ public function getPackageBySlug(string $slug): ?Package } $autoloaders = null; - $override_autoload = $this->config->getOverrideAutoload(); - if ($override_autoload !== false && isset($override_autoload->$slug)) { - $autoloaders = $override_autoload->$slug; + $overrideAutoload = $this->config->getOverrideAutoload(); + if ($overrideAutoload !== false && isset($overrideAutoload->$slug)) { + $autoloaders = $overrideAutoload->$slug; } $package = PackageFactory::createPackage($packageDir . 'composer.json', $autoloaders); diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index 39b4fa52..803467fd 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -15,7 +15,7 @@ class ClassmapReplacer extends BaseReplacer public $replacedClasses = []; /** @var string */ - public $classmap_prefix; + public $classmapPrefix; public function replace(string $contents): string { @@ -46,7 +46,7 @@ function ($matches) { } // The prepended class name. - $replace = $this->classmap_prefix . $matches[1]; + $replace = $this->classmapPrefix . $matches[1]; $this->saveReplacedClass($matches[1], $replace); return str_replace($matches[1], $replace, $matches[0]); }, diff --git a/src/Replace/NamespaceReplacer.php b/src/Replace/NamespaceReplacer.php index b348fb24..9c324c5e 100644 --- a/src/Replace/NamespaceReplacer.php +++ b/src/Replace/NamespaceReplacer.php @@ -11,7 +11,7 @@ class NamespaceReplacer extends BaseReplacer * * @var string "My\Mozart\Prefix". */ - public $dep_namespace = ''; + public $depNamespace = ''; /** * @param string $contents The text to make replacements in. @@ -20,7 +20,7 @@ class NamespaceReplacer extends BaseReplacer public function replace(string $contents, string $file = null): string { $searchNamespace = preg_quote($this->autoloader->getSearchNamespace(), '/'); - $dependencyNamespace = preg_quote($this->dep_namespace, '/'); + $dependencyNamespace = preg_quote($this->depNamespace, '/'); $replaced = preg_replace_callback( " @@ -35,7 +35,7 @@ public function replace(string $contents, string $file = null): string ) # End the namespace matcher /Ux", function ($matches) { - return $matches[1] . $this->dep_namespace . $matches[2]; + return $matches[1] . $this->depNamespace . $matches[2]; }, $contents ); diff --git a/src/Replacer.php b/src/Replacer.php index 2da61921..8cc76433 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -78,13 +78,13 @@ public function getReplacerByAutoloader(Autoloader $autoloader): ReplacerInterfa { if ($autoloader instanceof NamespaceAutoloader) { $replacer = new NamespaceReplacer(); - $replacer->dep_namespace = $this->config->getDependencyNamespace(); + $replacer->depNamespace = $this->config->getDependencyNamespace(); $replacer->setAutoloader($autoloader); return $replacer; } $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = $this->config->getClassmapPrefix(); + $replacer->classmapPrefix = $this->config->getClassmapPrefix(); $replacer->setAutoloader($autoloader); return $replacer; } diff --git a/tests/replacers/ClassMapReplacerTest.php b/tests/replacers/ClassMapReplacerTest.php index 10b10ce8..6f08af06 100644 --- a/tests/replacers/ClassMapReplacerTest.php +++ b/tests/replacers/ClassMapReplacerTest.php @@ -13,7 +13,7 @@ public function it_replaces_class_declarations(): void { $contents = 'class Hello_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals('class Mozart_Hello_World {', $contents); } @@ -24,7 +24,7 @@ public function it_replaces_abstract_class_declarations(): void { $contents = 'abstract class Hello_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals('abstract class Mozart_Hello_World {', $contents); } @@ -35,7 +35,7 @@ public function it_replaces_interface_class_declarations(): void { $contents = 'interface Hello_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals('interface Mozart_Hello_World {', $contents); } @@ -46,7 +46,7 @@ public function it_replaces_class_declarations_that_extend_other_classes(): void { $contents = 'class Hello_World extends Bye_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals('class Mozart_Hello_World extends Bye_World {', $contents); } @@ -57,7 +57,7 @@ public function it_replaces_class_declarations_that_implement_interfaces(): void { $contents = 'class Hello_World implements Bye_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals('class Mozart_Hello_World implements Bye_World {', $contents); } @@ -68,7 +68,7 @@ public function it_stores_replaced_class_names(): void { $contents = 'class Hello_World {'; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $replacer->replace($contents); $this->assertArrayHasKey('Hello_World', $replacer->replacedClasses); } @@ -79,7 +79,7 @@ public function it_replaces_class_declarations_psr2(): void { $contents = "class Hello_World\n{"; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals("class Mozart_Hello_World\n{", $contents); } @@ -94,7 +94,7 @@ public function it_replaces_class(): void { $contents = "class Hello_World"; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $contents = $replacer->replace($contents); $this->assertEquals("class Mozart_Hello_World", $contents); } @@ -114,7 +114,7 @@ public function it_does_not_replace_inside_namespace_multiline(): void class Hello_World "; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $result = $replacer->replace($input); $this->assertEquals($input, $result); @@ -131,7 +131,7 @@ public function it_does_not_replace_inside_namespace_singleline(): void { $input = "namespace Mozart; class Hello_World"; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $result = $replacer->replace($input); $this->assertEquals($input, $result); @@ -158,7 +158,7 @@ class B_Class { } "; $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; + $replacer->classmapPrefix = 'Mozart_'; $result = $replacer->replace($input); $this->assertStringNotContainsString('Mozart_A_Class', $result); diff --git a/tests/replacers/NamespaceReplacerTest.php b/tests/replacers/NamespaceReplacerTest.php index b0651bc7..2fa41651 100644 --- a/tests/replacers/NamespaceReplacerTest.php +++ b/tests/replacers/NamespaceReplacerTest.php @@ -27,7 +27,7 @@ protected static function createReplacer(string $namespace, string $prefix = sel $autoloader->namespace = $namespace; $replacer = new NamespaceReplacer(); $replacer->setAutoloader($autoloader); - $replacer->dep_namespace = $prefix; + $replacer->depNamespace = $prefix; return $replacer; } From f40546a2862b7f5aa9a0d1410c0b75632a0e566b Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 12 Sep 2024 17:58:18 +0200 Subject: [PATCH 05/15] Dumbed down if else constructions in autoloader classes --- src/Composer/Autoload/NamespaceAutoloader.php | 5 +++-- src/Config/Classmap.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Composer/Autoload/NamespaceAutoloader.php b/src/Composer/Autoload/NamespaceAutoloader.php index 62ef6328..314bf179 100644 --- a/src/Composer/Autoload/NamespaceAutoloader.php +++ b/src/Composer/Autoload/NamespaceAutoloader.php @@ -27,9 +27,10 @@ public function processConfig($autoloadConfig): void foreach ($autoloadConfig as $path) { array_push($this->paths, $path); } - } else { - array_push($this->paths, $autoloadConfig); + + return; } + array_push($this->paths, $autoloadConfig); } public function getNamespace(): string diff --git a/src/Config/Classmap.php b/src/Config/Classmap.php index c53529ed..5077e732 100644 --- a/src/Config/Classmap.php +++ b/src/Config/Classmap.php @@ -21,9 +21,10 @@ public function processConfig($autoloadConfig): void foreach ($autoloadConfig as $value) { if ('.php' == substr($value, -4, 4)) { array_push($this->files, $value); - } else { - array_push($this->paths, $value); + continue; } + + array_push($this->paths, $value); } } From b8ebe6838197498312572432b0901724a1b0f3ca Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Fri, 13 Sep 2024 15:13:26 +0200 Subject: [PATCH 06/15] Reduce Mover complexity by abstracting file handling to FileHandler --- src/FilesHandler.php | 26 ++++++++++++++ src/Mover.php | 80 ++++++++++++++++---------------------------- tests/MoverTest.php | 1 + 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/FilesHandler.php b/src/FilesHandler.php index a1d21b2e..b8ffda58 100644 --- a/src/FilesHandler.php +++ b/src/FilesHandler.php @@ -47,4 +47,30 @@ public function getFilesFromPath(string $path): Iterator $finder = new Finder(); return $finder->files()->in($path)->getIterator(); } + + public function getFile(string $path, string $fileName): Iterator + { + $finder = new Finder(); + return $finder->files()->name($fileName)->in($path)->getIterator(); + } + + public function createDirectory(string $path): void + { + $this->filesystem->createDirectory($path); + } + + public function deleteDirectory(string $path): void + { + $this->filesystem->deleteDirectory($path); + } + + public function isDirectoryEmpty(string $path): bool + { + return count($this->filesystem->listContents($path, true)->toArray()) === 0; + } + + public function copyFile(string $origin, string $destination): void + { + $this->filesystem->copy($origin, $destination); + } } diff --git a/src/Mover.php b/src/Mover.php index 8b676be7..18f976d1 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -9,9 +9,6 @@ use CoenJacobs\Mozart\Config\Package; use CoenJacobs\Mozart\Config\Psr0; use CoenJacobs\Mozart\Config\Psr4; -use League\Flysystem\Local\LocalFilesystemAdapter; -use League\Flysystem\Filesystem; -use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; class Mover @@ -25,8 +22,7 @@ class Mover /** @var Mozart */ protected $config; - /** @var Filesystem */ - protected $filesystem; + protected FilesHandler $files; /** @var array */ protected $movedPackages = []; @@ -36,13 +32,7 @@ public function __construct(string $workingDir, Mozart $config) $this->config = $config; $this->workingDir = $workingDir; $this->targetDir = $this->config->getDepDirectory(); - - $adapter = new LocalFilesystemAdapter( - $this->workingDir - ); - - // The FilesystemOperator - $this->filesystem = new Filesystem($adapter); + $this->files = new FilesHandler($config); } /** @@ -52,8 +42,8 @@ public function __construct(string $workingDir, Mozart $config) */ public function deleteTargetDirs($packages): void { - $this->filesystem->createDirectory($this->config->getDepDirectory()); - $this->filesystem->createDirectory($this->config->getClassmapDirectory()); + $this->files->createDirectory($this->config->getDepDirectory()); + $this->files->createDirectory($this->config->getClassmapDirectory()); foreach ($packages as $package) { $this->deleteDepTargetDirs($package); @@ -75,12 +65,12 @@ private function deleteDepTargetDirs(Package $package): void case Psr4::class: $outputDir = $this->config->getDepDirectory() . $packageAutoloader->getSearchNamespace(); $outputDir = str_replace('\\', DIRECTORY_SEPARATOR, $outputDir); - $this->filesystem->deleteDirectory($outputDir); + $this->files->deleteDirectory($outputDir); break; case Classmap::class: $outputDir = $this->config->getClassmapDirectory() . $package->getName(); $outputDir = str_replace('\\', DIRECTORY_SEPARATOR, $outputDir); - $this->filesystem->deleteDirectory($outputDir); + $this->files->deleteDirectory($outputDir); break; } } @@ -92,12 +82,12 @@ private function deleteDepTargetDirs(Package $package): void public function deleteEmptyDirs(): void { - if (count($this->filesystem->listContents($this->config->getDepDirectory(), true)->toArray()) === 0) { - $this->filesystem->deleteDirectory($this->config->getDepDirectory()); + if ($this->files->isDirectoryEmpty($this->config->getDepDirectory())) { + $this->files->deleteDirectory($this->config->getDepDirectory()); } - if (count($this->filesystem->listContents($this->config->getClassmapDirectory(), true)->toArray()) === 0) { - $this->filesystem->deleteDirectory($this->config->getClassmapDirectory()); + if ($this->files->isDirectoryEmpty($this->config->getClassmapDirectory())) { + $this->files->deleteDirectory($this->config->getClassmapDirectory()); } } @@ -126,51 +116,45 @@ public function movePackage(Package $package): void foreach ($package->getAutoloaders() as $autoloader) { if ($autoloader instanceof NamespaceAutoloader) { - $finder = new Finder(); - foreach ($autoloader->paths as $path) { - $source_path = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR . $path; - $source_path = str_replace('/', DIRECTORY_SEPARATOR, $source_path); + $sourcePath = str_replace('/', DIRECTORY_SEPARATOR, $sourcePath); - $finder->files()->in($source_path); - foreach ($finder as $file) { + $files = $this->files->getFilesFromPath($sourcePath); + foreach ($files as $file) { $this->moveFile($package, $autoloader, $file, $path); } } } elseif ($autoloader instanceof Classmap) { - $finder = new Finder(); - - $files_to_move = array(); + $filesToMove = array(); foreach ($autoloader->files as $file) { - $source_path = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName(); - $finder->files()->name($file)->in($source_path); - foreach ($finder as $foundFile) { + $files = $this->files->getFile($sourcePath, $file); + + foreach ($files as $foundFile) { $filePath = $foundFile->getRealPath(); - $files_to_move[ $filePath ] = $foundFile; + $filesToMove[ $filePath ] = $foundFile; } } - $finder = new Finder(); - foreach ($autoloader->paths as $path) { - $source_path = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR . $path; - $finder->files()->in($source_path); - - foreach ($finder as $foundFile) { + $files = $this->files->getFilesFromPath($sourcePath); + foreach ($files as $foundFile) { $filePath = $foundFile->getRealPath(); - $files_to_move[ $filePath ] = $foundFile; + $filesToMove[ $filePath ] = $foundFile; } } - foreach ($files_to_move as $foundFile) { + foreach ($filesToMove as $foundFile) { $this->moveFile($package, $autoloader, $foundFile); } } @@ -207,7 +191,7 @@ public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $ $targetFile = str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); } - $this->filesystem->copy( + $this->files->copyFile( str_replace($this->workingDir, '', $file->getPathname()), $targetFile ); @@ -228,20 +212,14 @@ protected function deletePackageVendorDirectories(): void continue; } - $this->filesystem->deleteDirectory($packageDir); + $this->files->deleteDirectory($packageDir); //Delete parent directory too if it became empty //(because that package was the only one from that vendor) $parentDir = dirname($packageDir); - if ($this->dirIsEmpty($parentDir)) { - $this->filesystem->deleteDirectory($parentDir); + if ($this->files->isDirectoryEmpty($parentDir)) { + $this->files->deleteDirectory($parentDir); } } } - - private function dirIsEmpty(string $dir): bool - { - $di = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS); - return iterator_count($di) === 0; - } } diff --git a/tests/MoverTest.php b/tests/MoverTest.php index d5de5d94..af4ba47f 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -55,6 +55,7 @@ public function setUp(): void ); $this->config = Mozart::loadFromString( json_encode($configArgs) ); + $this->config->setWorkingDir($this->testsWorkingDir); } /** From 8974877ec4793564e748449f442bcda0e7eaa796 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Fri, 13 Sep 2024 15:19:35 +0200 Subject: [PATCH 07/15] Remove else case from moveFile method to reduce complexity --- src/Mover.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Mover.php b/src/Mover.php index 18f976d1..1bf90337 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -180,23 +180,28 @@ public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $ . DIRECTORY_SEPARATOR . $path; $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); $targetFile = str_replace($packageVendorPath, '', $targetFile); - } else { - $namespacePath = $package->getName(); - $replaceWith = $this->config->getClassmapDirectory() . $namespacePath; - $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); - - $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() - . DIRECTORY_SEPARATOR; - $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); - $targetFile = str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); + $this->copyFile($file, $targetFile); + return $targetFile; } + $namespacePath = $package->getName(); + $replaceWith = $this->config->getClassmapDirectory() . $namespacePath; + $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); + + $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() + . DIRECTORY_SEPARATOR; + $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); + $targetFile = str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); + $this->copyFile($file, $targetFile); + return $targetFile; + } + + protected function copyFile(SplFileInfo $file, string $targetFile): void + { $this->files->copyFile( str_replace($this->workingDir, '', $file->getPathname()), $targetFile ); - - return $targetFile; } /** From 7f1a1404e54d4ec67f93a96f8d7c5cf7a6e8ecb7 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 16 Sep 2024 15:32:58 +0200 Subject: [PATCH 08/15] Setters for underscore case properties translated to snakeCase --- src/Config/Mozart.php | 63 ++++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/src/Config/Mozart.php b/src/Config/Mozart.php index a07c5b5b..4367d26e 100644 --- a/src/Config/Mozart.php +++ b/src/Config/Mozart.php @@ -11,22 +11,42 @@ class Mozart { use ReadsConfig; - public string $dep_namespace; - public string $dep_directory; - public string $classmap_directory; - public string $classmap_prefix; + public string $depNamespace; + public string $depDirectory; + public string $classmapDir; + public string $classmapPrefix; /** @var string[] */ public array $packages = []; /** @var string[] */ - public array $excluded_packages = []; + public array $excludedPackages = []; - public OverrideAutoload $override_autoload; - public bool $delete_vendor_directories; + public OverrideAutoload $overrideAutoload; + public bool $deleteVendorDir = true; public string $workingDir = ''; + public function setDepNamespace(string $depNamespace): void + { + $this->depNamespace = $depNamespace; + } + + public function setDepDirectory(string $depDirectory): void + { + $this->depDirectory = $depDirectory; + } + + public function setClassmapDirectory(string $classmapDirectory): void + { + $this->classmapDir = $classmapDirectory; + } + + public function setClassmapPrefix(string $classmapPrefix): void + { + $this->classmapPrefix = $classmapPrefix; + } + /** * @return string[] */ @@ -44,21 +64,26 @@ public function setPackages(array $packages): void } /** - * @param string[] $excluded_packages + * @param string[] $excludedPackages */ - public function setExcludedPackages(array $excluded_packages): void + public function setExcludedPackages(array $excludedPackages): void { - $this->excluded_packages = $excluded_packages; + $this->excludedPackages = $excludedPackages; } public function setOverrideAutoload(stdClass $object): void { - $this->override_autoload = new OverrideAutoload($object); + $this->overrideAutoload = new OverrideAutoload($object); + } + + public function setDeleteVendorDir(bool $deleteVendorDir): void + { + $this->deleteVendorDir = $deleteVendorDir; } public function isValidMozartConfig(): bool { - $required = [ 'dep_namespace', 'dep_directory', 'classmap_directory', 'classmap_prefix' ]; + $required = [ 'depNamespace', 'depDirectory', 'classmapDir', 'classmapPrefix' ]; foreach ($required as $requiredProp) { if (empty($this->$requiredProp)) { @@ -80,22 +105,22 @@ public function isExcludedPackage(Package $package): bool */ public function getDepDirectory(): string { - return rtrim($this->dep_directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + return rtrim($this->depDirectory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; } public function getClassmapDirectory(): string { - return rtrim($this->classmap_directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + return rtrim($this->classmapDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; } public function getDeleteVendorDirectories(): bool { - return $this->delete_vendor_directories; + return $this->deleteVendorDir; } public function getDependencyNamespace(): string { - $namespace = preg_replace("/\\\{2,}$/", "\\", $this->dep_namespace."\\"); + $namespace = preg_replace("/\\\{2,}$/", "\\", $this->depNamespace."\\"); if (empty($namespace)) { throw new Exception('Could not get target dependency namespace'); @@ -106,12 +131,12 @@ public function getDependencyNamespace(): string public function getClassmapPrefix(): string { - return $this->classmap_prefix; + return $this->classmapPrefix; } public function getOverrideAutoload(): OverrideAutoload { - return $this->override_autoload; + return $this->overrideAutoload; } /** @@ -119,7 +144,7 @@ public function getOverrideAutoload(): OverrideAutoload */ public function getExcludedPackages(): array { - return $this->excluded_packages; + return $this->excludedPackages; } public function setWorkingDir(string $workingDir): void From 26cc7d63d6fc9d868af548c5a5faec20240fe886 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 16 Sep 2024 15:57:57 +0200 Subject: [PATCH 09/15] Removed all static calls that shouldn't be static in the first place --- src/Config/Package.php | 3 +-- src/Config/ReadsConfig.php | 12 ++++++------ src/Console/Commands/Compose.php | 14 +++++++------- src/PackageFactory.php | 13 +++++++------ src/PackageFinder.php | 15 +++++---------- tests/Config/ConfigMapperTest.php | 7 +++++-- tests/MoverTest.php | 10 +++++++--- 7 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/Config/Package.php b/src/Config/Package.php index c466ee9f..68746edb 100644 --- a/src/Config/Package.php +++ b/src/Config/Package.php @@ -83,9 +83,8 @@ public function getDependencies(): array return $this->dependencies; } - public function loadDependencies(): void + public function loadDependencies(PackageFinder $finder): void { - $finder = PackageFinder::instance(); if ($this->isValidMozartConfig() && !empty($this->getExtra())) { $mozart = $this->getExtra()->getMozart(); diff --git a/src/Config/ReadsConfig.php b/src/Config/ReadsConfig.php index 4e7f3d30..22f7a83e 100644 --- a/src/Config/ReadsConfig.php +++ b/src/Config/ReadsConfig.php @@ -8,7 +8,7 @@ trait ReadsConfig { - public static function loadFromFile(string $filePath): self + public function loadFromFile(string $filePath): self { $fileContents = file_get_contents($filePath); @@ -16,13 +16,13 @@ public static function loadFromFile(string $filePath): self throw new Exception('Could not read config from provided file.'); } - return self::loadFromString($fileContents); + return $this->loadFromString($fileContents); } /** * @param array $config */ - public static function loadFromArray(array $config): self + public function loadFromArray(array $config): self { $encoded = json_encode($config); @@ -36,10 +36,10 @@ public static function loadFromArray(array $config): self throw new Exception('Could not read config from provided array.'); } - return self::loadFromStdClass($config); + return $this->loadFromStdClass($config); } - public static function loadFromStdClass(stdClass $config): self + public function loadFromStdClass(stdClass $config): self { $mapper = new JsonMapper(); $mapper->bEnforceMapType = false; @@ -52,7 +52,7 @@ public static function loadFromStdClass(stdClass $config): self return $object; } - public static function loadFromString(string $config): self + public function loadFromString(string $config): self { $config = json_decode($config); diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index c74a82d1..b17c1876 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -17,7 +17,6 @@ class Compose extends Command private Mover $mover; private Replacer $replacer; private Mozart $config; - private PackageFinder $finder; private string $workingDir; public function __construct() @@ -48,7 +47,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $composerFile = $this->workingDir . DIRECTORY_SEPARATOR. 'composer.json'; try { - $package = PackageFactory::createPackage($composerFile); + $factory = new PackageFactory(); + $package = $factory->createPackage($composerFile); } catch (Exception $e) { $output->write('Unable to read the composer.json file'); return 1; @@ -74,13 +74,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $require = $package->getRequire(); } - $this->finder = PackageFinder::instance(); - $this->finder->setConfig($this->config); + $finder = new PackageFinder(); + $finder->setConfig($this->config); - $package->loadDependencies(); + $package->loadDependencies($finder); - $packages = $this->finder->getPackagesBySlugs($require); - $packages = $this->finder->findPackages($packages); + $packages = $finder->getPackagesBySlugs($require); + $packages = $finder->findPackages($packages); $this->mover = new Mover($this->workingDir, $this->config); $this->replacer = new Replacer($this->workingDir, $this->config); diff --git a/src/PackageFactory.php b/src/PackageFactory.php index fcf4cb59..4591181a 100644 --- a/src/PackageFactory.php +++ b/src/PackageFactory.php @@ -8,21 +8,22 @@ class PackageFactory { /** @var array */ - public static array $cache = []; + public array $cache = []; - public static function createPackage(string $path, stdClass $overrideAutoload = null): Package + public function createPackage(string $path, stdClass $overrideAutoload = null): Package { - if (isset(self::$cache[$path])) { - return self::$cache[$path]; + if (isset($this->cache[$path])) { + return $this->cache[$path]; } - $package = Package::loadFromFile($path); + $package = new Package(); + $package = $package->loadFromFile($path); if (! empty($overrideAutoload)) { $package->setAutoload($overrideAutoload); } - self::$cache[$path] = $package; + $this->cache[$path] = $package; return $package; } } diff --git a/src/PackageFinder.php b/src/PackageFinder.php index df5b210a..73367ccf 100644 --- a/src/PackageFinder.php +++ b/src/PackageFinder.php @@ -9,16 +9,11 @@ class PackageFinder { private ?Mozart $config; + public PackageFactory $factory; - public static function instance(): self + public function __construct() { - static $instance; - - if (! is_object($instance) || ! $instance instanceof self) { - $instance = new self(); - } - - return $instance; + $this->factory = new PackageFactory(); } public function setConfig(Mozart $config): void @@ -53,8 +48,8 @@ public function getPackageBySlug(string $slug): ?Package $autoloaders = $overrideAutoload->$slug; } - $package = PackageFactory::createPackage($packageDir . 'composer.json', $autoloaders); - $package->loadDependencies(); + $package = $this->factory->createPackage($packageDir . 'composer.json', $autoloaders); + $package->loadDependencies($this); return $package; } diff --git a/tests/Config/ConfigMapperTest.php b/tests/Config/ConfigMapperTest.php index 433ae202..46d5553f 100644 --- a/tests/Config/ConfigMapperTest.php +++ b/tests/Config/ConfigMapperTest.php @@ -5,6 +5,7 @@ use CoenJacobs\Mozart\Config\Mozart; use CoenJacobs\Mozart\Config\Package; use CoenJacobs\Mozart\PackageFactory; +use CoenJacobs\Mozart\PackageFinder; use PHPUnit\Framework\TestCase; class ConfigMapperTest extends TestCase @@ -15,8 +16,10 @@ class ConfigMapperTest extends TestCase #[Test] public function it_creates_a_valid_config_object_based_on_composer_file() { - $package = PackageFactory::createPackage(__DIR__ . '/config-mapper-test.json'); - $package->loadDependencies(); + $finder = new PackageFinder(); + $factory = new PackageFactory(); + $package = $factory->createPackage(__DIR__ . '/config-mapper-test.json'); + $package->loadDependencies($finder); $this->assertInstanceOf(Package::class, $package); $this->assertInstanceOf(Mozart::class, $package->getExtra()->getMozart()); $this->assertCount(4, $package->autoload->getAutoloaders()); diff --git a/tests/MoverTest.php b/tests/MoverTest.php index af4ba47f..a21dbce6 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -5,6 +5,7 @@ use CoenJacobs\Mozart\PackageFactory; use CoenJacobs\Mozart\Console\Commands\Compose; use CoenJacobs\Mozart\Mover; +use CoenJacobs\Mozart\PackageFinder; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\Attributes\Test; use Symfony\Component\Console\Input\InputInterface; @@ -54,7 +55,8 @@ public function setUp(): void ), ); - $this->config = Mozart::loadFromString( json_encode($configArgs) ); + $mozart = new Mozart(); + $this->config = $mozart->loadFromString( json_encode($configArgs) ); $this->config->setWorkingDir($this->testsWorkingDir); } @@ -138,8 +140,10 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void if ( ! empty( $overrideAutoload ) ) { $overrideAutoload = $overrideAutoload->getByKey( $packageString ); } - $parsedPackage = PackageFactory::createPackage($testDummyComposerPath, $overrideAutoload); - $parsedPackage->loadDependencies(); + $factory = new PackageFactory(); + $finder = new PackageFinder(); + $parsedPackage = $factory->createPackage($testDummyComposerPath, $overrideAutoload); + $parsedPackage->loadDependencies($finder); $packages[] = $parsedPackage; } From 10e709b46d4abbbaaba452fc560fd92788d2d2a2 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 17 Sep 2024 11:42:53 +0200 Subject: [PATCH 10/15] Reduce complexity of moveFile method on Mover class --- src/Console/Commands/Compose.php | 4 +++ src/Mover.php | 42 ++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index b17c1876..9d6207ee 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -91,6 +91,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $this->replacer->replaceParentInTree($packages); $this->replacer->replaceParentClassesInDirectory($this->config->getClassmapDirectory()); + if ($this->config->getDeleteVendorDirectories()) { + $this->mover->deletePackageVendorDirectories(); + } + return 0; } } diff --git a/src/Mover.php b/src/Mover.php index 1bf90337..6729ab6a 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -163,27 +163,39 @@ public function movePackage(Package $package): void $this->movedPackages[] = $package->getName(); } } - - if ($this->config->getDeleteVendorDirectories()) { - $this->deletePackageVendorDirectories(); - } } public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $file, string $path = ''): string { if ($autoloader instanceof NamespaceAutoloader) { - $namespacePath = $autoloader->getNamespacePath(); - $replaceWith = $this->config->getDepDirectory() . $namespacePath; - $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); - - $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() - . DIRECTORY_SEPARATOR . $path; - $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); - $targetFile = str_replace($packageVendorPath, '', $targetFile); + $targetFile = $this->getNamespaceTargetFile($package, $autoloader, $file, $path); $this->copyFile($file, $targetFile); return $targetFile; } + $targetFile = $this->getClassmapTargetFile($package, $file); + $this->copyFile($file, $targetFile); + return $targetFile; + } + + private function getNamespaceTargetFile( + Package $package, + NamespaceAutoloader $autoloader, + SplFileInfo $file, + string $path + ): string { + $namespacePath = $autoloader->getNamespacePath(); + $replaceWith = $this->config->getDepDirectory() . $namespacePath; + $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); + + $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() + . DIRECTORY_SEPARATOR . $path; + $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); + return str_replace($packageVendorPath, '', $targetFile); + } + + private function getClassmapTargetFile(Package $package, SplFileInfo $file): string + { $namespacePath = $package->getName(); $replaceWith = $this->config->getClassmapDirectory() . $namespacePath; $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); @@ -191,9 +203,7 @@ public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $ $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR; $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); - $targetFile = str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); - $this->copyFile($file, $targetFile); - return $targetFile; + return str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); } protected function copyFile(SplFileInfo $file, string $targetFile): void @@ -209,7 +219,7 @@ protected function copyFile(SplFileInfo $file, string $targetFile): void * prevent packages that are prefixed/namespaced from being used or * influencing the output of the code. They just need to be gone. */ - protected function deletePackageVendorDirectories(): void + public function deletePackageVendorDirectories(): void { foreach ($this->movedPackages as $movedPackage) { $packageDir = 'vendor' . DIRECTORY_SEPARATOR . $movedPackage; From 00470e70e3182a18d157400aadb4053e32d316de Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 17 Sep 2024 12:03:31 +0200 Subject: [PATCH 11/15] Reduce complexity of movePackage method --- src/Mover.php | 109 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 37 deletions(-) diff --git a/src/Mover.php b/src/Mover.php index 6729ab6a..b4f9dfe2 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -106,53 +106,20 @@ public function movePackages($packages): void public function movePackage(Package $package): void { - if (in_array($package->getName(), $this->movedPackages)) { - return; - } - - if ($this->config->isExcludedPackage($package)) { + if (!$this->shouldPackageBeMoved($package)) { return; } foreach ($package->getAutoloaders() as $autoloader) { if ($autoloader instanceof NamespaceAutoloader) { foreach ($autoloader->paths as $path) { - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR - . $package->getName() . DIRECTORY_SEPARATOR . $path; - - $sourcePath = str_replace('/', DIRECTORY_SEPARATOR, $sourcePath); - - - $files = $this->files->getFilesFromPath($sourcePath); - foreach ($files as $file) { + $filesToMove = $this->getNamespaceFilesToMove($package, $path); + foreach ($filesToMove as $file) { $this->moveFile($package, $autoloader, $file, $path); } } } elseif ($autoloader instanceof Classmap) { - $filesToMove = array(); - - foreach ($autoloader->files as $file) { - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' - . DIRECTORY_SEPARATOR . $package->getName(); - - $files = $this->files->getFile($sourcePath, $file); - - foreach ($files as $foundFile) { - $filePath = $foundFile->getRealPath(); - $filesToMove[ $filePath ] = $foundFile; - } - } - - foreach ($autoloader->paths as $path) { - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' - . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR . $path; - - $files = $this->files->getFilesFromPath($sourcePath); - foreach ($files as $foundFile) { - $filePath = $foundFile->getRealPath(); - $filesToMove[ $filePath ] = $foundFile; - } - } + $filesToMove = $this->getClassmapFilesToMove($autoloader, $package); foreach ($filesToMove as $foundFile) { $this->moveFile($package, $autoloader, $foundFile); @@ -165,6 +132,74 @@ public function movePackage(Package $package): void } } + private function shouldPackageBeMoved(Package $package): bool + { + if (in_array($package->getName(), $this->movedPackages)) { + return false; + } + + if ($this->config->isExcludedPackage($package)) { + return false; + } + + return true; + } + + /** + * @return array + */ + private function getNamespaceFilesToMove(Package $package, string $path): array + { + $filesToMove = array(); + + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR + . $package->getName() . DIRECTORY_SEPARATOR . $path; + + $sourcePath = str_replace('/', DIRECTORY_SEPARATOR, $sourcePath); + + $files = $this->files->getFilesFromPath($sourcePath); + + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + + return $filesToMove; + } + + /** + * @return array + */ + private function getClassmapFilesToMove(Classmap $autoloader, Package $package): array + { + $filesToMove = array(); + + foreach ($autoloader->files as $file) { + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' + . DIRECTORY_SEPARATOR . $package->getName(); + + $files = $this->files->getFile($sourcePath, $file); + + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + } + + foreach ($autoloader->paths as $path) { + $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' + . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR . $path; + + $files = $this->files->getFilesFromPath($sourcePath); + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + } + + return $filesToMove; + } + public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $file, string $path = ''): string { if ($autoloader instanceof NamespaceAutoloader) { From defd19010823943d4bc65e7e98123c0dbd119465 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 17 Sep 2024 12:43:51 +0200 Subject: [PATCH 12/15] Reduce complexity of deleteDepTargetDirs methods --- src/Composer/Autoload/AbstractAutoloader.php | 13 ++++++ src/Composer/Autoload/Autoloader.php | 1 + src/Composer/Autoload/NamespaceAutoloader.php | 2 +- src/Config/Classmap.php | 4 +- src/Mover.php | 43 +++++++++++-------- 5 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/Composer/Autoload/AbstractAutoloader.php diff --git a/src/Composer/Autoload/AbstractAutoloader.php b/src/Composer/Autoload/AbstractAutoloader.php new file mode 100644 index 00000000..c2aeedee --- /dev/null +++ b/src/Composer/Autoload/AbstractAutoloader.php @@ -0,0 +1,13 @@ +config = $config; $this->workingDir = $workingDir; - $this->targetDir = $this->config->getDepDirectory(); + $this->config = $config; $this->files = new FilesHandler($config); } @@ -57,30 +53,40 @@ public function deleteTargetDirs($packages): void */ private function deleteDepTargetDirs(Package $package): void { - foreach ($package->getAutoloaders() as $packageAutoloader) { - $autoloaderType = get_class($packageAutoloader); + foreach ($package->getAutoloaders() as $autoloader) { + $autoloaderType = get_class($autoloader); + $outputDir = ''; switch ($autoloaderType) { case Psr0::class: case Psr4::class: - $outputDir = $this->config->getDepDirectory() . $packageAutoloader->getSearchNamespace(); - $outputDir = str_replace('\\', DIRECTORY_SEPARATOR, $outputDir); - $this->files->deleteDirectory($outputDir); + $outputDir = $autoloader->getOutputDir( + $this->config->getDepDirectory(), + $autoloader->getSearchNamespace() + ); break; case Classmap::class: - $outputDir = $this->config->getClassmapDirectory() . $package->getName(); - $outputDir = str_replace('\\', DIRECTORY_SEPARATOR, $outputDir); - $this->files->deleteDirectory($outputDir); + $outputDir = $autoloader->getOutputDir( + $this->config->getClassmapDirectory(), + $package->getName() + ); break; } + + if (empty($outputDir)) { + continue; + } + + $this->files->deleteDirectory($outputDir); } + foreach ($package->getDependencies() as $subPackage) { $this->deleteDepTargetDirs($subPackage); } } - public function deleteEmptyDirs(): void + private function deleteEmptyDirs(): void { if ($this->files->isDirectoryEmpty($this->config->getDepDirectory())) { $this->files->deleteDirectory($this->config->getDepDirectory()); @@ -104,7 +110,7 @@ public function movePackages($packages): void $this->deleteEmptyDirs(); } - public function movePackage(Package $package): void + private function movePackage(Package $package): void { if (!$this->shouldPackageBeMoved($package)) { return; @@ -200,17 +206,16 @@ private function getClassmapFilesToMove(Classmap $autoloader, Package $package): return $filesToMove; } - public function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $file, string $path = ''): string + private function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $file, string $path = ''): void { if ($autoloader instanceof NamespaceAutoloader) { $targetFile = $this->getNamespaceTargetFile($package, $autoloader, $file, $path); $this->copyFile($file, $targetFile); - return $targetFile; + return; } $targetFile = $this->getClassmapTargetFile($package, $file); $this->copyFile($file, $targetFile); - return $targetFile; } private function getNamespaceTargetFile( @@ -241,7 +246,7 @@ private function getClassmapTargetFile(Package $package, SplFileInfo $file): str return str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); } - protected function copyFile(SplFileInfo $file, string $targetFile): void + private function copyFile(SplFileInfo $file, string $targetFile): void { $this->files->copyFile( str_replace($this->workingDir, '', $file->getPathname()), From be0ba40d797c6763729418f8578fdd7f5f1b6b24 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 19 Sep 2024 10:03:44 +0200 Subject: [PATCH 13/15] Reduce Mover complexity by defering file path handling to autoloaders --- src/Composer/Autoload/AbstractAutoloader.php | 14 ++ src/Composer/Autoload/Autoloader.php | 8 ++ src/Composer/Autoload/NamespaceAutoloader.php | 51 +++++++ src/Config/Autoload.php | 5 +- src/Config/Classmap.php | 64 +++++++++ src/Config/Mozart.php | 6 +- src/Config/Package.php | 9 +- src/Console/Commands/Compose.php | 8 +- src/FilesHandler.php | 5 + src/Mover.php | 131 +++--------------- src/PackageFinder.php | 5 +- src/Replacer.php | 24 ++-- tests/MoverTest.php | 6 +- 13 files changed, 194 insertions(+), 142 deletions(-) diff --git a/src/Composer/Autoload/AbstractAutoloader.php b/src/Composer/Autoload/AbstractAutoloader.php index c2aeedee..05b8c379 100644 --- a/src/Composer/Autoload/AbstractAutoloader.php +++ b/src/Composer/Autoload/AbstractAutoloader.php @@ -2,8 +2,22 @@ namespace CoenJacobs\Mozart\Composer\Autoload; +use CoenJacobs\Mozart\Config\Package; + abstract class AbstractAutoloader implements Autoloader { + private Package $package; + + public function getPackage(): Package + { + return $this->package; + } + + public function setPackage(Package $package): void + { + $this->package = $package; + } + public function getOutputDir(string $basePath, string $autoloadPath): string { $outputDir = $basePath . $autoloadPath; diff --git a/src/Composer/Autoload/Autoloader.php b/src/Composer/Autoload/Autoloader.php index 609e2991..06ea8f90 100644 --- a/src/Composer/Autoload/Autoloader.php +++ b/src/Composer/Autoload/Autoloader.php @@ -2,6 +2,9 @@ namespace CoenJacobs\Mozart\Composer\Autoload; +use CoenJacobs\Mozart\FilesHandler; +use Symfony\Component\Finder\SplFileInfo; + interface Autoloader { /** @@ -10,4 +13,9 @@ interface Autoloader public function processConfig($autoloadConfig): void; public function getSearchNamespace(): string; public function getOutputDir(string $basePath, string $autoloadPath): string; + /** + * @return array + */ + public function getFiles(FilesHandler $files): array; + public function getTargetFilePath(SplFileInfo $file): string; } diff --git a/src/Composer/Autoload/NamespaceAutoloader.php b/src/Composer/Autoload/NamespaceAutoloader.php index 34e31c22..5e89eb23 100644 --- a/src/Composer/Autoload/NamespaceAutoloader.php +++ b/src/Composer/Autoload/NamespaceAutoloader.php @@ -2,6 +2,9 @@ namespace CoenJacobs\Mozart\Composer\Autoload; +use CoenJacobs\Mozart\FilesHandler; +use Symfony\Component\Finder\SplFileInfo; + abstract class NamespaceAutoloader extends AbstractAutoloader { /** @var string */ @@ -16,6 +19,8 @@ abstract class NamespaceAutoloader extends AbstractAutoloader */ public $paths = []; + private FilesHandler $fileHandler; + /** * A package's composer.json config autoload key's value, where $key is `psr-1`|`psr-4`|`classmap`. * @@ -47,4 +52,50 @@ public function getNamespacePath(): string { return ''; } + + public function getFiles(FilesHandler $fileHandler): array + { + $this->fileHandler = $fileHandler; + $filesToMove = array(); + + foreach ($this->paths as $path) { + $sourcePath = $fileHandler->getConfig()->getWorkingDir() . 'vendor' . DIRECTORY_SEPARATOR + . $this->getPackage()->getName() . DIRECTORY_SEPARATOR . $path; + + $sourcePath = str_replace('/', DIRECTORY_SEPARATOR, $sourcePath); + + + $files = $fileHandler->getFilesFromPath($sourcePath); + + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + } + + return $filesToMove; + } + + public function getTargetFilePath(SplFileInfo $file): string + { + $suffix = ''; + foreach ($this->paths as $path) { + if (! empty(strstr($file->getPathname(), $this->getPackage()->getName() . DIRECTORY_SEPARATOR . $path))) { + $suffix = $path; + break; + } + } + + $replaceWith = $this->fileHandler->getConfig()->getDepDirectory() . $this->getNamespacePath(); + $targetFile = str_replace($this->fileHandler->getConfig()->getWorkingDir(), $replaceWith, $file->getPathname()); + + $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $this->getPackage()->getName(); + + if (! empty($suffix)) { + $packageVendorPath = $packageVendorPath . DIRECTORY_SEPARATOR . $suffix; + } + + $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); + return str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); + } } diff --git a/src/Config/Autoload.php b/src/Config/Autoload.php index 55fd1aae..78198e14 100644 --- a/src/Config/Autoload.php +++ b/src/Config/Autoload.php @@ -10,7 +10,7 @@ class Autoload /** @var array */ public array $autoloaders = []; - public function setupAutoloaders(stdClass $autoloadData): void + public function setupAutoloaders(stdClass $autoloadData, Package $package): void { $autoloaders = []; @@ -20,6 +20,7 @@ public function setupAutoloaders(stdClass $autoloadData): void $autoloader = new Psr4(); $autoloader->namespace = $key; $autoloader->processConfig($value); + $autoloader->setPackage($package); $autoloaders[] = $autoloader; } } @@ -30,6 +31,7 @@ public function setupAutoloaders(stdClass $autoloadData): void $autoloader = new Psr0(); $autoloader->namespace = $key; $autoloader->processConfig($value); + $autoloader->setPackage($package); $autoloaders[] = $autoloader; } } @@ -37,6 +39,7 @@ public function setupAutoloaders(stdClass $autoloadData): void if (isset($autoloadData->classmap)) { $autoloader = new Classmap(); $autoloader->processConfig($autoloadData->classmap); + $autoloader->setPackage($package); $autoloaders[] = $autoloader; } diff --git a/src/Config/Classmap.php b/src/Config/Classmap.php index 4225d4be..4788f3d2 100644 --- a/src/Config/Classmap.php +++ b/src/Config/Classmap.php @@ -3,7 +3,9 @@ namespace CoenJacobs\Mozart\Config; use CoenJacobs\Mozart\Composer\Autoload\AbstractAutoloader; +use CoenJacobs\Mozart\FilesHandler; use Exception; +use Symfony\Component\Finder\SplFileInfo; class Classmap extends AbstractAutoloader { @@ -13,6 +15,8 @@ class Classmap extends AbstractAutoloader /** @var string[] */ public $paths = []; + private FilesHandler $fileHandler; + /** * @inheritdoc */ @@ -35,4 +39,64 @@ public function getSearchNamespace(): string { throw new Exception('Classmap autoloaders do not contain a namespace and this method can not be used.'); } + + /** + * @return array + */ + public function getFiles(FilesHandler $fileHandler): array + { + $this->fileHandler = $fileHandler; + $filesToMove = array(); + + foreach ($this->files as $file) { + $sourcePath = $fileHandler->getConfig()->getWorkingDir() . 'vendor' + . DIRECTORY_SEPARATOR . $this->getPackage()->getName(); + + $files = $fileHandler->getFile($sourcePath, $file); + + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + } + + foreach ($this->paths as $path) { + $sourcePath = $fileHandler->getConfig()->getWorkingDir() . 'vendor' + . DIRECTORY_SEPARATOR . $this->getPackage()->getName() . DIRECTORY_SEPARATOR . $path; + + $files = $fileHandler->getFilesFromPath($sourcePath); + foreach ($files as $foundFile) { + $filePath = $foundFile->getRealPath(); + $filesToMove[ $filePath ] = $foundFile; + } + } + + return $filesToMove; + } + + public function getTargetFilePath(SplFileInfo $file): string + { + $suffix = ''; + foreach ($this->paths as $path) { + if (! empty(strstr($file->getPathname(), $this->getPackage()->getName() . DIRECTORY_SEPARATOR . $path))) { + $suffix = $path; + break; + } + } + + $namespacePath = $this->getPackage()->getName(); + $replaceWith = $this->fileHandler->getConfig()->getClassmapDirectory() . $namespacePath . DIRECTORY_SEPARATOR; + + $targetFile = str_replace($this->fileHandler->getConfig()->getWorkingDir(), $replaceWith, $file->getPathname()); + + $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $this->getPackage()->getName() + . DIRECTORY_SEPARATOR; + + if (! empty($suffix)) { + $packageVendorPath = $packageVendorPath . DIRECTORY_SEPARATOR . $suffix; + } + + $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); + return str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); + } } diff --git a/src/Config/Mozart.php b/src/Config/Mozart.php index 4367d26e..ac02e32f 100644 --- a/src/Config/Mozart.php +++ b/src/Config/Mozart.php @@ -105,12 +105,12 @@ public function isExcludedPackage(Package $package): bool */ public function getDepDirectory(): string { - return rtrim($this->depDirectory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + return trim($this->depDirectory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; } public function getClassmapDirectory(): string { - return rtrim($this->classmapDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; + return trim($this->classmapDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; } public function getDeleteVendorDirectories(): bool @@ -154,6 +154,6 @@ public function setWorkingDir(string $workingDir): void public function getWorkingDir(): string { - return $this->workingDir; + return rtrim($this->workingDir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; } } diff --git a/src/Config/Package.php b/src/Config/Package.php index 68746edb..5e4dece2 100644 --- a/src/Config/Package.php +++ b/src/Config/Package.php @@ -25,10 +25,12 @@ class Package public ?Autoload $autoload = null; public ?Extra $extra = null; + private bool $dependenciesLoaded = false; + public function setAutoload(stdClass $data): void { $autoload = new Autoload(); - $autoload->setupAutoloaders($data); + $autoload->setupAutoloaders($data, $this); $this->autoload = $autoload; } @@ -85,6 +87,10 @@ public function getDependencies(): array public function loadDependencies(PackageFinder $finder): void { + if ($this->dependenciesLoaded) { + return; + } + if ($this->isValidMozartConfig() && !empty($this->getExtra())) { $mozart = $this->getExtra()->getMozart(); @@ -97,6 +103,7 @@ public function loadDependencies(PackageFinder $finder): void $dependencies = $finder->getPackagesBySlugs($this->getRequire()); $this->registerDependencies($dependencies); + $this->dependenciesLoaded = true; } public function registerDependency(Package $package): void diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index 9d6207ee..63856d8f 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -78,12 +78,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $finder->setConfig($this->config); $package->loadDependencies($finder); + $packages = $finder->findPackages($package->getDependencies()); - $packages = $finder->getPackagesBySlugs($require); - $packages = $finder->findPackages($packages); - - $this->mover = new Mover($this->workingDir, $this->config); - $this->replacer = new Replacer($this->workingDir, $this->config); + $this->mover = new Mover($this->config); + $this->replacer = new Replacer($this->config); $this->mover->deleteTargetDirs($packages); $this->mover->movePackages($packages); diff --git a/src/FilesHandler.php b/src/FilesHandler.php index b8ffda58..46787b55 100644 --- a/src/FilesHandler.php +++ b/src/FilesHandler.php @@ -37,6 +37,11 @@ public function readFile(string $path): string return $contents; } + public function getConfig(): Mozart + { + return $this->config; + } + public function writeFile(string $path, string $contents): void { $this->filesystem->write($path, $contents); diff --git a/src/Mover.php b/src/Mover.php index 3bcbd446..70b4427d 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -3,7 +3,6 @@ namespace CoenJacobs\Mozart; use CoenJacobs\Mozart\Composer\Autoload\Autoloader; -use CoenJacobs\Mozart\Composer\Autoload\NamespaceAutoloader; use CoenJacobs\Mozart\Config\Classmap; use CoenJacobs\Mozart\Config\Mozart; use CoenJacobs\Mozart\Config\Package; @@ -13,9 +12,6 @@ class Mover { - /** @var string */ - protected $workingDir; - /** @var Mozart */ protected $config; @@ -24,9 +20,11 @@ class Mover /** @var array */ protected $movedPackages = []; - public function __construct(string $workingDir, Mozart $config) + /** @var array */ + protected $movedFiles = []; + + public function __construct(Mozart $config) { - $this->workingDir = $workingDir; $this->config = $config; $this->files = new FilesHandler($config); } @@ -103,7 +101,6 @@ private function deleteEmptyDirs(): void public function movePackages($packages): void { foreach ($packages as $package) { - $this->movePackages($package->getDependencies()); $this->movePackage($package); } @@ -116,26 +113,21 @@ private function movePackage(Package $package): void return; } + /** + * @todo: This maybe even warrants its own 'File' class, where stuff + * like the SplFileInfo etc can be stored in. + */ foreach ($package->getAutoloaders() as $autoloader) { - if ($autoloader instanceof NamespaceAutoloader) { - foreach ($autoloader->paths as $path) { - $filesToMove = $this->getNamespaceFilesToMove($package, $path); - foreach ($filesToMove as $file) { - $this->moveFile($package, $autoloader, $file, $path); - } - } - } elseif ($autoloader instanceof Classmap) { - $filesToMove = $this->getClassmapFilesToMove($autoloader, $package); - - foreach ($filesToMove as $foundFile) { - $this->moveFile($package, $autoloader, $foundFile); - } - } + $filesToMove = $autoloader->getFiles($this->files); - if (!in_array($package->getName(), $this->movedPackages)) { - $this->movedPackages[] = $package->getName(); + foreach ($filesToMove as $foundFile) { + $this->moveFile($autoloader, $foundFile); } } + + if (!in_array($package->getName(), $this->movedPackages)) { + $this->movedPackages[] = $package->getName(); + } } private function shouldPackageBeMoved(Package $package): bool @@ -151,105 +143,22 @@ private function shouldPackageBeMoved(Package $package): bool return true; } - /** - * @return array - */ - private function getNamespaceFilesToMove(Package $package, string $path): array - { - $filesToMove = array(); - - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR - . $package->getName() . DIRECTORY_SEPARATOR . $path; - - $sourcePath = str_replace('/', DIRECTORY_SEPARATOR, $sourcePath); - - $files = $this->files->getFilesFromPath($sourcePath); - - foreach ($files as $foundFile) { - $filePath = $foundFile->getRealPath(); - $filesToMove[ $filePath ] = $foundFile; - } - - return $filesToMove; - } - - /** - * @return array - */ - private function getClassmapFilesToMove(Classmap $autoloader, Package $package): array - { - $filesToMove = array(); - - foreach ($autoloader->files as $file) { - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' - . DIRECTORY_SEPARATOR . $package->getName(); - - $files = $this->files->getFile($sourcePath, $file); - - foreach ($files as $foundFile) { - $filePath = $foundFile->getRealPath(); - $filesToMove[ $filePath ] = $foundFile; - } - } - - foreach ($autoloader->paths as $path) { - $sourcePath = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' - . DIRECTORY_SEPARATOR . $package->getName() . DIRECTORY_SEPARATOR . $path; - - $files = $this->files->getFilesFromPath($sourcePath); - foreach ($files as $foundFile) { - $filePath = $foundFile->getRealPath(); - $filesToMove[ $filePath ] = $foundFile; - } - } - - return $filesToMove; - } - - private function moveFile(Package $package, Autoloader $autoloader, SplFileInfo $file, string $path = ''): void + private function moveFile(Autoloader $autoloader, SplFileInfo $file): void { - if ($autoloader instanceof NamespaceAutoloader) { - $targetFile = $this->getNamespaceTargetFile($package, $autoloader, $file, $path); - $this->copyFile($file, $targetFile); + if (in_array($file->getRealPath(), $this->movedFiles)) { return; } - $targetFile = $this->getClassmapTargetFile($package, $file); + $targetFile = $autoloader->getTargetFilePath($file); $this->copyFile($file, $targetFile); - } - - private function getNamespaceTargetFile( - Package $package, - NamespaceAutoloader $autoloader, - SplFileInfo $file, - string $path - ): string { - $namespacePath = $autoloader->getNamespacePath(); - $replaceWith = $this->config->getDepDirectory() . $namespacePath; - $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); - - $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() - . DIRECTORY_SEPARATOR . $path; - $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); - return str_replace($packageVendorPath, '', $targetFile); - } - private function getClassmapTargetFile(Package $package, SplFileInfo $file): string - { - $namespacePath = $package->getName(); - $replaceWith = $this->config->getClassmapDirectory() . $namespacePath; - $targetFile = str_replace($this->workingDir, $replaceWith, $file->getPathname()); - - $packageVendorPath = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->getName() - . DIRECTORY_SEPARATOR; - $packageVendorPath = str_replace('/', DIRECTORY_SEPARATOR, $packageVendorPath); - return str_replace($packageVendorPath, DIRECTORY_SEPARATOR, $targetFile); + array_push($this->movedFiles, $file->getRealPath()); } private function copyFile(SplFileInfo $file, string $targetFile): void { $this->files->copyFile( - str_replace($this->workingDir, '', $file->getPathname()), + str_replace($this->config->getWorkingDir(), '', $file->getPathname()), $targetFile ); } diff --git a/src/PackageFinder.php b/src/PackageFinder.php index 73367ccf..5950cd4e 100644 --- a/src/PackageFinder.php +++ b/src/PackageFinder.php @@ -81,8 +81,9 @@ public function findPackages(array $packages): array foreach ($packages as $package) { $dependencies = $package->getDependencies(); - $package->registerDependencies($this->findPackages($dependencies)); - $packages[$package->getName()] = $package; + if (! empty($dependencies)) { + $packages = array_merge($packages, $this->findPackages($dependencies)); + } } return $packages; diff --git a/src/Replacer.php b/src/Replacer.php index 8cc76433..af4d4832 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -14,12 +14,6 @@ class Replacer { - /** @var string */ - protected $workingDir; - - /** @var string */ - protected $targetDir; - /** @var Mozart */ protected $config; @@ -29,11 +23,9 @@ class Replacer /** @var FilesHandler */ protected $files; - public function __construct(string $workingDir, Mozart $config) + public function __construct(Mozart $config) { - $this->workingDir = $workingDir; $this->config = $config; - $this->targetDir = $this->config->getDepDirectory(); $this->files = new FilesHandler($config); } @@ -57,7 +49,7 @@ public function replacePackage(Package $package): void public function replaceInFile(string $targetFile, Autoloader $autoloader): void { - $targetFile = str_replace($this->workingDir, '', $targetFile); + $targetFile = str_replace($this->config->getWorkingDir(), '', $targetFile); $contents = $this->files->readFile($targetFile); if (!$contents) { @@ -96,11 +88,11 @@ public function replacePackageByAutoloader(Package $package, Autoloader $autoloa } if ($autoloader instanceof NamespaceAutoloader) { - $sourcePath = $this->workingDir . $this->targetDir + $sourcePath = $this->config->getWorkingDir() . $this->config->getDepDirectory() . str_replace('\\', DIRECTORY_SEPARATOR, $autoloader->getNamespace()); $this->replaceInDirectory($autoloader, $sourcePath); } elseif ($autoloader instanceof Classmap) { - $sourcePath = $this->workingDir . $this->config->getClassmapDirectory() . $package->getName(); + $sourcePath = $this->config->getWorkingDir() . $this->config->getClassmapDirectory() . $package->getName(); $files = $this->files->getFilesFromPath($sourcePath); foreach ($files as $foundFile) { @@ -180,7 +172,7 @@ public function replaceParentPackage(Package $package, Package $parent): void foreach ($package->getAutoloaders() as $autoloader) { if ($parentAutoloader instanceof NamespaceAutoloader) { $namespace = str_replace('\\', DIRECTORY_SEPARATOR, $parentAutoloader->namespace); - $directory = $this->workingDir . $this->config->getDepDirectory() . $namespace + $directory = $this->config->getWorkingDir() . $this->config->getDepDirectory() . $namespace . DIRECTORY_SEPARATOR; if ($autoloader instanceof NamespaceAutoloader) { @@ -188,12 +180,12 @@ public function replaceParentPackage(Package $package, Package $parent): void return; } - $directory = str_replace($this->workingDir, '', $directory); + $directory = str_replace($this->config->getWorkingDir(), '', $directory); $this->replaceParentClassesInDirectory($directory); return; } - $directory = $this->workingDir . + $directory = $this->config->getWorkingDir() . $this->config->getClassmapDirectory() . $parent->getName(); if ($autoloader instanceof NamespaceAutoloader) { @@ -201,7 +193,7 @@ public function replaceParentPackage(Package $package, Package $parent): void return; } - $directory = str_replace($this->workingDir, '', $directory); + $directory = str_replace($this->config->getWorkingDir(), '', $directory); $this->replaceParentClassesInDirectory($directory); } } diff --git a/tests/MoverTest.php b/tests/MoverTest.php index a21dbce6..9e6550ad 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -68,7 +68,7 @@ public function setUp(): void #[Test] public function it_creates_absent_dirs(): void { - $mover = new Mover($this->testsWorkingDir, $this->config); + $mover = new Mover($this->config); $packages = array(); @@ -88,7 +88,7 @@ public function it_creates_absent_dirs(): void #[Test] public function it_is_unpertrubed_by_existing_dirs(): void { - $mover = new Mover($this->testsWorkingDir, $this->config); + $mover = new Mover($this->config); if (!file_exists($this->testsWorkingDir . $this->config->getDepDirectory())) { mkdir($this->testsWorkingDir . $this->config->getDepDirectory()); @@ -147,7 +147,7 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void $packages[] = $parsedPackage; } - $mover = new Mover($this->testsWorkingDir, $this->config); + $mover = new Mover($this->config); $mover->deleteTargetDirs($packages); $this->assertDirectoryDoesNotExist($this->testsWorkingDir . $this->config->getDepDirectory() . 'Pimple'); From 3f8e10c4480801714f8c66b8e8a4781215a8c084 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 19 Sep 2024 10:11:19 +0200 Subject: [PATCH 14/15] Suppress parameter not being used as it extends Symfony command class --- src/Console/Commands/Compose.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index 63856d8f..a8bf0dbd 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -39,6 +39,9 @@ protected function configure(): void $this->setHelp(''); } + /** + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ protected function execute(InputInterface $input, OutputInterface $output): int { if (! $this->workingDir) { From b1a58c58e9aea2b722637d8126ab2766ff19e914 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 19 Sep 2024 10:15:18 +0200 Subject: [PATCH 15/15] Add phpmd to test script and GitHub Actions --- .github/workflows/main.yml | 17 +++++++++++++++++ composer.json | 6 +++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f5583e8a..00f7d12e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -60,3 +60,20 @@ jobs: cache-to: type=gha,mode=max - name: Run analysis run: docker compose run --rm actions-tester composer test:phpstan + mess-detect: + runs-on: ubuntu-latest + name: Mess detector + steps: + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v2 + - uses: actions/checkout@v4 + - name: Build Docker image + id: build-and-push + uses: docker/build-push-action@v4 + with: + context: "{{defaultContext}}" + push: false + cache-from: type=gha + cache-to: type=gha,mode=max + - name: Run mess detector + run: docker compose run --rm actions-tester composer test:phpmd diff --git a/composer.json b/composer.json index 6f0af7e6..2170597c 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,8 @@ "test": [ "@test:lint", "@test:phpunit", - "@test:phpstan" + "@test:phpstan", + "@test:phpmd" ], "test:lint": [ "composer validate", @@ -58,6 +59,9 @@ ], "test:phpstan": [ "./vendor/bin/phpstan analyse -c phpstan.neon.dist --memory-limit=2G" + ], + "test:phpmd": [ + "./vendor/bin/phpmd src ansi phpmd.xml.dist" ] } }