From 54d7ca7d38c89257e9707b62bec3b4e9240697dc Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Tue, 24 Nov 2020 14:30:30 -0800 Subject: [PATCH 01/58] Move each file only once (classmap) Fixes #89 Before moving files, builds a dictionary of files to be moved, using the source filie path as the dictionary key, so if the same file is in the autoloader more than once, it is only moved once. --- src/Mover.php | 14 ++++++-- tests/MoverTest.php | 65 ++++++++++++++++++++++++++++++++++++- tests/issue89-composer.json | 18 ++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 tests/issue89-composer.json diff --git a/src/Mover.php b/src/Mover.php index 61cc2379..2ca807a5 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -123,13 +123,16 @@ public function movePackage(Package $package) } elseif ($autoloader instanceof Classmap) { $finder = new Finder(); + $files_to_move = array(); + foreach ($autoloader->files as $file) { $source_path = $this->workingDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $package->config->name; $finder->files()->name($file)->in($source_path); foreach ($finder as $foundFile) { - $this->moveFile($package, $autoloader, $foundFile); + $filePath = $foundFile->getRealPath(); + $files_to_move[ $filePath ] = $foundFile; } } @@ -141,10 +144,15 @@ public function movePackage(Package $package) $finder->files()->in($source_path); - foreach ($finder as $file) { - $this->moveFile($package, $autoloader, $file); + foreach ($finder as $foundFile) { + $filePath = $foundFile->getRealPath(); + $files_to_move[ $filePath ] = $foundFile; } } + + foreach ($files_to_move as $foundFile) { + $this->moveFile($package, $autoloader, $foundFile); + } } if (!in_array($package->config->name, $this->movedPackages)) { diff --git a/tests/MoverTest.php b/tests/MoverTest.php index 362514dc..3ec8a1b3 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -2,8 +2,11 @@ declare(strict_types=1); use CoenJacobs\Mozart\Composer\Package; +use CoenJacobs\Mozart\Console\Commands\Compose; use CoenJacobs\Mozart\Mover; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; class MoverTest extends TestCase { @@ -139,6 +142,65 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void $this->assertDirectoryNotExists($this->testsWorkingDir . $this->config->dep_directory . 'ezyang'); } + /** + * If a file is specified more than once in an autoloader, e.g. is explicitly listed and is also in a folder listed, + * a "File already exists at path" error occurs. + * + * To fix this, we enumerate the files to be copied using a dictionary indexed with the source file path, then loop + * and copy, thus only copying each one once. + * + * Original error: + * "League\Flysystem\FileExistsException : File already exists at path: lib/classes/tecnickcom/tcpdf/tcpdf.php" + * + * Test is using a known problematic autoloader: + * "iio/libmergepdf": { + * "classmap": [ + * "config", + * "include", + * "tcpdf.php", + * "tcpdf_parser.php", + * "tcpdf_import.php", + * "tcpdf_barcodes_1d.php", + * "tcpdf_barcodes_2d.php", + * "include/tcpdf_colors.php", + * "include/tcpdf_filters.php", + * "include/tcpdf_font_data.php", + * "include/tcpdf_fonts.php", + * "include/tcpdf_images.php", + * "include/tcpdf_static.php", + * "include/barcodes/datamatrix.php", + * "include/barcodes/pdf417.php", + * "include/barcodes/qrcode.php" + * ] + * } + * + * @see https://github.com/coenjacobs/mozart/issues/89 + * + * @test + */ + public function it_moves_each_file_once_per_namespace() + { + + // The composer.json with the Mozart requirement and `mozart compose` removed. + copy(__DIR__ . '/issue89-composer.json', $this->testsWorkingDir . '/composer.json'); + + chdir($this->testsWorkingDir); + + exec('composer install'); + + $inputInterfaceMock = $this->createMock(InputInterface::class); + $outputInterfaceMock = $this->createMock(OutputInterface::class); + + $mozartCompose = new Compose(); + + // $this->expectException(League\Flysystem\FileExistsException::class); + + $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); + + // On the failing test, an exception was thrown and this line was not reached. + $this->assertEquals(0, $result); + } + /** * Delete $this->testsWorkingDir after each test. * @@ -147,7 +209,7 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void public function tearDown(): void { parent::tearDown(); - + $dir = $this->testsWorkingDir; $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS); @@ -163,5 +225,6 @@ public function tearDown(): void } } rmdir($dir); + chdir(__DIR__); } } diff --git a/tests/issue89-composer.json b/tests/issue89-composer.json new file mode 100644 index 00000000..c2901720 --- /dev/null +++ b/tests/issue89-composer.json @@ -0,0 +1,18 @@ +{ + "require": { + "iio/libmergepdf": "^4.0" + }, + "extra": { + "mozart": { + "dep_namespace": "MyLibMerge\\Vendor", + "dep_directory": "/lib/packages/", + "classmap_directory": "/lib/classes/", + "classmap_prefix": "MyLibMerge_", + "excluded_packages": [ + ], + "override_autoload": { + }, + "delete_vendor_directories": true + } + } +} \ No newline at end of file From c40b6d564fa6d1699c217960ecf960b2e0903a2c Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 00:52:03 -0800 Subject: [PATCH 02/58] Do not confuse classnames with namespaces --- src/Replace/NamespaceReplacer.php | 1 + .../NamespaceReplacerIntegrationTest.php | 131 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 tests/replacers/NamespaceReplacerIntegrationTest.php diff --git a/src/Replace/NamespaceReplacer.php b/src/Replace/NamespaceReplacer.php index ddda03cd..711ec086 100644 --- a/src/Replace/NamespaceReplacer.php +++ b/src/Replace/NamespaceReplacer.php @@ -29,6 +29,7 @@ public function replace($contents, $file = null) ( # Start the namespace matcher (?testsWorkingDir = __DIR__ . '/temptestdir'; + if (!file_exists($this->testsWorkingDir)) { + mkdir($this->testsWorkingDir); + } + + $mozart_config = new class() { + public $dep_namespace = "Mozart"; + public $classmap_prefix = "Mozart_"; + public $dep_directory = "/dep_directory/"; + public $classmap_directory = "/classmap_directory/"; + + }; + + $composer = new class() { + public $require = array(); + public $extra; + }; + + $composer->extra = new class() { + public $mozart; + }; + + $composer->extra->mozart = $mozart_config; + + $this->composer = $composer; + } + + /** + * After PR #84, running Mozart on Mpdf began prefixing the class name inside the namespaced file. + * + * The problem coming from the filename matching the namespace name? + * + * dev-master#5d8041fdefc94ff57edcbe83ab468a9988c4fc11 + * + * @see https://github.com/coenjacobs/mozart/pull/84/files + * + * Should be: "class Mpdf implements" because its namespace has already been prefixed. + */ + public function test_it_does_not_make_classname_replacement_inside_namespaced_file() + { + + $composer = $this->composer; + + $composer->require["mpdf/mpdf"] = "8.0.8"; + + file_put_contents($this->testsWorkingDir . '/composer.json', json_encode($composer)); + + chdir($this->testsWorkingDir); + + exec('composer install'); + + $inputInterfaceMock = $this->createMock(InputInterface::class); + $outputInterfaceMock = $this->createMock(OutputInterface::class); + + $mozartCompose = new Compose(); + + $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); + + $mpdf_php = file_get_contents($this->testsWorkingDir .'/dep_directory/Mpdf/Mpdf.php'); + + // Confirm problem is gone. + $this->assertStringNotContainsString('class Mozart\Mpdf implements', $mpdf_php); + + // Confirm solution is correct. + $this->assertStringContainsString('class Mpdf implements', $mpdf_php); + } + + + /** + * Delete $this->testsWorkingDir after each test. + * + * @see https://stackoverflow.com/questions/3349753/delete-directory-with-files-in-it + */ + public function tearDown(): void + { + parent::tearDown(); + + $dir = $this->testsWorkingDir; + + $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS); + $files = new RecursiveIteratorIterator( + $it, + RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($files as $file) { + if ($file->isDir()) { + rmdir($file->getRealPath()); + } else { + unlink($file->getRealPath()); + } + } + rmdir($dir); + } +} From fd5d19485afb283d2d518832b9b986239fca175d Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 13:01:17 -0800 Subject: [PATCH 03/58] Add class comment and multiline comments to regex --- src/Replace/ClassmapReplacer.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index df1b069d..236bdb8b 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -1,10 +1,15 @@ classmap_prefix . $matches[1]; $this->saveReplacedClass($matches[1], $replace); From 8cd25a487c91666c5efa461511d5c4084486ac85 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 15:47:15 -0800 Subject: [PATCH 04/58] Updated regex Handles multiple namespaces per class. --- src/Replace/ClassmapReplacer.php | 24 ++- tests/replacers/ClassMapReplacerTest.php | 69 +++++++++ .../ClassmapReplacerIntegrationTest.php | 141 ++++++++++++++++++ 3 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 tests/replacers/ClassmapReplacerIntegrationTest.php diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index 236bdb8b..8f3225ba 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -17,16 +17,30 @@ class ClassmapReplacer extends BaseReplacer public function replace($contents) { + return preg_replace_callback( " - / # Start the pattern + / # Start the pattern + namespace\s+[a-zA-Z0-9_\x7f-\xff\\\\]+[;{\s\n]{1}.*?(?=namespace|$) + # Look for a preceeding namespace declaration, up until + # a potential second namespace declaration + | # if found, match that much before repeating the search + # on the remainder of the string (?:abstract\sclass|class|interface)\s+ # Look behind for class, abstract class, interface - ([a-zA-Z0-9_\x7f-\xff]+) # Match the word made of valid classname characters + ([a-zA-Z0-9_\x7f-\xff]*) # Match the word until the first + # non-classname-valid character \s? # Allow a space after - (?:{|extends|implements|\n) # Class declaration can be followed by {, extends, implements, or a new line - /x", // non-greedy matching by default, ignore whitespace in regex. + (?:{|extends|implements|\n) # Class declaration can be followed by {, extends, + # implements, or a new line + /sx", // # dot matches newline, ignore whitespace in regex. + function ($matches) use ($contents) { + + // If we're inside a namespace other than the global namesspace, just return. + if (preg_match('/^namespace\s+[a-zA-Z0-9_\x7f-\xff\\\\]+[;{\s\n]{1}.*/', $matches[0])) { + return $matches[0] ; + } - function ($matches) { + // The prepended class name. $replace = $this->classmap_prefix . $matches[1]; $this->saveReplacedClass($matches[1], $replace); return str_replace($matches[1], $replace, $matches[0]); diff --git a/tests/replacers/ClassMapReplacerTest.php b/tests/replacers/ClassMapReplacerTest.php index 27a5773e..1e4f83e5 100644 --- a/tests/replacers/ClassMapReplacerTest.php +++ b/tests/replacers/ClassMapReplacerTest.php @@ -89,4 +89,73 @@ public function it_replaces_class(): void $contents = $replacer->replace($contents); $this->assertEquals("class Mozart_Hello_World", $contents); } + + + /** + * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() + * @see https://github.com/coenjacobs/mozart/issues/93 + * + * @test + */ + public function it_does_not_replace_inside_namespace_multiline(): void + { + $input = " + namespace Mozart; + class Hello_World + "; + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); + + $this->assertEquals($input, $result); + } + + /** + * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() + * @see https://github.com/coenjacobs/mozart/issues/93 + * + * @test + */ + public function it_does_not_replace_inside_namespace_singleline(): void + { + $input = "namespace Mozart; class Hello_World"; + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); + + $this->assertEquals($input, $result); + } + + /** + * It's possible to have multiple namespaces inside one file. + * + * To have two classes in one file, one in a namespace and the other not, the global namespace needs to be explicit. + * + * @test + */ + public function it_does_not_replace_inside_named_namespace_but_does_inside_explicit_global_namespace(): void { + + $input = " + + namespace My_Project { + + class A_Class { } + + } + + + namespace { + + class B_Class { } + + } + + "; + + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); + + $this->assertStringContainsString( 'Mozart_B_Class', $result ); + } } diff --git a/tests/replacers/ClassmapReplacerIntegrationTest.php b/tests/replacers/ClassmapReplacerIntegrationTest.php new file mode 100644 index 00000000..981fa055 --- /dev/null +++ b/tests/replacers/ClassmapReplacerIntegrationTest.php @@ -0,0 +1,141 @@ +testsWorkingDir = __DIR__ . '/temptestdir'; + if (!file_exists($this->testsWorkingDir)) { + mkdir($this->testsWorkingDir); + } + + $mozart_config = new class() { + public $dep_namespace = "Mozart"; + public $classmap_prefix = "Mozart_"; + public $dep_directory = "/dep_directory/"; + public $classmap_directory = "/classmap_directory/"; + + }; + + $composer = new class() { + public $repositories = array(); + public $require = array(); + public $minimum_stability = "dev"; + public $extra; + }; + + $composer->extra = new class() { + public $mozart; + }; + + $composer->extra->mozart = $mozart_config; + + $this->composer = $composer; + } + + /** + * The unit test for issue #81 began failing when addressing #93, + */ + + /** + * Issue #93 shows a classname being updated inside a class whose namespace has also been updated + * by Mozart. + * + * This is caused by the same files being loaded by both a PSR-4 autolaoder and classmap autoloader. + * @see https://github.com/katzgrau/KLogger/blob/de2d3ab6777a393a9879e0496ebb8e0644066e3f/composer.json#L24-L29 + */ + public function test_it_does_not_make_classname_replacement_inside_namespaced_file() + { + + $composer = $this->composer; + + $composer->repositories[] = new class() { + public $url = "https://github.com/BrianHenryIE/bh-wp-logger"; + public $type = "git"; + }; + + $composer->require["brianhenryie/wp-logger"] = "dev-master#dd2bb0665e01e11b282178e76a2334198d3860c5"; + + $composer_json_string = json_encode($composer); + $composer_json_string = str_replace('minimum_stability','minimum-stability', $composer_json_string); + + file_put_contents($this->testsWorkingDir . '/composer.json', $composer_json_string); + + chdir($this->testsWorkingDir); + + exec('composer install'); + + $inputInterfaceMock = $this->createMock(InputInterface::class); + $outputInterfaceMock = $this->createMock(OutputInterface::class); + + $mozartCompose = new Compose(); + + $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); + + $mpdf_php = file_get_contents($this->testsWorkingDir .'/dep_directory/BrianHenryIE/WP_Logger/class-logger.php'); + + // Confirm problem is gone. + $this->assertStringNotContainsString('class Mozart_Logger extends', $mpdf_php); + + // Confirm solution is correct. + $this->assertStringContainsString('class Logger extends', $mpdf_php); + } + + + /** + * Delete $this->testsWorkingDir after each test. + * + * @see https://stackoverflow.com/questions/3349753/delete-directory-with-files-in-it + */ + public function tearDown(): void + { + parent::tearDown(); + + $dir = $this->testsWorkingDir; + + $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS); + $files = new RecursiveIteratorIterator( + $it, + RecursiveIteratorIterator::CHILD_FIRST + ); + foreach ($files as $file) { + if ($file->isDir()) { + rmdir($file->getRealPath()); + } else { + unlink($file->getRealPath()); + } + } + rmdir($dir); + } +} From 0c6daa1c30461acfe2c0391cbe7d91883a3145c2 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 15:48:20 -0800 Subject: [PATCH 05/58] Update ClassmapReplacerIntegrationTest.php Remove out-dated note. --- tests/replacers/ClassmapReplacerIntegrationTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/replacers/ClassmapReplacerIntegrationTest.php b/tests/replacers/ClassmapReplacerIntegrationTest.php index 981fa055..19d12140 100644 --- a/tests/replacers/ClassmapReplacerIntegrationTest.php +++ b/tests/replacers/ClassmapReplacerIntegrationTest.php @@ -64,10 +64,6 @@ public function setUp(): void $this->composer = $composer; } - /** - * The unit test for issue #81 began failing when addressing #93, - */ - /** * Issue #93 shows a classname being updated inside a class whose namespace has also been updated * by Mozart. From bd76217b7137092e02b7e595747c05f03c423c61 Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 15:53:22 -0800 Subject: [PATCH 06/58] Add test to clarify operation --- tests/replacers/ClassMapReplacerTest.php | 96 ++++++++++++------------ 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/tests/replacers/ClassMapReplacerTest.php b/tests/replacers/ClassMapReplacerTest.php index 1e4f83e5..6acb48b3 100644 --- a/tests/replacers/ClassMapReplacerTest.php +++ b/tests/replacers/ClassMapReplacerTest.php @@ -91,51 +91,52 @@ public function it_replaces_class(): void } - /** - * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() - * @see https://github.com/coenjacobs/mozart/issues/93 - * - * @test - */ - public function it_does_not_replace_inside_namespace_multiline(): void - { - $input = " + /** + * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() + * @see https://github.com/coenjacobs/mozart/issues/93 + * + * @test + */ + public function it_does_not_replace_inside_namespace_multiline(): void + { + $input = " namespace Mozart; class Hello_World "; - $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; - $result = $replacer->replace($input); - - $this->assertEquals($input, $result); - } - - /** - * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() - * @see https://github.com/coenjacobs/mozart/issues/93 - * - * @test - */ - public function it_does_not_replace_inside_namespace_singleline(): void - { - $input = "namespace Mozart; class Hello_World"; - $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; - $result = $replacer->replace($input); - - $this->assertEquals($input, $result); - } - - /** - * It's possible to have multiple namespaces inside one file. - * - * To have two classes in one file, one in a namespace and the other not, the global namespace needs to be explicit. - * - * @test - */ - public function it_does_not_replace_inside_named_namespace_but_does_inside_explicit_global_namespace(): void { - - $input = " + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); + + $this->assertEquals($input, $result); + } + + /** + * @see ClassmapReplacerIntegrationTest::test_it_does_not_make_classname_replacement_inside_namespaced_file() + * @see https://github.com/coenjacobs/mozart/issues/93 + * + * @test + */ + public function it_does_not_replace_inside_namespace_singleline(): void + { + $input = "namespace Mozart; class Hello_World"; + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); + + $this->assertEquals($input, $result); + } + + /** + * It's possible to have multiple namespaces inside one file. + * + * To have two classes in one file, one in a namespace and the other not, the global namespace needs to be explicit. + * + * @test + */ + public function it_does_not_replace_inside_named_namespace_but_does_inside_explicit_global_namespace(): void + { + + $input = " namespace My_Project { @@ -152,10 +153,11 @@ class B_Class { } "; - $replacer = new ClassmapReplacer(); - $replacer->classmap_prefix = 'Mozart_'; - $result = $replacer->replace($input); + $replacer = new ClassmapReplacer(); + $replacer->classmap_prefix = 'Mozart_'; + $result = $replacer->replace($input); - $this->assertStringContainsString( 'Mozart_B_Class', $result ); - } + $this->assertStringNotContainsString('Mozart_A_Class', $result); + $this->assertStringContainsString('Mozart_B_Class', $result); + } } From c903df89f81e4984977ec09c235ad86a29964dab Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 15:55:38 -0800 Subject: [PATCH 07/58] Remove whitespace --- tests/replacers/ClassMapReplacerTest.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/replacers/ClassMapReplacerTest.php b/tests/replacers/ClassMapReplacerTest.php index 6acb48b3..f14de75b 100644 --- a/tests/replacers/ClassMapReplacerTest.php +++ b/tests/replacers/ClassMapReplacerTest.php @@ -137,20 +137,12 @@ public function it_does_not_replace_inside_named_namespace_but_does_inside_expli { $input = " - namespace My_Project { - - class A_Class { } - + class A_Class { } } - - namespace { - - class B_Class { } - + class B_Class { } } - "; $replacer = new ClassmapReplacer(); From 2c873ed2f4dbcd4715fb65c2fc9d42c3f2cb6abd Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 18:14:05 -0800 Subject: [PATCH 08/58] Require minimum 1 character long class name! --- src/Replace/ClassmapReplacer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index 8f3225ba..911e0585 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -27,7 +27,7 @@ public function replace($contents) | # if found, match that much before repeating the search # on the remainder of the string (?:abstract\sclass|class|interface)\s+ # Look behind for class, abstract class, interface - ([a-zA-Z0-9_\x7f-\xff]*) # Match the word until the first + ([a-zA-Z0-9_\x7f-\xff]+) # Match the word until the first # non-classname-valid character \s? # Allow a space after (?:{|extends|implements|\n) # Class declaration can be followed by {, extends, From bb13952d11bbe434d1397e63d04981480f894e7f Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 13 Dec 2020 20:47:18 -0800 Subject: [PATCH 09/58] Fix variable naming --- tests/replacers/ClassmapReplacerIntegrationTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/replacers/ClassmapReplacerIntegrationTest.php b/tests/replacers/ClassmapReplacerIntegrationTest.php index 19d12140..e52422da 100644 --- a/tests/replacers/ClassmapReplacerIntegrationTest.php +++ b/tests/replacers/ClassmapReplacerIntegrationTest.php @@ -84,7 +84,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi $composer->require["brianhenryie/wp-logger"] = "dev-master#dd2bb0665e01e11b282178e76a2334198d3860c5"; $composer_json_string = json_encode($composer); - $composer_json_string = str_replace('minimum_stability','minimum-stability', $composer_json_string); + $composer_json_string = str_replace('minimum_stability', 'minimum-stability', $composer_json_string); file_put_contents($this->testsWorkingDir . '/composer.json', $composer_json_string); @@ -99,13 +99,13 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); - $mpdf_php = file_get_contents($this->testsWorkingDir .'/dep_directory/BrianHenryIE/WP_Logger/class-logger.php'); + $php_string = file_get_contents($this->testsWorkingDir .'/dep_directory/BrianHenryIE/WP_Logger/class-logger.php'); // Confirm problem is gone. - $this->assertStringNotContainsString('class Mozart_Logger extends', $mpdf_php); + $this->assertStringNotContainsString('class Mozart_Logger extends', $php_string); // Confirm solution is correct. - $this->assertStringContainsString('class Logger extends', $mpdf_php); + $this->assertStringContainsString('class Logger extends', $php_string); } From a7562235a2a70acb244b50357f289f35890296dc Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Mon, 14 Dec 2020 19:14:16 -0800 Subject: [PATCH 10/58] Create phar and attach to releases --- .github/workflows/release.yml | 30 +++++++++++++++++++++++++++++ README.md | 12 ++++++++++++ bin/mozart | 36 +++++++++++++++++++---------------- composer.json | 1 + 4 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e4dc9c94 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,30 @@ +name: Build and attach Mozart.phar to each release + +on: release + +jobs: + create-phar: + runs-on: ubuntu-latest + name: Create Mozart phar + steps: + - uses: actions/checkout@v1 + + - name: Install PHP + uses: shivammathur/setup-php@1.3.7 + with: + php-version: 7.2 + + - name: Install dependencies + run: composer install --prefer-dist --no-suggest --no-progress + + - name: Create .phar + run: | + vendor/bin/phar-composer build . + php mozart.phar --version + + - uses: meeDamian/github-release@2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + files: mozart.phar + gzip: false + allow_override: true \ No newline at end of file diff --git a/README.md b/README.md index 813edcff..dbfe1747 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,9 @@ This package requires PHP 7.2 or higher in order to run the tool. You can use th **Warning:** This package is very experimental and breaking changes are very likely until version 1.0.0 is tagged. Use with caution, always wear a helmet when using this in production environments. ## Installation + +### Composer + Install through Composer, only required in development environments: `composer require coenjacobs/mozart --dev` @@ -14,6 +17,15 @@ This gives you a bin file named `mozart` inside your `vendor/bin` directory, aft After configuring Mozart properly, the `mozart compose` command does all the magic. +### Standalone Phar + +`mozart.phar` can be [downloaded from the releases](https://github.com/coenjacobs/mozart/releases): + +``` +composer install --no-dev +php mozart.phar compose +``` + ## Configuration Mozart requires little configuration. All you need to do is tell it where the bundled dependencies are going to be stored and what namespace they should be put inside. This configuration needs to be done in the `extra` property of your `composer.json` file: diff --git a/bin/mozart b/bin/mozart index b84e56b0..0810db39 100755 --- a/bin/mozart +++ b/bin/mozart @@ -1,23 +1,27 @@ #!/usr/bin/env php Date: Wed, 16 Dec 2020 12:22:19 -0800 Subject: [PATCH 11/58] Do not "clean" $workingDir Source of `$workingDir` is `getcwd()`. Automated tests pass on MacOS. Manual test passes on Windows: https://github.com/coenjacobs/mozart/issues/90#issuecomment-746851736 --- src/Mover.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mover.php b/src/Mover.php index 1d8b835b..3c59a13c 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -41,8 +41,8 @@ class Mover public function __construct($workingDir, $config) { $this->config = $config; - - $this->workingDir = DIRECTORY_SEPARATOR . $this->clean($workingDir); + + $this->workingDir = $workingDir; $this->dep_directory = $this->clean($config->dep_directory); $this->classmap_directory = $this->clean($config->classmap_directory); From 9b6d9e6a3c0fd113b79c4e5bb2dcfa9b90ceb505 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 16:34:09 +0100 Subject: [PATCH 12/58] Docker image runs PHP 8, so this bumping version in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3beec772..f89bb703 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "prefer-stable": true, "license": "MIT", "require": { - "php": "^7.2", + "php": "^7.2|^8", "symfony/console": "^4|^5", "symfony/finder": "^4|^5", "league/flysystem": "^1.0" From 8337c05b055baa5327d11cc85d9cb314151b5672 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 16:36:55 +0100 Subject: [PATCH 13/58] Basic Dockerfile for the image --- Dockerfile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..480b1dfa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM composer:2.0.8 + +FROM php:8.0.1-cli-alpine AS base + +FROM base as builder +RUN apk update && apk add git +COPY --from=composer /usr/bin/composer /usr/bin/composer +COPY ./composer.json /mozart/ +WORKDIR /mozart/ +RUN --mount=type=cache,target=$(COMPOSER_HOME)/cache/ composer install --no-dev -o + +FROM base AS application +RUN mkdir project +WORKDIR /project/ +COPY --from=builder /mozart/ /mozart/ +COPY ./bin/ /mozart/bin/ +COPY ./src/ /mozart/src/ From ac3ff9ed253a575e4e7309379f74424da9a56bd8 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 16:41:04 +0100 Subject: [PATCH 14/58] Remove Travis badge from README as that is defunct --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b84c283..3594a5e1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mozart [![Build Status](https://api.travis-ci.org/coenjacobs/mozart.png)](https://travis-ci.org/coenjacobs/mozart) [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) +# Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) Composes all dependencies as a package inside a WordPress plugin. Load packages through Composer and have them wrapped inside your own namespace. Gone are the days when plugins could load conflicting versions of the same package, resulting in hard to reproduce bugs. This package requires PHP 7.2 or higher in order to run the tool. You can use the resulting files as a bundle, requiring any PHP version you like, even PHP 5.2. From c731aa7adf67f89c7aebbe455a04093d23b48a86 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 17:19:19 +0100 Subject: [PATCH 15/58] Master branch is now 0.7.0 development branch --- bin/mozart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mozart b/bin/mozart index b84e56b0..0c67c635 100755 --- a/bin/mozart +++ b/bin/mozart @@ -22,4 +22,4 @@ call_user_func(function ($version) { $app = new CoenJacobs\Mozart\Console\Application($version); $app->run(); -}, '0.6.0'); +}, '0.7.0'); From 2a1c673a9ba43f49d265b4a5c28a64cff8679258 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 18:23:43 +0100 Subject: [PATCH 16/58] Added psalm dependency and config on starter level 5 --- composer.json | 3 ++- psalm.xml | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 psalm.xml diff --git a/composer.json b/composer.json index 3beec772..78e6245e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "require-dev": { "phpunit/phpunit": "^8.5", "squizlabs/php_codesniffer": "^3.5", - "mheap/phpunit-github-actions-printer": "^1.4" + "mheap/phpunit-github-actions-printer": "^1.4", + "vimeo/psalm": "^4.4" }, "scripts": { "lint": [ diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..8dc065a2 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,15 @@ + + + + + + + + + From d03e026aac9284e4b79a55018b0ab00ff28cba02 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 18:24:46 +0100 Subject: [PATCH 17/58] Automatic fixes from Psalm --- src/Composer/Autoload/Classmap.php | 3 +++ src/Composer/Autoload/NamespaceAutoloader.php | 8 ++++++ src/Composer/Autoload/Psr4.php | 6 +++++ src/Composer/Package.php | 3 +++ src/Console/Commands/Compose.php | 27 +++++++++++++++---- src/Mover.php | 19 +++++++++---- src/Replace/BaseReplacer.php | 3 +++ src/Replace/ClassmapReplacer.php | 7 ++++- src/Replacer.php | 22 ++++++++++----- 9 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/Composer/Autoload/Classmap.php b/src/Composer/Autoload/Classmap.php index 2c0355f7..8c097442 100644 --- a/src/Composer/Autoload/Classmap.php +++ b/src/Composer/Autoload/Classmap.php @@ -10,6 +10,9 @@ class Classmap implements Autoloader /** @var array */ public $paths = []; + /** + * @return void + */ public function processConfig($autoloadConfig) { foreach ($autoloadConfig as $value) { diff --git a/src/Composer/Autoload/NamespaceAutoloader.php b/src/Composer/Autoload/NamespaceAutoloader.php index dfd20499..f8393995 100644 --- a/src/Composer/Autoload/NamespaceAutoloader.php +++ b/src/Composer/Autoload/NamespaceAutoloader.php @@ -20,6 +20,8 @@ abstract class NamespaceAutoloader implements Autoloader * A package's composer.json config autoload key's value, where $key is `psr-1`|`psr-4`|`classmap`. * * @param $autoloadConfig + * + * @return void */ public function processConfig($autoloadConfig) { @@ -29,11 +31,17 @@ public function processConfig($autoloadConfig) } } + /** + * @return string + */ public function getSearchNamespace() { return $this->namespace; } + /** + * @return string + */ public function getNamespacePath() { return ''; diff --git a/src/Composer/Autoload/Psr4.php b/src/Composer/Autoload/Psr4.php index 6521a6ec..eb1fa11c 100644 --- a/src/Composer/Autoload/Psr4.php +++ b/src/Composer/Autoload/Psr4.php @@ -4,11 +4,17 @@ class Psr4 extends NamespaceAutoloader { + /** + * @return string + */ public function getSearchNamespace() { return trim($this->namespace, '\\'); } + /** + * @return string + */ public function getNamespacePath() { return str_replace('\\', DIRECTORY_SEPARATOR, $this->namespace); diff --git a/src/Composer/Package.php b/src/Composer/Package.php index 0388b9ce..5ff0fb11 100644 --- a/src/Composer/Package.php +++ b/src/Composer/Package.php @@ -37,6 +37,9 @@ public function __construct($path, $overrideAutoload = null) } } + /** + * @return void + */ public function findAutoloaders() { $namespace_autoloaders = array( diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index d98dad62..ced06a51 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -25,6 +25,9 @@ class Compose extends Command /** @var */ private $config; + /** + * @return void + */ protected function configure() { $this->setName('compose'); @@ -94,8 +97,10 @@ protected function execute(InputInterface $input, OutputInterface $output) * @param $workingDir * @param $config * @param array $packages + * + * @return void */ - protected function movePackages($packages) + protected function movePackages($packages): void { foreach ($packages as $package) { $this->movePackage($package); @@ -108,8 +113,10 @@ protected function movePackages($packages) * @param $workingDir * @param $config * @param array $packages + * + * @return void */ - protected function replacePackages($packages) + protected function replacePackages($packages): void { foreach ($packages as $package) { $this->replacePackage($package); @@ -118,8 +125,10 @@ protected function replacePackages($packages) /** * Move all the packages over, one by one, starting on the deepest level of dependencies. + * + * @return void */ - public function movePackage($package) + public function movePackage($package): void { if (! empty($package->dependencies)) { foreach ($package->dependencies as $dependency) { @@ -132,8 +141,10 @@ public function movePackage($package) /** * Replace contents of all the packages, one by one, starting on the deepest level of dependencies. + * + * @return void */ - public function replacePackage($package) + public function replacePackage($package): void { if (! empty($package->dependencies)) { foreach ($package->dependencies as $dependency) { @@ -147,8 +158,14 @@ public function replacePackage($package) /** * Loops through all dependencies and their dependencies and so on... * will eventually return a list of all packages required by the full tree. + * + * @param ((int|string)|mixed)[] $slugs + * + * @return Package[] + * + * @psalm-return array */ - private function findPackages($slugs) + private function findPackages(array $slugs): array { $packages = []; diff --git a/src/Mover.php b/src/Mover.php index 2ca807a5..6106bf6c 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -43,8 +43,10 @@ public function __construct($workingDir, $config) * Create the required `dep_directory` and `classmap_directory` and delete targetDirs of packages about to be moved. * * @param Package[] $packages The packages that, in the next step, will be moved. + * + * @return void */ - public function deleteTargetDirs($packages) + public function deleteTargetDirs($packages): void { $this->filesystem->createDir($this->config->dep_directory); @@ -61,8 +63,10 @@ public function deleteTargetDirs($packages) * @visibility private to allow recursion through packages and subpackages. * * @param Package $package + * + * @return void */ - private function deleteDepTargetDirs($package) + private function deleteDepTargetDirs($package): void { foreach ($package->autoloaders as $packageAutoloader) { $autoloaderType = get_class($packageAutoloader); @@ -87,7 +91,7 @@ private function deleteDepTargetDirs($package) } } - public function deleteEmptyDirs() + public function deleteEmptyDirs(): void { if (count($this->filesystem->listContents($this->config->dep_directory, true)) === 0) { $this->filesystem->deleteDir($this->config->dep_directory); @@ -98,6 +102,9 @@ public function deleteEmptyDirs() } } + /** + * @return void + */ public function movePackage(Package $package) { if (in_array($package->config->name, $this->movedPackages)) { @@ -206,8 +213,10 @@ public function moveFile(Package $package, $autoloader, $file, $path = '') * Deletes all the packages that are moved from the /vendor/ directory to * prevent packages that are prefixed/namespaced from being used or * influencing the output of the code. They just need to be gone. + * + * @return void */ - protected function deletePackageVendorDirectories() + protected function deletePackageVendorDirectories(): void { foreach ($this->movedPackages as $movedPackage) { $packageDir = 'vendor' . DIRECTORY_SEPARATOR . $movedPackage; @@ -226,7 +235,7 @@ protected function deletePackageVendorDirectories() } } - private function dirIsEmpty($dir) + private function dirIsEmpty(string $dir): bool { $di = new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS); return iterator_count($di) === 0; diff --git a/src/Replace/BaseReplacer.php b/src/Replace/BaseReplacer.php index f0d17f46..f38aa453 100644 --- a/src/Replace/BaseReplacer.php +++ b/src/Replace/BaseReplacer.php @@ -9,6 +9,9 @@ abstract class BaseReplacer implements Replacer /** @var Autoloader */ public $autoloader; + /** + * @return void + */ public function setAutoloader($autoloader) { $this->autoloader = $autoloader; diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index 911e0585..ef781fdb 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -15,6 +15,11 @@ class ClassmapReplacer extends BaseReplacer /** @var string */ public $classmap_prefix; + /** + * @param false|string $contents + * + * @return null|string + */ public function replace($contents) { @@ -49,7 +54,7 @@ function ($matches) use ($contents) { ); } - public function saveReplacedClass($classname, $replacedName) + public function saveReplacedClass($classname, string $replacedName): void { $this->replacedClasses[ $classname ] = $replacedName; } diff --git a/src/Replacer.php b/src/Replacer.php index 515151f2..74d83e10 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -37,7 +37,7 @@ public function __construct($workingDir, $config) $this->filesystem = new Filesystem(new Local($this->workingDir)); } - public function replacePackage(Package $package) + public function replacePackage(Package $package): void { foreach ($package->autoloaders as $autoloader) { $this->replacePackageByAutoloader($package, $autoloader); @@ -47,8 +47,10 @@ public function replacePackage(Package $package) /** * @param $targetFile * @param $autoloader + * + * @return void */ - public function replaceInFile($targetFile, $autoloader) + public function replaceInFile($targetFile, Classmap $autoloader): void { $targetFile = str_replace($this->workingDir, '', $targetFile); $contents = $this->filesystem->read($targetFile); @@ -74,8 +76,10 @@ public function replaceInFile($targetFile, $autoloader) /** * @param Package $package * @param $autoloader + * + * @return void */ - public function replacePackageByAutoloader(Package $package, $autoloader) + public function replacePackageByAutoloader(Package $package, Composer\Autoload\Autoloader $autoloader): void { if ($autoloader instanceof NamespaceAutoloader) { $source_path = $this->workingDir . $this->targetDir @@ -101,8 +105,10 @@ public function replacePackageByAutoloader(Package $package, $autoloader) /** * @param $autoloader * @param $directory + * + * @return void */ - public function replaceParentClassesInDirectory($directory) + public function replaceParentClassesInDirectory(string $directory) { if (count($this->replacedClasses)===0) { return; @@ -141,8 +147,10 @@ function ($matches) use ($replacement) { /** * @param $autoloader * @param $directory + * + * @return void */ - public function replaceInDirectory($autoloader, $directory) + public function replaceInDirectory(NamespaceAutoloader $autoloader, string $directory): void { $finder = new Finder(); $finder->files()->in($directory); @@ -163,8 +171,10 @@ public function replaceInDirectory($autoloader, $directory) * * @param Package $package * @param Package $parent + * + * @return void */ - public function replaceParentPackage(Package $package, Package $parent) + public function replaceParentPackage(Package $package, Package $parent): void { foreach ($parent->autoloaders as $parentAutoloader) { foreach ($package->autoloaders as $autoloader) { From 0767c3fd137ac8fd907879d1e884b6fd3b8f4e35 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 18:32:27 +0100 Subject: [PATCH 18/58] Fixed level 5 errors from Psalm --- src/Composer/Autoload/Autoloader.php | 1 + src/Composer/Autoload/Classmap.php | 8 ++++++++ src/Replacer.php | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Composer/Autoload/Autoloader.php b/src/Composer/Autoload/Autoloader.php index fd3585a8..9aa6b218 100644 --- a/src/Composer/Autoload/Autoloader.php +++ b/src/Composer/Autoload/Autoloader.php @@ -5,4 +5,5 @@ interface Autoloader { public function processConfig($autoloadConfig); + public function getSearchNamespace(); } diff --git a/src/Composer/Autoload/Classmap.php b/src/Composer/Autoload/Classmap.php index 8c097442..58d34f77 100644 --- a/src/Composer/Autoload/Classmap.php +++ b/src/Composer/Autoload/Classmap.php @@ -23,4 +23,12 @@ public function processConfig($autoloadConfig) } } } + + /** + * @throws \Exception + */ + public function getSearchNamespace() + { + throw new \Exception('Classmap autoloaders do not contain a namespace and this method can not be used.'); + } } diff --git a/src/Replacer.php b/src/Replacer.php index 74d83e10..400ccf29 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -2,6 +2,7 @@ namespace CoenJacobs\Mozart; +use CoenJacobs\Mozart\Composer\Autoload\Autoloader; use CoenJacobs\Mozart\Composer\Autoload\Classmap; use CoenJacobs\Mozart\Composer\Autoload\NamespaceAutoloader; use CoenJacobs\Mozart\Composer\Package; @@ -50,7 +51,7 @@ public function replacePackage(Package $package): void * * @return void */ - public function replaceInFile($targetFile, Classmap $autoloader): void + public function replaceInFile($targetFile, Autoloader $autoloader): void { $targetFile = str_replace($this->workingDir, '', $targetFile); $contents = $this->filesystem->read($targetFile); From 6420b8575ee87c5d4f048814262f932a58a40127 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 19:24:59 +0100 Subject: [PATCH 19/58] Added Psalm on GitHub action push and pull_request as well --- .github/workflows/analysis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/analysis.yml diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml new file mode 100644 index 00000000..3953dd5a --- /dev/null +++ b/.github/workflows/analysis.yml @@ -0,0 +1,14 @@ +name: Psalm analysis + +on: [push, pull_request] + +jobs: + psalm: + name: Psalm + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Psalm + uses: docker://vimeo/psalm-github-actions \ No newline at end of file From fd948f09dcb2fd36789cd73b7945e117bc7c0cef Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 19:34:56 +0100 Subject: [PATCH 20/58] Only run Psalm on PR or push to master branch --- .github/workflows/analysis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 3953dd5a..bed9ebf5 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -1,6 +1,12 @@ name: Psalm analysis -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: psalm: From 8222de2e20c48c3e3e461be642866d435bdcd20b Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 19:53:19 +0100 Subject: [PATCH 21/58] Drop PHP 7.2 compat and introduce testing PHP 8.0 --- .github/workflows/main.yml | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1d3841f6..6fc1026e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['7.2', '7.3', '7.4'] + php: ['7.3', '7.4', '8.0'] name: PHP ${{ matrix.php }} tests steps: - uses: actions/checkout@v1 diff --git a/composer.json b/composer.json index 78e6245e..c97d2253 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "prefer-stable": true, "license": "MIT", "require": { - "php": "^7.2", + "php": "^7.3|^8.0", "symfony/console": "^4|^5", "symfony/finder": "^4|^5", "league/flysystem": "^1.0" From 4a0c12e222b235a2152d2b32abe7fb002afb2c5e Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 20:05:39 +0100 Subject: [PATCH 22/58] Only run main test workflow on PR or push to master branch --- .github/workflows/main.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6fc1026e..bef8a5f7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,12 @@ name: Lint and test -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: tests: From e7a7eb77c2e304fe56856957cff40eb362a75fea Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:13:49 +0100 Subject: [PATCH 23/58] Docker Hub workflows pushing latest master and releases --- .github/workflows/docker-latest.yml | 52 ++++++++++++++++++++++ .github/workflows/release.yml | 67 +++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 .github/workflows/docker-latest.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/docker-latest.yml b/.github/workflows/docker-latest.yml new file mode 100644 index 00000000..a8160922 --- /dev/null +++ b/.github/workflows/docker-latest.yml @@ -0,0 +1,52 @@ +name: Publish latest to Docker Hub + +on: + push: + branches: + - master + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=coenjacobs/mozart + VERSION=latest + TAGS="${DOCKER_IMAGE}:${VERSION}" + echo ::set-output name=tags::${TAGS} + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + file: ./Dockerfile + target: prod + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.prep.outputs.tags }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a6981c88 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,67 @@ +name: Publish release to Docker Hub + +on: + push: + tags: + - "*.*.*" + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=coenjacobs/mozart + VERSION=latest + if [[ $GITHUB_REF == refs/tags/* ]]; then + VERSION=${GITHUB_REF#refs/tags/v} + fi + TAGS="${DOCKER_IMAGE}:${VERSION}" + if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + TAGS="$TAGS,${DOCKER_IMAGE}:latest" + fi + echo ::set-output name=tags::${TAGS} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + platforms: all + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Cache Docker layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + file: ./Dockerfile + target: prod + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.prep.outputs.tags }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache + + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} From f30f7dfc5b22a3e263a9b0e468405e17649e8062 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:23:04 +0100 Subject: [PATCH 24/58] Fixed target stage for Docker Hub push workflows --- .github/workflows/docker-latest.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-latest.yml b/.github/workflows/docker-latest.yml index a8160922..f8232cdf 100644 --- a/.github/workflows/docker-latest.yml +++ b/.github/workflows/docker-latest.yml @@ -44,7 +44,7 @@ jobs: builder: ${{ steps.buildx.outputs.name }} context: . file: ./Dockerfile - target: prod + target: application platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a6981c88..8e751eca 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,7 +56,7 @@ jobs: builder: ${{ steps.buildx.outputs.name }} context: . file: ./Dockerfile - target: prod + target: application platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} From 9bc53aae2781d4c866917c030cf076c08afc2d58 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:26:07 +0100 Subject: [PATCH 25/58] Remove explicit Composer cache as buildx does that as well --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 480b1dfa..240bd4c5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN apk update && apk add git COPY --from=composer /usr/bin/composer /usr/bin/composer COPY ./composer.json /mozart/ WORKDIR /mozart/ -RUN --mount=type=cache,target=$(COMPOSER_HOME)/cache/ composer install --no-dev -o +RUN composer install --no-dev -o FROM base AS application RUN mkdir project From 8823c51371e431d8c22d210e87b98a1aed25a059 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:31:06 +0100 Subject: [PATCH 26/58] Build linux/amd64 only for now --- .github/workflows/docker-latest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-latest.yml b/.github/workflows/docker-latest.yml index f8232cdf..f0e5b779 100644 --- a/.github/workflows/docker-latest.yml +++ b/.github/workflows/docker-latest.yml @@ -45,7 +45,7 @@ jobs: context: . file: ./Dockerfile target: application - platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x + platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} cache-from: type=local,src=/tmp/.buildx-cache From c3e7b1fcd0486a7c5d8592d988021fc3da7e82c9 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:35:17 +0100 Subject: [PATCH 27/58] Bump PHP requirement in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3594a5e1..0b67615b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) Composes all dependencies as a package inside a WordPress plugin. Load packages through Composer and have them wrapped inside your own namespace. Gone are the days when plugins could load conflicting versions of the same package, resulting in hard to reproduce bugs. -This package requires PHP 7.2 or higher in order to run the tool. You can use the resulting files as a bundle, requiring any PHP version you like, even PHP 5.2. +This package requires PHP 7.3 or higher in order to run the tool. You can use the resulting files as a bundle, requiring any PHP version you like, even PHP 5.2. **Warning:** This package is very experimental and breaking changes are very likely until version 1.0.0 is tagged. Use with caution, always wear a helmet when using this in production environments. From 3a487e5d8bd8395c01e7a8ce7ebf91ca45ec8d36 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:45:24 +0100 Subject: [PATCH 28/58] Docker pulls README badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3594a5e1..df464aa3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) +# Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) [![Docker Image Pulls](https://img.shields.io/docker/pulls/coenjacobs/mozart.svg)](https://hub.docker.com/r/coenjacobs/mozart) Composes all dependencies as a package inside a WordPress plugin. Load packages through Composer and have them wrapped inside your own namespace. Gone are the days when plugins could load conflicting versions of the same package, resulting in hard to reproduce bugs. This package requires PHP 7.2 or higher in order to run the tool. You can use the resulting files as a bundle, requiring any PHP version you like, even PHP 5.2. From 619cc4a5367f822a25f4a08b9dc6f82c289c5b09 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:47:16 +0100 Subject: [PATCH 29/58] Releases workflow should also only build linux/amd64 for now --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e751eca..c61efa0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,7 +57,7 @@ jobs: context: . file: ./Dockerfile target: application - platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x + platforms: linux/amd64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} cache-from: type=local,src=/tmp/.buildx-cache From f7df51fb6cd747e7b0d34f403c0d123ce1a0ca59 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 21:58:40 +0100 Subject: [PATCH 30/58] Bare bones Docker installation instructions in README --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index df464aa3..940f5a4f 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,25 @@ This package requires PHP 7.2 or higher in order to run the tool. You can use th **Warning:** This package is very experimental and breaking changes are very likely until version 1.0.0 is tagged. Use with caution, always wear a helmet when using this in production environments. ## Installation + +### Docker +Pull the Docker image from the registry: + +``` +docker pull coenjacobs/mozart +``` + +Then you can start the container and run the `mozart compose` command in the container. In a single command: + +``` +docker run --rm -it -v ${PWD}:/project/ coenjacobs/mozart /mozart/bin/mozart compose +``` + +Above command automatically adds the current working directory as a volume into the designated directory for the project: `/project/`. In the Docker container, Mozart is installed in the `/mozart/` directory. Using the above command will run Mozart on the current working directory. + +Please note that the Docker image for Mozart is only available starting from the `latest` build of version 0.7.0. The `latest` tag is always the latest build of the `master` branch and not a stable version. You can see [all available tags on Docker Hub](https://hub.docker.com/r/coenjacobs/mozart/tags). + +### Composer Install through Composer, only required in development environments: `composer require coenjacobs/mozart --dev` From 407b55c46d799244f3deb68b668bf256d9ad050a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Sun, 17 Jan 2021 22:01:35 +0100 Subject: [PATCH 31/58] Use a PHP 8 compatible mpdf verion (#115) --- tests/replacers/NamespaceReplacerIntegrationTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/replacers/NamespaceReplacerIntegrationTest.php b/tests/replacers/NamespaceReplacerIntegrationTest.php index b4af5205..6e388a76 100644 --- a/tests/replacers/NamespaceReplacerIntegrationTest.php +++ b/tests/replacers/NamespaceReplacerIntegrationTest.php @@ -78,7 +78,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi $composer = $this->composer; - $composer->require["mpdf/mpdf"] = "8.0.8"; + $composer->require["mpdf/mpdf"] = "8.0.10"; file_put_contents($this->testsWorkingDir . '/composer.json', json_encode($composer)); From edb840173c41e5273e95aa5117651eac8f1040a9 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 22:29:54 +0100 Subject: [PATCH 32/58] Move to errorLevel 4 on Psalm --- psalm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psalm.xml b/psalm.xml index 8dc065a2..3e4e3d08 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ Date: Sun, 17 Jan 2021 22:31:02 +0100 Subject: [PATCH 33/58] Automatic fixes from Psalm --- src/Composer/Autoload/Classmap.php | 2 ++ src/Replace/BaseReplacer.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Autoload/Classmap.php b/src/Composer/Autoload/Classmap.php index 58d34f77..10e4d007 100644 --- a/src/Composer/Autoload/Classmap.php +++ b/src/Composer/Autoload/Classmap.php @@ -26,6 +26,8 @@ public function processConfig($autoloadConfig) /** * @throws \Exception + * + * @return void */ public function getSearchNamespace() { diff --git a/src/Replace/BaseReplacer.php b/src/Replace/BaseReplacer.php index f38aa453..56266fe7 100644 --- a/src/Replace/BaseReplacer.php +++ b/src/Replace/BaseReplacer.php @@ -12,7 +12,7 @@ abstract class BaseReplacer implements Replacer /** * @return void */ - public function setAutoloader($autoloader) + public function setAutoloader(Autoloader $autoloader) { $this->autoloader = $autoloader; } From d3392df3f09d037f33ef94e981ca21a04ed19c9e Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 22:39:28 +0100 Subject: [PATCH 34/58] Psalm level 4 fixes --- src/Composer/Autoload/Classmap.php | 2 +- src/Composer/Package.php | 2 +- src/Replace/BaseReplacer.php | 1 + src/Replace/Replacer.php | 4 +++- src/Replacer.php | 6 +++--- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Composer/Autoload/Classmap.php b/src/Composer/Autoload/Classmap.php index 10e4d007..981df843 100644 --- a/src/Composer/Autoload/Classmap.php +++ b/src/Composer/Autoload/Classmap.php @@ -16,7 +16,7 @@ class Classmap implements Autoloader public function processConfig($autoloadConfig) { foreach ($autoloadConfig as $value) { - if ('.php' == substr($value, '-4', 4)) { + if ('.php' == substr($value, -4, 4)) { array_push($this->files, $value); } else { array_push($this->paths, $value); diff --git a/src/Composer/Package.php b/src/Composer/Package.php index 5ff0fb11..78800fe8 100644 --- a/src/Composer/Package.php +++ b/src/Composer/Package.php @@ -59,7 +59,7 @@ public function findAutoloaders() $autoloadConfig = (array)$this->config->autoload->$key; - /** @var $autoloader Autoloader */ + /** @var Autoloader $autoloader */ $autoloader = new $value(); $autoloader->processConfig($autoloadConfig); diff --git a/src/Replace/BaseReplacer.php b/src/Replace/BaseReplacer.php index 56266fe7..442551e8 100644 --- a/src/Replace/BaseReplacer.php +++ b/src/Replace/BaseReplacer.php @@ -10,6 +10,7 @@ abstract class BaseReplacer implements Replacer public $autoloader; /** + * @param Autoloader $autoloader * @return void */ public function setAutoloader(Autoloader $autoloader) diff --git a/src/Replace/Replacer.php b/src/Replace/Replacer.php index c803ff65..33b1a150 100644 --- a/src/Replace/Replacer.php +++ b/src/Replace/Replacer.php @@ -2,8 +2,10 @@ namespace CoenJacobs\Mozart\Replace; +use CoenJacobs\Mozart\Composer\Autoload\Autoloader; + interface Replacer { - public function setAutoloader($autoloader); + public function setAutoloader(Autoloader $autoloader); public function replace($contents); } diff --git a/src/Replacer.php b/src/Replacer.php index 400ccf29..f59355fb 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -96,7 +96,7 @@ public function replacePackageByAutoloader(Package $package, Composer\Autoload\A foreach ($finder as $foundFile) { $targetFile = $foundFile->getRealPath(); - if ('.php' == substr($targetFile, '-4', 4)) { + if ('.php' == substr($targetFile, -4, 4)) { $this->replaceInFile($targetFile, $autoloader); } } @@ -124,7 +124,7 @@ public function replaceParentClassesInDirectory(string $directory) foreach ($finder as $file) { $targetFile = $file->getPathName(); - if ('.php' == substr($targetFile, '-4', 4)) { + if ('.php' == substr($targetFile, -4, 4)) { $contents = $this->filesystem->read($targetFile); foreach ($replacedClasses as $original => $replacement) { @@ -159,7 +159,7 @@ public function replaceInDirectory(NamespaceAutoloader $autoloader, string $dire foreach ($finder as $file) { $targetFile = $file->getPathName(); - if ('.php' == substr($targetFile, '-4', 4)) { + if ('.php' == substr($targetFile, -4, 4)) { $this->replaceInFile($targetFile, $autoloader); } } From 3f2a1cc706d21557e7ae1763a2a54a54c2cb4103 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Sun, 17 Jan 2021 22:41:43 +0100 Subject: [PATCH 35/58] Move to errorLevel 3 on Psalm --- psalm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psalm.xml b/psalm.xml index 3e4e3d08..30258a70 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ Date: Sun, 17 Jan 2021 22:49:24 +0100 Subject: [PATCH 36/58] Psalm level 3 fixes --- src/Replace/ClassmapReplacer.php | 7 +++++-- src/Replacer.php | 23 ++++++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/Replace/ClassmapReplacer.php b/src/Replace/ClassmapReplacer.php index ef781fdb..2cc297ed 100644 --- a/src/Replace/ClassmapReplacer.php +++ b/src/Replace/ClassmapReplacer.php @@ -18,10 +18,13 @@ class ClassmapReplacer extends BaseReplacer /** * @param false|string $contents * - * @return null|string + * @return string */ - public function replace($contents) + public function replace($contents): string { + if (empty($contents) || false === $contents) { + return ''; + } return preg_replace_callback( " diff --git a/src/Replacer.php b/src/Replacer.php index f59355fb..8fb289b6 100644 --- a/src/Replacer.php +++ b/src/Replacer.php @@ -9,6 +9,7 @@ use CoenJacobs\Mozart\Replace\ClassmapReplacer; use CoenJacobs\Mozart\Replace\NamespaceReplacer; use League\Flysystem\Adapter\Local; +use League\Flysystem\FileNotFoundException; use League\Flysystem\Filesystem; use Symfony\Component\Finder\Finder; @@ -54,7 +55,15 @@ public function replacePackage(Package $package): void public function replaceInFile($targetFile, Autoloader $autoloader): void { $targetFile = str_replace($this->workingDir, '', $targetFile); - $contents = $this->filesystem->read($targetFile); + try { + $contents = $this->filesystem->read($targetFile); + } catch (FileNotFoundException $e) { + return; + } + + if (empty($contents) || false === $contents) { + return; + } if ($autoloader instanceof NamespaceAutoloader) { $replacer = new NamespaceReplacer(); @@ -109,7 +118,7 @@ public function replacePackageByAutoloader(Package $package, Composer\Autoload\A * * @return void */ - public function replaceParentClassesInDirectory(string $directory) + public function replaceParentClassesInDirectory(string $directory): void { if (count($this->replacedClasses)===0) { return; @@ -125,7 +134,15 @@ public function replaceParentClassesInDirectory(string $directory) $targetFile = $file->getPathName(); if ('.php' == substr($targetFile, -4, 4)) { - $contents = $this->filesystem->read($targetFile); + try { + $contents = $this->filesystem->read($targetFile); + } catch (FileNotFoundException $e) { + continue; + } + + if (empty($contents) || false === $contents) { + continue; + } foreach ($replacedClasses as $original => $replacement) { $contents = preg_replace_callback( From 43258873454631212455756a6f34350b836805ad Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sat, 30 Jan 2021 12:58:28 -0800 Subject: [PATCH 37/58] Bad merge conflict fix fixed --- src/Composer/Autoload/NamespaceAutoloader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Autoload/NamespaceAutoloader.php b/src/Composer/Autoload/NamespaceAutoloader.php index e5999247..669b02c8 100644 --- a/src/Composer/Autoload/NamespaceAutoloader.php +++ b/src/Composer/Autoload/NamespaceAutoloader.php @@ -22,7 +22,6 @@ abstract class NamespaceAutoloader implements Autoloader * A package's composer.json config autoload key's value, where $key is `psr-0`|`psr-4`|`classmap`. * * @param stdClass[] $autoloadConfig - * @param $autoloadConfig * * @return void */ From fe4702e2189d8ee7835bdb45995549227f65e98d Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sat, 30 Jan 2021 13:06:52 -0800 Subject: [PATCH 38/58] lint psalm --- src/Composer/Autoload/NamespaceAutoloader.php | 2 +- src/Mover.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Composer/Autoload/NamespaceAutoloader.php b/src/Composer/Autoload/NamespaceAutoloader.php index 669b02c8..b073eb69 100644 --- a/src/Composer/Autoload/NamespaceAutoloader.php +++ b/src/Composer/Autoload/NamespaceAutoloader.php @@ -21,7 +21,7 @@ abstract class NamespaceAutoloader implements Autoloader /** * A package's composer.json config autoload key's value, where $key is `psr-0`|`psr-4`|`classmap`. * - * @param stdClass[] $autoloadConfig + * @param $autoloadConfig * * @return void */ diff --git a/src/Mover.php b/src/Mover.php index 4bf4e296..cd23ffd7 100644 --- a/src/Mover.php +++ b/src/Mover.php @@ -198,14 +198,13 @@ public function moveFile(Package $package, $autoloader, $file, $path = '') $namespacePath = $this->clean($autoloader->getNamespacePath()); // TODO: Should $path come from the NameSpaceAutoloader object? - $sourceVendorPath = $this->clean('vendor' . DIRECTORY_SEPARATOR . $packageName + $sourceVendorPath = $this->clean('vendor' . DIRECTORY_SEPARATOR . $packageName . DIRECTORY_SEPARATOR . $path); - $destinationMozartPath = $this->dep_directory . DIRECTORY_SEPARATOR . $namespacePath; + $destinationMozartPath = $this->dep_directory . DIRECTORY_SEPARATOR . $namespacePath; $targetFilePath = str_ireplace($sourceVendorPath, $destinationMozartPath, $sourceFilePath); } else { - $sourceVendorPath = 'vendor' . DIRECTORY_SEPARATOR . $packageName; $destinationMozartPath = $this->classmap_directory . DIRECTORY_SEPARATOR . $packageName; From 009079aae5b0c550c590196ff50692ad3bd23d2a Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 19:55:37 +0100 Subject: [PATCH 39/58] Add philosophy to the README --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 1d53cfc6..d23858b0 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,15 @@ Mozart is designed to install and be forgotten about. Using Composer scripts, th ] } ``` + +## Background and philosophy +Mozart is designed to bridge the gap between the WordPress ecosytem and the vast packages ecosystem of PHP as a whole. Since WordPress is such an end-user friendly focussed CMS (for good reasons), there is no place within the ecosystem where an end-user would be burdened with using a developers tool like Composer. Also, since WordPress has to run on basically any hosting infrastructure, running Composer to install packages from the administration panel (trust me, I've tried - it can be done) is a mission impossible to make it happen and compatible with every server out there. + +But why make a new tool for this? There are other tools that enable you to do this, right? Yes, there are now. [PHP-Scoper](https://github.com/humbug/php-scoper), for example. PHP-Scoper is a fantastic tool, that does the job right. But, PHP-Scoper wasn't available back when I started the Mozart project. Also, PHP-Scoper has a few limitations (no support for classmap autoloaders, for example) that were and are still quite common within the WordPress ecosystem. Finally, PHP-Scoper can be quite the tool to add to your development flow, while Mozart was designed to be _simple to implement_, specifically tailored for WordPress projects. + +The key values of what's important to Mozart: +- Must be able to be easily installable by a developer, preferably in a specific version. +- Distribution must be done through an existing package manager or easily maintained separately. +- Shouldn't add a whole layer of complexity to the development process, i.e. learning a whole new tool/language. + +Mozart always has been and always will be geared towards solving the conflicting dependencies problem in the WordPress ecosystem, as efficiently and opinionated as possible. By being opinionated in certain ways and specifically focussed on WordPress projects, Mozart has quickly become easy to understand and implement. From 0d4d8f84693f4b9a2b3a5e6700d59d8b0562d3dd Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 19:58:56 +0100 Subject: [PATCH 40/58] Scripts documentation added for Docker container use --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d23858b0..15be2369 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,8 @@ Mozart is designed to install and be forgotten about. Using Composer scripts, th } ``` +When using Mozart through its Docker container, you can replace the `"\"vendor/bin/mozart\" compose",` lines with the actual commands you use to [run the Docker container](#docker) for your specific project. Running Mozart from inside the Docker container is really fast and shouldn't take more than a couple seconds. + ## Background and philosophy Mozart is designed to bridge the gap between the WordPress ecosytem and the vast packages ecosystem of PHP as a whole. Since WordPress is such an end-user friendly focussed CMS (for good reasons), there is no place within the ecosystem where an end-user would be burdened with using a developers tool like Composer. Also, since WordPress has to run on basically any hosting infrastructure, running Composer to install packages from the administration panel (trust me, I've tried - it can be done) is a mission impossible to make it happen and compatible with every server out there. From 30a8a0d7795a2c4c9358251546c882d34bbdc5dc Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 20:30:21 +0100 Subject: [PATCH 41/58] Simplify release script, using releases over tags --- .github/workflows/release.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c61efa0a..3be51568 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,6 @@ name: Publish release to Docker Hub -on: - push: - tags: - - "*.*.*" +on: release jobs: docker: @@ -16,14 +13,8 @@ jobs: id: prep run: | DOCKER_IMAGE=coenjacobs/mozart - VERSION=latest - if [[ $GITHUB_REF == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/v} - fi + VERSION=${{ github.event.release.tag_name }} TAGS="${DOCKER_IMAGE}:${VERSION}" - if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - TAGS="$TAGS,${DOCKER_IMAGE}:latest" - fi echo ::set-output name=tags::${TAGS} - name: Set up QEMU From ca83fd183f09fc3ed33ac9947a2f8fa582074833 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:00:45 +0100 Subject: [PATCH 42/58] Extra installer documentation for phar/phive --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d7ca6fcc..e9eadb06 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,16 @@ This gives you a bin file named `mozart` inside your `vendor/bin` directory, aft After configuring Mozart properly, the `mozart compose` command does all the magic. -### Standalone Phar -`mozart.phar` can be [downloaded from the releases page](https://github.com/coenjacobs/mozart/releases): +### PHAR (via Phive) +Mozart can be installed via [Phive](https://github.com/phar-io/phive): + +``` +phive install coenjacobs/mozart --force-accept-unsigned +``` + +Alternatively, the `mozart.phar` file can be [downloaded from the releases page](https://github.com/coenjacobs/mozart/releases) and then be run from your project directory: ``` -composer install --no-dev php mozart.phar compose ``` From e5dceb66cf4060cfa8993373f58e1eba6a785a0e Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:01:35 +0100 Subject: [PATCH 43/58] Promote PHAR installation over Composer --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e9eadb06..6f76e6b5 100644 --- a/README.md +++ b/README.md @@ -24,15 +24,6 @@ Above command automatically adds the current working directory as a volume into Please note that the Docker image for Mozart is only available starting from the `latest` build of version 0.7.0. The `latest` tag is always the latest build of the `master` branch and not a stable version. You can see [all available tags on Docker Hub](https://hub.docker.com/r/coenjacobs/mozart/tags). -### Composer -Install through Composer, only required in development environments: - -`composer require coenjacobs/mozart --dev` - -This gives you a bin file named `mozart` inside your `vendor/bin` directory, after loading the whole package inside your project. Try running `vendor/bin/mozart` to verify it works. - -After configuring Mozart properly, the `mozart compose` command does all the magic. - ### PHAR (via Phive) Mozart can be installed via [Phive](https://github.com/phar-io/phive): @@ -46,6 +37,15 @@ Alternatively, the `mozart.phar` file can be [downloaded from the releases page] php mozart.phar compose ``` +### Composer +Install through Composer, only required in development environments: + +`composer require coenjacobs/mozart --dev` + +This gives you a bin file named `mozart` inside your `vendor/bin` directory, after loading the whole package inside your project. Try running `vendor/bin/mozart` to verify it works. + +After configuring Mozart properly, the `mozart compose` command does all the magic. + ## Configuration Mozart requires little configuration. All you need to do is tell it where the bundled dependencies are going to be stored and what namespace they should be put inside. This configuration needs to be done in the `extra` property of your `composer.json` file: From 6ffdceac7c10c39bc5b8b4239bc7ae45b2e645aa Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:02:56 +0100 Subject: [PATCH 44/58] Fix composer install script markup in README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f76e6b5..1c112e3d 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,9 @@ php mozart.phar compose ### Composer Install through Composer, only required in development environments: -`composer require coenjacobs/mozart --dev` +``` +composer require coenjacobs/mozart --dev +``` This gives you a bin file named `mozart` inside your `vendor/bin` directory, after loading the whole package inside your project. Try running `vendor/bin/mozart` to verify it works. From adce56db4d198547605e98a4dd56606f9400b74c Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:07:21 +0100 Subject: [PATCH 45/58] Add installation documentation around running Mozart in isolation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1c112e3d..0ccdf909 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ This package requires PHP 7.3 or higher in order to run the tool. You can use th **Warning:** This package is very experimental and breaking changes are very likely until version 1.0.0 is tagged. Use with caution, always wear a helmet when using this in production environments. ## Installation +Mozart brings its own dependencies to the table and that potentially introduces its own problems (yes, I realise how meta that is, for a package like this). That's why installing Mozart in isolation, either through the Docker container, the available PHAR file or installing Mozart as a global dependency with Composer is prefered. In all cases, the [configuration](#configuration) still needs to be placed in the `composer.json` file of the project iself. ### Docker Pull the Docker image from the registry: From ba8dc726ab2b5a4f1d550259ab38338b50e0126c Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:13:55 +0100 Subject: [PATCH 46/58] Global Composer install documentation instructions --- README.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0ccdf909..cdb239d4 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,23 @@ php mozart.phar compose ``` ### Composer -Install through Composer, only required in development environments: +To install Mozart and its dependencies, without conflicting with the dependencies of your project, it is recommended that you install Mozart as a global package, if you choose to install Mozart via Composer. + +#### Global package +Using the `global` command when installing Mozart, it will be installed as a system wide package: + +``` +composer global require coenjacobs/mozart +``` + +You can then find the bin file named `mozart` inside your `~/.composer/vendor/bin/` directory and run it from your project directory, referencing the full path to the bin file: + +``` +~/.composer/vendor/bin/mozart compose +``` + +#### Development dependency of your project +You can install through Composer in the project itself, only required in development environments: ``` composer require coenjacobs/mozart --dev @@ -47,7 +63,11 @@ composer require coenjacobs/mozart --dev This gives you a bin file named `mozart` inside your `vendor/bin` directory, after loading the whole package inside your project. Try running `vendor/bin/mozart` to verify it works. -After configuring Mozart properly, the `mozart compose` command does all the magic. +After configuring Mozart properly, the `mozart compose` command does all the magic: + +``` +vendor/bin/mozart compose +``` ## Configuration Mozart requires little configuration. All you need to do is tell it where the bundled dependencies are going to be stored and what namespace they should be put inside. This configuration needs to be done in the `extra` property of your `composer.json` file: From b0b55760a7577f96b3bf7fb27ef31a00997fb620 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:26:38 +0100 Subject: [PATCH 47/58] Creating the PHAR requires PHP 7.3 now --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 225bd0a9..3e483632 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@1.3.7 with: - php-version: 7.2 + php-version: 7.3 - name: Install dependencies run: composer install --prefer-dist --no-suggest --no-progress From 3d192d1f133320850dd220cf57aea0e70e10098d Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Mon, 1 Feb 2021 21:47:42 +0100 Subject: [PATCH 48/58] Master branch is now 0.8.0 development branch --- bin/mozart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/mozart b/bin/mozart index ea752f3b..da02275f 100755 --- a/bin/mozart +++ b/bin/mozart @@ -26,4 +26,4 @@ call_user_func(function ($version) { $app = new CoenJacobs\Mozart\Console\Application($version); $app->run(); -}, '0.7.0'); +}, '0.8.0'); From d820156290f24ae43b1dfbdccea2734666a9f25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Mon, 1 Feb 2021 21:47:55 +0100 Subject: [PATCH 49/58] Exclude dev. deps from PHAR file --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e483632..ed65d0aa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: php-version: 7.3 - name: Install dependencies - run: composer install --prefer-dist --no-suggest --no-progress + run: composer install --no-dev --prefer-dist --no-suggest --no-progress - name: Create .phar run: | From bb9afafc1357348b33e83b315008a94b92c6e8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20Sz=C3=A9pe?= Date: Mon, 1 Feb 2021 22:26:17 +0100 Subject: [PATCH 50/58] Fix release script --- .github/workflows/release.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed65d0aa..90eb88b5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,8 +19,11 @@ jobs: - name: Create .phar run: | - vendor/bin/phar-composer build . - php mozart.phar --version + wget -O phar-composer.phar https://github.com/clue/phar-composer/releases/download/v1.2.0/phar-composer-1.2.0.phar + php phar-composer.phar build . + + - name: Test run mozart + run: php mozart.phar --version - uses: meeDamian/github-release@2.0 with: From 742b8a3b0a19f85a8ffd70ccddbe0b070a867f50 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 2 Feb 2021 22:33:10 +0100 Subject: [PATCH 51/58] Build PHAR in subdir and with specific files only --- .github/workflows/release.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 90eb88b5..074b4a87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,12 @@ jobs: - name: Create .phar run: | wget -O phar-composer.phar https://github.com/clue/phar-composer/releases/download/v1.2.0/phar-composer-1.2.0.phar - php phar-composer.phar build . + mkdir build + mv vendor build/vendor + mv src build/src + mv bin build/bin + mv composer.json build + php -d phar.readonly=off phar-composer.phar build ./build/ - name: Test run mozart run: php mozart.phar --version From a4657b92e2db18962dda0b6965a67384c1ff43c3 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 2 Feb 2021 22:35:17 +0100 Subject: [PATCH 52/58] Remove clue/phar-composer as development dependency --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index dc6edc0b..c97d2253 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ } }, "require-dev": { - "clue/phar-composer": "^1.2", "phpunit/phpunit": "^8.5", "squizlabs/php_codesniffer": "^3.5", "mheap/phpunit-github-actions-printer": "^1.4", From 04a7a7810c1e9ec028a552fb780045f024e320d1 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 2 Feb 2021 22:47:56 +0100 Subject: [PATCH 53/58] Added packagist downloads README badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cdb239d4..b519938e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) [![Docker Image Pulls](https://img.shields.io/docker/pulls/coenjacobs/mozart.svg)](https://hub.docker.com/r/coenjacobs/mozart) +# Mozart [![Latest Stable Version](https://poser.pugx.org/coenjacobs/mozart/v/stable.svg)](https://packagist.org/packages/coenjacobs/mozart) [![License](https://poser.pugx.org/coenjacobs/mozart/license.svg)](https://packagist.org/packages/coenjacobs/mozart) [![Total Downloads](https://poser.pugx.org/coenjacobs/mozart/downloads)](//packagist.org/packages/coenjacobs/mozart) [![Docker Image Pulls](https://img.shields.io/docker/pulls/coenjacobs/mozart.svg)](https://hub.docker.com/r/coenjacobs/mozart) Composes all dependencies as a package inside a WordPress plugin. Load packages through Composer and have them wrapped inside your own namespace. Gone are the days when plugins could load conflicting versions of the same package, resulting in hard to reproduce bugs. This package requires PHP 7.3 or higher in order to run the tool. You can use the resulting files as a bundle, requiring any PHP version you like, even PHP 5.2. From 5efba0b0118b957ff4235f75f28d54c5248bbf48 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Tue, 2 Feb 2021 23:22:51 +0100 Subject: [PATCH 54/58] Stripped todo comment that was obsolete and old --- tests/MoverTest.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/MoverTest.php b/tests/MoverTest.php index 3ec8a1b3..1bb170f6 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -36,7 +36,7 @@ public function setUp(): void if (!file_exists($this->testsWorkingDir)) { mkdir($this->testsWorkingDir); } - + $config = new class() { }; $config->dep_directory = "/dep_directory/"; @@ -93,7 +93,7 @@ public function it_is_unpertrubed_by_existing_dirs(): void $this->assertDirectoryExists($this->testsWorkingDir . $this->config->dep_directory); $this->assertDirectoryExists($this->testsWorkingDir . $this->config->classmap_directory); - + $packages = array(); ob_start(); @@ -118,7 +118,6 @@ public function it_deletes_subdirs_for_packages_about_to_be_moved(): void mkdir($this->testsWorkingDir . DIRECTORY_SEPARATOR . $this->config->dep_directory); mkdir($this->testsWorkingDir . DIRECTORY_SEPARATOR . $this->config->classmap_directory); - // TODO: Create the subdirs that should be deleted. mkdir($this->testsWorkingDir . DIRECTORY_SEPARATOR . $this->config->dep_directory . 'Pimple'); mkdir($this->testsWorkingDir . DIRECTORY_SEPARATOR . $this->config->classmap_directory . 'ezyang'); @@ -209,7 +208,7 @@ public function it_moves_each_file_once_per_namespace() public function tearDown(): void { parent::tearDown(); - + $dir = $this->testsWorkingDir; $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS); From 239905a5ecbd6f8514caec852397f04e980ea058 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Wed, 3 Feb 2021 21:31:37 +0100 Subject: [PATCH 55/58] Run composer update instead of install because no lock file in tests To prevent the "No lock file found. Updating dependencies instead of installing from lock file. Use composer update over composer install if you do not have a lock file." warning while running tests. --- tests/MoverTest.php | 2 +- tests/replacers/ClassmapReplacerIntegrationTest.php | 2 +- tests/replacers/NamespaceReplacerIntegrationTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/MoverTest.php b/tests/MoverTest.php index 1bb170f6..d92c1a19 100644 --- a/tests/MoverTest.php +++ b/tests/MoverTest.php @@ -185,7 +185,7 @@ public function it_moves_each_file_once_per_namespace() chdir($this->testsWorkingDir); - exec('composer install'); + exec('composer update'); $inputInterfaceMock = $this->createMock(InputInterface::class); $outputInterfaceMock = $this->createMock(OutputInterface::class); diff --git a/tests/replacers/ClassmapReplacerIntegrationTest.php b/tests/replacers/ClassmapReplacerIntegrationTest.php index e52422da..835bb0d8 100644 --- a/tests/replacers/ClassmapReplacerIntegrationTest.php +++ b/tests/replacers/ClassmapReplacerIntegrationTest.php @@ -90,7 +90,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi chdir($this->testsWorkingDir); - exec('composer install'); + exec('composer update'); $inputInterfaceMock = $this->createMock(InputInterface::class); $outputInterfaceMock = $this->createMock(OutputInterface::class); diff --git a/tests/replacers/NamespaceReplacerIntegrationTest.php b/tests/replacers/NamespaceReplacerIntegrationTest.php index 6e388a76..7ca5decc 100644 --- a/tests/replacers/NamespaceReplacerIntegrationTest.php +++ b/tests/replacers/NamespaceReplacerIntegrationTest.php @@ -84,7 +84,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi chdir($this->testsWorkingDir); - exec('composer install'); + exec('composer update'); $inputInterfaceMock = $this->createMock(InputInterface::class); $outputInterfaceMock = $this->createMock(OutputInterface::class); From 782a9282a7097ae38ddb7600388885059de10ea1 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Wed, 3 Feb 2021 21:37:56 +0100 Subject: [PATCH 56/58] Run release workflow only on published release --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 074b4a87..8738ecb5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,8 @@ name: Build, tag and attach releases -on: release +on: + release: + types: [published] jobs: create-phar: From 3b1243ca8505fa6436569800dc34269178930f39 Mon Sep 17 00:00:00 2001 From: Coen Jacobs Date: Thu, 4 Feb 2021 21:20:50 +0100 Subject: [PATCH 57/58] Remove unused variables and imports --- src/Console/Commands/Compose.php | 2 -- tests/Console/Commands/ComposeTest.php | 12 ++++++------ tests/replacers/ClassmapReplacerIntegrationTest.php | 2 +- tests/replacers/NamespaceReplacerIntegrationTest.php | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Console/Commands/Compose.php b/src/Console/Commands/Compose.php index ced06a51..c0971f78 100644 --- a/src/Console/Commands/Compose.php +++ b/src/Console/Commands/Compose.php @@ -2,8 +2,6 @@ namespace CoenJacobs\Mozart\Console\Commands; -use CoenJacobs\Mozart\Composer\Autoload\Classmap; -use CoenJacobs\Mozart\Composer\Autoload\NamespaceAutoloader; use CoenJacobs\Mozart\Composer\Package; use CoenJacobs\Mozart\Mover; use CoenJacobs\Mozart\Replacer; diff --git a/tests/Console/Commands/ComposeTest.php b/tests/Console/Commands/ComposeTest.php index 0203fae4..3282c81b 100644 --- a/tests/Console/Commands/ComposeTest.php +++ b/tests/Console/Commands/ComposeTest.php @@ -44,7 +44,7 @@ public function it_fails_gracefully_when_composer_json_absent(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); @@ -74,7 +74,7 @@ public function it_handles_malformed_json_with_grace(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); @@ -104,7 +104,7 @@ public function it_handles_absent_extra_config_with_grace(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); @@ -135,7 +135,7 @@ public function it_handles_malformed_extra_config_with_grace(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); @@ -165,7 +165,7 @@ public function it_handles_absent_mozart_config_with_grace(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); @@ -197,7 +197,7 @@ public function it_handles_malformed_mozart_config__with_grace(): void $outputInterfaceMock->expects($this->exactly(1)) ->method('write'); - $compose = new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { + new class( $inputInterfaceMock, $outputInterfaceMock ) extends Compose { public function __construct($inputInterfaceMock, $outputInterfaceMock) { parent::__construct(); diff --git a/tests/replacers/ClassmapReplacerIntegrationTest.php b/tests/replacers/ClassmapReplacerIntegrationTest.php index 835bb0d8..4ff6a566 100644 --- a/tests/replacers/ClassmapReplacerIntegrationTest.php +++ b/tests/replacers/ClassmapReplacerIntegrationTest.php @@ -97,7 +97,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi $mozartCompose = new Compose(); - $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); + $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); $php_string = file_get_contents($this->testsWorkingDir .'/dep_directory/BrianHenryIE/WP_Logger/class-logger.php'); diff --git a/tests/replacers/NamespaceReplacerIntegrationTest.php b/tests/replacers/NamespaceReplacerIntegrationTest.php index 7ca5decc..80bc04a3 100644 --- a/tests/replacers/NamespaceReplacerIntegrationTest.php +++ b/tests/replacers/NamespaceReplacerIntegrationTest.php @@ -91,7 +91,7 @@ public function test_it_does_not_make_classname_replacement_inside_namespaced_fi $mozartCompose = new Compose(); - $result = $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); + $mozartCompose->run($inputInterfaceMock, $outputInterfaceMock); $mpdf_php = file_get_contents($this->testsWorkingDir .'/dep_directory/Mpdf/Mpdf.php'); From f78e341b6c1e169e73d325b50306d2b2a03ecddb Mon Sep 17 00:00:00 2001 From: Brian Henry Date: Sun, 7 Feb 2021 13:09:07 -0800 Subject: [PATCH 58/58] Update libmergepdf versioin for PHP 8 --- tests/MoverIntegrationTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MoverIntegrationTest.php b/tests/MoverIntegrationTest.php index def655bf..45d6cfc6 100644 --- a/tests/MoverIntegrationTest.php +++ b/tests/MoverIntegrationTest.php @@ -121,7 +121,7 @@ public function testLibpdfmergeSucceeds() $composer = $this->composer; - $composer->require["iio/libmergepdf"] = "4.0.3"; + $composer->require["iio/libmergepdf"] = "4.0.4"; file_put_contents($this->testsWorkingDir . '/composer.json', json_encode($composer));