Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.65% covered (success)
93.65%
59 / 63
50.00% covered (warning)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Xml
93.65% covered (success)
93.65%
59 / 63
50.00% covered (warning)
50.00%
1 / 2
28.20
0.00% covered (danger)
0.00%
0 / 1
 createFile
100.00% covered (success)
100.00%
40 / 40
100.00% covered (success)
100.00%
1 / 1
18
 createFragment
82.61% covered (success)
82.61%
19 / 23
0.00% covered (danger)
0.00%
0 / 1
10.53
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\I18n\Format;
15
16/**
17 * I18n XML format class
18 *
19 * @category   Pop
20 * @package    Pop_I18n
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    4.0.0
25 */
26class Xml
27{
28
29    /**
30     * Create an XML language file from an array of data.
31     * The format of the parameters should be as follows:
32     *
33     * $lang = [
34     *     'src'    => 'en',
35     *     'output' => 'de',
36     *     'name'   => 'German',
37     *     'native' => 'Deutsch'
38     * ];
39     *
40     * $locales = [
41     *     [
42     *         'region' => 'DE',
43     *         'name'   => 'Germany',
44     *         'native' => 'Deutschland',
45     *         'text' => [
46     *             [
47     *                 'source' => 'This field is required.',
48     *                 'output' => 'Dieses Feld ist erforderlich.'
49     *             ], ...
50     *         ]
51     *     ], ...
52     * ];
53     *
54     * @param  array  $lang
55     * @param  array  $locales
56     * @param  string $file
57     * @throws Exception
58     * @return void
59     */
60    public static function createFile(array $lang, array $locales, string $file): void
61    {
62        // Validate the $lang parameter
63        if (!isset($lang['src']) || !isset($lang['output'])) {
64            throw new Exception("Error: The language parameter must have at least the 'src' and 'output' keys defined.");
65        }
66
67        // Validate the $locales parameter
68        foreach ($locales as $locale) {
69            if (!isset($locale['region'])) {
70                throw new Exception("Error: The locales parameter must have at least the 'region' key defined in each locale.");
71            }
72            if (!isset($locale['text'])) {
73                throw new Exception("Error: The locales parameter must have at least the 'text' key defined in each locale.");
74            }
75            if (!is_array($locale['text'])) {
76                throw new Exception("Error: The parameter key 'text' in each locale must be an array.");
77            }
78        }
79
80        $xmlHeader = file_get_contents(__DIR__ . '/../Data/__.xml');
81        $xmlHeader = substr($xmlHeader, 0, (strpos($xmlHeader, 'native="">') + 10));
82        $xmlHeader = str_replace(
83            ['src=""', 'output=""'],
84            ['src="' . $lang['src'] . '"', 'output="' . $lang['output'] . '"'],
85            $xmlHeader
86        );
87
88        if (isset($lang['name'])) {
89            $xmlHeader = str_replace('name=""', 'name="' . $lang['name'] . '"', $xmlHeader);
90        }
91
92        if (isset($lang['native'])) {
93            $xmlHeader = str_replace('native=""', 'native="' . $lang['native'] . '"', $xmlHeader);
94        }
95
96        // Format the Locales
97        $xmlLocales = null;
98
99        foreach ($locales as $locale) {
100            $name = (isset($locale['name'])) ? $locale['name'] : null;
101            $native = (isset($locale['native'])) ? $locale['native'] : null;
102            $xmlLocales .= '    <locale region="' . $locale['region'] . '" name="' . $name . '" native="' . $native . '">' . PHP_EOL;
103            foreach ($locale['text'] as $text) {
104                if (!isset($text['source']) || !isset($text['output'])) {
105                    throw new Exception("Error: The 'source' and 'output' keys must be defined in each 'text' array.");
106                }
107                $xmlLocales .= '        <text>' . PHP_EOL;
108                $xmlLocales .= '            <source>' . $text['source'] . '</source>' . PHP_EOL;
109                if (is_array($text['output'])) {
110                    $xmlLocales .= '            <output>' . PHP_EOL;
111                    foreach ($text['output'] as $alt => $output) {
112                        $altAttrib   = (!is_numeric($alt)) ? ' alt="' . $alt . '"' : null;
113                        $xmlLocales .= '                <output' . $altAttrib . '>' . $output . '</output>' . PHP_EOL;
114                    }
115                    $xmlLocales .= '            </output>' . PHP_EOL;
116                } else {
117                    $xmlLocales .= '            <output>' . $text['output'] . '</output>' . PHP_EOL;
118                }
119                $xmlLocales .= '        </text>' . PHP_EOL;
120            }
121            $xmlLocales .= '    </locale>' . PHP_EOL;
122        }
123
124        // Save XML file
125        file_put_contents($file, $xmlHeader . PHP_EOL . $xmlLocales . '</language>');
126    }
127
128    /**
129     * Create an language file fragment from a source file and an output file,
130     * each entry separated by a new line
131     *
132     * @param  string  $source
133     * @param  string  $output
134     * @param  ?string $dir
135     * @throws Exception
136     * @return void
137     */
138    public static function createFragment(string $source, string $output, ?string $dir = null): void
139    {
140        if (!file_exists($source)) {
141            throw new Exception('Error: The source file does not exist.');
142        }
143        if (!file_exists($output)) {
144            throw new Exception('Error: The output file does not exist.');
145        }
146
147        $sourceLines = explode(PHP_EOL, file_get_contents($source));
148        $outputLines = explode(PHP_EOL, file_get_contents($output));
149
150        $targetDir = ($dir !== null) ? $dir : dirname($output);
151
152        if (!file_exists($targetDir)) {
153            throw new Exception('Error: The target directory does not exist.');
154        }
155
156        if (str_contains($output, '/')) {
157            $lang = substr($output, (strrpos($output, '/') + 1));
158            $lang = substr($lang, 0, strpos($lang, '.'));
159        } else if (str_contains($output, "\\")) {
160            $lang = substr($output, (strrpos($output, "\\") + 1));
161            $lang = substr($lang, 0, strpos($lang, '.'));
162        } else {
163            $lang = substr($output, 0, strpos($output, '.'));
164        }
165
166        $xml  = null;
167
168        foreach ($outputLines as $key => $value) {
169            if (!empty($value) && !empty($sourceLines[$key])) {
170                $xml .= '        <text>' . PHP_EOL . '            <source>' . $sourceLines[$key] . '</source>' . PHP_EOL .
171                    '            <output>' . $value . '</output>' . PHP_EOL .
172                    '        </text>' . PHP_EOL;
173            }
174        }
175
176        file_put_contents($targetDir . DIRECTORY_SEPARATOR . $lang . '.xml', $xml);
177    }
178
179}