Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
89.80% |
44 / 49 |
|
75.00% |
3 / 4 |
CRAP | |
0.00% |
0 / 1 |
CopyStringCommand | |
89.80% |
44 / 49 |
|
75.00% |
3 / 4 |
11.13 | |
0.00% |
0 / 1 |
configure | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
1 | |||
addLineToFile | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
applyReplaceRule | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
execute | |
100.00% |
20 / 20 |
|
100.00% |
1 / 1 |
6 |
1 | <?php |
2 | |
3 | /** |
4 | * Language command: copy string. |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2020. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package Console |
25 | * @author Demian Katz <demian.katz@villanova.edu> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org/wiki/development Wiki |
28 | */ |
29 | |
30 | namespace VuFindConsole\Command\Language; |
31 | |
32 | use Symfony\Component\Console\Attribute\AsCommand; |
33 | use Symfony\Component\Console\Input\InputArgument; |
34 | use Symfony\Component\Console\Input\InputInterface; |
35 | use Symfony\Component\Console\Input\InputOption; |
36 | use Symfony\Component\Console\Output\OutputInterface; |
37 | |
38 | /** |
39 | * Language command: copy string. |
40 | * |
41 | * @category VuFind |
42 | * @package Console |
43 | * @author Demian Katz <demian.katz@villanova.edu> |
44 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
45 | * @link https://vufind.org/wiki/development Wiki |
46 | */ |
47 | #[AsCommand( |
48 | name: 'language/copystring', |
49 | description: 'String copier' |
50 | )] |
51 | class CopyStringCommand extends AbstractCommand |
52 | { |
53 | /** |
54 | * Configure the command. |
55 | * |
56 | * @return void |
57 | */ |
58 | protected function configure() |
59 | { |
60 | $note = "(may include 'textdomain::' prefix)"; |
61 | $this |
62 | ->setHelp('Copies one language string to another.') |
63 | ->addArgument( |
64 | 'source', |
65 | InputArgument::REQUIRED, |
66 | 'the source key to read ' . $note |
67 | )->addArgument( |
68 | 'target', |
69 | InputArgument::REQUIRED, |
70 | 'the target key to write ' . $note |
71 | )->addOption( |
72 | 'replace', |
73 | null, |
74 | InputOption::VALUE_REQUIRED, |
75 | 'string delimited by replaceDelimiter option, representing ' |
76 | . "search-and-replace operation.\ne.g. textToReplace/replacementText" |
77 | )->addOption( |
78 | 'replaceDelimiter', |
79 | null, |
80 | InputOption::VALUE_REQUIRED, |
81 | 'delimiter used in replace option', |
82 | '/' |
83 | ); |
84 | } |
85 | |
86 | /** |
87 | * Add a line to a language file |
88 | * |
89 | * @param string $filename File to update |
90 | * @param string $key Name of language key |
91 | * @param string $value Value of translation |
92 | * |
93 | * @return void |
94 | */ |
95 | protected function addLineToFile($filename, $key, $value) |
96 | { |
97 | $fHandle = fopen($filename, 'a'); |
98 | if (!$fHandle) { |
99 | throw new \Exception('Cannot open ' . $filename . ' for writing.'); |
100 | } |
101 | fwrite($fHandle, "\n$key = \"" . $value . "\"\n"); |
102 | fclose($fHandle); |
103 | } |
104 | |
105 | /** |
106 | * Apply a replacement rule, if necessary. |
107 | * |
108 | * @param string $text Text to transform |
109 | * @param array $rule Replacement rule (empty for no change; [text to replace, |
110 | * replacement] array to apply a transformation) |
111 | * |
112 | * @return string |
113 | */ |
114 | protected function applyReplaceRule(string $text, array $rule): string |
115 | { |
116 | return empty($rule) ? $text : str_replace($rule[0], $rule[1], $text); |
117 | } |
118 | |
119 | /** |
120 | * Run the command. |
121 | * |
122 | * @param InputInterface $input Input object |
123 | * @param OutputInterface $output Output object |
124 | * |
125 | * @return int 0 for success |
126 | */ |
127 | protected function execute(InputInterface $input, OutputInterface $output) |
128 | { |
129 | $source = $input->getArgument('source'); |
130 | $target = $input->getArgument('target'); |
131 | $replace = $input->getOption('replace'); |
132 | $replaceDelimiter = $input->getOption('replaceDelimiter'); |
133 | $replaceRule = empty($replace) ? [] : explode($replaceDelimiter, $replace); |
134 | |
135 | [$sourceDomain, $sourceKey] = $this->extractTextDomain($source); |
136 | [$targetDomain, $targetKey] = $this->extractTextDomain($target); |
137 | |
138 | if ( |
139 | !($sourceDir = $this->getLangDir($output, $sourceDomain)) |
140 | || !($targetDir = $this->getLangDir($output, $targetDomain, true)) |
141 | ) { |
142 | return 1; |
143 | } |
144 | |
145 | // First, collect the source values from the source text domain: |
146 | $sources = []; |
147 | $sourceCallback |
148 | = function ($full) use ($output, $replaceRule, $sourceKey, &$sources) { |
149 | $strings = $this->reader->getTextDomain($full, false); |
150 | if (!isset($strings[$sourceKey])) { |
151 | $output->writeln('Source key not found.'); |
152 | return; |
153 | } |
154 | $sources[basename($full)] = $this->applyReplaceRule( |
155 | $strings[$sourceKey], |
156 | $replaceRule |
157 | ); |
158 | }; |
159 | $this->processDirectory($sourceDir, $sourceCallback, [$output, 'writeln']); |
160 | |
161 | // Make sure that all target files exist: |
162 | $this->createMissingFiles($targetDir->path, array_keys($sources)); |
163 | |
164 | // Now copy the values to their destination: |
165 | $targetCallback = function ($full) use ($targetKey, $sources) { |
166 | if (isset($sources[basename($full)])) { |
167 | $this->addLineToFile($full, $targetKey, $sources[basename($full)]); |
168 | $this->normalizer->normalizeFile($full); |
169 | } |
170 | }; |
171 | $this->processDirectory($targetDir, $targetCallback, [$output, 'writeln']); |
172 | |
173 | return 0; |
174 | } |
175 | } |