Subir todo el proyecto incluyendo vendor y dependencias
This commit is contained in:
5
vendor/symfony/deprecation-contracts/CHANGELOG.md
vendored
Executable file
5
vendor/symfony/deprecation-contracts/CHANGELOG.md
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
The changelog is maintained for all Symfony contracts at the following URL:
|
||||
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
|
||||
19
vendor/symfony/deprecation-contracts/LICENSE
vendored
Executable file
19
vendor/symfony/deprecation-contracts/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
26
vendor/symfony/deprecation-contracts/README.md
vendored
Executable file
26
vendor/symfony/deprecation-contracts/README.md
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
Symfony Deprecation Contracts
|
||||
=============================
|
||||
|
||||
A generic function and convention to trigger deprecation notices.
|
||||
|
||||
This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices.
|
||||
|
||||
By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
|
||||
the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.
|
||||
|
||||
The function requires at least 3 arguments:
|
||||
- the name of the Composer package that is triggering the deprecation
|
||||
- the version of the package that introduced the deprecation
|
||||
- the message of the deprecation
|
||||
- more arguments can be provided: they will be inserted in the message using `printf()` formatting
|
||||
|
||||
Example:
|
||||
```php
|
||||
trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');
|
||||
```
|
||||
|
||||
This will generate the following message:
|
||||
`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.`
|
||||
|
||||
While not recommended, the deprecation notices can be completely ignored by declaring an empty
|
||||
`function trigger_deprecation() {}` in your application.
|
||||
35
vendor/symfony/deprecation-contracts/composer.json
vendored
Executable file
35
vendor/symfony/deprecation-contracts/composer.json
vendored
Executable file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"type": "library",
|
||||
"description": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.php"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.6-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
}
|
||||
}
|
||||
27
vendor/symfony/deprecation-contracts/function.php
vendored
Executable file
27
vendor/symfony/deprecation-contracts/function.php
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (!function_exists('trigger_deprecation')) {
|
||||
/**
|
||||
* Triggers a silenced deprecation notice.
|
||||
*
|
||||
* @param string $package The name of the Composer package that is triggering the deprecation
|
||||
* @param string $version The version of the package that introduced the deprecation
|
||||
* @param string $message The message of the deprecation
|
||||
* @param mixed ...$args Values to insert in the message using printf() formatting
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void
|
||||
{
|
||||
@trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
96
vendor/symfony/options-resolver/CHANGELOG.md
vendored
Executable file
96
vendor/symfony/options-resolver/CHANGELOG.md
vendored
Executable file
@@ -0,0 +1,96 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
6.4
|
||||
---
|
||||
|
||||
* Improve message with full path on invalid type in nested option
|
||||
|
||||
6.3
|
||||
---
|
||||
|
||||
* Add `OptionsResolver::setIgnoreUndefined()` and `OptionConfigurator::ignoreUndefined()` to ignore not defined options while resolving
|
||||
|
||||
6.0
|
||||
---
|
||||
|
||||
* Remove `OptionsResolverIntrospector::getDeprecationMessage()`
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Add prototype definition for nested options
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
||||
* added fluent configuration of options using `OptionResolver::define()`
|
||||
* added `setInfo()` and `getInfo()` methods
|
||||
* updated the signature of method `OptionsResolver::setDeprecated()` to `OptionsResolver::setDeprecation(string $option, string $package, string $version, $message)`
|
||||
* deprecated `OptionsResolverIntrospector::getDeprecationMessage()`, use `OptionsResolverIntrospector::getDeprecation()` instead
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* added argument `$triggerDeprecation` to `OptionsResolver::offsetGet()`
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added `OptionsResolver::addNormalizer` method
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* added support for nested options definition
|
||||
* added `setDeprecated` and `isDeprecated` methods
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance
|
||||
* added array of types support in allowed types (e.g int[])
|
||||
|
||||
2.6.0
|
||||
-----
|
||||
|
||||
* deprecated OptionsResolverInterface
|
||||
* [BC BREAK] removed "array" type hint from OptionsResolverInterface methods
|
||||
setRequired(), setAllowedValues(), addAllowedValues(), setAllowedTypes() and
|
||||
addAllowedTypes()
|
||||
* added OptionsResolver::setDefault()
|
||||
* added OptionsResolver::hasDefault()
|
||||
* added OptionsResolver::setNormalizer()
|
||||
* added OptionsResolver::isRequired()
|
||||
* added OptionsResolver::getRequiredOptions()
|
||||
* added OptionsResolver::isMissing()
|
||||
* added OptionsResolver::getMissingOptions()
|
||||
* added OptionsResolver::setDefined()
|
||||
* added OptionsResolver::isDefined()
|
||||
* added OptionsResolver::getDefinedOptions()
|
||||
* added OptionsResolver::remove()
|
||||
* added OptionsResolver::clear()
|
||||
* deprecated OptionsResolver::replaceDefaults()
|
||||
* deprecated OptionsResolver::setOptional() in favor of setDefined()
|
||||
* deprecated OptionsResolver::isKnown() in favor of isDefined()
|
||||
* [BC BREAK] OptionsResolver::isRequired() returns true now if a required
|
||||
option has a default value set
|
||||
* [BC BREAK] merged Options into OptionsResolver and turned Options into an
|
||||
interface
|
||||
* deprecated Options::overload() (now in OptionsResolver)
|
||||
* deprecated Options::set() (now in OptionsResolver)
|
||||
* deprecated Options::get() (now in OptionsResolver)
|
||||
* deprecated Options::has() (now in OptionsResolver)
|
||||
* deprecated Options::replace() (now in OptionsResolver)
|
||||
* [BC BREAK] Options::get() (now in OptionsResolver) can only be used within
|
||||
lazy option/normalizer closures now
|
||||
* [BC BREAK] removed Traversable interface from Options since using within
|
||||
lazy option/normalizer closures resulted in exceptions
|
||||
* [BC BREAK] removed Options::all() since using within lazy option/normalizer
|
||||
closures resulted in exceptions
|
||||
* [BC BREAK] OptionDefinitionException now extends LogicException instead of
|
||||
RuntimeException
|
||||
* [BC BREAK] normalizers are not executed anymore for unset options
|
||||
* normalizers are executed after validating the options now
|
||||
* [BC BREAK] an UndefinedOptionsException is now thrown instead of an
|
||||
InvalidOptionsException when non-existing options are passed
|
||||
104
vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php
vendored
Executable file
104
vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php
vendored
Executable file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Debug;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Exception\NoConfigurationException;
|
||||
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class OptionsResolverIntrospector
|
||||
{
|
||||
private \Closure $get;
|
||||
|
||||
public function __construct(OptionsResolver $optionsResolver)
|
||||
{
|
||||
$this->get = \Closure::bind(function ($property, $option, $message) {
|
||||
/** @var OptionsResolver $this */
|
||||
if (!$this->isDefined($option)) {
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist.', $option));
|
||||
}
|
||||
|
||||
if (!\array_key_exists($option, $this->{$property})) {
|
||||
throw new NoConfigurationException($message);
|
||||
}
|
||||
|
||||
return $this->{$property}[$option];
|
||||
}, $optionsResolver, $optionsResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoConfigurationException on no configured value
|
||||
*/
|
||||
public function getDefault(string $option): mixed
|
||||
{
|
||||
return ($this->get)('defaults', $option, \sprintf('No default value was set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure[]
|
||||
*
|
||||
* @throws NoConfigurationException on no configured closures
|
||||
*/
|
||||
public function getLazyClosures(string $option): array
|
||||
{
|
||||
return ($this->get)('lazy', $option, \sprintf('No lazy closures were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*
|
||||
* @throws NoConfigurationException on no configured types
|
||||
*/
|
||||
public function getAllowedTypes(string $option): array
|
||||
{
|
||||
return ($this->get)('allowedTypes', $option, \sprintf('No allowed types were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*
|
||||
* @throws NoConfigurationException on no configured values
|
||||
*/
|
||||
public function getAllowedValues(string $option): array
|
||||
{
|
||||
return ($this->get)('allowedValues', $option, \sprintf('No allowed values were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoConfigurationException on no configured normalizer
|
||||
*/
|
||||
public function getNormalizer(string $option): \Closure
|
||||
{
|
||||
return current($this->getNormalizers($option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoConfigurationException when no normalizer is configured
|
||||
*/
|
||||
public function getNormalizers(string $option): array
|
||||
{
|
||||
return ($this->get)('normalizers', $option, \sprintf('No normalizer was set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NoConfigurationException on no configured deprecation
|
||||
*/
|
||||
public function getDeprecation(string $option): array
|
||||
{
|
||||
return ($this->get)('deprecated', $option, \sprintf('No deprecation was set for the "%s" option.', $option));
|
||||
}
|
||||
}
|
||||
22
vendor/symfony/options-resolver/Exception/AccessException.php
vendored
Executable file
22
vendor/symfony/options-resolver/Exception/AccessException.php
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to read an option outside of or write it inside of
|
||||
* {@link \Symfony\Component\OptionsResolver\Options::resolve()}.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class AccessException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/options-resolver/Exception/ExceptionInterface.php
vendored
Executable file
21
vendor/symfony/options-resolver/Exception/ExceptionInterface.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Marker interface for all exceptions thrown by the OptionsResolver component.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/options-resolver/Exception/InvalidArgumentException.php
vendored
Executable file
21
vendor/symfony/options-resolver/Exception/InvalidArgumentException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when an argument is invalid.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
23
vendor/symfony/options-resolver/Exception/InvalidOptionsException.php
vendored
Executable file
23
vendor/symfony/options-resolver/Exception/InvalidOptionsException.php
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when the value of an option does not match its validation rules.
|
||||
*
|
||||
* You should make sure a valid value is passed to the option.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class InvalidOptionsException extends InvalidArgumentException
|
||||
{
|
||||
}
|
||||
23
vendor/symfony/options-resolver/Exception/MissingOptionsException.php
vendored
Executable file
23
vendor/symfony/options-resolver/Exception/MissingOptionsException.php
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a required option is missing.
|
||||
*
|
||||
* Add the option to the passed options array.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class MissingOptionsException extends InvalidArgumentException
|
||||
{
|
||||
}
|
||||
26
vendor/symfony/options-resolver/Exception/NoConfigurationException.php
vendored
Executable file
26
vendor/symfony/options-resolver/Exception/NoConfigurationException.php
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
|
||||
|
||||
/**
|
||||
* Thrown when trying to introspect an option definition property
|
||||
* for which no value was configured inside the OptionsResolver instance.
|
||||
*
|
||||
* @see OptionsResolverIntrospector
|
||||
*
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class NoConfigurationException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
26
vendor/symfony/options-resolver/Exception/NoSuchOptionException.php
vendored
Executable file
26
vendor/symfony/options-resolver/Exception/NoSuchOptionException.php
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to read an option that has no value set.
|
||||
*
|
||||
* When accessing optional options from within a lazy option or normalizer you should first
|
||||
* check whether the optional option is set. You can do this with `isset($options['optional'])`.
|
||||
* In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can
|
||||
* occur when evaluating lazy options.
|
||||
*
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*/
|
||||
class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/options-resolver/Exception/OptionDefinitionException.php
vendored
Executable file
21
vendor/symfony/options-resolver/Exception/OptionDefinitionException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when two lazy options have a cyclic dependency.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class OptionDefinitionException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
24
vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php
vendored
Executable file
24
vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when an undefined option is passed.
|
||||
*
|
||||
* You should remove the options in question from your code or define them
|
||||
* beforehand.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class UndefinedOptionsException extends InvalidArgumentException
|
||||
{
|
||||
}
|
||||
19
vendor/symfony/options-resolver/LICENSE
vendored
Executable file
19
vendor/symfony/options-resolver/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
149
vendor/symfony/options-resolver/OptionConfigurator.php
vendored
Executable file
149
vendor/symfony/options-resolver/OptionConfigurator.php
vendored
Executable file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver;
|
||||
|
||||
use Symfony\Component\OptionsResolver\Exception\AccessException;
|
||||
|
||||
final class OptionConfigurator
|
||||
{
|
||||
private string $name;
|
||||
private OptionsResolver $resolver;
|
||||
|
||||
public function __construct(string $name, OptionsResolver $resolver)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->resolver = $resolver;
|
||||
$this->resolver->setDefined($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds allowed types for this option.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function allowedTypes(string ...$types): static
|
||||
{
|
||||
$this->resolver->setAllowedTypes($this->name, $types);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets allowed values for this option.
|
||||
*
|
||||
* @param mixed ...$values One or more acceptable values/closures
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function allowedValues(mixed ...$values): static
|
||||
{
|
||||
$this->resolver->setAllowedValues($this->name, $values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value for this option.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function default(mixed $value): static
|
||||
{
|
||||
$this->resolver->setDefault($this->name, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines an option configurator with the given name.
|
||||
*/
|
||||
public function define(string $option): self
|
||||
{
|
||||
return $this->resolver->define($option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this option as deprecated.
|
||||
*
|
||||
* @param string $package The name of the composer package that is triggering the deprecation
|
||||
* @param string $version The version of the package that introduced the deprecation
|
||||
* @param string|\Closure $message The deprecation message to use
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function deprecated(string $package, string $version, string|\Closure $message = 'The option "%name%" is deprecated.'): static
|
||||
{
|
||||
$this->resolver->setDeprecated($this->name, $package, $version, $message);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the normalizer for this option.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function normalize(\Closure $normalizer): static
|
||||
{
|
||||
$this->resolver->setNormalizer($this->name, $normalizer);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this option as required.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function required(): static
|
||||
{
|
||||
$this->resolver->setRequired($this->name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an info message for an option.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
*/
|
||||
public function info(string $info): static
|
||||
{
|
||||
$this->resolver->setInfo($this->name, $info);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether ignore undefined options.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function ignoreUndefined(bool $ignore = true): static
|
||||
{
|
||||
$this->resolver->setIgnoreUndefined($ignore);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
22
vendor/symfony/options-resolver/Options.php
vendored
Executable file
22
vendor/symfony/options-resolver/Options.php
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\OptionsResolver;
|
||||
|
||||
/**
|
||||
* Contains resolved option values.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
* @author Tobias Schultze <http://tobion.de>
|
||||
*/
|
||||
interface Options extends \ArrayAccess, \Countable
|
||||
{
|
||||
}
|
||||
1317
vendor/symfony/options-resolver/OptionsResolver.php
vendored
Executable file
1317
vendor/symfony/options-resolver/OptionsResolver.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
15
vendor/symfony/options-resolver/README.md
vendored
Executable file
15
vendor/symfony/options-resolver/README.md
vendored
Executable file
@@ -0,0 +1,15 @@
|
||||
OptionsResolver Component
|
||||
=========================
|
||||
|
||||
The OptionsResolver component is `array_replace` on steroids. It allows you to
|
||||
create an options system with required options, defaults, validation (type,
|
||||
value), normalization and more.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Documentation](https://symfony.com/doc/current/components/options_resolver.html)
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||
29
vendor/symfony/options-resolver/composer.json
vendored
Executable file
29
vendor/symfony/options-resolver/composer.json
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"type": "library",
|
||||
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||
"keywords": ["options", "config", "configuration"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/deprecation-contracts": "^2.5|^3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\OptionsResolver\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
232
vendor/symfony/polyfill-ctype/Ctype.php
vendored
Executable file
232
vendor/symfony/polyfill-ctype/Ctype.php
vendored
Executable file
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Ctype;
|
||||
|
||||
/**
|
||||
* Ctype implementation through regex.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Gert de Pagter <BackEndTea@gmail.com>
|
||||
*/
|
||||
final class Ctype
|
||||
{
|
||||
/**
|
||||
* Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-alnum
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_alnum($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is a letter, FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-alpha
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_alpha($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-cntrl
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_cntrl($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-digit
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_digit($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-graph
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_graph($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is a lowercase letter.
|
||||
*
|
||||
* @see https://php.net/ctype-lower
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_lower($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
|
||||
*
|
||||
* @see https://php.net/ctype-print
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_print($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-punct
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_punct($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
|
||||
*
|
||||
* @see https://php.net/ctype-space
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_space($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is an uppercase letter.
|
||||
*
|
||||
* @see https://php.net/ctype-upper
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_upper($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
|
||||
*
|
||||
* @see https://php.net/ctype-xdigit
|
||||
*
|
||||
* @param mixed $text
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ctype_xdigit($text)
|
||||
{
|
||||
$text = self::convert_int_to_char_for_ctype($text, __FUNCTION__);
|
||||
|
||||
return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts integers to their char versions according to normal ctype behaviour, if needed.
|
||||
*
|
||||
* If an integer between -128 and 255 inclusive is provided,
|
||||
* it is interpreted as the ASCII value of a single character
|
||||
* (negative values have 256 added in order to allow characters in the Extended ASCII range).
|
||||
* Any other integer is interpreted as a string containing the decimal digits of the integer.
|
||||
*
|
||||
* @param mixed $int
|
||||
* @param string $function
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function convert_int_to_char_for_ctype($int, $function)
|
||||
{
|
||||
if (!\is_int($int)) {
|
||||
return $int;
|
||||
}
|
||||
|
||||
if ($int < -128 || $int > 255) {
|
||||
return (string) $int;
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID >= 80100) {
|
||||
@trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($int < 0) {
|
||||
$int += 256;
|
||||
}
|
||||
|
||||
return \chr($int);
|
||||
}
|
||||
}
|
||||
19
vendor/symfony/polyfill-ctype/LICENSE
vendored
Executable file
19
vendor/symfony/polyfill-ctype/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2018-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
12
vendor/symfony/polyfill-ctype/README.md
vendored
Executable file
12
vendor/symfony/polyfill-ctype/README.md
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
Symfony Polyfill / Ctype
|
||||
========================
|
||||
|
||||
This component provides `ctype_*` functions to users who run php versions without the ctype extension.
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
50
vendor/symfony/polyfill-ctype/bootstrap.php
vendored
Executable file
50
vendor/symfony/polyfill-ctype/bootstrap.php
vendored
Executable file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Ctype as p;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
return require __DIR__.'/bootstrap80.php';
|
||||
}
|
||||
|
||||
if (!function_exists('ctype_alnum')) {
|
||||
function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
|
||||
}
|
||||
if (!function_exists('ctype_alpha')) {
|
||||
function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
|
||||
}
|
||||
if (!function_exists('ctype_cntrl')) {
|
||||
function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
|
||||
}
|
||||
if (!function_exists('ctype_digit')) {
|
||||
function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
|
||||
}
|
||||
if (!function_exists('ctype_graph')) {
|
||||
function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
|
||||
}
|
||||
if (!function_exists('ctype_lower')) {
|
||||
function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
|
||||
}
|
||||
if (!function_exists('ctype_print')) {
|
||||
function ctype_print($text) { return p\Ctype::ctype_print($text); }
|
||||
}
|
||||
if (!function_exists('ctype_punct')) {
|
||||
function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
|
||||
}
|
||||
if (!function_exists('ctype_space')) {
|
||||
function ctype_space($text) { return p\Ctype::ctype_space($text); }
|
||||
}
|
||||
if (!function_exists('ctype_upper')) {
|
||||
function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
|
||||
}
|
||||
if (!function_exists('ctype_xdigit')) {
|
||||
function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
|
||||
}
|
||||
46
vendor/symfony/polyfill-ctype/bootstrap80.php
vendored
Executable file
46
vendor/symfony/polyfill-ctype/bootstrap80.php
vendored
Executable file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Ctype as p;
|
||||
|
||||
if (!function_exists('ctype_alnum')) {
|
||||
function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
|
||||
}
|
||||
if (!function_exists('ctype_alpha')) {
|
||||
function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
|
||||
}
|
||||
if (!function_exists('ctype_cntrl')) {
|
||||
function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
|
||||
}
|
||||
if (!function_exists('ctype_digit')) {
|
||||
function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
|
||||
}
|
||||
if (!function_exists('ctype_graph')) {
|
||||
function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
|
||||
}
|
||||
if (!function_exists('ctype_lower')) {
|
||||
function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
|
||||
}
|
||||
if (!function_exists('ctype_print')) {
|
||||
function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
|
||||
}
|
||||
if (!function_exists('ctype_punct')) {
|
||||
function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
|
||||
}
|
||||
if (!function_exists('ctype_space')) {
|
||||
function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
|
||||
}
|
||||
if (!function_exists('ctype_upper')) {
|
||||
function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
|
||||
}
|
||||
if (!function_exists('ctype_xdigit')) {
|
||||
function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
|
||||
}
|
||||
38
vendor/symfony/polyfill-ctype/composer.json
vendored
Executable file
38
vendor/symfony/polyfill-ctype/composer.json
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"type": "library",
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"keywords": ["polyfill", "compatibility", "portable", "ctype"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ctype": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
|
||||
"files": [ "bootstrap.php" ]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/symfony/polyfill-mbstring/LICENSE
vendored
Executable file
19
vendor/symfony/polyfill-mbstring/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
1045
vendor/symfony/polyfill-mbstring/Mbstring.php
vendored
Executable file
1045
vendor/symfony/polyfill-mbstring/Mbstring.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
13
vendor/symfony/polyfill-mbstring/README.md
vendored
Executable file
13
vendor/symfony/polyfill-mbstring/README.md
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
Symfony Polyfill / Mbstring
|
||||
===========================
|
||||
|
||||
This component provides a partial, native PHP implementation for the
|
||||
[Mbstring](https://php.net/mbstring) extension.
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
119
vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php
vendored
Executable file
119
vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php
vendored
Executable file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'İ' => 'i̇',
|
||||
'µ' => 'μ',
|
||||
'ſ' => 's',
|
||||
'ͅ' => 'ι',
|
||||
'ς' => 'σ',
|
||||
'ϐ' => 'β',
|
||||
'ϑ' => 'θ',
|
||||
'ϕ' => 'φ',
|
||||
'ϖ' => 'π',
|
||||
'ϰ' => 'κ',
|
||||
'ϱ' => 'ρ',
|
||||
'ϵ' => 'ε',
|
||||
'ẛ' => 'ṡ',
|
||||
'ι' => 'ι',
|
||||
'ß' => 'ss',
|
||||
'ʼn' => 'ʼn',
|
||||
'ǰ' => 'ǰ',
|
||||
'ΐ' => 'ΐ',
|
||||
'ΰ' => 'ΰ',
|
||||
'և' => 'եւ',
|
||||
'ẖ' => 'ẖ',
|
||||
'ẗ' => 'ẗ',
|
||||
'ẘ' => 'ẘ',
|
||||
'ẙ' => 'ẙ',
|
||||
'ẚ' => 'aʾ',
|
||||
'ẞ' => 'ss',
|
||||
'ὐ' => 'ὐ',
|
||||
'ὒ' => 'ὒ',
|
||||
'ὔ' => 'ὔ',
|
||||
'ὖ' => 'ὖ',
|
||||
'ᾀ' => 'ἀι',
|
||||
'ᾁ' => 'ἁι',
|
||||
'ᾂ' => 'ἂι',
|
||||
'ᾃ' => 'ἃι',
|
||||
'ᾄ' => 'ἄι',
|
||||
'ᾅ' => 'ἅι',
|
||||
'ᾆ' => 'ἆι',
|
||||
'ᾇ' => 'ἇι',
|
||||
'ᾈ' => 'ἀι',
|
||||
'ᾉ' => 'ἁι',
|
||||
'ᾊ' => 'ἂι',
|
||||
'ᾋ' => 'ἃι',
|
||||
'ᾌ' => 'ἄι',
|
||||
'ᾍ' => 'ἅι',
|
||||
'ᾎ' => 'ἆι',
|
||||
'ᾏ' => 'ἇι',
|
||||
'ᾐ' => 'ἠι',
|
||||
'ᾑ' => 'ἡι',
|
||||
'ᾒ' => 'ἢι',
|
||||
'ᾓ' => 'ἣι',
|
||||
'ᾔ' => 'ἤι',
|
||||
'ᾕ' => 'ἥι',
|
||||
'ᾖ' => 'ἦι',
|
||||
'ᾗ' => 'ἧι',
|
||||
'ᾘ' => 'ἠι',
|
||||
'ᾙ' => 'ἡι',
|
||||
'ᾚ' => 'ἢι',
|
||||
'ᾛ' => 'ἣι',
|
||||
'ᾜ' => 'ἤι',
|
||||
'ᾝ' => 'ἥι',
|
||||
'ᾞ' => 'ἦι',
|
||||
'ᾟ' => 'ἧι',
|
||||
'ᾠ' => 'ὠι',
|
||||
'ᾡ' => 'ὡι',
|
||||
'ᾢ' => 'ὢι',
|
||||
'ᾣ' => 'ὣι',
|
||||
'ᾤ' => 'ὤι',
|
||||
'ᾥ' => 'ὥι',
|
||||
'ᾦ' => 'ὦι',
|
||||
'ᾧ' => 'ὧι',
|
||||
'ᾨ' => 'ὠι',
|
||||
'ᾩ' => 'ὡι',
|
||||
'ᾪ' => 'ὢι',
|
||||
'ᾫ' => 'ὣι',
|
||||
'ᾬ' => 'ὤι',
|
||||
'ᾭ' => 'ὥι',
|
||||
'ᾮ' => 'ὦι',
|
||||
'ᾯ' => 'ὧι',
|
||||
'ᾲ' => 'ὰι',
|
||||
'ᾳ' => 'αι',
|
||||
'ᾴ' => 'άι',
|
||||
'ᾶ' => 'ᾶ',
|
||||
'ᾷ' => 'ᾶι',
|
||||
'ᾼ' => 'αι',
|
||||
'ῂ' => 'ὴι',
|
||||
'ῃ' => 'ηι',
|
||||
'ῄ' => 'ήι',
|
||||
'ῆ' => 'ῆ',
|
||||
'ῇ' => 'ῆι',
|
||||
'ῌ' => 'ηι',
|
||||
'ῒ' => 'ῒ',
|
||||
'ῖ' => 'ῖ',
|
||||
'ῗ' => 'ῗ',
|
||||
'ῢ' => 'ῢ',
|
||||
'ῤ' => 'ῤ',
|
||||
'ῦ' => 'ῦ',
|
||||
'ῧ' => 'ῧ',
|
||||
'ῲ' => 'ὼι',
|
||||
'ῳ' => 'ωι',
|
||||
'ῴ' => 'ώι',
|
||||
'ῶ' => 'ῶ',
|
||||
'ῷ' => 'ῶι',
|
||||
'ῼ' => 'ωι',
|
||||
'ff' => 'ff',
|
||||
'fi' => 'fi',
|
||||
'fl' => 'fl',
|
||||
'ffi' => 'ffi',
|
||||
'ffl' => 'ffl',
|
||||
'ſt' => 'st',
|
||||
'st' => 'st',
|
||||
'ﬓ' => 'մն',
|
||||
'ﬔ' => 'մե',
|
||||
'ﬕ' => 'մի',
|
||||
'ﬖ' => 'վն',
|
||||
'ﬗ' => 'մխ',
|
||||
];
|
||||
1397
vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
vendored
Executable file
1397
vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
5
vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
vendored
Executable file
5
vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php
vendored
Executable file
File diff suppressed because one or more lines are too long
1489
vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
vendored
Executable file
1489
vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
172
vendor/symfony/polyfill-mbstring/bootstrap.php
vendored
Executable file
172
vendor/symfony/polyfill-mbstring/bootstrap.php
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Mbstring as p;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
return require __DIR__.'/bootstrap80.php';
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_encoding')) {
|
||||
function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); }
|
||||
}
|
||||
if (!function_exists('mb_decode_mimeheader')) {
|
||||
function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); }
|
||||
}
|
||||
if (!function_exists('mb_encode_mimeheader')) {
|
||||
function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); }
|
||||
}
|
||||
if (!function_exists('mb_decode_numericentity')) {
|
||||
function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_encode_numericentity')) {
|
||||
function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); }
|
||||
}
|
||||
if (!function_exists('mb_convert_case')) {
|
||||
function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_internal_encoding')) {
|
||||
function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_language')) {
|
||||
function mb_language($language = null) { return p\Mbstring::mb_language($language); }
|
||||
}
|
||||
if (!function_exists('mb_list_encodings')) {
|
||||
function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
|
||||
}
|
||||
if (!function_exists('mb_encoding_aliases')) {
|
||||
function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_check_encoding')) {
|
||||
function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); }
|
||||
}
|
||||
if (!function_exists('mb_detect_order')) {
|
||||
function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_parse_str')) {
|
||||
function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; }
|
||||
}
|
||||
if (!function_exists('mb_strlen')) {
|
||||
function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strpos')) {
|
||||
function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtolower')) {
|
||||
function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtoupper')) {
|
||||
function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substitute_character')) {
|
||||
function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); }
|
||||
}
|
||||
if (!function_exists('mb_substr')) {
|
||||
function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stripos')) {
|
||||
function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stristr')) {
|
||||
function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrchr')) {
|
||||
function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrichr')) {
|
||||
function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strripos')) {
|
||||
function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrpos')) {
|
||||
function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strstr')) {
|
||||
function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_get_info')) {
|
||||
function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
|
||||
}
|
||||
if (!function_exists('mb_http_output')) {
|
||||
function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strwidth')) {
|
||||
function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substr_count')) {
|
||||
function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_output_handler')) {
|
||||
function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); }
|
||||
}
|
||||
if (!function_exists('mb_http_input')) {
|
||||
function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_variables')) {
|
||||
function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ord')) {
|
||||
function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_chr')) {
|
||||
function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_scrub')) {
|
||||
function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_str_split')) {
|
||||
function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_str_pad')) {
|
||||
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ucfirst')) {
|
||||
function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_lcfirst')) {
|
||||
function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_trim')) {
|
||||
function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ltrim')) {
|
||||
function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_rtrim')) {
|
||||
function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
|
||||
if (extension_loaded('mbstring')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('MB_CASE_UPPER')) {
|
||||
define('MB_CASE_UPPER', 0);
|
||||
}
|
||||
if (!defined('MB_CASE_LOWER')) {
|
||||
define('MB_CASE_LOWER', 1);
|
||||
}
|
||||
if (!defined('MB_CASE_TITLE')) {
|
||||
define('MB_CASE_TITLE', 2);
|
||||
}
|
||||
167
vendor/symfony/polyfill-mbstring/bootstrap80.php
vendored
Executable file
167
vendor/symfony/polyfill-mbstring/bootstrap80.php
vendored
Executable file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Mbstring as p;
|
||||
|
||||
if (!function_exists('mb_convert_encoding')) {
|
||||
function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); }
|
||||
}
|
||||
if (!function_exists('mb_decode_mimeheader')) {
|
||||
function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); }
|
||||
}
|
||||
if (!function_exists('mb_encode_mimeheader')) {
|
||||
function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); }
|
||||
}
|
||||
if (!function_exists('mb_decode_numericentity')) {
|
||||
function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_encode_numericentity')) {
|
||||
function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); }
|
||||
}
|
||||
if (!function_exists('mb_convert_case')) {
|
||||
function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_internal_encoding')) {
|
||||
function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_language')) {
|
||||
function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); }
|
||||
}
|
||||
if (!function_exists('mb_list_encodings')) {
|
||||
function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); }
|
||||
}
|
||||
if (!function_exists('mb_encoding_aliases')) {
|
||||
function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_check_encoding')) {
|
||||
function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); }
|
||||
}
|
||||
if (!function_exists('mb_detect_order')) {
|
||||
function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_parse_str')) {
|
||||
function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; }
|
||||
}
|
||||
if (!function_exists('mb_strlen')) {
|
||||
function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strpos')) {
|
||||
function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtolower')) {
|
||||
function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strtoupper')) {
|
||||
function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substitute_character')) {
|
||||
function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); }
|
||||
}
|
||||
if (!function_exists('mb_substr')) {
|
||||
function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stripos')) {
|
||||
function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_stristr')) {
|
||||
function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrchr')) {
|
||||
function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrichr')) {
|
||||
function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strripos')) {
|
||||
function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strrpos')) {
|
||||
function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strstr')) {
|
||||
function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_get_info')) {
|
||||
function mb_get_info(?string $type = 'all'): array|string|int|false|null { return p\Mbstring::mb_get_info((string) $type); }
|
||||
}
|
||||
if (!function_exists('mb_http_output')) {
|
||||
function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); }
|
||||
}
|
||||
if (!function_exists('mb_strwidth')) {
|
||||
function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_substr_count')) {
|
||||
function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_output_handler')) {
|
||||
function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); }
|
||||
}
|
||||
if (!function_exists('mb_http_input')) {
|
||||
function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_convert_variables')) {
|
||||
function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ord')) {
|
||||
function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_chr')) {
|
||||
function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_scrub')) {
|
||||
function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); }
|
||||
}
|
||||
if (!function_exists('mb_str_split')) {
|
||||
function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_str_pad')) {
|
||||
function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ucfirst')) {
|
||||
function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_lcfirst')) {
|
||||
function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_trim')) {
|
||||
function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_ltrim')) {
|
||||
function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
if (!function_exists('mb_rtrim')) {
|
||||
function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); }
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('MB_CASE_UPPER')) {
|
||||
define('MB_CASE_UPPER', 0);
|
||||
}
|
||||
if (!defined('MB_CASE_LOWER')) {
|
||||
define('MB_CASE_LOWER', 1);
|
||||
}
|
||||
if (!defined('MB_CASE_TITLE')) {
|
||||
define('MB_CASE_TITLE', 2);
|
||||
}
|
||||
39
vendor/symfony/polyfill-mbstring/composer.json
vendored
Executable file
39
vendor/symfony/polyfill-mbstring/composer.json
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"type": "library",
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"ext-iconv": "*"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
|
||||
"files": [ "bootstrap.php" ]
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/symfony/polyfill-php80/LICENSE
vendored
Executable file
19
vendor/symfony/polyfill-php80/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
115
vendor/symfony/polyfill-php80/Php80.php
vendored
Executable file
115
vendor/symfony/polyfill-php80/Php80.php
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Php80;
|
||||
|
||||
/**
|
||||
* @author Ion Bazan <ion.bazan@gmail.com>
|
||||
* @author Nico Oelgart <nicoswd@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Php80
|
||||
{
|
||||
public static function fdiv(float $dividend, float $divisor): float
|
||||
{
|
||||
return @($dividend / $divisor);
|
||||
}
|
||||
|
||||
public static function get_debug_type($value): string
|
||||
{
|
||||
switch (true) {
|
||||
case null === $value: return 'null';
|
||||
case \is_bool($value): return 'bool';
|
||||
case \is_string($value): return 'string';
|
||||
case \is_array($value): return 'array';
|
||||
case \is_int($value): return 'int';
|
||||
case \is_float($value): return 'float';
|
||||
case \is_object($value): break;
|
||||
case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class';
|
||||
default:
|
||||
if (null === $type = @get_resource_type($value)) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
if ('Unknown' === $type) {
|
||||
$type = 'closed';
|
||||
}
|
||||
|
||||
return "resource ($type)";
|
||||
}
|
||||
|
||||
$class = \get_class($value);
|
||||
|
||||
if (false === strpos($class, '@')) {
|
||||
return $class;
|
||||
}
|
||||
|
||||
return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous';
|
||||
}
|
||||
|
||||
public static function get_resource_id($res): int
|
||||
{
|
||||
if (!\is_resource($res) && null === @get_resource_type($res)) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
|
||||
}
|
||||
|
||||
return (int) $res;
|
||||
}
|
||||
|
||||
public static function preg_last_error_msg(): string
|
||||
{
|
||||
switch (preg_last_error()) {
|
||||
case \PREG_INTERNAL_ERROR:
|
||||
return 'Internal error';
|
||||
case \PREG_BAD_UTF8_ERROR:
|
||||
return 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||
case \PREG_BAD_UTF8_OFFSET_ERROR:
|
||||
return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
|
||||
case \PREG_BACKTRACK_LIMIT_ERROR:
|
||||
return 'Backtrack limit exhausted';
|
||||
case \PREG_RECURSION_LIMIT_ERROR:
|
||||
return 'Recursion limit exhausted';
|
||||
case \PREG_JIT_STACKLIMIT_ERROR:
|
||||
return 'JIT stack limit exhausted';
|
||||
case \PREG_NO_ERROR:
|
||||
return 'No error';
|
||||
default:
|
||||
return 'Unknown error';
|
||||
}
|
||||
}
|
||||
|
||||
public static function str_contains(string $haystack, string $needle): bool
|
||||
{
|
||||
return '' === $needle || false !== strpos($haystack, $needle);
|
||||
}
|
||||
|
||||
public static function str_starts_with(string $haystack, string $needle): bool
|
||||
{
|
||||
return 0 === strncmp($haystack, $needle, \strlen($needle));
|
||||
}
|
||||
|
||||
public static function str_ends_with(string $haystack, string $needle): bool
|
||||
{
|
||||
if ('' === $needle || $needle === $haystack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ('' === $haystack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$needleLength = \strlen($needle);
|
||||
|
||||
return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);
|
||||
}
|
||||
}
|
||||
106
vendor/symfony/polyfill-php80/PhpToken.php
vendored
Executable file
106
vendor/symfony/polyfill-php80/PhpToken.php
vendored
Executable file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Polyfill\Php80;
|
||||
|
||||
/**
|
||||
* @author Fedonyuk Anton <info@ensostudio.ru>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class PhpToken implements \Stringable
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $text;
|
||||
|
||||
/**
|
||||
* @var -1|positive-int
|
||||
*/
|
||||
public $line;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $pos;
|
||||
|
||||
/**
|
||||
* @param -1|positive-int $line
|
||||
*/
|
||||
public function __construct(int $id, string $text, int $line = -1, int $position = -1)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->text = $text;
|
||||
$this->line = $line;
|
||||
$this->pos = $position;
|
||||
}
|
||||
|
||||
public function getTokenName(): ?string
|
||||
{
|
||||
if ('UNKNOWN' === $name = token_name($this->id)) {
|
||||
$name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string|array $kind
|
||||
*/
|
||||
public function is($kind): bool
|
||||
{
|
||||
foreach ((array) $kind as $value) {
|
||||
if (\in_array($value, [$this->id, $this->text], true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isIgnorable(): bool
|
||||
{
|
||||
return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return (string) $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<static>
|
||||
*/
|
||||
public static function tokenize(string $code, int $flags = 0): array
|
||||
{
|
||||
$line = 1;
|
||||
$position = 0;
|
||||
$tokens = token_get_all($code, $flags);
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (\is_string($token)) {
|
||||
$id = \ord($token);
|
||||
$text = $token;
|
||||
} else {
|
||||
[$id, $text, $line] = $token;
|
||||
}
|
||||
$tokens[$index] = new static($id, $text, $line, $position);
|
||||
$position += \strlen($text);
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
25
vendor/symfony/polyfill-php80/README.md
vendored
Executable file
25
vendor/symfony/polyfill-php80/README.md
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
Symfony Polyfill / Php80
|
||||
========================
|
||||
|
||||
This component provides features added to PHP 8.0 core:
|
||||
|
||||
- [`Stringable`](https://php.net/stringable) interface
|
||||
- [`fdiv`](https://php.net/fdiv)
|
||||
- [`ValueError`](https://php.net/valueerror) class
|
||||
- [`UnhandledMatchError`](https://php.net/unhandledmatcherror) class
|
||||
- `FILTER_VALIDATE_BOOL` constant
|
||||
- [`get_debug_type`](https://php.net/get_debug_type)
|
||||
- [`PhpToken`](https://php.net/phptoken) class
|
||||
- [`preg_last_error_msg`](https://php.net/preg_last_error_msg)
|
||||
- [`str_contains`](https://php.net/str_contains)
|
||||
- [`str_starts_with`](https://php.net/str_starts_with)
|
||||
- [`str_ends_with`](https://php.net/str_ends_with)
|
||||
- [`get_resource_id`](https://php.net/get_resource_id)
|
||||
|
||||
More information can be found in the
|
||||
[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This library is released under the [MIT license](LICENSE).
|
||||
31
vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
vendored
Executable file
31
vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)]
|
||||
final class Attribute
|
||||
{
|
||||
public const TARGET_CLASS = 1;
|
||||
public const TARGET_FUNCTION = 2;
|
||||
public const TARGET_METHOD = 4;
|
||||
public const TARGET_PROPERTY = 8;
|
||||
public const TARGET_CLASS_CONSTANT = 16;
|
||||
public const TARGET_PARAMETER = 32;
|
||||
public const TARGET_ALL = 63;
|
||||
public const IS_REPEATABLE = 64;
|
||||
|
||||
/** @var int */
|
||||
public $flags;
|
||||
|
||||
public function __construct(int $flags = self::TARGET_ALL)
|
||||
{
|
||||
$this->flags = $flags;
|
||||
}
|
||||
}
|
||||
16
vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php
vendored
Executable file
16
vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (\PHP_VERSION_ID < 80000 && extension_loaded('tokenizer')) {
|
||||
class PhpToken extends Symfony\Polyfill\Php80\PhpToken
|
||||
{
|
||||
}
|
||||
}
|
||||
20
vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
vendored
Executable file
20
vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
interface Stringable
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
||||
}
|
||||
16
vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
vendored
Executable file
16
vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
class UnhandledMatchError extends Error
|
||||
{
|
||||
}
|
||||
}
|
||||
16
vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
vendored
Executable file
16
vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php
vendored
Executable file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (\PHP_VERSION_ID < 80000) {
|
||||
class ValueError extends Error
|
||||
{
|
||||
}
|
||||
}
|
||||
42
vendor/symfony/polyfill-php80/bootstrap.php
vendored
Executable file
42
vendor/symfony/polyfill-php80/bootstrap.php
vendored
Executable file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Symfony\Polyfill\Php80 as p;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
|
||||
define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
if (!function_exists('fdiv')) {
|
||||
function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); }
|
||||
}
|
||||
if (!function_exists('preg_last_error_msg')) {
|
||||
function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
|
||||
}
|
||||
if (!function_exists('str_contains')) {
|
||||
function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
|
||||
}
|
||||
if (!function_exists('str_starts_with')) {
|
||||
function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
|
||||
}
|
||||
if (!function_exists('str_ends_with')) {
|
||||
function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
|
||||
}
|
||||
if (!function_exists('get_debug_type')) {
|
||||
function get_debug_type($value): string { return p\Php80::get_debug_type($value); }
|
||||
}
|
||||
if (!function_exists('get_resource_id')) {
|
||||
function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); }
|
||||
}
|
||||
37
vendor/symfony/polyfill-php80/composer.json
vendored
Executable file
37
vendor/symfony/polyfill-php80/composer.json
vendored
Executable file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"type": "library",
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"keywords": ["polyfill", "shim", "compatibility", "portable"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
|
||||
"files": [ "bootstrap.php" ],
|
||||
"classmap": [ "Resources/stubs" ]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
vendor/symfony/translation-contracts/CHANGELOG.md
vendored
Executable file
5
vendor/symfony/translation-contracts/CHANGELOG.md
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
The changelog is maintained for all Symfony contracts at the following URL:
|
||||
https://github.com/symfony/contracts/blob/main/CHANGELOG.md
|
||||
19
vendor/symfony/translation-contracts/LICENSE
vendored
Executable file
19
vendor/symfony/translation-contracts/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2018-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
29
vendor/symfony/translation-contracts/LocaleAwareInterface.php
vendored
Executable file
29
vendor/symfony/translation-contracts/LocaleAwareInterface.php
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Contracts\Translation;
|
||||
|
||||
interface LocaleAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets the current locale.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException If the locale contains invalid characters
|
||||
*/
|
||||
public function setLocale(string $locale);
|
||||
|
||||
/**
|
||||
* Returns the current locale.
|
||||
*/
|
||||
public function getLocale(): string;
|
||||
}
|
||||
9
vendor/symfony/translation-contracts/README.md
vendored
Executable file
9
vendor/symfony/translation-contracts/README.md
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
Symfony Translation Contracts
|
||||
=============================
|
||||
|
||||
A set of abstractions extracted out of the Symfony components.
|
||||
|
||||
Can be used to build on semantics that the Symfony components proved useful and
|
||||
that already have battle tested implementations.
|
||||
|
||||
See https://github.com/symfony/contracts/blob/main/README.md for more information.
|
||||
398
vendor/symfony/translation-contracts/Test/TranslatorTest.php
vendored
Executable file
398
vendor/symfony/translation-contracts/Test/TranslatorTest.php
vendored
Executable file
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Contracts\Translation\Test;
|
||||
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||
|
||||
/**
|
||||
* Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
|
||||
* and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms.
|
||||
*
|
||||
* See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
|
||||
* The mozilla code is also interesting to check for.
|
||||
*
|
||||
* As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
|
||||
*
|
||||
* The goal to cover all languages is to far fetched so this test case is smaller.
|
||||
*
|
||||
* @author Clemens Tolboom clemens@build2be.nl
|
||||
*/
|
||||
class TranslatorTest extends TestCase
|
||||
{
|
||||
private string $defaultLocale;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->defaultLocale = \Locale::getDefault();
|
||||
\Locale::setDefault('en');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
\Locale::setDefault($this->defaultLocale);
|
||||
}
|
||||
|
||||
public function getTranslator(): TranslatorInterface
|
||||
{
|
||||
return new class implements TranslatorInterface {
|
||||
use TranslatorTrait;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTransTests
|
||||
*/
|
||||
#[DataProvider('getTransTests')]
|
||||
public function testTrans($expected, $id, $parameters)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, $parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceTests
|
||||
*/
|
||||
#[DataProvider('getTransChoiceTests')]
|
||||
public function testTransChoiceWithExplicitLocale($expected, $id, $number)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*
|
||||
* @dataProvider getTransChoiceTests
|
||||
*/
|
||||
#[DataProvider('getTransChoiceTests')]
|
||||
#[RequiresPhpExtension('intl')]
|
||||
public function testTransChoiceWithDefaultLocale($expected, $id, $number)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTransChoiceTests
|
||||
*/
|
||||
#[DataProvider('getTransChoiceTests')]
|
||||
public function testTransChoiceWithEnUsPosix($expected, $id, $number)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
$translator->setLocale('en_US_POSIX');
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number]));
|
||||
}
|
||||
|
||||
public function testGetSetLocale()
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals('en', $translator->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
#[RequiresPhpExtension('intl')]
|
||||
public function testGetLocaleReturnsDefaultLocaleIfNotSet()
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
\Locale::setDefault('pt_BR');
|
||||
$this->assertEquals('pt_BR', $translator->getLocale());
|
||||
|
||||
\Locale::setDefault('en');
|
||||
$this->assertEquals('en', $translator->getLocale());
|
||||
}
|
||||
|
||||
public static function getTransTests()
|
||||
{
|
||||
return [
|
||||
['Symfony is great!', 'Symfony is great!', []],
|
||||
['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']],
|
||||
];
|
||||
}
|
||||
|
||||
public static function getTransChoiceTests()
|
||||
{
|
||||
return [
|
||||
['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
|
||||
['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
|
||||
['There are 0 apples', 'There is 1 apple|There are %count% apples', 0],
|
||||
['There is 1 apple', 'There is 1 apple|There are %count% apples', 1],
|
||||
['There are 10 apples', 'There is 1 apple|There are %count% apples', 10],
|
||||
// custom validation messages may be coded with a fixed value
|
||||
['There are 2 apples', 'There are 2 apples', 2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getInterval
|
||||
*/
|
||||
#[DataProvider('getInterval')]
|
||||
public function testInterval($expected, $number, $interval)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number]));
|
||||
}
|
||||
|
||||
public static function getInterval()
|
||||
{
|
||||
return [
|
||||
['foo', 3, '{1,2, 3 ,4}'],
|
||||
['bar', 10, '{1,2, 3 ,4}'],
|
||||
['bar', 3, '[1,2]'],
|
||||
['foo', 1, '[1,2]'],
|
||||
['foo', 2, '[1,2]'],
|
||||
['bar', 1, ']1,2['],
|
||||
['bar', 2, ']1,2['],
|
||||
['foo', log(0), '[-Inf,2['],
|
||||
['foo', -log(0), '[-2,+Inf]'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getChooseTests
|
||||
*/
|
||||
#[DataProvider('getChooseTests')]
|
||||
public function testChoose($expected, $id, $number, $locale = null)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale));
|
||||
}
|
||||
|
||||
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNonMatchingMessages
|
||||
*/
|
||||
#[DataProvider('getNonMatchingMessages')]
|
||||
public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
|
||||
{
|
||||
$translator = $this->getTranslator();
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
|
||||
$translator->trans($id, ['%count%' => $number]);
|
||||
}
|
||||
|
||||
public static function getNonMatchingMessages()
|
||||
{
|
||||
return [
|
||||
['{0} There are no apples|{1} There is one apple', 2],
|
||||
['{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
['{1} There is one apple|]2,Inf] There are %count% apples', 2],
|
||||
['{0} There are no apples|There is one apple', 2],
|
||||
];
|
||||
}
|
||||
|
||||
public static function getChooseTests()
|
||||
{
|
||||
return [
|
||||
['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
|
||||
['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1],
|
||||
|
||||
['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
|
||||
['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10],
|
||||
['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10],
|
||||
|
||||
['There are 0 apples', 'There is one apple|There are %count% apples', 0],
|
||||
['There is one apple', 'There is one apple|There are %count% apples', 1],
|
||||
['There are 10 apples', 'There is one apple|There are %count% apples', 10],
|
||||
|
||||
['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0],
|
||||
['There is one apple', 'one: There is one apple|more: There are %count% apples', 1],
|
||||
['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10],
|
||||
|
||||
['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0],
|
||||
['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1],
|
||||
['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10],
|
||||
|
||||
['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0],
|
||||
['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1],
|
||||
|
||||
// Indexed only tests which are Gettext PoFile* compatible strings.
|
||||
['There are 0 apples', 'There is one apple|There are %count% apples', 0],
|
||||
['There is one apple', 'There is one apple|There are %count% apples', 1],
|
||||
['There are 2 apples', 'There is one apple|There are %count% apples', 2],
|
||||
|
||||
// Tests for float numbers
|
||||
['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7],
|
||||
['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1],
|
||||
['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7],
|
||||
['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
|
||||
['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0],
|
||||
['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0],
|
||||
|
||||
// Test texts with new-lines
|
||||
// with double-quotes and \n in id & double-quotes and actual newlines in text
|
||||
["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a
|
||||
new-line in it. Selector = 0.|{1}This is a text with a
|
||||
new-line in it. Selector = 1.|[1,Inf]This is a text with a
|
||||
new-line in it. Selector > 1.', 0],
|
||||
// with double-quotes and \n in id and single-quotes and actual newlines in text
|
||||
["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a
|
||||
new-line in it. Selector = 0.|{1}This is a text with a
|
||||
new-line in it. Selector = 1.|[1,Inf]This is a text with a
|
||||
new-line in it. Selector > 1.', 1],
|
||||
["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a
|
||||
new-line in it. Selector = 0.|{1}This is a text with a
|
||||
new-line in it. Selector = 1.|[1,Inf]This is a text with a
|
||||
new-line in it. Selector > 1.', 5],
|
||||
// with double-quotes and id split across lines
|
||||
['This is a text with a
|
||||
new-line in it. Selector = 1.', '{0}This is a text with a
|
||||
new-line in it. Selector = 0.|{1}This is a text with a
|
||||
new-line in it. Selector = 1.|[1,Inf]This is a text with a
|
||||
new-line in it. Selector > 1.', 1],
|
||||
// with single-quotes and id split across lines
|
||||
['This is a text with a
|
||||
new-line in it. Selector > 1.', '{0}This is a text with a
|
||||
new-line in it. Selector = 0.|{1}This is a text with a
|
||||
new-line in it. Selector = 1.|[1,Inf]This is a text with a
|
||||
new-line in it. Selector > 1.', 5],
|
||||
// with single-quotes and \n in text
|
||||
['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0],
|
||||
// with double-quotes and id split across lines
|
||||
["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1],
|
||||
// escape pipe
|
||||
['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0],
|
||||
// Empty plural set (2 plural forms) from a .PO file
|
||||
['', '|', 1],
|
||||
// Empty plural set (3 plural forms) from a .PO file
|
||||
['', '||', 1],
|
||||
|
||||
// Floating values
|
||||
['1.5 liters', '%count% liter|%count% liters', 1.5],
|
||||
['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'],
|
||||
|
||||
// Negative values
|
||||
['-1 degree', '%count% degree|%count% degrees', -1],
|
||||
['-1 degré', '%count% degré|%count% degrés', -1],
|
||||
['-1.5 degrees', '%count% degree|%count% degrees', -1.5],
|
||||
['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'],
|
||||
['-2 degrees', '%count% degree|%count% degrees', -2],
|
||||
['-2 degrés', '%count% degré|%count% degrés', -2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider failingLangcodes
|
||||
*/
|
||||
#[DataProvider('failingLangcodes')]
|
||||
public function testFailedLangcodes($nplural, $langCodes)
|
||||
{
|
||||
$matrix = $this->generateTestData($langCodes);
|
||||
$this->validateMatrix($nplural, $matrix, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider successLangcodes
|
||||
*/
|
||||
#[DataProvider('successLangcodes')]
|
||||
public function testLangcodes($nplural, $langCodes)
|
||||
{
|
||||
$matrix = $this->generateTestData($langCodes);
|
||||
$this->validateMatrix($nplural, $matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* This array should contain all currently known langcodes.
|
||||
*
|
||||
* As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
|
||||
*/
|
||||
public static function successLangcodes(): array
|
||||
{
|
||||
return [
|
||||
['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']],
|
||||
['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM', 'en_US_POSIX']],
|
||||
['3', ['be', 'bs', 'cs', 'hr']],
|
||||
['4', ['cy', 'mt', 'sl']],
|
||||
['6', ['ar']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This array should be at least empty within the near future.
|
||||
*
|
||||
* This both depends on a complete list trying to add above as understanding
|
||||
* the plural rules of the current failing languages.
|
||||
*
|
||||
* @return array with nplural together with langcodes
|
||||
*/
|
||||
public static function failingLangcodes(): array
|
||||
{
|
||||
return [
|
||||
['1', ['fa']],
|
||||
['2', ['jbo']],
|
||||
['3', ['cbs']],
|
||||
['4', ['gd', 'kw']],
|
||||
['5', ['ga']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* We validate only on the plural coverage. Thus the real rules is not tested.
|
||||
*
|
||||
* @param string $nplural Plural expected
|
||||
* @param array $matrix Containing langcodes and their plural index values
|
||||
*/
|
||||
protected function validateMatrix(string $nplural, array $matrix, bool $expectSuccess = true)
|
||||
{
|
||||
foreach ($matrix as $langCode => $data) {
|
||||
$indexes = array_flip($data);
|
||||
if ($expectSuccess) {
|
||||
$this->assertCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
|
||||
} else {
|
||||
$this->assertNotCount($nplural, $indexes, "Langcode '$langCode' has '$nplural' plural forms.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function generateTestData($langCodes)
|
||||
{
|
||||
$translator = new class {
|
||||
use TranslatorTrait {
|
||||
getPluralizationRule as public;
|
||||
}
|
||||
};
|
||||
|
||||
$matrix = [];
|
||||
foreach ($langCodes as $langCode) {
|
||||
for ($count = 0; $count < 200; ++$count) {
|
||||
$plural = $translator->getPluralizationRule($count, $langCode);
|
||||
$matrix[$langCode][$count] = $plural;
|
||||
}
|
||||
}
|
||||
|
||||
return $matrix;
|
||||
}
|
||||
}
|
||||
20
vendor/symfony/translation-contracts/TranslatableInterface.php
vendored
Executable file
20
vendor/symfony/translation-contracts/TranslatableInterface.php
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Contracts\Translation;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
interface TranslatableInterface
|
||||
{
|
||||
public function trans(TranslatorInterface $translator, ?string $locale = null): string;
|
||||
}
|
||||
68
vendor/symfony/translation-contracts/TranslatorInterface.php
vendored
Executable file
68
vendor/symfony/translation-contracts/TranslatorInterface.php
vendored
Executable file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Contracts\Translation;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface TranslatorInterface
|
||||
{
|
||||
/**
|
||||
* Translates the given message.
|
||||
*
|
||||
* When a number is provided as a parameter named "%count%", the message is parsed for plural
|
||||
* forms and a translation is chosen according to this number using the following rules:
|
||||
*
|
||||
* Given a message with different plural translations separated by a
|
||||
* pipe (|), this method returns the correct portion of the message based
|
||||
* on the given number, locale and the pluralization rules in the message
|
||||
* itself.
|
||||
*
|
||||
* The message supports two different types of pluralization rules:
|
||||
*
|
||||
* interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
|
||||
* indexed: There is one apple|There are %count% apples
|
||||
*
|
||||
* The indexed solution can also contain labels (e.g. one: There is one apple).
|
||||
* This is purely for making the translations more clear - it does not
|
||||
* affect the functionality.
|
||||
*
|
||||
* The two methods can also be mixed:
|
||||
* {0} There are no apples|one: There is one apple|more: There are %count% apples
|
||||
*
|
||||
* An interval can represent a finite set of numbers:
|
||||
* {1,2,3,4}
|
||||
*
|
||||
* An interval can represent numbers between two numbers:
|
||||
* [1, +Inf]
|
||||
* ]-1,2[
|
||||
*
|
||||
* The left delimiter can be [ (inclusive) or ] (exclusive).
|
||||
* The right delimiter can be [ (exclusive) or ] (inclusive).
|
||||
* Beside numbers, you can use -Inf and +Inf for the infinite.
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/ISO_31-11
|
||||
*
|
||||
* @param string $id The message id (may also be an object that can be cast to string)
|
||||
* @param array $parameters An array of parameters for the message
|
||||
* @param string|null $domain The domain for the message or null to use the default
|
||||
* @param string|null $locale The locale or null to use the default
|
||||
*
|
||||
* @throws \InvalidArgumentException If the locale contains invalid characters
|
||||
*/
|
||||
public function trans(string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string;
|
||||
|
||||
/**
|
||||
* Returns the default locale.
|
||||
*/
|
||||
public function getLocale(): string;
|
||||
}
|
||||
225
vendor/symfony/translation-contracts/TranslatorTrait.php
vendored
Executable file
225
vendor/symfony/translation-contracts/TranslatorTrait.php
vendored
Executable file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Contracts\Translation;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* A trait to help implement TranslatorInterface and LocaleAwareInterface.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
trait TranslatorTrait
|
||||
{
|
||||
private ?string $locale = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setLocale(string $locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
public function getLocale(): string
|
||||
{
|
||||
return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
|
||||
}
|
||||
|
||||
public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
|
||||
{
|
||||
if (null === $id || '' === $id) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
|
||||
return strtr($id, $parameters);
|
||||
}
|
||||
|
||||
$number = (float) $parameters['%count%'];
|
||||
$locale = $locale ?: $this->getLocale();
|
||||
|
||||
$parts = [];
|
||||
if (preg_match('/^\|++$/', $id)) {
|
||||
$parts = explode('|', $id);
|
||||
} elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
|
||||
$parts = $matches[0];
|
||||
}
|
||||
|
||||
$intervalRegexp = <<<'EOF'
|
||||
/^(?P<interval>
|
||||
({\s*
|
||||
(\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
|
||||
\s*})
|
||||
|
||||
|
|
||||
|
||||
(?P<left_delimiter>[\[\]])
|
||||
\s*
|
||||
(?P<left>-Inf|\-?\d+(\.\d+)?)
|
||||
\s*,\s*
|
||||
(?P<right>\+?Inf|\-?\d+(\.\d+)?)
|
||||
\s*
|
||||
(?P<right_delimiter>[\[\]])
|
||||
)\s*(?P<message>.*?)$/xs
|
||||
EOF;
|
||||
|
||||
$standardRules = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = trim(str_replace('||', '|', $part));
|
||||
|
||||
// try to match an explicit rule, then fallback to the standard ones
|
||||
if (preg_match($intervalRegexp, $part, $matches)) {
|
||||
if ($matches[2]) {
|
||||
foreach (explode(',', $matches[3]) as $n) {
|
||||
if ($number == $n) {
|
||||
return strtr($matches['message'], $parameters);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left'];
|
||||
$rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF;
|
||||
|
||||
if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
|
||||
&& (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
|
||||
) {
|
||||
return strtr($matches['message'], $parameters);
|
||||
}
|
||||
}
|
||||
} elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
|
||||
$standardRules[] = $matches[1];
|
||||
} else {
|
||||
$standardRules[] = $part;
|
||||
}
|
||||
}
|
||||
|
||||
$position = $this->getPluralizationRule($number, $locale);
|
||||
|
||||
if (!isset($standardRules[$position])) {
|
||||
// when there's exactly one rule given, and that rule is a standard
|
||||
// rule, use this rule
|
||||
if (1 === \count($parts) && isset($standardRules[0])) {
|
||||
return strtr($standardRules[0], $parameters);
|
||||
}
|
||||
|
||||
$message = \sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
|
||||
|
||||
if (class_exists(InvalidArgumentException::class)) {
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
return strtr($standardRules[$position], $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plural position to use for the given locale and number.
|
||||
*
|
||||
* The plural rules are derived from code of the Zend Framework (2010-09-25),
|
||||
* which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
|
||||
* Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
*/
|
||||
private function getPluralizationRule(float $number, string $locale): int
|
||||
{
|
||||
$number = abs($number);
|
||||
|
||||
return match ('pt_BR' !== $locale && 'en_US_POSIX' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
|
||||
'af',
|
||||
'bn',
|
||||
'bg',
|
||||
'ca',
|
||||
'da',
|
||||
'de',
|
||||
'el',
|
||||
'en',
|
||||
'en_US_POSIX',
|
||||
'eo',
|
||||
'es',
|
||||
'et',
|
||||
'eu',
|
||||
'fa',
|
||||
'fi',
|
||||
'fo',
|
||||
'fur',
|
||||
'fy',
|
||||
'gl',
|
||||
'gu',
|
||||
'ha',
|
||||
'he',
|
||||
'hu',
|
||||
'is',
|
||||
'it',
|
||||
'ku',
|
||||
'lb',
|
||||
'ml',
|
||||
'mn',
|
||||
'mr',
|
||||
'nah',
|
||||
'nb',
|
||||
'ne',
|
||||
'nl',
|
||||
'nn',
|
||||
'no',
|
||||
'oc',
|
||||
'om',
|
||||
'or',
|
||||
'pa',
|
||||
'pap',
|
||||
'ps',
|
||||
'pt',
|
||||
'so',
|
||||
'sq',
|
||||
'sv',
|
||||
'sw',
|
||||
'ta',
|
||||
'te',
|
||||
'tk',
|
||||
'ur',
|
||||
'zu' => (1 == $number) ? 0 : 1,
|
||||
'am',
|
||||
'bh',
|
||||
'fil',
|
||||
'fr',
|
||||
'gun',
|
||||
'hi',
|
||||
'hy',
|
||||
'ln',
|
||||
'mg',
|
||||
'nso',
|
||||
'pt_BR',
|
||||
'ti',
|
||||
'wa' => ($number < 2) ? 0 : 1,
|
||||
'be',
|
||||
'bs',
|
||||
'hr',
|
||||
'ru',
|
||||
'sh',
|
||||
'sr',
|
||||
'uk' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
|
||||
'cs',
|
||||
'sk' => (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2),
|
||||
'ga' => (1 == $number) ? 0 : ((2 == $number) ? 1 : 2),
|
||||
'lt' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
|
||||
'sl' => (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)),
|
||||
'mk' => (1 == $number % 10) ? 0 : 1,
|
||||
'mt' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)),
|
||||
'lv' => (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2),
|
||||
'pl' => (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2),
|
||||
'cy' => (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)),
|
||||
'ro' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2),
|
||||
'ar' => (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))),
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
37
vendor/symfony/translation-contracts/composer.json
vendored
Executable file
37
vendor/symfony/translation-contracts/composer.json
vendored
Executable file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "symfony/translation-contracts",
|
||||
"type": "library",
|
||||
"description": "Generic abstractions related to translation",
|
||||
"keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Contracts\\Translation\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Test/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.6-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
}
|
||||
}
|
||||
205
vendor/symfony/translation/CHANGELOG.md
vendored
Executable file
205
vendor/symfony/translation/CHANGELOG.md
vendored
Executable file
@@ -0,0 +1,205 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
6.4
|
||||
---
|
||||
|
||||
* Give current locale to `LocaleSwitcher::runWithLocale()`'s callback
|
||||
* Add `--as-tree` option to `translation:pull` command to write YAML messages as a tree-like structure
|
||||
* [BC BREAK] Add argument `$buildDir` to `DataCollectorTranslator::warmUp()`
|
||||
* Add `DataCollectorTranslatorPass` and `LoggingTranslatorPass` (moved from `FrameworkBundle`)
|
||||
* Add `PhraseTranslationProvider`
|
||||
|
||||
6.2.7
|
||||
-----
|
||||
|
||||
* [BC BREAK] The following data providers for `ProviderFactoryTestCase` are now static:
|
||||
`supportsProvider()`, `createProvider()`, `unsupportedSchemeProvider()`and `incompleteDsnProvider()`
|
||||
* [BC BREAK] `ProviderTestCase::toStringProvider()` is now static
|
||||
|
||||
6.2
|
||||
---
|
||||
|
||||
* Deprecate `PhpStringTokenParser`
|
||||
* Deprecate `PhpExtractor` in favor of `PhpAstExtractor`
|
||||
* Add `PhpAstExtractor` (requires [nikic/php-parser](https://github.com/nikic/php-parser) to be installed)
|
||||
|
||||
6.1
|
||||
---
|
||||
|
||||
* Parameters implementing `TranslatableInterface` are processed
|
||||
* Add the file extension to the `XliffFileDumper` constructor
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Add `github` format & autodetection to render errors as annotations when
|
||||
running the XLIFF linter command in a Github Actions environment.
|
||||
* Translation providers are not experimental anymore
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Add `translation:pull` and `translation:push` commands to manage translations with third-party providers
|
||||
* Add `TranslatorBagInterface::getCatalogues` method
|
||||
* Add support to load XLIFF string in `XliffFileLoader`
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
* added support for calling `trans` with ICU formatted messages
|
||||
* added `PseudoLocalizationTranslator`
|
||||
* added `TranslatableMessage` objects that represent a message that can be translated
|
||||
* added the `t()` function to easily create `TranslatableMessage` objects
|
||||
* Added support for extracting messages from `TranslatableMessage` objects
|
||||
|
||||
5.1.0
|
||||
-----
|
||||
|
||||
* added support for `name` attribute on `unit` element from xliff2 to be used as a translation key instead of always the `source` element
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* removed support for using `null` as the locale in `Translator`
|
||||
* removed `TranslatorInterface`
|
||||
* removed `MessageSelector`
|
||||
* removed `ChoiceMessageFormatterInterface`
|
||||
* removed `PluralizationRule`
|
||||
* removed `Interval`
|
||||
* removed `transChoice()` methods, use the trans() method instead with a %count% parameter
|
||||
* removed `FileDumper::setBackup()` and `TranslationWriter::disableBackup()`
|
||||
* removed `MessageFormatter::choiceFormat()`
|
||||
* added argument `$filename` to `PhpExtractor::parseTokens()`
|
||||
* removed support for implicit STDIN usage in the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* deprecated support for using `null` as the locale in `Translator`
|
||||
* deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
|
||||
* Marked the `TranslationDataCollector` class as `@final`.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* Improved Xliff 1.2 loader to load the original file's metadata
|
||||
* Added `TranslatorPathsPass`
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* Started using ICU parent locales as fallback locales.
|
||||
* allow using the ICU message format using domains with the "+intl-icu" suffix
|
||||
* deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter
|
||||
* deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
||||
* deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
|
||||
* Added `IntlFormatter` and `IntlFormatterInterface`
|
||||
* added support for multiple files and directories in `XliffLintCommand`
|
||||
* Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
* The `FileDumper::setBackup()` method is deprecated.
|
||||
* The `TranslationWriter::disableBackup()` method is deprecated.
|
||||
* The `XliffFileDumper` will write "name" on the "unit" node when dumping XLIFF 2.0.
|
||||
|
||||
4.0.0
|
||||
-----
|
||||
|
||||
* removed the backup feature of the `FileDumper` class
|
||||
* removed `TranslationWriter::writeTranslations()` method
|
||||
* removed support for passing `MessageSelector` instances to the constructor of the `Translator` class
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* Added `TranslationDumperPass`
|
||||
* Added `TranslationExtractorPass`
|
||||
* Added `TranslatorPass`
|
||||
* Added `TranslationReader` and `TranslationReaderInterface`
|
||||
* Added `<notes>` section to the Xliff 2.0 dumper.
|
||||
* Improved Xliff 2.0 loader to load `<notes>` section.
|
||||
* Added `TranslationWriterInterface`
|
||||
* Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
|
||||
* added support for adding custom message formatter and decoupling the default one.
|
||||
* Added `PhpExtractor`
|
||||
* Added `PhpStringTokenParser`
|
||||
|
||||
3.2.0
|
||||
-----
|
||||
|
||||
* Added support for escaping `|` in plural translations with double pipe.
|
||||
|
||||
3.1.0
|
||||
-----
|
||||
|
||||
* Deprecated the backup feature of the file dumper classes.
|
||||
|
||||
3.0.0
|
||||
-----
|
||||
|
||||
* removed `FileDumper::format()` method.
|
||||
* Changed the visibility of the locale property in `Translator` from protected to private.
|
||||
|
||||
2.8.0
|
||||
-----
|
||||
|
||||
* deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead.
|
||||
* deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead.
|
||||
* added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file.
|
||||
* added option `json_encoding` to JsonFileDumper
|
||||
* added options `as_tree`, `inline` to YamlFileDumper
|
||||
* added support for XLIFF 2.0.
|
||||
* added support for XLIFF target and tool attributes.
|
||||
* added message parameters to DataCollectorTranslator.
|
||||
* [DEPRECATION] The `DiffOperation` class has been deprecated and
|
||||
will be removed in Symfony 3.0, since its operation has nothing to do with 'diff',
|
||||
so the class name is misleading. The `TargetOperation` class should be used for
|
||||
this use-case instead.
|
||||
|
||||
2.7.0
|
||||
-----
|
||||
|
||||
* added DataCollectorTranslator for collecting the translated messages.
|
||||
|
||||
2.6.0
|
||||
-----
|
||||
|
||||
* added possibility to cache catalogues
|
||||
* added TranslatorBagInterface
|
||||
* added LoggingTranslator
|
||||
* added Translator::getMessages() for retrieving the message catalogue as an array
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* added relative file path template to the file dumpers
|
||||
* added optional backup to the file dumpers
|
||||
* changed IcuResFileDumper to extend FileDumper
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues)
|
||||
* added Translator::getFallbackLocales()
|
||||
* deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3.
|
||||
* [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now
|
||||
throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found
|
||||
and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid.
|
||||
* changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException
|
||||
(IcuDatFileLoader, IcuResFileLoader and QtFileLoader)
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added support for more than one fallback locale
|
||||
* added support for extracting translation messages from templates (Twig and PHP)
|
||||
* added dumpers for translation catalogs
|
||||
* added support for QT, gettext, and ResourceBundles
|
||||
187
vendor/symfony/translation/Catalogue/AbstractOperation.php
vendored
Executable file
187
vendor/symfony/translation/Catalogue/AbstractOperation.php
vendored
Executable file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\LogicException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Base catalogues binary operation class.
|
||||
*
|
||||
* A catalogue binary operation performs operation on
|
||||
* source (the left argument) and target (the right argument) catalogues.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
abstract class AbstractOperation implements OperationInterface
|
||||
{
|
||||
public const OBSOLETE_BATCH = 'obsolete';
|
||||
public const NEW_BATCH = 'new';
|
||||
public const ALL_BATCH = 'all';
|
||||
|
||||
protected $source;
|
||||
protected $target;
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
|
||||
*
|
||||
* The data structure of this array is as follows:
|
||||
*
|
||||
* [
|
||||
* 'domain 1' => [
|
||||
* 'all' => [...],
|
||||
* 'new' => [...],
|
||||
* 'obsolete' => [...]
|
||||
* ],
|
||||
* 'domain 2' => [
|
||||
* 'all' => [...],
|
||||
* 'new' => [...],
|
||||
* 'obsolete' => [...]
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* @var array The array that stores 'all', 'new' and 'obsolete' messages
|
||||
*/
|
||||
protected $messages;
|
||||
|
||||
private array $domains;
|
||||
|
||||
/**
|
||||
* @throws LogicException
|
||||
*/
|
||||
public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
|
||||
{
|
||||
if ($source->getLocale() !== $target->getLocale()) {
|
||||
throw new LogicException('Operated catalogues must belong to the same locale.');
|
||||
}
|
||||
|
||||
$this->source = $source;
|
||||
$this->target = $target;
|
||||
$this->result = new MessageCatalogue($source->getLocale());
|
||||
$this->messages = [];
|
||||
}
|
||||
|
||||
public function getDomains(): array
|
||||
{
|
||||
if (!isset($this->domains)) {
|
||||
$domains = [];
|
||||
foreach ([$this->source, $this->target] as $catalogue) {
|
||||
foreach ($catalogue->getDomains() as $domain) {
|
||||
$domains[$domain] = $domain;
|
||||
|
||||
if ($catalogue->all($domainIcu = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX)) {
|
||||
$domains[$domainIcu] = $domainIcu;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->domains = array_values($domains);
|
||||
}
|
||||
|
||||
return $this->domains;
|
||||
}
|
||||
|
||||
public function getMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::ALL_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::ALL_BATCH];
|
||||
}
|
||||
|
||||
public function getNewMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::NEW_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::NEW_BATCH];
|
||||
}
|
||||
|
||||
public function getObsoleteMessages(string $domain): array
|
||||
{
|
||||
if (!\in_array($domain, $this->getDomains())) {
|
||||
throw new InvalidArgumentException(\sprintf('Invalid domain: "%s".', $domain));
|
||||
}
|
||||
|
||||
if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
|
||||
return $this->messages[$domain][self::OBSOLETE_BATCH];
|
||||
}
|
||||
|
||||
public function getResult(): MessageCatalogueInterface
|
||||
{
|
||||
foreach ($this->getDomains() as $domain) {
|
||||
if (!isset($this->messages[$domain])) {
|
||||
$this->processDomain($domain);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param self::*_BATCH $batch
|
||||
*/
|
||||
public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
|
||||
{
|
||||
// If MessageFormatter class does not exists, intl domains are not supported.
|
||||
if (!class_exists(\MessageFormatter::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getDomains() as $domain) {
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
$messages = match ($batch) {
|
||||
self::OBSOLETE_BATCH => $this->getObsoleteMessages($domain),
|
||||
self::NEW_BATCH => $this->getNewMessages($domain),
|
||||
self::ALL_BATCH => $this->getMessages($domain),
|
||||
default => throw new \InvalidArgumentException(\sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH)),
|
||||
};
|
||||
|
||||
if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->getResult();
|
||||
$allIntlMessages = $result->all($intlDomain);
|
||||
$currentMessages = array_diff_key($messages, $result->all($domain));
|
||||
$result->replace($currentMessages, $domain);
|
||||
$result->replace($allIntlMessages + $messages, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs operation on source and target catalogues for the given domain and
|
||||
* stores the results.
|
||||
*
|
||||
* @param string $domain The domain which the operation will be performed for
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract protected function processDomain(string $domain);
|
||||
}
|
||||
72
vendor/symfony/translation/Catalogue/MergeOperation.php
vendored
Executable file
72
vendor/symfony/translation/Catalogue/MergeOperation.php
vendored
Executable file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Merge operation between two catalogues as follows:
|
||||
* all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
|
||||
* new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
|
||||
* obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
|
||||
* Basically, the result contains messages from both catalogues.
|
||||
*
|
||||
* @author Jean-François Simon <contact@jfsimon.fr>
|
||||
*/
|
||||
class MergeOperation extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function processDomain(string $domain)
|
||||
{
|
||||
$this->messages[$domain] = [
|
||||
'all' => [],
|
||||
'new' => [],
|
||||
'obsolete' => [],
|
||||
];
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $domain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->all($domain) as $id => $message) {
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
61
vendor/symfony/translation/Catalogue/OperationInterface.php
vendored
Executable file
61
vendor/symfony/translation/Catalogue/OperationInterface.php
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Represents an operation on catalogue(s).
|
||||
*
|
||||
* An instance of this interface performs an operation on one or more catalogues and
|
||||
* stores intermediate and final results of the operation.
|
||||
*
|
||||
* The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
|
||||
* the following results are stored:
|
||||
*
|
||||
* Messages: also called 'all', are valid messages for the given domain after the operation is performed.
|
||||
*
|
||||
* New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
|
||||
*
|
||||
* Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
|
||||
*
|
||||
* Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
|
||||
*
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
interface OperationInterface
|
||||
{
|
||||
/**
|
||||
* Returns domains affected by operation.
|
||||
*/
|
||||
public function getDomains(): array;
|
||||
|
||||
/**
|
||||
* Returns all valid messages ('all') after operation.
|
||||
*/
|
||||
public function getMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns new messages ('new') after operation.
|
||||
*/
|
||||
public function getNewMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns obsolete messages ('obsolete') after operation.
|
||||
*/
|
||||
public function getObsoleteMessages(string $domain): array;
|
||||
|
||||
/**
|
||||
* Returns resulting catalogue ('result').
|
||||
*/
|
||||
public function getResult(): MessageCatalogueInterface;
|
||||
}
|
||||
86
vendor/symfony/translation/Catalogue/TargetOperation.php
vendored
Executable file
86
vendor/symfony/translation/Catalogue/TargetOperation.php
vendored
Executable file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Catalogue;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
|
||||
/**
|
||||
* Target operation between two catalogues:
|
||||
* intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
|
||||
* all = intersection ∪ (target ∖ intersection) = target
|
||||
* new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
|
||||
* obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
|
||||
* Basically, the result contains messages from the target catalogue.
|
||||
*
|
||||
* @author Michael Lee <michael.lee@zerustech.com>
|
||||
*/
|
||||
class TargetOperation extends AbstractOperation
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function processDomain(string $domain)
|
||||
{
|
||||
$this->messages[$domain] = [
|
||||
'all' => [],
|
||||
'new' => [],
|
||||
'obsolete' => [],
|
||||
];
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $domain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $domain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->getCatalogueMetadata('', $intlDomain) ?? [] as $key => $value) {
|
||||
if (null === $this->result->getCatalogueMetadata($key, $intlDomain)) {
|
||||
$this->result->setCatalogueMetadata($key, $value, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
// For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
|
||||
// because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
|
||||
//
|
||||
// For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
|
||||
// because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
|
||||
//
|
||||
// For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
|
||||
// because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
|
||||
|
||||
foreach ($this->source->all($domain) as $id => $message) {
|
||||
if ($this->target->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
} else {
|
||||
$this->messages[$domain]['obsolete'][$id] = $message;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->target->all($domain) as $id => $message) {
|
||||
if (!$this->source->has($id, $domain)) {
|
||||
$this->messages[$domain]['all'][$id] = $message;
|
||||
$this->messages[$domain]['new'][$id] = $message;
|
||||
$d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
|
||||
$this->result->add([$id => $message], $d);
|
||||
if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
|
||||
$this->result->setMetadata($id, $keyMetadata, $d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
vendor/symfony/translation/CatalogueMetadataAwareInterface.php
vendored
Executable file
48
vendor/symfony/translation/CatalogueMetadataAwareInterface.php
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
/**
|
||||
* This interface is used to get, set, and delete metadata about the Catalogue.
|
||||
*
|
||||
* @author Hugo Alliaume <hugo@alliau.me>
|
||||
*/
|
||||
interface CatalogueMetadataAwareInterface
|
||||
{
|
||||
/**
|
||||
* Gets catalogue metadata for the given domain and key.
|
||||
*
|
||||
* Passing an empty domain will return an array with all catalogue metadata indexed by
|
||||
* domain and then by key. Passing an empty key will return an array with all
|
||||
* catalogue metadata for the given domain.
|
||||
*
|
||||
* @return mixed The value that was set or an array with the domains/keys or null
|
||||
*/
|
||||
public function getCatalogueMetadata(string $key = '', string $domain = 'messages'): mixed;
|
||||
|
||||
/**
|
||||
* Adds catalogue metadata to a message domain.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setCatalogueMetadata(string $key, mixed $value, string $domain = 'messages');
|
||||
|
||||
/**
|
||||
* Deletes catalogue metadata for the given key and domain.
|
||||
*
|
||||
* Passing an empty domain will delete all catalogue metadata. Passing an empty key will
|
||||
* delete all metadata for the given domain.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCatalogueMetadata(string $key = '', string $domain = 'messages');
|
||||
}
|
||||
184
vendor/symfony/translation/Command/TranslationPullCommand.php
vendored
Executable file
184
vendor/symfony/translation/Command/TranslationPullCommand.php
vendored
Executable file
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Translation\Catalogue\TargetOperation;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
|
||||
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
|
||||
use Symfony\Component\Translation\Writer\TranslationWriterInterface;
|
||||
|
||||
/**
|
||||
* @author Mathieu Santostefano <msantostefano@protonmail.com>
|
||||
*/
|
||||
#[AsCommand(name: 'translation:pull', description: 'Pull translations from a given provider.')]
|
||||
final class TranslationPullCommand extends Command
|
||||
{
|
||||
use TranslationTrait;
|
||||
|
||||
private TranslationProviderCollection $providerCollection;
|
||||
private TranslationWriterInterface $writer;
|
||||
private TranslationReaderInterface $reader;
|
||||
private string $defaultLocale;
|
||||
private array $transPaths;
|
||||
private array $enabledLocales;
|
||||
|
||||
public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = [])
|
||||
{
|
||||
$this->providerCollection = $providerCollection;
|
||||
$this->writer = $writer;
|
||||
$this->reader = $reader;
|
||||
$this->defaultLocale = $defaultLocale;
|
||||
$this->transPaths = $transPaths;
|
||||
$this->enabledLocales = $enabledLocales;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestArgumentValuesFor('provider')) {
|
||||
$suggestions->suggestValues($this->providerCollection->keys());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('domains')) {
|
||||
$provider = $this->providerCollection->get($input->getArgument('provider'));
|
||||
|
||||
if (method_exists($provider, 'getDomains')) {
|
||||
$suggestions->suggestValues($provider->getDomains());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('locales')) {
|
||||
$suggestions->suggestValues($this->enabledLocales);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues(['php', 'xlf', 'xlf12', 'xlf20', 'po', 'mo', 'yml', 'yaml', 'ts', 'csv', 'json', 'ini', 'res']);
|
||||
}
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$keys = $this->providerCollection->keys();
|
||||
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
|
||||
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
|
||||
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
|
||||
new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
|
||||
new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
|
||||
new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format.', 'xlf12'),
|
||||
new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Write messages as a tree-like structure. Needs --format=yaml. The given value defines the level where to switch to inline YAML'),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</> command pulls translations from the given provider. Only
|
||||
new translations are pulled, existing ones are not overwritten.
|
||||
|
||||
You can overwrite existing translations (and remove the missing ones on local side) by using the <comment>--force</> flag:
|
||||
|
||||
<info>php %command.full_name% --force provider</>
|
||||
|
||||
Full example:
|
||||
|
||||
<info>php %command.full_name% provider --force --domains=messages --domains=validators --locales=en</>
|
||||
|
||||
This command pulls all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
|
||||
Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case.
|
||||
Local translations for others domains and locales are ignored.
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$provider = $this->providerCollection->get($input->getArgument('provider'));
|
||||
$force = $input->getOption('force');
|
||||
$intlIcu = $input->getOption('intl-icu');
|
||||
$locales = $input->getOption('locales') ?: $this->enabledLocales;
|
||||
$domains = $input->getOption('domains');
|
||||
$format = $input->getOption('format');
|
||||
$asTree = (int) $input->getOption('as-tree');
|
||||
$xliffVersion = '1.2';
|
||||
|
||||
if ($intlIcu && !$force) {
|
||||
$io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.');
|
||||
}
|
||||
|
||||
switch ($format) {
|
||||
case 'xlf20': $xliffVersion = '2.0';
|
||||
// no break
|
||||
case 'xlf12': $format = 'xlf';
|
||||
}
|
||||
|
||||
$writeOptions = [
|
||||
'path' => end($this->transPaths),
|
||||
'xliff_version' => $xliffVersion,
|
||||
'default_locale' => $this->defaultLocale,
|
||||
'as_tree' => (bool) $asTree,
|
||||
'inline' => $asTree,
|
||||
];
|
||||
|
||||
if (!$domains) {
|
||||
$domains = $provider->getDomains();
|
||||
}
|
||||
|
||||
$providerTranslations = $provider->read($domains, $locales);
|
||||
|
||||
if ($force) {
|
||||
foreach ($providerTranslations->getCatalogues() as $catalogue) {
|
||||
$operation = new TargetOperation(new MessageCatalogue($catalogue->getLocale()), $catalogue);
|
||||
if ($intlIcu) {
|
||||
$operation->moveMessagesToIntlDomainsIfPossible();
|
||||
}
|
||||
$this->writer->write($operation->getResult(), $format, $writeOptions);
|
||||
}
|
||||
|
||||
$io->success(\sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
|
||||
|
||||
// Append pulled translations to local ones.
|
||||
$localTranslations->addBag($providerTranslations->diff($localTranslations));
|
||||
|
||||
foreach ($localTranslations->getCatalogues() as $catalogue) {
|
||||
$this->writer->write($catalogue, $format, $writeOptions);
|
||||
}
|
||||
|
||||
$io->success(\sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
182
vendor/symfony/translation/Command/TranslationPushCommand.php
vendored
Executable file
182
vendor/symfony/translation/Command/TranslationPushCommand.php
vendored
Executable file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Translation\Provider\FilteringProvider;
|
||||
use Symfony\Component\Translation\Provider\TranslationProviderCollection;
|
||||
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
|
||||
use Symfony\Component\Translation\TranslatorBag;
|
||||
|
||||
/**
|
||||
* @author Mathieu Santostefano <msantostefano@protonmail.com>
|
||||
*/
|
||||
#[AsCommand(name: 'translation:push', description: 'Push translations to a given provider.')]
|
||||
final class TranslationPushCommand extends Command
|
||||
{
|
||||
use TranslationTrait;
|
||||
|
||||
private TranslationProviderCollection $providers;
|
||||
private TranslationReaderInterface $reader;
|
||||
private array $transPaths;
|
||||
private array $enabledLocales;
|
||||
|
||||
public function __construct(TranslationProviderCollection $providers, TranslationReaderInterface $reader, array $transPaths = [], array $enabledLocales = [])
|
||||
{
|
||||
$this->providers = $providers;
|
||||
$this->reader = $reader;
|
||||
$this->transPaths = $transPaths;
|
||||
$this->enabledLocales = $enabledLocales;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestArgumentValuesFor('provider')) {
|
||||
$suggestions->suggestValues($this->providers->keys());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('domains')) {
|
||||
$provider = $this->providers->get($input->getArgument('provider'));
|
||||
|
||||
if ($provider && method_exists($provider, 'getDomains')) {
|
||||
$domains = $provider->getDomains();
|
||||
$suggestions->suggestValues($domains);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('locales')) {
|
||||
$suggestions->suggestValues($this->enabledLocales);
|
||||
}
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$keys = $this->providers->keys();
|
||||
$defaultProvider = 1 === \count($keys) ? $keys[0] : null;
|
||||
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
|
||||
new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
|
||||
new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
|
||||
new InputOption('domains', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
|
||||
new InputOption('locales', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
|
||||
])
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</> command pushes translations to the given provider. Only new
|
||||
translations are pushed, existing ones are not overwritten.
|
||||
|
||||
You can overwrite existing translations by using the <comment>--force</> flag:
|
||||
|
||||
<info>php %command.full_name% --force provider</>
|
||||
|
||||
You can delete provider translations which are not present locally by using the <comment>--delete-missing</> flag:
|
||||
|
||||
<info>php %command.full_name% --delete-missing provider</>
|
||||
|
||||
Full example:
|
||||
|
||||
<info>php %command.full_name% provider --force --delete-missing --domains=messages --domains=validators --locales=en</>
|
||||
|
||||
This command pushes all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
|
||||
Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case.
|
||||
Provider translations for others domains and locales are ignored.
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$provider = $this->providers->get($input->getArgument('provider'));
|
||||
|
||||
if (!$this->enabledLocales) {
|
||||
throw new InvalidArgumentException(\sprintf('You must define "framework.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
|
||||
}
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$domains = $input->getOption('domains');
|
||||
$locales = $input->getOption('locales');
|
||||
$force = $input->getOption('force');
|
||||
$deleteMissing = $input->getOption('delete-missing');
|
||||
|
||||
if (!$domains && $provider instanceof FilteringProvider) {
|
||||
$domains = $provider->getDomains();
|
||||
}
|
||||
|
||||
// Reading local translations must be done after retrieving the domains from the provider
|
||||
// in order to manage only translations from configured domains
|
||||
$localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
|
||||
|
||||
if (!$domains) {
|
||||
$domains = $this->getDomainsFromTranslatorBag($localTranslations);
|
||||
}
|
||||
|
||||
if (!$deleteMissing && $force) {
|
||||
$provider->write($localTranslations);
|
||||
|
||||
$io->success(\sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$providerTranslations = $provider->read($domains, $locales);
|
||||
|
||||
if ($deleteMissing) {
|
||||
$provider->delete($providerTranslations->diff($localTranslations));
|
||||
|
||||
$io->success(\sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
|
||||
|
||||
// Read provider translations again, after missing translations deletion,
|
||||
// to avoid push freshly deleted translations.
|
||||
$providerTranslations = $provider->read($domains, $locales);
|
||||
}
|
||||
|
||||
$translationsToWrite = $localTranslations->diff($providerTranslations);
|
||||
|
||||
if ($force) {
|
||||
$translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
|
||||
}
|
||||
|
||||
$provider->write($translationsToWrite);
|
||||
|
||||
$io->success(\sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array
|
||||
{
|
||||
$domains = [];
|
||||
|
||||
foreach ($translatorBag->getCatalogues() as $catalogue) {
|
||||
$domains += $catalogue->getDomains();
|
||||
}
|
||||
|
||||
return array_unique($domains);
|
||||
}
|
||||
}
|
||||
77
vendor/symfony/translation/Command/TranslationTrait.php
vendored
Executable file
77
vendor/symfony/translation/Command/TranslationTrait.php
vendored
Executable file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Command;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\MessageCatalogueInterface;
|
||||
use Symfony\Component\Translation\TranslatorBag;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait TranslationTrait
|
||||
{
|
||||
private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag
|
||||
{
|
||||
$bag = new TranslatorBag();
|
||||
|
||||
foreach ($locales as $locale) {
|
||||
$catalogue = new MessageCatalogue($locale);
|
||||
foreach ($transPaths as $path) {
|
||||
$this->reader->read($path, $catalogue);
|
||||
}
|
||||
|
||||
if ($domains) {
|
||||
foreach ($domains as $domain) {
|
||||
$bag->addCatalogue($this->filterCatalogue($catalogue, $domain));
|
||||
}
|
||||
} else {
|
||||
$bag->addCatalogue($catalogue);
|
||||
}
|
||||
}
|
||||
|
||||
return $bag;
|
||||
}
|
||||
|
||||
private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
|
||||
{
|
||||
$filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
|
||||
|
||||
// extract intl-icu messages only
|
||||
$intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
|
||||
if ($intlMessages = $catalogue->all($intlDomain)) {
|
||||
$filteredCatalogue->add($intlMessages, $intlDomain);
|
||||
}
|
||||
|
||||
// extract all messages and subtract intl-icu messages
|
||||
if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
|
||||
$filteredCatalogue->add($messages, $domain);
|
||||
}
|
||||
foreach ($catalogue->getResources() as $resource) {
|
||||
$filteredCatalogue->addResource($resource);
|
||||
}
|
||||
|
||||
if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
|
||||
foreach ($metadata as $k => $v) {
|
||||
$filteredCatalogue->setMetadata($k, $v, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
if ($metadata = $catalogue->getMetadata('', $domain)) {
|
||||
foreach ($metadata as $k => $v) {
|
||||
$filteredCatalogue->setMetadata($k, $v, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredCatalogue;
|
||||
}
|
||||
}
|
||||
285
vendor/symfony/translation/Command/XliffLintCommand.php
vendored
Executable file
285
vendor/symfony/translation/Command/XliffLintCommand.php
vendored
Executable file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\CI\GithubActionReporter;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Util\XliffUtils;
|
||||
|
||||
/**
|
||||
* Validates XLIFF files syntax and outputs encountered errors.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Robin Chalas <robin.chalas@gmail.com>
|
||||
* @author Javier Eguiluz <javier.eguiluz@gmail.com>
|
||||
*/
|
||||
#[AsCommand(name: 'lint:xliff', description: 'Lint an XLIFF file and outputs encountered errors')]
|
||||
class XliffLintCommand extends Command
|
||||
{
|
||||
private string $format;
|
||||
private bool $displayCorrectFiles;
|
||||
private ?\Closure $directoryIteratorProvider;
|
||||
private ?\Closure $isReadableProvider;
|
||||
private bool $requireStrictFileNames;
|
||||
|
||||
public function __construct(?string $name = null, ?callable $directoryIteratorProvider = null, ?callable $isReadableProvider = null, bool $requireStrictFileNames = true)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
||||
$this->directoryIteratorProvider = null === $directoryIteratorProvider ? null : $directoryIteratorProvider(...);
|
||||
$this->isReadableProvider = null === $isReadableProvider ? null : $isReadableProvider(...);
|
||||
$this->requireStrictFileNames = $requireStrictFileNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())))
|
||||
->setHelp(<<<EOF
|
||||
The <info>%command.name%</info> command lints an XLIFF file and outputs to STDOUT
|
||||
the first encountered syntax error.
|
||||
|
||||
You can validates XLIFF contents passed from STDIN:
|
||||
|
||||
<info>cat filename | php %command.full_name% -</info>
|
||||
|
||||
You can also validate the syntax of a file:
|
||||
|
||||
<info>php %command.full_name% filename</info>
|
||||
|
||||
Or of a whole directory:
|
||||
|
||||
<info>php %command.full_name% dirname</info>
|
||||
<info>php %command.full_name% dirname --format=json</info>
|
||||
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$filenames = (array) $input->getArgument('filename');
|
||||
$this->format = $input->getOption('format') ?? (GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt');
|
||||
$this->displayCorrectFiles = $output->isVerbose();
|
||||
|
||||
if (['-'] === $filenames) {
|
||||
return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]);
|
||||
}
|
||||
|
||||
if (!$filenames) {
|
||||
throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
|
||||
}
|
||||
|
||||
$filesInfo = [];
|
||||
foreach ($filenames as $filename) {
|
||||
if (!$this->isReadable($filename)) {
|
||||
throw new RuntimeException(\sprintf('File or directory "%s" is not readable.', $filename));
|
||||
}
|
||||
|
||||
foreach ($this->getFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate(file_get_contents($file), $file);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->display($io, $filesInfo);
|
||||
}
|
||||
|
||||
private function validate(string $content, ?string $file = null): array
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
// Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input
|
||||
if ('' === trim($content)) {
|
||||
return ['file' => $file, 'valid' => true];
|
||||
}
|
||||
|
||||
$internal = libxml_use_internal_errors(true);
|
||||
|
||||
$document = new \DOMDocument();
|
||||
$document->loadXML($content);
|
||||
|
||||
if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
|
||||
$normalizedLocalePattern = \sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
|
||||
// strict file names require translation files to be named '____.locale.xlf'
|
||||
// otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
|
||||
// also, the regexp matching must be case-insensitive, as defined for 'target-language' values
|
||||
// http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language
|
||||
$expectedFilenamePattern = $this->requireStrictFileNames ? \sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : \sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);
|
||||
|
||||
if (0 === preg_match($expectedFilenamePattern, basename($file))) {
|
||||
$errors[] = [
|
||||
'line' => -1,
|
||||
'column' => -1,
|
||||
'message' => \sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XliffUtils::validateSchema($document) as $xmlError) {
|
||||
$errors[] = [
|
||||
'line' => $xmlError['line'],
|
||||
'column' => $xmlError['column'],
|
||||
'message' => $xmlError['message'],
|
||||
];
|
||||
}
|
||||
|
||||
libxml_clear_errors();
|
||||
libxml_use_internal_errors($internal);
|
||||
|
||||
return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors];
|
||||
}
|
||||
|
||||
private function display(SymfonyStyle $io, array $files): int
|
||||
{
|
||||
return match ($this->format) {
|
||||
'txt' => $this->displayTxt($io, $files),
|
||||
'json' => $this->displayJson($io, $files),
|
||||
'github' => $this->displayTxt($io, $files, true),
|
||||
default => throw new InvalidArgumentException(\sprintf('Supported formats are "%s".', implode('", "', $this->getAvailableFormatOptions()))),
|
||||
};
|
||||
}
|
||||
|
||||
private function displayTxt(SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false): int
|
||||
{
|
||||
$countFiles = \count($filesInfo);
|
||||
$erroredFiles = 0;
|
||||
$githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($io) : null;
|
||||
|
||||
foreach ($filesInfo as $info) {
|
||||
if ($info['valid'] && $this->displayCorrectFiles) {
|
||||
$io->comment('<info>OK</info>'.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
|
||||
} elseif (!$info['valid']) {
|
||||
++$erroredFiles;
|
||||
$io->text('<error> ERROR </error>'.($info['file'] ? \sprintf(' in %s', $info['file']) : ''));
|
||||
$io->listing(array_map(function ($error) use ($info, $githubReporter) {
|
||||
// general document errors have a '-1' line number
|
||||
$line = -1 === $error['line'] ? null : $error['line'];
|
||||
|
||||
$githubReporter?->error($error['message'], $info['file'], $line, null !== $line ? $error['column'] : null);
|
||||
|
||||
return null === $line ? $error['message'] : \sprintf('Line %d, Column %d: %s', $line, $error['column'], $error['message']);
|
||||
}, $info['messages']));
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === $erroredFiles) {
|
||||
$io->success(\sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
|
||||
} else {
|
||||
$io->warning(\sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
|
||||
}
|
||||
|
||||
return min($erroredFiles, 1);
|
||||
}
|
||||
|
||||
private function displayJson(SymfonyStyle $io, array $filesInfo): int
|
||||
{
|
||||
$errors = 0;
|
||||
|
||||
array_walk($filesInfo, function (&$v) use (&$errors) {
|
||||
$v['file'] = (string) $v['file'];
|
||||
if (!$v['valid']) {
|
||||
++$errors;
|
||||
}
|
||||
});
|
||||
|
||||
$io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
|
||||
|
||||
return min($errors, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<\SplFileInfo>
|
||||
*/
|
||||
private function getFiles(string $fileOrDirectory): iterable
|
||||
{
|
||||
if (is_file($fileOrDirectory)) {
|
||||
yield new \SplFileInfo($fileOrDirectory);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
|
||||
if (!\in_array($file->getExtension(), ['xlf', 'xliff'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<\SplFileInfo>
|
||||
*/
|
||||
private function getDirectoryIterator(string $directory): iterable
|
||||
{
|
||||
$default = fn ($directory) => new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
if (null !== $this->directoryIteratorProvider) {
|
||||
return ($this->directoryIteratorProvider)($directory, $default);
|
||||
}
|
||||
|
||||
return $default($directory);
|
||||
}
|
||||
|
||||
private function isReadable(string $fileOrDirectory): bool
|
||||
{
|
||||
$default = fn ($fileOrDirectory) => is_readable($fileOrDirectory);
|
||||
|
||||
if (null !== $this->isReadableProvider) {
|
||||
return ($this->isReadableProvider)($fileOrDirectory, $default);
|
||||
}
|
||||
|
||||
return $default($fileOrDirectory);
|
||||
}
|
||||
|
||||
private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string
|
||||
{
|
||||
foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) {
|
||||
if ('target-language' === $attribute->nodeName) {
|
||||
return $attribute->nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues($this->getAvailableFormatOptions());
|
||||
}
|
||||
}
|
||||
|
||||
private function getAvailableFormatOptions(): array
|
||||
{
|
||||
return ['txt', 'json', 'github'];
|
||||
}
|
||||
}
|
||||
148
vendor/symfony/translation/DataCollector/TranslationDataCollector.php
vendored
Executable file
148
vendor/symfony/translation/DataCollector/TranslationDataCollector.php
vendored
Executable file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Symfony\Component\Translation\DataCollectorTranslator;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
private DataCollectorTranslator $translator;
|
||||
|
||||
public function __construct(DataCollectorTranslator $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function lateCollect(): void
|
||||
{
|
||||
$messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages());
|
||||
|
||||
$this->data += $this->computeCount($messages);
|
||||
$this->data['messages'] = $messages;
|
||||
|
||||
$this->data = $this->cloneVar($this->data);
|
||||
}
|
||||
|
||||
public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
|
||||
{
|
||||
$this->data['locale'] = $this->translator->getLocale();
|
||||
$this->data['fallback_locales'] = $this->translator->getFallbackLocales();
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
public function getMessages(): array|Data
|
||||
{
|
||||
return $this->data['messages'] ?? [];
|
||||
}
|
||||
|
||||
public function getCountMissings(): int
|
||||
{
|
||||
return $this->data[DataCollectorTranslator::MESSAGE_MISSING] ?? 0;
|
||||
}
|
||||
|
||||
public function getCountFallbacks(): int
|
||||
{
|
||||
return $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] ?? 0;
|
||||
}
|
||||
|
||||
public function getCountDefines(): int
|
||||
{
|
||||
return $this->data[DataCollectorTranslator::MESSAGE_DEFINED] ?? 0;
|
||||
}
|
||||
|
||||
public function getLocale(): ?string
|
||||
{
|
||||
return !empty($this->data['locale']) ? $this->data['locale'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getFallbackLocales(): Data|array
|
||||
{
|
||||
return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : [];
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'translation';
|
||||
}
|
||||
|
||||
private function sanitizeCollectedMessages(array $messages): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($messages as $key => $message) {
|
||||
$messageId = $message['locale'].$message['domain'].$message['id'];
|
||||
|
||||
if (!isset($result[$messageId])) {
|
||||
$message['count'] = 1;
|
||||
$message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : [];
|
||||
$messages[$key]['translation'] = $this->sanitizeString($message['translation']);
|
||||
$result[$messageId] = $message;
|
||||
} else {
|
||||
if (!empty($message['parameters'])) {
|
||||
$result[$messageId]['parameters'][] = $message['parameters'];
|
||||
}
|
||||
|
||||
++$result[$messageId]['count'];
|
||||
}
|
||||
|
||||
unset($messages[$key]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function computeCount(array $messages): array
|
||||
{
|
||||
$count = [
|
||||
DataCollectorTranslator::MESSAGE_DEFINED => 0,
|
||||
DataCollectorTranslator::MESSAGE_MISSING => 0,
|
||||
DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0,
|
||||
];
|
||||
|
||||
foreach ($messages as $message) {
|
||||
++$count[$message['state']];
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function sanitizeString(string $string, int $length = 80): string
|
||||
{
|
||||
$string = trim(preg_replace('/\s+/', ' ', $string));
|
||||
|
||||
if (false !== $encoding = mb_detect_encoding($string, null, true)) {
|
||||
if (mb_strlen($string, $encoding) > $length) {
|
||||
return mb_substr($string, 0, $length - 3, $encoding).'...';
|
||||
}
|
||||
} elseif (\strlen($string) > $length) {
|
||||
return substr($string, 0, $length - 3).'...';
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
143
vendor/symfony/translation/DataCollectorTranslator.php
vendored
Executable file
143
vendor/symfony/translation/DataCollectorTranslator.php
vendored
Executable file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation;
|
||||
|
||||
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Contracts\Translation\LocaleAwareInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, WarmableInterface
|
||||
{
|
||||
public const MESSAGE_DEFINED = 0;
|
||||
public const MESSAGE_MISSING = 1;
|
||||
public const MESSAGE_EQUALS_FALLBACK = 2;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
private array $messages = [];
|
||||
|
||||
/**
|
||||
* @param TranslatorInterface&TranslatorBagInterface&LocaleAwareInterface $translator
|
||||
*/
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
|
||||
throw new InvalidArgumentException(\sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
|
||||
}
|
||||
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function trans(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null): string
|
||||
{
|
||||
$trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
|
||||
$this->collectMessage($locale, $domain, $id, $trans, $parameters);
|
||||
|
||||
return $trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setLocale(string $locale)
|
||||
{
|
||||
$this->translator->setLocale($locale);
|
||||
}
|
||||
|
||||
public function getLocale(): string
|
||||
{
|
||||
return $this->translator->getLocale();
|
||||
}
|
||||
|
||||
public function getCatalogue(?string $locale = null): MessageCatalogueInterface
|
||||
{
|
||||
return $this->translator->getCatalogue($locale);
|
||||
}
|
||||
|
||||
public function getCatalogues(): array
|
||||
{
|
||||
return $this->translator->getCatalogues();
|
||||
}
|
||||
|
||||
public function warmUp(string $cacheDir, ?string $buildDir = null): array
|
||||
{
|
||||
if ($this->translator instanceof WarmableInterface) {
|
||||
return (array) $this->translator->warmUp($cacheDir, $buildDir);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fallback locales.
|
||||
*/
|
||||
public function getFallbackLocales(): array
|
||||
{
|
||||
if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
|
||||
return $this->translator->getFallbackLocales();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $method, array $args)
|
||||
{
|
||||
return $this->translator->{$method}(...$args);
|
||||
}
|
||||
|
||||
public function getCollectedMessages(): array
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
private function collectMessage(?string $locale, ?string $domain, string $id, string $translation, ?array $parameters = []): void
|
||||
{
|
||||
$domain ??= 'messages';
|
||||
|
||||
$catalogue = $this->translator->getCatalogue($locale);
|
||||
$locale = $catalogue->getLocale();
|
||||
$fallbackLocale = null;
|
||||
if ($catalogue->defines($id, $domain)) {
|
||||
$state = self::MESSAGE_DEFINED;
|
||||
} elseif ($catalogue->has($id, $domain)) {
|
||||
$state = self::MESSAGE_EQUALS_FALLBACK;
|
||||
|
||||
$fallbackCatalogue = $catalogue->getFallbackCatalogue();
|
||||
while ($fallbackCatalogue) {
|
||||
if ($fallbackCatalogue->defines($id, $domain)) {
|
||||
$fallbackLocale = $fallbackCatalogue->getLocale();
|
||||
break;
|
||||
}
|
||||
$fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
|
||||
}
|
||||
} else {
|
||||
$state = self::MESSAGE_MISSING;
|
||||
}
|
||||
|
||||
$this->messages[] = [
|
||||
'locale' => $locale,
|
||||
'fallbackLocale' => $fallbackLocale,
|
||||
'domain' => $domain,
|
||||
'id' => $id,
|
||||
'translation' => $translation,
|
||||
'parameters' => $parameters,
|
||||
'state' => $state,
|
||||
'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
36
vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php
vendored
Executable file
36
vendor/symfony/translation/DependencyInjection/DataCollectorTranslatorPass.php
vendored
Executable file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Translation\TranslatorBagInterface;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
*/
|
||||
class DataCollectorTranslatorPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
if (!$container->has('translator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass());
|
||||
|
||||
if (!is_subclass_of($translatorClass, TranslatorBagInterface::class)) {
|
||||
$container->removeDefinition('translator.data_collector');
|
||||
$container->removeDefinition('data_collector.translation');
|
||||
}
|
||||
}
|
||||
}
|
||||
59
vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php
vendored
Executable file
59
vendor/symfony/translation/DependencyInjection/LoggingTranslatorPass.php
vendored
Executable file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\TranslatorBagInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class LoggingTranslatorPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$container->hasParameter('translator.logging') || !$container->getParameter('translator.logging')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$translatorAlias = $container->getAlias('translator');
|
||||
$definition = $container->getDefinition((string) $translatorAlias);
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
|
||||
}
|
||||
|
||||
if (!$r->isSubclassOf(TranslatorInterface::class) || !$r->isSubclassOf(TranslatorBagInterface::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$container->getDefinition('translator.logging')->setDecoratedService('translator');
|
||||
$warmer = $container->getDefinition('translation.warmer');
|
||||
$subscriberAttributes = $warmer->getTag('container.service_subscriber');
|
||||
$warmer->clearTag('container.service_subscriber');
|
||||
|
||||
foreach ($subscriberAttributes as $k => $v) {
|
||||
if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) {
|
||||
$warmer->addTag('container.service_subscriber', $v);
|
||||
}
|
||||
}
|
||||
$warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']);
|
||||
}
|
||||
}
|
||||
38
vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
vendored
Executable file
38
vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Adds tagged translation.formatter services to translation writer.
|
||||
*/
|
||||
class TranslationDumperPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('translation.writer')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$definition = $container->getDefinition('translation.writer');
|
||||
|
||||
foreach ($container->findTaggedServiceIds('translation.dumper', true) as $id => $attributes) {
|
||||
$definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
43
vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
vendored
Executable file
43
vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
vendored
Executable file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Adds tagged translation.extractor services to translation extractor.
|
||||
*/
|
||||
class TranslationExtractorPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('translation.extractor')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$definition = $container->getDefinition('translation.extractor');
|
||||
|
||||
foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) {
|
||||
if (!isset($attributes[0]['alias'])) {
|
||||
throw new RuntimeException(\sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
|
||||
}
|
||||
|
||||
$definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
94
vendor/symfony/translation/DependencyInjection/TranslatorPass.php
vendored
Executable file
94
vendor/symfony/translation/DependencyInjection/TranslatorPass.php
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
class TranslatorPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('translator.default')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$loaders = [];
|
||||
$loaderRefs = [];
|
||||
foreach ($container->findTaggedServiceIds('translation.loader', true) as $id => $attributes) {
|
||||
$loaderRefs[$id] = new Reference($id);
|
||||
$loaders[$id][] = $attributes[0]['alias'];
|
||||
if (isset($attributes[0]['legacy-alias'])) {
|
||||
$loaders[$id][] = $attributes[0]['legacy-alias'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($container->hasDefinition('translation.reader')) {
|
||||
$definition = $container->getDefinition('translation.reader');
|
||||
foreach ($loaders as $id => $formats) {
|
||||
foreach ($formats as $format) {
|
||||
$definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$container
|
||||
->findDefinition('translator.default')
|
||||
->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
|
||||
->replaceArgument(3, $loaders)
|
||||
;
|
||||
|
||||
if ($container->hasDefinition('validator') && $container->hasDefinition('translation.extractor.visitor.constraint')) {
|
||||
$constraintVisitorDefinition = $container->getDefinition('translation.extractor.visitor.constraint');
|
||||
$constraintClassNames = [];
|
||||
|
||||
foreach ($container->getDefinitions() as $definition) {
|
||||
if (!$definition->hasTag('validator.constraint_validator')) {
|
||||
continue;
|
||||
}
|
||||
// Resolve constraint validator FQCN even if defined as %foo.validator.class% parameter
|
||||
$className = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
// Extraction of the constraint class name from the Constraint Validator FQCN
|
||||
$constraintClassNames[] = str_replace('Validator', '', substr(strrchr($className, '\\'), 1));
|
||||
}
|
||||
|
||||
$constraintVisitorDefinition->setArgument(0, $constraintClassNames);
|
||||
}
|
||||
|
||||
if (!$container->hasParameter('twig.default_path')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(1));
|
||||
if ($container->hasDefinition('console.command.translation_debug')) {
|
||||
$definition = $container->getDefinition('console.command.translation_debug');
|
||||
$definition->replaceArgument(4, $container->getParameter('twig.default_path'));
|
||||
|
||||
if (\count($definition->getArguments()) > 6) {
|
||||
$definition->replaceArgument(6, $paths);
|
||||
}
|
||||
}
|
||||
if ($container->hasDefinition('console.command.translation_extract')) {
|
||||
$definition = $container->getDefinition('console.command.translation_extract');
|
||||
$definition->replaceArgument(5, $container->getParameter('twig.default_path'));
|
||||
|
||||
if (\count($definition->getArguments()) > 7) {
|
||||
$definition->replaceArgument(7, $paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
145
vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
vendored
Executable file
145
vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
vendored
Executable file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver;
|
||||
|
||||
/**
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*/
|
||||
class TranslatorPathsPass extends AbstractRecursivePass
|
||||
{
|
||||
protected bool $skipScalars = true;
|
||||
|
||||
private int $level = 0;
|
||||
|
||||
/**
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private array $paths = [];
|
||||
|
||||
/**
|
||||
* @var array<int, Definition>
|
||||
*/
|
||||
private array $definitions = [];
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool>>
|
||||
*/
|
||||
private array $controllers = [];
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('translator')) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->findControllerArguments($container) as $controller => $argument) {
|
||||
$id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller));
|
||||
if ($container->hasDefinition($id)) {
|
||||
[$locatorRef] = $argument->getValues();
|
||||
$this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
parent::process($container);
|
||||
|
||||
$paths = [];
|
||||
foreach ($this->paths as $class => $_) {
|
||||
if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
|
||||
$paths[] = $r->getFileName();
|
||||
foreach ($r->getTraits() as $trait) {
|
||||
$paths[] = $trait->getFileName();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($paths) {
|
||||
if ($container->hasDefinition('console.command.translation_debug')) {
|
||||
$definition = $container->getDefinition('console.command.translation_debug');
|
||||
$definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths));
|
||||
}
|
||||
if ($container->hasDefinition('console.command.translation_extract')) {
|
||||
$definition = $container->getDefinition('console.command.translation_extract');
|
||||
$definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$this->level = 0;
|
||||
$this->paths = [];
|
||||
$this->definitions = [];
|
||||
}
|
||||
}
|
||||
|
||||
protected function processValue(mixed $value, bool $isRoot = false): mixed
|
||||
{
|
||||
if ($value instanceof Reference) {
|
||||
if ('translator' === (string) $value) {
|
||||
for ($i = $this->level - 1; $i >= 0; --$i) {
|
||||
$class = $this->definitions[$i]->getClass();
|
||||
|
||||
if (ServiceLocator::class === $class) {
|
||||
if (!isset($this->controllers[$this->currentId ?? ''])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->controllers[$this->currentId ?? ''] as $class => $_) {
|
||||
$this->paths[$class] = true;
|
||||
}
|
||||
} else {
|
||||
$this->paths[$class] = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($value instanceof Definition) {
|
||||
$this->definitions[$this->level++] = $value;
|
||||
$value = parent::processValue($value, $isRoot);
|
||||
unset($this->definitions[--$this->level]);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
private function findControllerArguments(ContainerBuilder $container): array
|
||||
{
|
||||
if (!$container->has('argument_resolver.service')) {
|
||||
return [];
|
||||
}
|
||||
$resolverDef = $container->findDefinition('argument_resolver.service');
|
||||
|
||||
if (TraceableValueResolver::class === $resolverDef->getClass()) {
|
||||
$resolverDef = $container->getDefinition($resolverDef->getArgument(0));
|
||||
}
|
||||
|
||||
$argument = $resolverDef->getArgument(0);
|
||||
if ($argument instanceof Reference) {
|
||||
$argument = $container->getDefinition($argument);
|
||||
}
|
||||
|
||||
return $argument->getArgument(0);
|
||||
}
|
||||
}
|
||||
56
vendor/symfony/translation/Dumper/CsvFileDumper.php
vendored
Executable file
56
vendor/symfony/translation/Dumper/CsvFileDumper.php
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* CsvFileDumper generates a csv formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author Stealth35
|
||||
*/
|
||||
class CsvFileDumper extends FileDumper
|
||||
{
|
||||
private string $delimiter = ';';
|
||||
private string $enclosure = '"';
|
||||
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$handle = fopen('php://memory', 'r+');
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure, '\\');
|
||||
}
|
||||
|
||||
rewind($handle);
|
||||
$output = stream_get_contents($handle);
|
||||
fclose($handle);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delimiter and escape character for CSV.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setCsvControl(string $delimiter = ';', string $enclosure = '"')
|
||||
{
|
||||
$this->delimiter = $delimiter;
|
||||
$this->enclosure = $enclosure;
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'csv';
|
||||
}
|
||||
}
|
||||
32
vendor/symfony/translation/Dumper/DumperInterface.php
vendored
Executable file
32
vendor/symfony/translation/Dumper/DumperInterface.php
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* DumperInterface is the interface implemented by all translation dumpers.
|
||||
* There is no common option.
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
*/
|
||||
interface DumperInterface
|
||||
{
|
||||
/**
|
||||
* Dumps the message catalogue.
|
||||
*
|
||||
* @param array $options Options that are used by the dumper
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function dump(MessageCatalogue $messages, array $options = []);
|
||||
}
|
||||
108
vendor/symfony/translation/Dumper/FileDumper.php
vendored
Executable file
108
vendor/symfony/translation/Dumper/FileDumper.php
vendored
Executable file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\Exception\RuntimeException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
|
||||
*
|
||||
* Options:
|
||||
* - path (mandatory): the directory where the files should be saved
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
*/
|
||||
abstract class FileDumper implements DumperInterface
|
||||
{
|
||||
/**
|
||||
* A template for the relative paths to files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relativePathTemplate = '%domain%.%locale%.%extension%';
|
||||
|
||||
/**
|
||||
* Sets the template for the relative paths to files.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setRelativePathTemplate(string $relativePathTemplate)
|
||||
{
|
||||
$this->relativePathTemplate = $relativePathTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function dump(MessageCatalogue $messages, array $options = [])
|
||||
{
|
||||
if (!\array_key_exists('path', $options)) {
|
||||
throw new InvalidArgumentException('The file dumper needs a path option.');
|
||||
}
|
||||
|
||||
// save a file for each domain
|
||||
foreach ($messages->getDomains() as $domain) {
|
||||
$fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
|
||||
if (!file_exists($fullpath)) {
|
||||
$directory = \dirname($fullpath);
|
||||
if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
|
||||
throw new RuntimeException(\sprintf('Unable to create directory "%s".', $directory));
|
||||
}
|
||||
}
|
||||
|
||||
$intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX;
|
||||
$intlMessages = $messages->all($intlDomain);
|
||||
|
||||
if ($intlMessages) {
|
||||
$intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale());
|
||||
file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options));
|
||||
|
||||
$messages->replace([], $intlDomain);
|
||||
|
||||
try {
|
||||
if ($messages->all($domain)) {
|
||||
file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
|
||||
}
|
||||
continue;
|
||||
} finally {
|
||||
$messages->replace($intlMessages, $intlDomain);
|
||||
}
|
||||
}
|
||||
|
||||
file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a domain of a message catalogue to its string representation.
|
||||
*/
|
||||
abstract public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string;
|
||||
|
||||
/**
|
||||
* Gets the file extension of the dumper.
|
||||
*/
|
||||
abstract protected function getExtension(): string;
|
||||
|
||||
/**
|
||||
* Gets the relative file path using the template.
|
||||
*/
|
||||
private function getRelativePath(string $domain, string $locale): string
|
||||
{
|
||||
return strtr($this->relativePathTemplate, [
|
||||
'%domain%' => $domain,
|
||||
'%locale%' => $locale,
|
||||
'%extension%' => $this->getExtension(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
95
vendor/symfony/translation/Dumper/IcuResFileDumper.php
vendored
Executable file
95
vendor/symfony/translation/Dumper/IcuResFileDumper.php
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author Stealth35
|
||||
*/
|
||||
class IcuResFileDumper extends FileDumper
|
||||
{
|
||||
protected $relativePathTemplate = '%domain%/%locale%.%extension%';
|
||||
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$data = $indexes = $resources = '';
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$indexes .= pack('v', \strlen($data) + 28);
|
||||
$data .= $source."\0";
|
||||
}
|
||||
|
||||
$data .= $this->writePadding($data);
|
||||
|
||||
$keyTop = $this->getPosition($data);
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$resources .= pack('V', $this->getPosition($data));
|
||||
|
||||
$data .= pack('V', \strlen($target))
|
||||
.mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
|
||||
.$this->writePadding($data)
|
||||
;
|
||||
}
|
||||
|
||||
$resOffset = $this->getPosition($data);
|
||||
|
||||
$data .= pack('v', \count($messages->all($domain)))
|
||||
.$indexes
|
||||
.$this->writePadding($data)
|
||||
.$resources
|
||||
;
|
||||
|
||||
$bundleTop = $this->getPosition($data);
|
||||
|
||||
$root = pack('V7',
|
||||
$resOffset + (2 << 28), // Resource Offset + Resource Type
|
||||
6, // Index length
|
||||
$keyTop, // Index keys top
|
||||
$bundleTop, // Index resources top
|
||||
$bundleTop, // Index bundle top
|
||||
\count($messages->all($domain)), // Index max table length
|
||||
0 // Index attributes
|
||||
);
|
||||
|
||||
$header = pack('vC2v4C12@32',
|
||||
32, // Header size
|
||||
0xDA, 0x27, // Magic number 1 and 2
|
||||
20, 0, 0, 2, // Rest of the header, ..., Size of a char
|
||||
0x52, 0x65, 0x73, 0x42, // Data format identifier
|
||||
1, 2, 0, 0, // Data version
|
||||
1, 4, 0, 0 // Unicode version
|
||||
);
|
||||
|
||||
return $header.$root.$data;
|
||||
}
|
||||
|
||||
private function writePadding(string $data): ?string
|
||||
{
|
||||
$padding = \strlen($data) % 4;
|
||||
|
||||
return $padding ? str_repeat("\xAA", 4 - $padding) : null;
|
||||
}
|
||||
|
||||
private function getPosition(string $data): float|int
|
||||
{
|
||||
return (\strlen($data) + 28) / 4;
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'res';
|
||||
}
|
||||
}
|
||||
39
vendor/symfony/translation/Dumper/IniFileDumper.php
vendored
Executable file
39
vendor/symfony/translation/Dumper/IniFileDumper.php
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* IniFileDumper generates an ini formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author Stealth35
|
||||
*/
|
||||
class IniFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$output = '';
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$escapeTarget = str_replace('"', '\"', $target);
|
||||
$output .= $source.'="'.$escapeTarget."\"\n";
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'ini';
|
||||
}
|
||||
}
|
||||
34
vendor/symfony/translation/Dumper/JsonFileDumper.php
vendored
Executable file
34
vendor/symfony/translation/Dumper/JsonFileDumper.php
vendored
Executable file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* JsonFileDumper generates an json formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author singles
|
||||
*/
|
||||
class JsonFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT;
|
||||
|
||||
return json_encode($messages->all($domain), $flags);
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'json';
|
||||
}
|
||||
}
|
||||
76
vendor/symfony/translation/Dumper/MoFileDumper.php
vendored
Executable file
76
vendor/symfony/translation/Dumper/MoFileDumper.php
vendored
Executable file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\Loader\MoFileLoader;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* MoFileDumper generates a gettext formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author Stealth35
|
||||
*/
|
||||
class MoFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$sources = $targets = $sourceOffsets = $targetOffsets = '';
|
||||
$offsets = [];
|
||||
$size = 0;
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$offsets[] = array_map('strlen', [$sources, $source, $targets, $target]);
|
||||
$sources .= "\0".$source;
|
||||
$targets .= "\0".$target;
|
||||
++$size;
|
||||
}
|
||||
|
||||
$header = [
|
||||
'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
|
||||
'formatRevision' => 0,
|
||||
'count' => $size,
|
||||
'offsetId' => MoFileLoader::MO_HEADER_SIZE,
|
||||
'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
|
||||
'sizeHashes' => 0,
|
||||
'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
|
||||
];
|
||||
|
||||
$sourcesSize = \strlen($sources);
|
||||
$sourcesStart = $header['offsetHashes'] + 1;
|
||||
|
||||
foreach ($offsets as $offset) {
|
||||
$sourceOffsets .= $this->writeLong($offset[1])
|
||||
.$this->writeLong($offset[0] + $sourcesStart);
|
||||
$targetOffsets .= $this->writeLong($offset[3])
|
||||
.$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
|
||||
}
|
||||
|
||||
$output = implode('', array_map($this->writeLong(...), $header))
|
||||
.$sourceOffsets
|
||||
.$targetOffsets
|
||||
.$sources
|
||||
.$targets
|
||||
;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'mo';
|
||||
}
|
||||
|
||||
private function writeLong(mixed $str): string
|
||||
{
|
||||
return pack('V*', $str);
|
||||
}
|
||||
}
|
||||
32
vendor/symfony/translation/Dumper/PhpFileDumper.php
vendored
Executable file
32
vendor/symfony/translation/Dumper/PhpFileDumper.php
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* PhpFileDumper generates PHP files from a message catalogue.
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
*/
|
||||
class PhpFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
return "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'php';
|
||||
}
|
||||
}
|
||||
131
vendor/symfony/translation/Dumper/PoFileDumper.php
vendored
Executable file
131
vendor/symfony/translation/Dumper/PoFileDumper.php
vendored
Executable file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* PoFileDumper generates a gettext formatted string representation of a message catalogue.
|
||||
*
|
||||
* @author Stealth35
|
||||
*/
|
||||
class PoFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$output = 'msgid ""'."\n";
|
||||
$output .= 'msgstr ""'."\n";
|
||||
$output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
|
||||
$output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
|
||||
$output .= '"Language: '.$messages->getLocale().'\n"'."\n";
|
||||
$output .= "\n";
|
||||
|
||||
$newLine = false;
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
if ($newLine) {
|
||||
$output .= "\n";
|
||||
} else {
|
||||
$newLine = true;
|
||||
}
|
||||
$metadata = $messages->getMetadata($source, $domain);
|
||||
|
||||
if (isset($metadata['comments'])) {
|
||||
$output .= $this->formatComments($metadata['comments']);
|
||||
}
|
||||
if (isset($metadata['flags'])) {
|
||||
$output .= $this->formatComments(implode(',', (array) $metadata['flags']), ',');
|
||||
}
|
||||
if (isset($metadata['sources'])) {
|
||||
$output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':');
|
||||
}
|
||||
|
||||
$sourceRules = $this->getStandardRules($source);
|
||||
$targetRules = $this->getStandardRules($target);
|
||||
if (2 == \count($sourceRules) && [] !== $targetRules) {
|
||||
$output .= \sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
|
||||
$output .= \sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
|
||||
foreach ($targetRules as $i => $targetRule) {
|
||||
$output .= \sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
|
||||
}
|
||||
} else {
|
||||
$output .= \sprintf('msgid "%s"'."\n", $this->escape($source));
|
||||
$output .= \sprintf('msgstr "%s"'."\n", $this->escape($target));
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function getStandardRules(string $id): array
|
||||
{
|
||||
// Partly copied from TranslatorTrait::trans.
|
||||
$parts = [];
|
||||
if (preg_match('/^\|++$/', $id)) {
|
||||
$parts = explode('|', $id);
|
||||
} elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
|
||||
$parts = $matches[0];
|
||||
}
|
||||
|
||||
$intervalRegexp = <<<'EOF'
|
||||
/^(?P<interval>
|
||||
({\s*
|
||||
(\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
|
||||
\s*})
|
||||
|
||||
|
|
||||
|
||||
(?P<left_delimiter>[\[\]])
|
||||
\s*
|
||||
(?P<left>-Inf|\-?\d+(\.\d+)?)
|
||||
\s*,\s*
|
||||
(?P<right>\+?Inf|\-?\d+(\.\d+)?)
|
||||
\s*
|
||||
(?P<right_delimiter>[\[\]])
|
||||
)\s*(?P<message>.*?)$/xs
|
||||
EOF;
|
||||
|
||||
$standardRules = [];
|
||||
foreach ($parts as $part) {
|
||||
$part = trim(str_replace('||', '|', $part));
|
||||
|
||||
if (preg_match($intervalRegexp, $part)) {
|
||||
// Explicit rule is not a standard rule.
|
||||
return [];
|
||||
} else {
|
||||
$standardRules[] = $part;
|
||||
}
|
||||
}
|
||||
|
||||
return $standardRules;
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'po';
|
||||
}
|
||||
|
||||
private function escape(string $str): string
|
||||
{
|
||||
return addcslashes($str, "\0..\37\42\134");
|
||||
}
|
||||
|
||||
private function formatComments(string|array $comments, string $prefix = ''): ?string
|
||||
{
|
||||
$output = null;
|
||||
|
||||
foreach ((array) $comments as $comment) {
|
||||
$output .= \sprintf('#%s %s'."\n", $prefix, $comment);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
55
vendor/symfony/translation/Dumper/QtFileDumper.php
vendored
Executable file
55
vendor/symfony/translation/Dumper/QtFileDumper.php
vendored
Executable file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* QtFileDumper generates ts files from a message catalogue.
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class QtFileDumper extends FileDumper
|
||||
{
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'utf-8');
|
||||
$dom->formatOutput = true;
|
||||
$ts = $dom->appendChild($dom->createElement('TS'));
|
||||
$context = $ts->appendChild($dom->createElement('context'));
|
||||
$context->appendChild($dom->createElement('name', $domain));
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$message = $context->appendChild($dom->createElement('message'));
|
||||
$metadata = $messages->getMetadata($source, $domain);
|
||||
if (isset($metadata['sources'])) {
|
||||
foreach ((array) $metadata['sources'] as $location) {
|
||||
$loc = explode(':', $location, 2);
|
||||
$location = $message->appendChild($dom->createElement('location'));
|
||||
$location->setAttribute('filename', $loc[0]);
|
||||
if (isset($loc[1])) {
|
||||
$location->setAttribute('line', $loc[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$message->appendChild($dom->createElement('source', $source));
|
||||
$message->appendChild($dom->createElement('translation', $target));
|
||||
}
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return 'ts';
|
||||
}
|
||||
}
|
||||
221
vendor/symfony/translation/Dumper/XliffFileDumper.php
vendored
Executable file
221
vendor/symfony/translation/Dumper/XliffFileDumper.php
vendored
Executable file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
|
||||
/**
|
||||
* XliffFileDumper generates xliff files from a message catalogue.
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
*/
|
||||
class XliffFileDumper extends FileDumper
|
||||
{
|
||||
public function __construct(
|
||||
private string $extension = 'xlf',
|
||||
) {
|
||||
}
|
||||
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
$xliffVersion = '1.2';
|
||||
if (\array_key_exists('xliff_version', $options)) {
|
||||
$xliffVersion = $options['xliff_version'];
|
||||
}
|
||||
|
||||
if (\array_key_exists('default_locale', $options)) {
|
||||
$defaultLocale = $options['default_locale'];
|
||||
} else {
|
||||
$defaultLocale = \Locale::getDefault();
|
||||
}
|
||||
|
||||
if ('1.2' === $xliffVersion) {
|
||||
return $this->dumpXliff1($defaultLocale, $messages, $domain, $options);
|
||||
}
|
||||
if ('2.0' === $xliffVersion) {
|
||||
return $this->dumpXliff2($defaultLocale, $messages, $domain);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(\sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return $this->extension;
|
||||
}
|
||||
|
||||
private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = []): string
|
||||
{
|
||||
$toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony'];
|
||||
if (\array_key_exists('tool_info', $options)) {
|
||||
$toolInfo = array_merge($toolInfo, $options['tool_info']);
|
||||
}
|
||||
|
||||
$dom = new \DOMDocument('1.0', 'utf-8');
|
||||
$dom->formatOutput = true;
|
||||
|
||||
$xliff = $dom->appendChild($dom->createElement('xliff'));
|
||||
$xliff->setAttribute('version', '1.2');
|
||||
$xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');
|
||||
|
||||
$xliffFile = $xliff->appendChild($dom->createElement('file'));
|
||||
$xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale));
|
||||
$xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
|
||||
$xliffFile->setAttribute('datatype', 'plaintext');
|
||||
$xliffFile->setAttribute('original', 'file.ext');
|
||||
|
||||
$xliffHead = $xliffFile->appendChild($dom->createElement('header'));
|
||||
$xliffTool = $xliffHead->appendChild($dom->createElement('tool'));
|
||||
foreach ($toolInfo as $id => $value) {
|
||||
$xliffTool->setAttribute($id, $value);
|
||||
}
|
||||
|
||||
if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) {
|
||||
$xliffPropGroup = $xliffHead->appendChild($dom->createElement('prop-group'));
|
||||
foreach ($catalogueMetadata as $key => $value) {
|
||||
$xliffProp = $xliffPropGroup->appendChild($dom->createElement('prop'));
|
||||
$xliffProp->setAttribute('prop-type', $key);
|
||||
$xliffProp->appendChild($dom->createTextNode($value));
|
||||
}
|
||||
}
|
||||
|
||||
$xliffBody = $xliffFile->appendChild($dom->createElement('body'));
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$translation = $dom->createElement('trans-unit');
|
||||
|
||||
$translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
|
||||
$translation->setAttribute('resname', $source);
|
||||
|
||||
$s = $translation->appendChild($dom->createElement('source'));
|
||||
$s->appendChild($dom->createTextNode($source));
|
||||
|
||||
// Does the target contain characters requiring a CDATA section?
|
||||
$text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
|
||||
|
||||
$targetElement = $dom->createElement('target');
|
||||
$metadata = $messages->getMetadata($source, $domain);
|
||||
if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
|
||||
foreach ($metadata['target-attributes'] as $name => $value) {
|
||||
$targetElement->setAttribute($name, $value);
|
||||
}
|
||||
}
|
||||
$t = $translation->appendChild($targetElement);
|
||||
$t->appendChild($text);
|
||||
|
||||
if ($this->hasMetadataArrayInfo('notes', $metadata)) {
|
||||
foreach ($metadata['notes'] as $note) {
|
||||
if (!isset($note['content'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$n = $translation->appendChild($dom->createElement('note'));
|
||||
$n->appendChild($dom->createTextNode($note['content']));
|
||||
|
||||
if (isset($note['priority'])) {
|
||||
$n->setAttribute('priority', $note['priority']);
|
||||
}
|
||||
|
||||
if (isset($note['from'])) {
|
||||
$n->setAttribute('from', $note['from']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$xliffBody->appendChild($translation);
|
||||
}
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain): string
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'utf-8');
|
||||
$dom->formatOutput = true;
|
||||
|
||||
$xliff = $dom->appendChild($dom->createElement('xliff'));
|
||||
$xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0');
|
||||
$xliff->setAttribute('version', '2.0');
|
||||
$xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale));
|
||||
$xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
|
||||
|
||||
$xliffFile = $xliff->appendChild($dom->createElement('file'));
|
||||
if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
|
||||
$xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
|
||||
} else {
|
||||
$xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
|
||||
}
|
||||
|
||||
if ($catalogueMetadata = $messages->getCatalogueMetadata('', $domain) ?? []) {
|
||||
$xliff->setAttribute('xmlns:m', 'urn:oasis:names:tc:xliff:metadata:2.0');
|
||||
$xliffMetadata = $xliffFile->appendChild($dom->createElement('m:metadata'));
|
||||
foreach ($catalogueMetadata as $key => $value) {
|
||||
$xliffMeta = $xliffMetadata->appendChild($dom->createElement('prop'));
|
||||
$xliffMeta->setAttribute('type', $key);
|
||||
$xliffMeta->appendChild($dom->createTextNode($value));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($messages->all($domain) as $source => $target) {
|
||||
$translation = $dom->createElement('unit');
|
||||
$translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
|
||||
|
||||
if (\strlen($source) <= 80) {
|
||||
$translation->setAttribute('name', $source);
|
||||
}
|
||||
|
||||
$metadata = $messages->getMetadata($source, $domain);
|
||||
|
||||
// Add notes section
|
||||
if ($this->hasMetadataArrayInfo('notes', $metadata) && $metadata['notes']) {
|
||||
$notesElement = $dom->createElement('notes');
|
||||
foreach ($metadata['notes'] as $note) {
|
||||
$n = $dom->createElement('note');
|
||||
$n->appendChild($dom->createTextNode($note['content'] ?? ''));
|
||||
unset($note['content']);
|
||||
|
||||
foreach ($note as $name => $value) {
|
||||
$n->setAttribute($name, $value);
|
||||
}
|
||||
$notesElement->appendChild($n);
|
||||
}
|
||||
$translation->appendChild($notesElement);
|
||||
}
|
||||
|
||||
$segment = $translation->appendChild($dom->createElement('segment'));
|
||||
|
||||
$s = $segment->appendChild($dom->createElement('source'));
|
||||
$s->appendChild($dom->createTextNode($source));
|
||||
|
||||
// Does the target contain characters requiring a CDATA section?
|
||||
$text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
|
||||
|
||||
$targetElement = $dom->createElement('target');
|
||||
if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
|
||||
foreach ($metadata['target-attributes'] as $name => $value) {
|
||||
$targetElement->setAttribute($name, $value);
|
||||
}
|
||||
}
|
||||
$t = $segment->appendChild($targetElement);
|
||||
$t->appendChild($text);
|
||||
|
||||
$xliffFile->appendChild($translation);
|
||||
}
|
||||
|
||||
return $dom->saveXML();
|
||||
}
|
||||
|
||||
private function hasMetadataArrayInfo(string $key, ?array $metadata = null): bool
|
||||
{
|
||||
return is_iterable($metadata[$key] ?? null);
|
||||
}
|
||||
}
|
||||
56
vendor/symfony/translation/Dumper/YamlFileDumper.php
vendored
Executable file
56
vendor/symfony/translation/Dumper/YamlFileDumper.php
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Dumper;
|
||||
|
||||
use Symfony\Component\Translation\Exception\LogicException;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Symfony\Component\Translation\Util\ArrayConverter;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* YamlFileDumper generates yaml files from a message catalogue.
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
*/
|
||||
class YamlFileDumper extends FileDumper
|
||||
{
|
||||
private string $extension;
|
||||
|
||||
public function __construct(string $extension = 'yml')
|
||||
{
|
||||
$this->extension = $extension;
|
||||
}
|
||||
|
||||
public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []): string
|
||||
{
|
||||
if (!class_exists(Yaml::class)) {
|
||||
throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
|
||||
}
|
||||
|
||||
$data = $messages->all($domain);
|
||||
|
||||
if (isset($options['as_tree']) && $options['as_tree']) {
|
||||
$data = ArrayConverter::expandToTree($data);
|
||||
}
|
||||
|
||||
if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
|
||||
return Yaml::dump($data, $inline);
|
||||
}
|
||||
|
||||
return Yaml::dump($data);
|
||||
}
|
||||
|
||||
protected function getExtension(): string
|
||||
{
|
||||
return $this->extension;
|
||||
}
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/ExceptionInterface.php
vendored
Executable file
21
vendor/symfony/translation/Exception/ExceptionInterface.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Exception interface for all exceptions thrown by the component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
24
vendor/symfony/translation/Exception/IncompleteDsnException.php
vendored
Executable file
24
vendor/symfony/translation/Exception/IncompleteDsnException.php
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
class IncompleteDsnException extends InvalidArgumentException
|
||||
{
|
||||
public function __construct(string $message, ?string $dsn = null, ?\Throwable $previous = null)
|
||||
{
|
||||
if ($dsn) {
|
||||
$message = \sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
|
||||
}
|
||||
|
||||
parent::__construct($message, 0, $previous);
|
||||
}
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/InvalidArgumentException.php
vendored
Executable file
21
vendor/symfony/translation/Exception/InvalidArgumentException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Base InvalidArgumentException for the Translation component.
|
||||
*
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/InvalidResourceException.php
vendored
Executable file
21
vendor/symfony/translation/Exception/InvalidResourceException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when a resource cannot be loaded.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/LogicException.php
vendored
Executable file
21
vendor/symfony/translation/Exception/LogicException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Base LogicException for Translation component.
|
||||
*
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
25
vendor/symfony/translation/Exception/MissingRequiredOptionException.php
vendored
Executable file
25
vendor/symfony/translation/Exception/MissingRequiredOptionException.php
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* @author Oskar Stark <oskarstark@googlemail.com>
|
||||
*/
|
||||
class MissingRequiredOptionException extends IncompleteDsnException
|
||||
{
|
||||
public function __construct(string $option, ?string $dsn = null, ?\Throwable $previous = null)
|
||||
{
|
||||
$message = \sprintf('The option "%s" is required but missing.', $option);
|
||||
|
||||
parent::__construct($message, $dsn, $previous);
|
||||
}
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/NotFoundResourceException.php
vendored
Executable file
21
vendor/symfony/translation/Exception/NotFoundResourceException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when a resource does not exist.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
41
vendor/symfony/translation/Exception/ProviderException.php
vendored
Executable file
41
vendor/symfony/translation/Exception/ProviderException.php
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ProviderException extends RuntimeException implements ProviderExceptionInterface
|
||||
{
|
||||
private ResponseInterface $response;
|
||||
private string $debug;
|
||||
|
||||
public function __construct(string $message, ResponseInterface $response, int $code = 0, ?\Exception $previous = null)
|
||||
{
|
||||
$this->response = $response;
|
||||
$this->debug = $response->getInfo('debug') ?? '';
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
public function getResponse(): ResponseInterface
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function getDebug(): string
|
||||
{
|
||||
return $this->debug;
|
||||
}
|
||||
}
|
||||
23
vendor/symfony/translation/Exception/ProviderExceptionInterface.php
vendored
Executable file
23
vendor/symfony/translation/Exception/ProviderExceptionInterface.php
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface ProviderExceptionInterface extends ExceptionInterface
|
||||
{
|
||||
/*
|
||||
* Returns debug info coming from the Symfony\Contracts\HttpClient\ResponseInterface
|
||||
*/
|
||||
public function getDebug(): string;
|
||||
}
|
||||
21
vendor/symfony/translation/Exception/RuntimeException.php
vendored
Executable file
21
vendor/symfony/translation/Exception/RuntimeException.php
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
/**
|
||||
* Base RuntimeException for the Translation component.
|
||||
*
|
||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
58
vendor/symfony/translation/Exception/UnsupportedSchemeException.php
vendored
Executable file
58
vendor/symfony/translation/Exception/UnsupportedSchemeException.php
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Exception;
|
||||
|
||||
use Symfony\Component\Translation\Bridge;
|
||||
use Symfony\Component\Translation\Provider\Dsn;
|
||||
|
||||
class UnsupportedSchemeException extends LogicException
|
||||
{
|
||||
private const SCHEME_TO_PACKAGE_MAP = [
|
||||
'crowdin' => [
|
||||
'class' => Bridge\Crowdin\CrowdinProviderFactory::class,
|
||||
'package' => 'symfony/crowdin-translation-provider',
|
||||
],
|
||||
'loco' => [
|
||||
'class' => Bridge\Loco\LocoProviderFactory::class,
|
||||
'package' => 'symfony/loco-translation-provider',
|
||||
],
|
||||
'lokalise' => [
|
||||
'class' => Bridge\Lokalise\LokaliseProviderFactory::class,
|
||||
'package' => 'symfony/lokalise-translation-provider',
|
||||
],
|
||||
'phrase' => [
|
||||
'class' => Bridge\Phrase\PhraseProviderFactory::class,
|
||||
'package' => 'symfony/phrase-translation-provider',
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct(Dsn $dsn, ?string $name = null, array $supported = [])
|
||||
{
|
||||
$provider = $dsn->getScheme();
|
||||
if (false !== $pos = strpos($provider, '+')) {
|
||||
$provider = substr($provider, 0, $pos);
|
||||
}
|
||||
$package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null;
|
||||
if ($package && !class_exists($package['class'])) {
|
||||
parent::__construct(\sprintf('Unable to synchronize translations via "%s" as the provider is not installed. Try running "composer require %s".', $provider, $package['package']));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$message = \sprintf('The "%s" scheme is not supported', $dsn->getScheme());
|
||||
if ($name && $supported) {
|
||||
$message .= \sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
|
||||
}
|
||||
|
||||
parent::__construct($message.'.');
|
||||
}
|
||||
}
|
||||
67
vendor/symfony/translation/Extractor/AbstractFileExtractor.php
vendored
Executable file
67
vendor/symfony/translation/Extractor/AbstractFileExtractor.php
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Translation\Extractor;
|
||||
|
||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Base class used by classes that extract translation messages from files.
|
||||
*
|
||||
* @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
|
||||
*/
|
||||
abstract class AbstractFileExtractor
|
||||
{
|
||||
protected function extractFiles(string|iterable $resource): iterable
|
||||
{
|
||||
if (is_iterable($resource)) {
|
||||
$files = [];
|
||||
foreach ($resource as $file) {
|
||||
if ($this->canBeExtracted($file)) {
|
||||
$files[] = $this->toSplFileInfo($file);
|
||||
}
|
||||
}
|
||||
} elseif (is_file($resource)) {
|
||||
$files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : [];
|
||||
} else {
|
||||
$files = $this->extractFromDirectory($resource);
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function toSplFileInfo(string $file): \SplFileInfo
|
||||
{
|
||||
return new \SplFileInfo($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function isFile(string $file): bool
|
||||
{
|
||||
if (!is_file($file)) {
|
||||
throw new InvalidArgumentException(\sprintf('The "%s" file does not exist.', $file));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function canBeExtracted(string $file);
|
||||
|
||||
/**
|
||||
* @return iterable
|
||||
*/
|
||||
abstract protected function extractFromDirectory(string|array $resource);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user