Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.35% covered (success)
95.35%
41 / 43
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
AddUsingTemplateCommand
95.35% covered (success)
95.35%
41 / 43
50.00% covered (danger)
50.00%
1 / 2
11
0.00% covered (danger)
0.00%
0 / 1
 configure
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 execute
93.33% covered (success)
93.33%
28 / 30
0.00% covered (danger)
0.00%
0 / 1
10.03
1<?php
2
3/**
4 * Language command: add string using template.
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
30namespace VuFindConsole\Command\Language;
31
32use Symfony\Component\Console\Attribute\AsCommand;
33use Symfony\Component\Console\Input\InputArgument;
34use Symfony\Component\Console\Input\InputInterface;
35use Symfony\Component\Console\Output\OutputInterface;
36
37/**
38 * Language command: add string using template.
39 *
40 * @category VuFind
41 * @package  Console
42 * @author   Demian Katz <demian.katz@villanova.edu>
43 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
44 * @link     https://vufind.org/wiki/development Wiki
45 */
46#[AsCommand(
47    name: 'language/addusingtemplate',
48    description: 'Template-based string builder'
49)]
50class AddUsingTemplateCommand extends AbstractCommand
51{
52    /**
53     * Configure the command.
54     *
55     * @return void
56     */
57    protected function configure()
58    {
59        $this
60            ->setHelp(
61                'Builds new language strings from existing ones using a template'
62            )->addArgument(
63                'target',
64                InputArgument::REQUIRED,
65                "the target key to add (may include 'textdomain::' prefix)"
66            )->addArgument(
67                'template',
68                InputArgument::REQUIRED,
69                'the template to build the string, using ||string||'
70                . ' to import existing strings'
71            );
72    }
73
74    /**
75     * Run the command.
76     *
77     * @param InputInterface  $input  Input object
78     * @param OutputInterface $output Output object
79     *
80     * @return int 0 for success
81     */
82    protected function execute(InputInterface $input, OutputInterface $output)
83    {
84        $target = $input->getArgument('target');
85        $template = $input->getArgument('template');
86
87        // Make sure a valid target has been specified:
88        [$targetDomain, $targetKey] = $this->extractTextDomain($target);
89        if (!($targetDir = $this->getLangDir($output, $targetDomain, true))) {
90            return 1;
91        }
92
93        // Extract required source values from template:
94        preg_match_all('/\|\|[^|]+\|\|/', $template, $matches);
95        $lookups = [];
96        foreach ($matches[0] as $current) {
97            $key = trim($current, '|');
98            [$sourceDomain, $sourceKey] = $this->extractTextDomain($key);
99            $lookups[$sourceDomain][$current] = [
100                'key' => $sourceKey,
101                'translations' => [],
102            ];
103        }
104
105        // Look up translations of all references in template:
106        foreach ($lookups as $domain => & $tokens) {
107            $sourceDir = $this->getLangDir($output, $domain, false);
108            if (!$sourceDir) {
109                return 1;
110            }
111            $sourceCallback = function ($full) use (&$tokens) {
112                $strings = $this->reader->getTextDomain($full, false);
113                foreach ($tokens as & $current) {
114                    $sourceKey = $current['key'];
115                    if (isset($strings[$sourceKey])) {
116                        $current['translations'][basename($full)]
117                            = $strings[$sourceKey];
118                    }
119                }
120            };
121            $this->processDirectory($sourceDir, $sourceCallback, false);
122        }
123
124        // Fill in template, write results:
125        $targetCallback = function ($full) use (
126            $output,
127            $template,
128            $targetKey,
129            $lookups
130        ) {
131            $lang = basename($full);
132            $in = $out = [];
133            foreach ($lookups as $domain => $tokens) {
134                foreach ($tokens as $token => $details) {
135                    if (!isset($details['translations'][$lang])) {
136                        $output->writeln("Skipping; no match for token: $token");
137                        return;
138                    }
139                    $in[] = $token;
140                    $out[] = $details['translations'][$lang];
141                }
142            }
143            $this->addLineToFile(
144                $full,
145                $targetKey,
146                str_replace($in, $out, $template)
147            );
148            $this->normalizer->normalizeFile($full);
149        };
150        $this->processDirectory($targetDir, $targetCallback, [$output, 'writeln']);
151        return 0;
152    }
153}