diff --git a/module/VuFindConsole/src/VuFindConsole/Command/Language/CopyStringCommand.php b/module/VuFindConsole/src/VuFindConsole/Command/Language/CopyStringCommand.php index 1701b370d9149c11ed8e3360136db6d7f52a42de..8aab056b80fdce3a9230ca3532252dfcccc772fc 100644 --- a/module/VuFindConsole/src/VuFindConsole/Command/Language/CopyStringCommand.php +++ b/module/VuFindConsole/src/VuFindConsole/Command/Language/CopyStringCommand.php @@ -29,6 +29,7 @@ namespace VuFindConsole\Command\Language; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -68,6 +69,18 @@ class CopyStringCommand extends AbstractCommand 'target', InputArgument::REQUIRED, 'the target key to write ' . $note + )->addOption( + 'replace', + null, + InputOption::VALUE_REQUIRED, + 'string delimited by replaceDelimiter option, representing ' + . "search-and-replace operation.\ne.g. textToReplace/replacementText" + )->addOption( + 'replaceDelimiter', + null, + InputOption::VALUE_REQUIRED, + 'delimiter used in replace option', + '/' ); } @@ -90,6 +103,20 @@ class CopyStringCommand extends AbstractCommand fclose($fHandle); } + /** + * Apply a replacement rule, if necessary. + * + * @param string $text Text to transform + * @param array $rule Replacement rule (empty for no change; [text to replace, + * replacement] array to apply a transformation) + * + * @return string + */ + protected function applyReplaceRule(string $text, array $rule): string + { + return empty($rule) ? $text : str_replace($rule[0], $rule[1], $text); + } + /** * Run the command. * @@ -102,6 +129,9 @@ class CopyStringCommand extends AbstractCommand { $source = $input->getArgument('source'); $target = $input->getArgument('target'); + $replace = $input->getOption('replace'); + $replaceDelimiter = $input->getOption('replaceDelimiter'); + $replaceRule = empty($replace) ? [] : explode($replaceDelimiter, $replace); list($sourceDomain, $sourceKey) = $this->extractTextDomain($source); list($targetDomain, $targetKey) = $this->extractTextDomain($target); @@ -114,14 +144,17 @@ class CopyStringCommand extends AbstractCommand // First, collect the source values from the source text domain: $sources = []; - $sourceCallback = function ($full) use ($output, $sourceKey, & $sources) { - $strings = $this->reader->getTextDomain($full, false); - if (!isset($strings[$sourceKey])) { - $output->writeln('Source key not found.'); - } else { - $sources[basename($full)] = $strings[$sourceKey]; - } - }; + $sourceCallback + = function ($full) use ($output, $replaceRule, $sourceKey, & $sources) { + $strings = $this->reader->getTextDomain($full, false); + if (!isset($strings[$sourceKey])) { + $output->writeln('Source key not found.'); + return; + } + $sources[basename($full)] = $this->applyReplaceRule( + $strings[$sourceKey], $replaceRule + ); + }; $this->processDirectory($sourceDir, $sourceCallback, [$output, 'writeln']); // Make sure that all target files exist: diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php index 7abec14fb09e186d8216428f0130da0c5c80a3d6..c7fab3cace62430a65fc87d1b5d3c85396cb8426 100644 --- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php +++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Command/Language/CopyStringCommandTest.php @@ -72,11 +72,13 @@ class CopyStringCommandTest extends \PHPUnit\Framework\TestCase } /** - * Test the simplest possible success case. + * Get a command mock with expectations of success. * - * @return void + * @param string $expectedString The expected output string of the process. + * + * @return CopyStringCommand */ - public function testSuccessWithMinimalParameters() + protected function getSuccessfulMockCommand($expectedString = 'baz') { $expectedPath = realpath($this->languageFixtureDir) . '/foo/en.ini'; $normalizer = $this->getMockNormalizer(); @@ -91,8 +93,19 @@ class CopyStringCommandTest extends \PHPUnit\Framework\TestCase ->with( $this->equalTo($expectedPath), $this->equalTo('xyzzy'), - $this->equalTo('baz') + $this->equalTo($expectedString) ); + return $command; + } + + /** + * Test the simplest possible success case. + * + * @return void + */ + public function testSuccessWithMinimalParameters() + { + $command = $this->getSuccessfulMockCommand(); $commandTester = new CommandTester($command); $commandTester->execute(['source' => 'foo::bar', 'target' => 'foo::xyzzy']); $this->assertEquals( @@ -102,6 +115,53 @@ class CopyStringCommandTest extends \PHPUnit\Framework\TestCase $this->assertEquals(0, $commandTester->getStatusCode()); } + /** + * Test success with the replace option set. + * + * @return void + */ + public function testSuccessWithReplaceOptionAndDefaultDelimiter() + { + $command = $this->getSuccessfulMockCommand('transformed'); + $commandTester = new CommandTester($command); + $commandTester->execute( + [ + 'source' => 'foo::bar', + 'target' => 'foo::xyzzy', + '--replace' => 'baz/transformed' + ] + ); + $this->assertEquals( + "Processing en.ini...\nProcessing en.ini...\n", + $commandTester->getDisplay() + ); + $this->assertEquals(0, $commandTester->getStatusCode()); + } + + /** + * Test success with the replace and replaceDelimiter options set. + * + * @return void + */ + public function testSuccessWithReplaceOptionAndCustomDelimiter() + { + $command = $this->getSuccessfulMockCommand('transformed'); + $commandTester = new CommandTester($command); + $commandTester->execute( + [ + 'source' => 'foo::bar', + 'target' => 'foo::xyzzy', + '--replace' => 'baz|transformed', + '--replaceDelimiter' => '|', + ] + ); + $this->assertEquals( + "Processing en.ini...\nProcessing en.ini...\n", + $commandTester->getDisplay() + ); + $this->assertEquals(0, $commandTester->getStatusCode()); + } + /** * Test failure due to missing text domain. *