diff --git a/src/Configurator/AbstractConfigurator.php b/src/Configurator/AbstractConfigurator.php index 26711fcc0..aea4dda94 100644 --- a/src/Configurator/AbstractConfigurator.php +++ b/src/Configurator/AbstractConfigurator.php @@ -43,7 +43,7 @@ abstract public function unconfigure(Recipe $recipe, $config, Lock $lock); abstract public function update(RecipeUpdate $recipeUpdate, array $originalConfig, array $newConfig): void; - protected function write($messages) + protected function write($messages, $verbosity = IOInterface::VERBOSE) { if (!\is_array($messages)) { $messages = [$messages]; @@ -51,7 +51,7 @@ protected function write($messages) foreach ($messages as $i => $message) { $messages[$i] = ' '.$message; } - $this->io->writeError($messages, true, IOInterface::VERBOSE); + $this->io->writeError($messages, true, $verbosity); } protected function isFileMarked(Recipe $recipe, string $file): bool diff --git a/src/Configurator/AddLinesConfigurator.php b/src/Configurator/AddLinesConfigurator.php index b22c1cb92..87fd320bf 100644 --- a/src/Configurator/AddLinesConfigurator.php +++ b/src/Configurator/AddLinesConfigurator.php @@ -2,6 +2,7 @@ namespace Symfony\Flex\Configurator; +use Composer\IO\IOInterface; use Symfony\Flex\Lock; use Symfony\Flex\Recipe; use Symfony\Flex\Update\RecipeUpdate; @@ -35,7 +36,11 @@ public function configure(Recipe $recipe, $config, Lock $lock, array $options = $file = $this->path->concatenate([$this->options->get('root-dir'), $patch['file']]); if (!is_file($file)) { - $this->write(sprintf('Skipping patch on file "%s": it does not exist.', $patch['file'])); + $this->write( + sprintf('Skipping update of file "%s": it does not exist.', $patch['file']), + isset($patch['warn_if_missing']) && $patch['warn_if_missing'] ? IOInterface::NORMAL : IOInterface::VERBOSE + ); + continue; } @@ -50,7 +55,7 @@ public function configure(Recipe $recipe, $config, Lock $lock, array $options = throw new \InvalidArgumentException(sprintf('The "position" key is required for the "add-lines" configurator for recipe "%s".', $recipe->getName())); } $position = $patch['position']; - if (!in_array($position, self::VALID_POSITIONS, true)) { + if (!\in_array($position, self::VALID_POSITIONS, true)) { throw new \InvalidArgumentException(sprintf('The "position" key must be one of "%s" for the "add-lines" configurator for recipe "%s".', implode('", "', self::VALID_POSITIONS), $recipe->getName())); } @@ -96,7 +101,7 @@ public function update(RecipeUpdate $recipeUpdate, array $originalConfig, array return !isset($item['requires']) || $this->isPackageInstalled($item['requires']); }); - $filterDuplicates = function(array $sourceConfig, array $comparisonConfig) { + $filterDuplicates = function (array $sourceConfig, array $comparisonConfig) { $filtered = []; foreach ($sourceConfig as $sourceItem) { $found = false; @@ -177,7 +182,7 @@ private function unPatchFile(string $file, $value) } $position = strpos($fileContents, $value); - $fileContents = substr_replace($fileContents, '', $position, strlen($value)); + $fileContents = substr_replace($fileContents, '', $position, \strlen($value)); file_put_contents($file, $fileContents); } diff --git a/src/PackageJsonSynchronizer.php b/src/PackageJsonSynchronizer.php index ae845c013..4efe1e229 100644 --- a/src/PackageJsonSynchronizer.php +++ b/src/PackageJsonSynchronizer.php @@ -126,7 +126,7 @@ private function resolvePackageJsonDependencies($phpPackage): array } if ($packageJson->read()['symfony']['needsPackageAsADependency'] ?? true) { - $dependencies['@' . $phpPackage['name']] = 'file:' . substr($packageJson->getPath(), 1 + \strlen($this->rootDir), -13); + $dependencies['@'.$phpPackage['name']] = 'file:'.substr($packageJson->getPath(), 1 + \strlen($this->rootDir), -13); } foreach ($packageJson->read()['peerDependencies'] ?? [] as $peerDependency => $constraint) { @@ -147,7 +147,7 @@ private function resolveImportMapPackages($phpPackage): array foreach ($packageJson->read()['symfony']['importmap'] ?? [] as $dependency => $constraint) { if (0 === strpos($constraint, 'path:')) { $dependencies[$dependency] = [ - 'path' => dirname($packageJson->getPath()).'/'.substr($constraint, 5) + 'path' => \dirname($packageJson->getPath()).'/'.substr($constraint, 5), ]; continue; @@ -226,7 +226,7 @@ private function updateImportMap(array $importMapEntries): void return; } - $importMapData = include($this->rootDir.'/importmap.php'); + $importMapData = include $this->rootDir.'/importmap.php'; $remotePackageNameAndConstraints = []; foreach ($importMapEntries as $name => $importMapEntry) { @@ -250,7 +250,11 @@ private function updateImportMap(array $importMapEntries): void continue; } - throw new \InvalidArgumentException(sprintf('Invalid importmap entry: %s', var_export($importMapEntry, true))); + throw new \InvalidArgumentException(sprintf('Invalid importmap entry: "%s".', var_export($importMapEntry, true))); + } + + if (!$remotePackageNameAndConstraints) { + return; } $this->scriptExecutor->execute( diff --git a/src/ScriptExecutor.php b/src/ScriptExecutor.php index 20f5194e6..d61694735 100644 --- a/src/ScriptExecutor.php +++ b/src/ScriptExecutor.php @@ -117,7 +117,7 @@ private function expandPhpScript(string $cmd, array $scriptArguments): string $arguments = $phpFinder->findArguments(); - if ($env = (string) (getenv('COMPOSER_ORIGINAL_INIS'))) { + if ($env = (string) getenv('COMPOSER_ORIGINAL_INIS')) { $paths = explode(\PATH_SEPARATOR, $env); $ini = array_shift($paths); } else { diff --git a/tests/Configurator/AddLinesConfiguratorTest.php b/tests/Configurator/AddLinesConfiguratorTest.php index 17cbb71c4..5c94f7dc6 100644 --- a/tests/Configurator/AddLinesConfiguratorTest.php +++ b/tests/Configurator/AddLinesConfiguratorTest.php @@ -32,11 +32,10 @@ protected function setUp(): void $filesystem->remove(FLEX_TEST_DIR); } - public function testFileDoesNotExistSkipped() { $this->runConfigure([ - ['file' => 'non-existent.php'] + ['file' => 'non-existent.php'], ]); $this->assertFileDoesNotExist(FLEX_TEST_DIR.'/non-existent.php'); } @@ -54,7 +53,7 @@ public function testLinesAddedToTopOfFile() [ 'file' => 'assets/app.js', 'position' => 'top', - 'content' => "import './bootstrap';" + 'content' => "import './bootstrap';", ], ]); $actualContents = $this->readFile('assets/app.js'); @@ -63,7 +62,8 @@ public function testLinesAddedToTopOfFile() import * as Turbo from '@hotwired/turbo'; console.log(Turbo); -EOF, +EOF + , $actualContents); } @@ -80,7 +80,7 @@ public function testLinesAddedToBottomOfFile() [ 'file' => 'assets/app.js', 'position' => 'bottom', - 'content' => "import './bootstrap';" + 'content' => "import './bootstrap';", ], ]); $actualContents = $this->readFile('assets/app.js'); @@ -89,7 +89,8 @@ public function testLinesAddedToBottomOfFile() console.log(Turbo); import './bootstrap'; -EOF, +EOF + , $actualContents); } @@ -122,7 +123,6 @@ public function testLinesAddedAfterTarget() // enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js) .enableStimulusBridge('./assets/controllers.json') EOF - ], ]); @@ -144,7 +144,8 @@ public function testLinesAddedAfterTarget() ; module.exports = Encore.getWebpackConfig(); -EOF, +EOF + , $actualContents); } @@ -171,7 +172,6 @@ public function testSkippedIfTargetCannotBeFound() // some new line EOF - ], ]); @@ -193,7 +193,7 @@ public function testPatchIgnoredIfValueAlreadyExists() [ 'file' => 'assets/app.js', 'position' => 'top', - 'content' => "import './bootstrap';" + 'content' => "import './bootstrap';", ], ]); $actualContents = $this->readFile('assets/app.js'); @@ -212,30 +212,31 @@ public function testLinesAddedToMultipleFiles() EOF ); - $this->runConfigure([ [ 'file' => 'assets/app.js', 'position' => 'top', - 'content' => "import './bootstrap';" + 'content' => "import './bootstrap';", ], [ 'file' => 'assets/bootstrap.js', 'position' => 'bottom', - 'content' => "console.log('on the bottom');" + 'content' => "console.log('on the bottom');", ], ]); $this->assertSame(<<readFile('assets/app.js')); $this->assertSame(<<readFile('assets/bootstrap.js')); } @@ -248,6 +249,7 @@ public function testLineSkippedIfRequiredPackageMissing() EOF ); + $composer = $this->createComposerMockWithPackagesInstalled([]); $this->runConfigure([ [ 'file' => 'assets/app.js', @@ -255,13 +257,14 @@ public function testLineSkippedIfRequiredPackageMissing() 'content' => "import './bootstrap';", 'requires' => 'symfony/invented-package', ], - ]); + ], $composer); $actualContents = $this->readFile('assets/app.js'); $this->assertSame(<< [ ['assets/app.js' => $appJs], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';"] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';"], ], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';"] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';"], ], ['assets/app.js' => << [ ['assets/app.js' => $appJs], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"], ], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"], ], ['assets/app.js' => $appJs], ]; @@ -471,17 +474,18 @@ public function getUpdateTests() yield 'different_files_unconfigures_old_and_configures_new' => [ ['assets/app.js' => $appJs, 'assets/bootstrap.js' => $bootstrapJs], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"], ], [ - ['file' => 'assets/bootstrap.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"] + ['file' => 'assets/bootstrap.js', 'position' => 'top', 'content' => "import * as Turbo from '@hotwired/turbo';"], ], [ 'assets/app.js' => << << [ ['assets/app.js' => $appJs], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';", 'requires' => 'symfony/not-installed'] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';", 'requires' => 'symfony/not-installed'], ], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';", 'requires' => 'symfony/not-installed'] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';", 'requires' => 'symfony/not-installed'], ], ['assets/app.js' => $appJs], ]; @@ -505,10 +509,10 @@ public function getUpdateTests() yield 'recipe_changes_are_applied_if_required_package_installed' => [ ['assets/app.js' => $appJs], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';", 'requires' => 'symfony/installed-package'] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './bootstrap';", 'requires' => 'symfony/installed-package'], ], [ - ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';", 'requires' => 'symfony/installed-package'] + ['file' => 'assets/app.js', 'position' => 'top', 'content' => "import './stimulus_bootstrap';", 'requires' => 'symfony/installed-package'], ], ['assets/app.js' => <<getMockBuilder(Composer::class)->getMock(), + $composer ?: $this->getMockBuilder(Composer::class)->getMock(), $this->getMockBuilder(IOInterface::class)->getMock(), new Options(['config-dir' => 'config', 'root-dir' => FLEX_TEST_DIR]) );