|
15 | 15 | use Symfony\Component\Translation\MessageCatalogue; |
16 | 16 | use Symfony\Component\Translation\Exception\InvalidResourceException; |
17 | 17 | use Symfony\Component\Translation\Exception\NotFoundResourceException; |
18 | | -use Symfony\Component\Translation\Exception\InvalidArgumentException; |
19 | 18 | use Symfony\Component\Config\Resource\FileResource; |
| 19 | +use Symfony\Component\Translation\Util\XliffUtils; |
20 | 20 |
|
21 | 21 | /** |
22 | 22 | * XliffFileLoader loads translations from XLIFF files. |
@@ -56,8 +56,10 @@ private function extract($resource, MessageCatalogue $catalogue, $domain) |
56 | 56 | throw new InvalidResourceException(sprintf('Unable to load "%s": %s', $resource, $e->getMessage()), $e->getCode(), $e); |
57 | 57 | } |
58 | 58 |
|
59 | | - $xliffVersion = $this->getVersionNumber($dom); |
60 | | - $this->validateSchema($xliffVersion, $dom, $this->getSchema($xliffVersion)); |
| 59 | + $xliffVersion = XliffUtils::getVersionNumber($dom); |
| 60 | + if ($errors = XliffUtils::validateSchema($dom)) { |
| 61 | + throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s', $xliffVersion, XliffUtils::getErrorsAsString($errors))); |
| 62 | + } |
61 | 63 |
|
62 | 64 | if ('1.2' === $xliffVersion) { |
63 | 65 | $this->extractXliff1($dom, $catalogue, $domain); |
@@ -169,123 +171,6 @@ private function utf8ToCharset(string $content, string $encoding = null): string |
169 | 171 | return $content; |
170 | 172 | } |
171 | 173 |
|
172 | | - /** |
173 | | - * Validates and parses the given file into a DOMDocument. |
174 | | - * |
175 | | - * @throws InvalidResourceException |
176 | | - */ |
177 | | - private function validateSchema(string $file, \DOMDocument $dom, string $schema) |
178 | | - { |
179 | | - $internalErrors = libxml_use_internal_errors(true); |
180 | | - |
181 | | - $disableEntities = libxml_disable_entity_loader(false); |
182 | | - |
183 | | - if (!@$dom->schemaValidateSource($schema)) { |
184 | | - libxml_disable_entity_loader($disableEntities); |
185 | | - |
186 | | - throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s', $file, implode("\n", $this->getXmlErrors($internalErrors)))); |
187 | | - } |
188 | | - |
189 | | - libxml_disable_entity_loader($disableEntities); |
190 | | - |
191 | | - $dom->normalizeDocument(); |
192 | | - |
193 | | - libxml_clear_errors(); |
194 | | - libxml_use_internal_errors($internalErrors); |
195 | | - } |
196 | | - |
197 | | - private function getSchema($xliffVersion) |
198 | | - { |
199 | | - if ('1.2' === $xliffVersion) { |
200 | | - $schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd'); |
201 | | - $xmlUri = 'http://www.w3.org/2001/xml.xsd'; |
202 | | - } elseif ('2.0' === $xliffVersion) { |
203 | | - $schemaSource = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-2.0.xsd'); |
204 | | - $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd'; |
205 | | - } else { |
206 | | - throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion)); |
207 | | - } |
208 | | - |
209 | | - return $this->fixXmlLocation($schemaSource, $xmlUri); |
210 | | - } |
211 | | - |
212 | | - /** |
213 | | - * Internally changes the URI of a dependent xsd to be loaded locally. |
214 | | - */ |
215 | | - private function fixXmlLocation(string $schemaSource, string $xmlUri): string |
216 | | - { |
217 | | - $newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd'; |
218 | | - $parts = explode('/', $newPath); |
219 | | - $locationstart = 'file:///'; |
220 | | - if (0 === stripos($newPath, 'phar://')) { |
221 | | - $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); |
222 | | - if ($tmpfile) { |
223 | | - copy($newPath, $tmpfile); |
224 | | - $parts = explode('/', str_replace('\\', '/', $tmpfile)); |
225 | | - } else { |
226 | | - array_shift($parts); |
227 | | - $locationstart = 'phar:///'; |
228 | | - } |
229 | | - } |
230 | | - |
231 | | - $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; |
232 | | - $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); |
233 | | - |
234 | | - return str_replace($xmlUri, $newPath, $schemaSource); |
235 | | - } |
236 | | - |
237 | | - /** |
238 | | - * Returns the XML errors of the internal XML parser. |
239 | | - */ |
240 | | - private function getXmlErrors(bool $internalErrors): array |
241 | | - { |
242 | | - $errors = array(); |
243 | | - foreach (libxml_get_errors() as $error) { |
244 | | - $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', |
245 | | - LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', |
246 | | - $error->code, |
247 | | - trim($error->message), |
248 | | - $error->file ?: 'n/a', |
249 | | - $error->line, |
250 | | - $error->column |
251 | | - ); |
252 | | - } |
253 | | - |
254 | | - libxml_clear_errors(); |
255 | | - libxml_use_internal_errors($internalErrors); |
256 | | - |
257 | | - return $errors; |
258 | | - } |
259 | | - |
260 | | - /** |
261 | | - * Gets xliff file version based on the root "version" attribute. |
262 | | - * Defaults to 1.2 for backwards compatibility. |
263 | | - * |
264 | | - * @throws InvalidArgumentException |
265 | | - */ |
266 | | - private function getVersionNumber(\DOMDocument $dom): string |
267 | | - { |
268 | | - /** @var \DOMNode $xliff */ |
269 | | - foreach ($dom->getElementsByTagName('xliff') as $xliff) { |
270 | | - $version = $xliff->attributes->getNamedItem('version'); |
271 | | - if ($version) { |
272 | | - return $version->nodeValue; |
273 | | - } |
274 | | - |
275 | | - $namespace = $xliff->attributes->getNamedItem('xmlns'); |
276 | | - if ($namespace) { |
277 | | - if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) { |
278 | | - throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s"', $namespace)); |
279 | | - } |
280 | | - |
281 | | - return substr($namespace, 34); |
282 | | - } |
283 | | - } |
284 | | - |
285 | | - // Falls back to v1.2 |
286 | | - return '1.2'; |
287 | | - } |
288 | | - |
289 | 174 | private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array |
290 | 175 | { |
291 | 176 | $notes = array(); |
|
0 commit comments