Merge branch '4.4'
* 4.4: (27 commits) [Validator] add notice in UPGRADE file for new Range constraint option [CssSelector] Support *:only-of-type pseudo class selector [Intl] Update the ICU data to 65.1 (4.4 branch) [Intl] Update the ICU data to 65.1 (4.3 branch) Replace deprecated calls in tests [Intl] Update the ICU data to 65.1 Delete 5_Security_issue.md [DI] Whitelist error_renderer.renderer tag in UnusedTagsPass [DI] Whitelist validator.auto_mapper in UnusedTagsPass Update CHANGELOG.md [HttpClient] Fixed #33832 NO_PROXY option ignored in NativeHttpClient::request() method [EventDispatcher] A compiler pass for aliased userland events. [Cache] give 100ms before starting the expiration countdown [Cache] fix logger usage in CacheTrait::doGet() [VarDumper] fix dumping uninitialized SplFileInfo Added missing translations. [Form] Added CountryType option for using alpha3 country codes Fixed invalid changelog 4.0.0 for VarDumper [Workflow] Fixed BC break on WorkflowInterface Fix wrong expression language value ...
This commit is contained in:
commit
e3e502ef6f
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
name: ⛔ Security Issue
|
||||
about: See https://symfony.com/security to report security-related issues
|
||||
|
||||
---
|
||||
|
||||
⚠ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
|
||||
|
||||
If you have found a security issue in Symfony, please send the details to
|
||||
security [at] symfony.com and don't disclose it publicly until we can provide a
|
||||
fix for it.
|
||||
|
||||
More information: https://symfony.com/security
|
|
@ -924,7 +924,7 @@ Validator
|
|||
VarDumper
|
||||
---------
|
||||
|
||||
* The `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$context = null`
|
||||
* The `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0`
|
||||
argument and moves `$message = ''` argument at 4th position.
|
||||
|
||||
Before:
|
||||
|
@ -939,7 +939,7 @@ VarDumper
|
|||
VarDumperTestTrait::assertDumpEquals($dump, $data, $filter = 0, $message = '');
|
||||
```
|
||||
|
||||
* The `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$context = null`
|
||||
* The `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0`
|
||||
argument and moves `$message = ''` argument at 4th position.
|
||||
|
||||
Before:
|
||||
|
|
|
@ -242,6 +242,28 @@ Workflow
|
|||
initial_marking: [draft]
|
||||
```
|
||||
|
||||
* `WorkflowInterface::apply()` will have a third argument in Symfony 5.0.
|
||||
|
||||
Before:
|
||||
```php
|
||||
class MyWorkflow implements WorkflowInterface
|
||||
{
|
||||
public function apply($subject, $transitionName)
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
```php
|
||||
class MyWorkflow implements WorkflowInterface
|
||||
{
|
||||
public function apply($subject, $transitionName, array $context = [])
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `MarkingStoreInterface::setMarking()` will have a third argument in Symfony 5.0.
|
||||
|
||||
Before:
|
||||
|
|
|
@ -344,6 +344,8 @@ Validator
|
|||
* Overriding the methods `ConstraintValidatorTestCase::setUp()` and `ConstraintValidatorTestCase::tearDown()` without the `void` return-type is deprecated.
|
||||
* deprecated `Symfony\Component\Validator\Mapping\Cache\CacheInterface` and all implementations in favor of PSR-6.
|
||||
* deprecated `ValidatorBuilder::setMetadataCache`, use `ValidatorBuilder::setMappingCache` instead.
|
||||
* The `Range` constraint has a new message option `notInRangeMessage` that is used when both `min` and `max` values are set.
|
||||
In case you are using custom translations make sure to add one for this new message.
|
||||
|
||||
WebProfilerBundle
|
||||
-----------------
|
||||
|
|
|
@ -611,6 +611,7 @@ Workflow
|
|||
* `add` method has been removed use `addWorkflow` method in `Workflow\Registry` instead.
|
||||
* `SupportStrategyInterface` has been removed, use `WorkflowSupportStrategyInterface` instead.
|
||||
* `ClassInstanceSupportStrategy` has been removed, use `InstanceOfSupportStrategy` instead.
|
||||
* `WorkflowInterface::apply()` has a third argument: `array $context = []`.
|
||||
* `MarkingStoreInterface::setMarking()` has a third argument: `array $context = []`.
|
||||
* Removed support of `initial_place`. Use `initial_places` instead.
|
||||
* `MultipleStateMarkingStore` has been removed. Use `MethodMarkingStore` instead.
|
||||
|
|
|
@ -32,6 +32,7 @@ class UnusedTagsPass implements CompilerPassInterface
|
|||
'controller.service_arguments',
|
||||
'config_cache.resource_checker',
|
||||
'data_collector',
|
||||
'error_renderer.renderer',
|
||||
'form.type',
|
||||
'form.type_extension',
|
||||
'form.type_guesser',
|
||||
|
@ -63,6 +64,7 @@ class UnusedTagsPass implements CompilerPassInterface
|
|||
'twig.loader',
|
||||
'validator.constraint_validator',
|
||||
'validator.initializer',
|
||||
'validator.auto_mapper',
|
||||
];
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
<parameter key="Symfony\Component\HttpKernel\Event\ViewEvent">kernel.view</parameter>
|
||||
<parameter key="Symfony\Component\HttpKernel\Event\ExceptionEvent">kernel.exception</parameter>
|
||||
<parameter key="Symfony\Component\HttpKernel\Event\TerminateEvent">kernel.terminate</parameter>
|
||||
<parameter key="Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent">security.authentication.success</parameter>
|
||||
<parameter key="Symfony\Component\Security\Core\Event\AuthenticationFailureEvent">security.authentication.failure</parameter>
|
||||
<parameter key="Symfony\Component\Security\Http\Event\InteractiveLoginEvent">security.interactive_login</parameter>
|
||||
<parameter key="Symfony\Component\Security\Http\Event\SwitchUserEvent">security.switch_user</parameter>
|
||||
<parameter key="Symfony\Component\Workflow\Event\GuardEvent">workflow.guard</parameter>
|
||||
<parameter key="Symfony\Component\Workflow\Event\LeaveEvent">workflow.leave</parameter>
|
||||
<parameter key="Symfony\Component\Workflow\Event\TransitionEvent">workflow.transition</parameter>
|
||||
|
|
|
@ -31,7 +31,14 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMe
|
|||
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\LdapFactory;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\Security\Core\AuthenticationEvents;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
|
||||
/**
|
||||
* Bundle.
|
||||
|
@ -64,5 +71,12 @@ class SecurityBundle extends Bundle
|
|||
$container->addCompilerPass(new AddSessionDomainConstraintPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$container->addCompilerPass(new RegisterCsrfTokenClearingLogoutHandlerPass());
|
||||
$container->addCompilerPass(new RegisterTokenUsageTrackingPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 200);
|
||||
|
||||
$container->addCompilerPass(new AddEventAliasesPass([
|
||||
AuthenticationSuccessEvent::class => AuthenticationEvents::AUTHENTICATION_SUCCESS,
|
||||
AuthenticationFailureEvent::class => AuthenticationEvents::AUTHENTICATION_FAILURE,
|
||||
InteractiveLoginEvent::class => SecurityEvents::INTERACTIVE_LOGIN,
|
||||
SwitchUserEvent::class => SecurityEvents::SWITCH_USER,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventSubscriber\TestSubscriber;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
|
||||
final class EventExtension extends Extension
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container): void
|
||||
{
|
||||
$container->register('test_subscriber', TestSubscriber::class)
|
||||
->setPublic(true)
|
||||
->addTag('kernel.event_subscriber');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?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\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
final class EventBundle extends Bundle
|
||||
{
|
||||
}
|
|
@ -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\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventSubscriber;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
|
||||
|
||||
final class TestSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public $calledMethods = [];
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
AuthenticationSuccessEvent::class => 'onAuthenticationSuccess',
|
||||
AuthenticationFailureEvent::class => 'onAuthenticationFailure',
|
||||
InteractiveLoginEvent::class => 'onInteractiveLogin',
|
||||
SwitchUserEvent::class => 'onSwitchUser',
|
||||
];
|
||||
}
|
||||
|
||||
public function __call(string $name, array $arguments)
|
||||
{
|
||||
$this->calledMethods[$name] = ($this->calledMethods[$name] ?? 0) + 1;
|
||||
}
|
||||
}
|
|
@ -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\Bundle\SecurityBundle\Tests\Functional;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\AuthenticationEvents;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
|
||||
use Symfony\Component\Security\Core\Event\AuthenticationSuccessEvent;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
|
||||
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
|
||||
use Symfony\Component\Security\Http\SecurityEvents;
|
||||
|
||||
final class EventAliasTest extends AbstractWebTestCase
|
||||
{
|
||||
public function testAliasedEvents(): void
|
||||
{
|
||||
$client = $this->createClient(['test_case' => 'AliasedEvents', 'root_config' => 'config.yml']);
|
||||
$container = $client->getContainer();
|
||||
$dispatcher = $container->get('event_dispatcher');
|
||||
|
||||
$dispatcher->dispatch(new AuthenticationSuccessEvent($this->createMock(TokenInterface::class)), AuthenticationEvents::AUTHENTICATION_SUCCESS);
|
||||
$dispatcher->dispatch(new AuthenticationFailureEvent($this->createMock(TokenInterface::class), new AuthenticationException()), AuthenticationEvents::AUTHENTICATION_FAILURE);
|
||||
$dispatcher->dispatch(new InteractiveLoginEvent($this->createMock(Request::class), $this->createMock(TokenInterface::class)), SecurityEvents::INTERACTIVE_LOGIN);
|
||||
$dispatcher->dispatch(new SwitchUserEvent($this->createMock(Request::class), $this->createMock(UserInterface::class), $this->createMock(TokenInterface::class)), SecurityEvents::SWITCH_USER);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'onAuthenticationSuccess' => 1,
|
||||
'onAuthenticationFailure' => 1,
|
||||
'onInteractiveLogin' => 1,
|
||||
'onSwitchUser' => 1,
|
||||
],
|
||||
$container->get('test_subscriber')->calledMethods
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
|
||||
use Symfony\Bundle\SecurityBundle\SecurityBundle;
|
||||
use Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\EventBundle\EventBundle;
|
||||
|
||||
return [
|
||||
new FrameworkBundle(),
|
||||
new SecurityBundle(),
|
||||
new EventBundle(),
|
||||
];
|
|
@ -0,0 +1,2 @@
|
|||
imports:
|
||||
- { resource: ./../config/framework.yml }
|
|
@ -76,7 +76,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
|
|||
$key = (string) $key;
|
||||
if (null === $item->expiry) {
|
||||
$ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
|
||||
} elseif (0 >= $ttl = (int) ($item->expiry - $now)) {
|
||||
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
|
||||
$expiredIds[] = $getId($key);
|
||||
continue;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
|
|||
unset($metadata[CacheItem::METADATA_TAGS]);
|
||||
}
|
||||
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
|
||||
$byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
|
||||
$byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
|
||||
}
|
||||
|
||||
return $byLifetime;
|
||||
|
|
|
@ -81,7 +81,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
|
|||
$key = (string) $key;
|
||||
if (null === $item->expiry) {
|
||||
$ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0;
|
||||
} elseif (0 >= $ttl = (int) ($item->expiry - $now)) {
|
||||
} elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
|
||||
$expiredIds[] = $getId($key);
|
||||
continue;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
|
|||
|
||||
if ($metadata) {
|
||||
// For compactness, expiry and creation duration are packed, using magic numbers as separators
|
||||
$value['meta'] = pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME]);
|
||||
$value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]);
|
||||
}
|
||||
|
||||
// Extract tag changes, these should be removed from values in doSave()
|
||||
|
|
|
@ -84,7 +84,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
|
|||
}
|
||||
if ($metadata) {
|
||||
// For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
|
||||
$item["\0*\0value"] = ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - CacheItem::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
|
||||
$item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
|
||||
}
|
||||
$innerItem->set($item["\0*\0value"]);
|
||||
$innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', $item["\0*\0expiry"])) : null);
|
||||
|
|
|
@ -177,7 +177,7 @@ class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterf
|
|||
unset($metadata[CacheItem::METADATA_TAGS]);
|
||||
|
||||
if ($metadata) {
|
||||
$values[$key] = ["\x9D".pack('VN', (int) $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET, $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
|
||||
$values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ abstract class AdapterTestCase extends CachePoolTest
|
|||
$cache->deleteItem('foo');
|
||||
$cache->get('foo', function ($item) {
|
||||
$item->expiresAfter(10);
|
||||
sleep(1);
|
||||
usleep(999000);
|
||||
|
||||
return 'bar';
|
||||
});
|
||||
|
|
|
@ -61,7 +61,7 @@ trait ContractsTrait
|
|||
static function (CacheItem $item, float $startTime, ?array &$metadata) {
|
||||
if ($item->expiry > $endTime = microtime(true)) {
|
||||
$item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry;
|
||||
$item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = 1000 * (int) ($endTime - $startTime);
|
||||
$item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime));
|
||||
} else {
|
||||
unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
CHANGELOG
|
||||
=========
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* Added support for `*:only-of-type`
|
||||
|
||||
2.8.0
|
||||
-----
|
||||
|
||||
|
|
|
@ -308,6 +308,8 @@ HTML
|
|||
['li div:only-child', ['li-div']],
|
||||
['div *:only-child', ['li-div', 'foobar-span']],
|
||||
['p:only-of-type', ['paragraph']],
|
||||
[':only-of-type', ['html', 'li-div', 'foobar-span', 'paragraph']],
|
||||
['div#foobar-div :only-of-type', ['foobar-span']],
|
||||
['a:empty', ['name-anchor']],
|
||||
['a:EMpty', ['name-anchor']],
|
||||
['li:empty', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li']],
|
||||
|
|
|
@ -100,17 +100,10 @@ class PseudoClassExtension extends AbstractExtension
|
|||
->addCondition('last() = 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ExpressionErrorException
|
||||
*/
|
||||
public function translateOnlyOfType(XPathExpr $xpath): XPathExpr
|
||||
{
|
||||
$element = $xpath->getElement();
|
||||
|
||||
if ('*' === $element) {
|
||||
throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
|
||||
}
|
||||
|
||||
return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,13 @@ class TaggedIteratorArgument extends IteratorArgument
|
|||
private $needsIndexes = false;
|
||||
|
||||
/**
|
||||
* @param string $tag The name of the tag identifying the target services
|
||||
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
|
||||
* @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute
|
||||
* @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
|
||||
* @param string $tag The name of the tag identifying the target services
|
||||
* @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
|
||||
* @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute
|
||||
* @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
|
||||
* @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
|
||||
*/
|
||||
public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false)
|
||||
public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null)
|
||||
{
|
||||
parent::__construct([]);
|
||||
|
||||
|
@ -41,6 +42,7 @@ class TaggedIteratorArgument extends IteratorArgument
|
|||
$this->indexAttribute = $indexAttribute;
|
||||
$this->defaultIndexMethod = $defaultIndexMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Name');
|
||||
$this->needsIndexes = $needsIndexes;
|
||||
$this->defaultPriorityMethod = $defaultPriorityMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Priority');
|
||||
}
|
||||
|
||||
public function getTag()
|
||||
|
@ -62,4 +64,9 @@ class TaggedIteratorArgument extends IteratorArgument
|
|||
{
|
||||
return $this->needsIndexes;
|
||||
}
|
||||
|
||||
public function getDefaultPriorityMethod(): ?string
|
||||
{
|
||||
return $this->defaultPriorityMethod;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ CHANGELOG
|
|||
* deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
|
||||
* added support for binding iterable and tagged services
|
||||
* made singly-implemented interfaces detection be scoped by file
|
||||
* added ability to define a static priority method for tagged service
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
|
|
@ -40,19 +40,43 @@ trait PriorityTaggedServiceTrait
|
|||
*/
|
||||
private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array
|
||||
{
|
||||
$indexAttribute = $defaultIndexMethod = $needsIndexes = null;
|
||||
$indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null;
|
||||
|
||||
if ($tagName instanceof TaggedIteratorArgument) {
|
||||
$indexAttribute = $tagName->getIndexAttribute();
|
||||
$defaultIndexMethod = $tagName->getDefaultIndexMethod();
|
||||
$needsIndexes = $tagName->needsIndexes();
|
||||
$defaultPriorityMethod = $tagName->getDefaultPriorityMethod();
|
||||
$tagName = $tagName->getTag();
|
||||
}
|
||||
|
||||
$services = [];
|
||||
|
||||
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
|
||||
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
|
||||
$class = $r = null;
|
||||
$priority = 0;
|
||||
if (isset($attributes[0]['priority'])) {
|
||||
$priority = $attributes[0]['priority'];
|
||||
} elseif ($defaultPriorityMethod) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
|
||||
if (($r = $container->getReflectionClass($class)) && $r->hasMethod($defaultPriorityMethod)) {
|
||||
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
|
||||
if (!$rm->isPublic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
|
||||
$priority = $rm->invoke(null);
|
||||
|
||||
if (!\is_int($priority)) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $indexAttribute && !$needsIndexes) {
|
||||
$services[$priority][] = new Reference($serviceId);
|
||||
|
@ -60,8 +84,10 @@ trait PriorityTaggedServiceTrait
|
|||
continue;
|
||||
}
|
||||
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
if (!$class) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
}
|
||||
|
||||
if (null !== $indexAttribute && isset($attributes[0][$indexAttribute])) {
|
||||
$services[$priority][$attributes[0][$indexAttribute]] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $attributes[0][$indexAttribute]);
|
||||
|
@ -69,7 +95,7 @@ trait PriorityTaggedServiceTrait
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!$r = $container->getReflectionClass($class)) {
|
||||
if (!$r && !$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId));
|
||||
}
|
||||
|
||||
|
|
|
@ -274,6 +274,9 @@ class XmlDumper extends Dumper
|
|||
if (null !== $tag->getDefaultIndexMethod()) {
|
||||
$element->setAttribute('default-index-method', $tag->getDefaultIndexMethod());
|
||||
}
|
||||
if (null !== $tag->getDefaultPriorityMethod()) {
|
||||
$element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod());
|
||||
}
|
||||
}
|
||||
} elseif ($value instanceof IteratorArgument) {
|
||||
$element->setAttribute('type', 'iterator');
|
||||
|
|
|
@ -244,6 +244,9 @@ class YamlDumper extends Dumper
|
|||
if (null !== $tag->getDefaultIndexMethod()) {
|
||||
$content['default_index_method'] = $tag->getDefaultIndexMethod();
|
||||
}
|
||||
if (null !== $tag->getDefaultPriorityMethod()) {
|
||||
$content['default_priority_method'] = $tag->getDefaultPriorityMethod();
|
||||
}
|
||||
}
|
||||
|
||||
return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content);
|
||||
|
|
|
@ -116,9 +116,9 @@ function iterator(array $values): IteratorArgument
|
|||
/**
|
||||
* Creates a lazy iterator by tag name.
|
||||
*/
|
||||
function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null): TaggedIteratorArgument
|
||||
function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): TaggedIteratorArgument
|
||||
{
|
||||
return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod);
|
||||
return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -510,7 +510,7 @@ class XmlFileLoader extends FileLoader
|
|||
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file));
|
||||
}
|
||||
|
||||
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator);
|
||||
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null);
|
||||
|
||||
if ($forLocator) {
|
||||
$arguments[$key] = new ServiceLocatorArgument($arguments[$key]);
|
||||
|
|
|
@ -709,11 +709,11 @@ class YamlFileLoader extends FileLoader
|
|||
$forLocator = 'tagged_locator' === $value->getTag();
|
||||
|
||||
if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
|
||||
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method'])) {
|
||||
throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by" and "default_index_method".', $value->getTag(), implode('"", "', $diff)));
|
||||
if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) {
|
||||
throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by", "default_index_method", and "default_priority_method".', $value->getTag(), implode('"", "', $diff)));
|
||||
}
|
||||
|
||||
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator);
|
||||
$argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null);
|
||||
} elseif (\is_string($argument) && $argument) {
|
||||
$argument = new TaggedIteratorArgument($argument, null, null, $forLocator);
|
||||
} else {
|
||||
|
|
|
@ -236,6 +236,7 @@
|
|||
<xsd:attribute name="tag" type="xsd:string" />
|
||||
<xsd:attribute name="index-by" type="xsd:string" />
|
||||
<xsd:attribute name="default-index-method" type="xsd:string" />
|
||||
<xsd:attribute name="default-priority-method" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="call">
|
||||
|
|
|
@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Reference;
|
|||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedClass;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooBarTaggedForDefaultPriorityClass;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooTagClass;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
|
@ -289,6 +290,30 @@ class IntegrationTest extends TestCase
|
|||
$this->assertSame(['bar_tab_class_with_defaultmethod' => $container->get(BarTagClass::class), 'foo' => $container->get(FooTagClass::class)], $param);
|
||||
}
|
||||
|
||||
public function testTaggedServiceWithDefaultPriorityMethod()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(BarTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar')
|
||||
;
|
||||
$container->register(FooTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar', ['foo' => 'foo'])
|
||||
;
|
||||
$container->register(FooBarTaggedForDefaultPriorityClass::class)
|
||||
->addArgument(new TaggedIteratorArgument('foo_bar', null, null, false, 'getPriority'))
|
||||
->setPublic(true)
|
||||
;
|
||||
|
||||
$container->compile();
|
||||
|
||||
$s = $container->get(FooBarTaggedForDefaultPriorityClass::class);
|
||||
|
||||
$param = iterator_to_array($s->getParam()->getIterator());
|
||||
$this->assertSame([$container->get(FooTagClass::class), $container->get(BarTagClass::class)], $param);
|
||||
}
|
||||
|
||||
public function testTaggedServiceLocatorWithIndexAttribute()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
|
|
@ -204,7 +204,7 @@ class XmlDumperTest extends TestCase
|
|||
|
||||
public function testTaggedArguments()
|
||||
{
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar');
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', false, 'getPriority');
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo', 'Foo')->addTag('foo_tag');
|
||||
$container->register('foo_tagged_iterator', 'Bar')
|
||||
|
|
|
@ -99,7 +99,7 @@ class YamlDumperTest extends TestCase
|
|||
|
||||
public function testTaggedArguments()
|
||||
{
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar');
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar', false, 'getPriority');
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo_service', 'Foo')->addTag('foo');
|
||||
$container->register('foo_service_tagged_iterator', 'Bar')->addArgument($taggedIterator);
|
||||
|
|
|
@ -13,4 +13,9 @@ class BarTagClass
|
|||
{
|
||||
return 'bar_tab_class_with_defaultmethod';
|
||||
}
|
||||
|
||||
public static function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||
|
||||
class FooBarTaggedForDefaultPriorityClass
|
||||
{
|
||||
private $param;
|
||||
|
||||
public function __construct($param = [])
|
||||
{
|
||||
$this->param = $param;
|
||||
}
|
||||
|
||||
public function getParam()
|
||||
{
|
||||
return $this->param;
|
||||
}
|
||||
}
|
|
@ -8,4 +8,11 @@ class FooTagClass
|
|||
{
|
||||
return 'foo_tag_class';
|
||||
}
|
||||
|
||||
public static function getPriority(): int
|
||||
{
|
||||
// Should be more than BarTagClass. More because this class is after
|
||||
// BarTagClass (order by name). So we want to ensure it will be before it
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
<tag name="foo_tag"/>
|
||||
</service>
|
||||
<service id="foo_tagged_iterator" class="Bar" public="true">
|
||||
<argument type="tagged_iterator" tag="foo_tag" index-by="barfoo" default-index-method="foobar"/>
|
||||
<argument type="tagged_iterator" tag="foo_tag" index-by="barfoo" default-index-method="foobar" default-priority-method="getPriority"/>
|
||||
</service>
|
||||
<service id="foo_tagged_locator" class="Bar" public="true">
|
||||
<argument type="tagged_locator" tag="foo_tag" index-by="barfoo" default-index-method="foobar"/>
|
||||
<argument type="tagged_locator" tag="foo_tag" index-by="barfoo" default-index-method="foobar" default-priority-method="getPriority"/>
|
||||
</service>
|
||||
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
|
||||
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
|
||||
|
|
|
@ -10,10 +10,10 @@ services:
|
|||
- { name: foo }
|
||||
foo_service_tagged_iterator:
|
||||
class: Bar
|
||||
arguments: [!tagged_iterator { tag: foo, index_by: barfoo, default_index_method: foobar }]
|
||||
arguments: [!tagged_iterator { tag: foo, index_by: barfoo, default_index_method: foobar, default_priority_method: getPriority }]
|
||||
foo_service_tagged_locator:
|
||||
class: Bar
|
||||
arguments: [!tagged_locator { tag: foo, index_by: barfoo, default_index_method: foobar }]
|
||||
arguments: [!tagged_locator { tag: foo, index_by: barfoo, default_index_method: foobar, default_priority_method: getPriority }]
|
||||
bar_service_tagged_locator:
|
||||
class: Bar
|
||||
arguments: [!tagged_locator foo]
|
||||
|
|
|
@ -327,10 +327,10 @@ class XmlFileLoaderTest extends TestCase
|
|||
$this->assertCount(1, $container->getDefinition('foo_tagged_iterator')->getArguments());
|
||||
$this->assertCount(1, $container->getDefinition('foo_tagged_locator')->getArguments());
|
||||
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar');
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', false, 'getPriority');
|
||||
$this->assertEquals($taggedIterator, $container->getDefinition('foo_tagged_iterator')->getArgument(0));
|
||||
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', true);
|
||||
$taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', true, 'getPriority');
|
||||
$this->assertEquals(new ServiceLocatorArgument($taggedIterator), $container->getDefinition('foo_tagged_locator')->getArgument(0));
|
||||
}
|
||||
|
||||
|
|
|
@ -277,10 +277,10 @@ class YamlFileLoaderTest extends TestCase
|
|||
$this->assertCount(1, $container->getDefinition('foo_service_tagged_iterator')->getArguments());
|
||||
$this->assertCount(1, $container->getDefinition('foo_service_tagged_locator')->getArguments());
|
||||
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar');
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar', false, 'getPriority');
|
||||
$this->assertEquals($taggedIterator, $container->getDefinition('foo_service_tagged_iterator')->getArgument(0));
|
||||
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar', true);
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', 'barfoo', 'foobar', true, 'getPriority');
|
||||
$this->assertEquals(new ServiceLocatorArgument($taggedIterator), $container->getDefinition('foo_service_tagged_locator')->getArgument(0));
|
||||
|
||||
$taggedIterator = new TaggedIteratorArgument('foo', null, null, true);
|
||||
|
|
|
@ -9,6 +9,11 @@ CHANGELOG
|
|||
* The `TraceableEventDispatcherInterface` has been removed.
|
||||
* The `WrappedListener` class is now final.
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
|
@ -18,7 +23,7 @@ CHANGELOG
|
|||
4.1.0
|
||||
-----
|
||||
|
||||
* added support for invokable event listeners tagged with `kernel.event_listener` by default
|
||||
* added support for invokable event listeners tagged with `kernel.event_listener` by default
|
||||
* The `TraceableEventDispatcher::getOrphanedEvents()` method has been added.
|
||||
* The `TraceableEventDispatcherInterface` has been deprecated.
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\EventDispatcher\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* This pass allows bundles to extend the list of event aliases.
|
||||
*
|
||||
* @author Alexander M. Turek <me@derrabus.de>
|
||||
*/
|
||||
class AddEventAliasesPass implements CompilerPassInterface
|
||||
{
|
||||
private $eventAliases;
|
||||
private $eventAliasesParameter;
|
||||
|
||||
public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases')
|
||||
{
|
||||
$this->eventAliases = $eventAliases;
|
||||
$this->eventAliasesParameter = $eventAliasesParameter;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container): void
|
||||
{
|
||||
$eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : [];
|
||||
|
||||
$container->setParameter(
|
||||
$this->eventAliasesParameter,
|
||||
array_merge($eventAliases, $this->eventAliases)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
|
|||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\AddEventAliasesPass;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
|
@ -67,6 +68,9 @@ class RegisterListenersPassTest extends TestCase
|
|||
$builder->register('my_event_subscriber', AliasedSubscriber::class)
|
||||
->addTag('kernel.event_subscriber');
|
||||
|
||||
$eventAliasPass = new AddEventAliasesPass([CustomEvent::class => 'custom_event']);
|
||||
$eventAliasPass->process($builder);
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($builder);
|
||||
|
||||
|
@ -79,6 +83,14 @@ class RegisterListenersPassTest extends TestCase
|
|||
0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'addListener',
|
||||
[
|
||||
'custom_event',
|
||||
[new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onCustomEvent'],
|
||||
0,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expectedCalls, $builder->getDefinition('event_dispatcher')->getMethodCalls());
|
||||
}
|
||||
|
@ -202,8 +214,12 @@ class RegisterListenersPassTest extends TestCase
|
|||
$container = new ContainerBuilder();
|
||||
$container->setParameter('event_dispatcher.event_aliases', [AliasedEvent::class => 'aliased_event']);
|
||||
$container->register('foo', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => AliasedEvent::class, 'method' => 'onEvent']);
|
||||
$container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => CustomEvent::class, 'method' => 'onEvent']);
|
||||
$container->register('event_dispatcher');
|
||||
|
||||
$eventAliasPass = new AddEventAliasesPass([CustomEvent::class => 'custom_event']);
|
||||
$eventAliasPass->process($container);
|
||||
|
||||
$registerListenersPass = new RegisterListenersPass();
|
||||
$registerListenersPass->process($container);
|
||||
|
||||
|
@ -217,6 +233,14 @@ class RegisterListenersPassTest extends TestCase
|
|||
0,
|
||||
],
|
||||
],
|
||||
[
|
||||
'addListener',
|
||||
[
|
||||
'custom_event',
|
||||
[new ServiceClosureArgument(new Reference('bar')), 'onEvent'],
|
||||
0,
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
|
||||
}
|
||||
|
@ -249,6 +273,7 @@ final class AliasedSubscriber implements EventSubscriberInterface
|
|||
{
|
||||
return [
|
||||
AliasedEvent::class => 'onAliasedEvent',
|
||||
CustomEvent::class => 'onCustomEvent',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -256,3 +281,7 @@ final class AliasedSubscriber implements EventSubscriberInterface
|
|||
final class AliasedEvent
|
||||
{
|
||||
}
|
||||
|
||||
final class CustomEvent
|
||||
{
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ CHANGELOG
|
|||
* Overriding the methods `FormIntegrationTestCase::setUp()`, `TypeTestCase::setUp()` and `TypeTestCase::tearDown()` without the `void` return-type is deprecated.
|
||||
* marked all dispatched event classes as `@final`
|
||||
* Added the `validate` option to `SubmitType` to toggle the browser built-in form validation.
|
||||
* Added the `alpha3` option to `LanguageType` and `CountryType` to use alpha3 instead of alpha2 codes
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
|
|
@ -156,7 +156,7 @@ EOF
|
|||
return 0;
|
||||
}
|
||||
|
||||
private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, string $shortClassName)
|
||||
private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, string $shortClassName): string
|
||||
{
|
||||
$classes = [];
|
||||
sort($this->namespaces);
|
||||
|
@ -197,7 +197,7 @@ EOF
|
|||
return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\nSelect one of the following form types to display its information:", $shortClassName), $classes, $classes[0]);
|
||||
}
|
||||
|
||||
private function getCoreTypes()
|
||||
private function getCoreTypes(): array
|
||||
{
|
||||
$coreExtension = new CoreExtension();
|
||||
$loadTypesRefMethod = (new \ReflectionObject($coreExtension))->getMethod('loadTypes');
|
||||
|
@ -225,7 +225,7 @@ EOF
|
|||
return $typesWithDeprecatedOptions;
|
||||
}
|
||||
|
||||
private function findAlternatives(string $name, array $collection)
|
||||
private function findAlternatives(string $name, array $collection): array
|
||||
{
|
||||
$alternatives = [];
|
||||
foreach ($collection as $item) {
|
||||
|
|
|
@ -167,7 +167,7 @@ abstract class Descriptor implements DescriptorInterface
|
|||
$this->extensionOptions = $filterByDeprecated($this->extensionOptions);
|
||||
}
|
||||
|
||||
private function getParentOptionsResolver(ResolvedFormTypeInterface $type)
|
||||
private function getParentOptionsResolver(ResolvedFormTypeInterface $type): OptionsResolver
|
||||
{
|
||||
$this->parents[$class = \get_class($type->getInnerType())] = [];
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ class TextDescriptor extends Descriptor
|
|||
return $tableRows;
|
||||
}
|
||||
|
||||
private function normalizeAndSortOptionsColumns(array $options)
|
||||
private function normalizeAndSortOptionsColumns(array $options): array
|
||||
{
|
||||
foreach ($options as $group => $opts) {
|
||||
$sorted = false;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Symfony\Component\Form\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
|
||||
|
@ -59,7 +60,7 @@ class FormPass implements CompilerPassInterface
|
|||
$definition->replaceArgument(2, $this->processFormTypeGuessers($container));
|
||||
}
|
||||
|
||||
private function processFormTypes(ContainerBuilder $container)
|
||||
private function processFormTypes(ContainerBuilder $container): Reference
|
||||
{
|
||||
// Get service locator argument
|
||||
$servicesMap = [];
|
||||
|
@ -82,7 +83,7 @@ class FormPass implements CompilerPassInterface
|
|||
return ServiceLocatorTagPass::register($container, $servicesMap);
|
||||
}
|
||||
|
||||
private function processFormTypeExtensions(ContainerBuilder $container)
|
||||
private function processFormTypeExtensions(ContainerBuilder $container): array
|
||||
{
|
||||
$typeExtensions = [];
|
||||
$typeExtensionsClasses = [];
|
||||
|
@ -123,7 +124,7 @@ class FormPass implements CompilerPassInterface
|
|||
return $typeExtensions;
|
||||
}
|
||||
|
||||
private function processFormTypeGuessers(ContainerBuilder $container)
|
||||
private function processFormTypeGuessers(ContainerBuilder $container): ArgumentInterface
|
||||
{
|
||||
$guessers = [];
|
||||
$guessersClasses = [];
|
||||
|
|
|
@ -94,7 +94,7 @@ class DateIntervalToStringTransformer implements DataTransformerInterface
|
|||
return $dateInterval;
|
||||
}
|
||||
|
||||
private function isISO8601(string $string)
|
||||
private function isISO8601(string $string): bool
|
||||
{
|
||||
return preg_match('/^P(?=\w*(?:\d|%\w))(?:\d+Y|%[yY]Y)?(?:\d+M|%[mM]M)?(?:(?:\d+D|%[dD]D)|(?:\d+W|%[wW]W))?(?:T(?:\d+H|[hH]H)?(?:\d+M|[iI]M)?(?:\d+S|[sS]S)?)?$/', $string);
|
||||
}
|
||||
|
|
|
@ -27,16 +27,19 @@ class CountryType extends AbstractType
|
|||
$resolver->setDefaults([
|
||||
'choice_loader' => function (Options $options) {
|
||||
$choiceTranslationLocale = $options['choice_translation_locale'];
|
||||
$alpha3 = $options['alpha3'];
|
||||
|
||||
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) {
|
||||
return array_flip(Countries::getNames($choiceTranslationLocale));
|
||||
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3) {
|
||||
return array_flip($alpha3 ? Countries::getAlpha3Names($choiceTranslationLocale) : Countries::getNames($choiceTranslationLocale));
|
||||
});
|
||||
},
|
||||
'choice_translation_domain' => false,
|
||||
'choice_translation_locale' => null,
|
||||
'alpha3' => false,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']);
|
||||
$resolver->setAllowedTypes('alpha3', 'bool');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,16 +27,19 @@ class LanguageType extends AbstractType
|
|||
$resolver->setDefaults([
|
||||
'choice_loader' => function (Options $options) {
|
||||
$choiceTranslationLocale = $options['choice_translation_locale'];
|
||||
$alpha3 = $options['alpha3'];
|
||||
|
||||
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale) {
|
||||
return array_flip(Languages::getNames($choiceTranslationLocale));
|
||||
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3) {
|
||||
return array_flip($alpha3 ? Languages::getAlpha3Names($choiceTranslationLocale) : Languages::getNames($choiceTranslationLocale));
|
||||
});
|
||||
},
|
||||
'choice_translation_domain' => false,
|
||||
'choice_translation_locale' => null,
|
||||
'alpha3' => false,
|
||||
]);
|
||||
|
||||
$resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']);
|
||||
$resolver->setAllowedTypes('alpha3', 'bool');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -188,7 +188,7 @@ class FormValidator extends ConstraintValidator
|
|||
*
|
||||
* @param string|GroupSequence|(string|GroupSequence)[]|callable $groups The validation groups
|
||||
*
|
||||
* @return (string|GroupSequence)[] The validation groups
|
||||
* @return GroupSequence|(string|GroupSequence)[] The validation groups
|
||||
*/
|
||||
private static function resolveValidationGroups($groups, FormInterface $form)
|
||||
{
|
||||
|
|
|
@ -288,7 +288,7 @@ class FormRenderer implements FormRendererInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function encodeCurrency(Environment $environment, string $text, string $widget = '')
|
||||
public function encodeCurrency(Environment $environment, string $text, string $widget = ''): string
|
||||
{
|
||||
if ('UTF-8' === $charset = $environment->getCharset()) {
|
||||
$text = htmlspecialchars($text, ENT_QUOTES | (\defined('ENT_SUBSTITUTE') ? ENT_SUBSTITUTE : 0), 'UTF-8');
|
||||
|
|
|
@ -57,6 +57,42 @@ class CountryTypeTest extends BaseTypeTest
|
|||
$this->assertContainsEquals(new ChoiceView('MY', 'MY', 'Малайзія'), $choices);
|
||||
}
|
||||
|
||||
public function testAlpha3Option()
|
||||
{
|
||||
$choices = $this->factory
|
||||
->create(static::TESTED_TYPE, null, [
|
||||
'alpha3' => true,
|
||||
])
|
||||
->createView()->vars['choices'];
|
||||
|
||||
// Don't check objects for identity
|
||||
$this->assertContainsEquals(new ChoiceView('DEU', 'DEU', 'Germany'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('GBR', 'GBR', 'United Kingdom'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('USA', 'USA', 'United States'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('FRA', 'FRA', 'France'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('MYS', 'MYS', 'Malaysia'), $choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
public function testChoiceTranslationLocaleAndAlpha3Option()
|
||||
{
|
||||
$choices = $this->factory
|
||||
->create(static::TESTED_TYPE, null, [
|
||||
'choice_translation_locale' => 'uk',
|
||||
'alpha3' => true,
|
||||
])
|
||||
->createView()->vars['choices'];
|
||||
|
||||
// Don't check objects for identity
|
||||
$this->assertContainsEquals(new ChoiceView('DEU', 'DEU', 'Німеччина'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('GBR', 'GBR', 'Велика Британія'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('USA', 'USA', 'Сполучені Штати'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('FRA', 'FRA', 'Франція'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('MYS', 'MYS', 'Малайзія'), $choices);
|
||||
}
|
||||
|
||||
public function testUnknownCountryIsNotIncluded()
|
||||
{
|
||||
$choices = $this->factory->create(static::TESTED_TYPE, 'country')
|
||||
|
|
|
@ -52,6 +52,40 @@ class LanguageTypeTest extends BaseTypeTest
|
|||
$this->assertContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices);
|
||||
}
|
||||
|
||||
public function testAlpha3Option()
|
||||
{
|
||||
$choices = $this->factory
|
||||
->create(static::TESTED_TYPE, null, [
|
||||
'alpha3' => true,
|
||||
])
|
||||
->createView()->vars['choices'];
|
||||
|
||||
// Don't check objects for identity
|
||||
$this->assertContainsEquals(new ChoiceView('eng', 'eng', 'English'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('fra', 'fra', 'French'), $choices);
|
||||
// Burmese has no three letter language code
|
||||
$this->assertNotContainsEquals(new ChoiceView('my', 'my', 'Burmese'), $choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension intl
|
||||
*/
|
||||
public function testChoiceTranslationLocaleAndAlpha3Option()
|
||||
{
|
||||
$choices = $this->factory
|
||||
->create(static::TESTED_TYPE, null, [
|
||||
'choice_translation_locale' => 'uk',
|
||||
'alpha3' => true,
|
||||
])
|
||||
->createView()->vars['choices'];
|
||||
|
||||
// Don't check objects for identity
|
||||
$this->assertContainsEquals(new ChoiceView('eng', 'eng', 'англійська'), $choices);
|
||||
$this->assertContainsEquals(new ChoiceView('fra', 'fra', 'французька'), $choices);
|
||||
// Burmese has no three letter language code
|
||||
$this->assertNotContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices);
|
||||
}
|
||||
|
||||
public function testMultipleLanguagesIsNotIncluded()
|
||||
{
|
||||
$choices = $this->factory->create(static::TESTED_TYPE, 'language')
|
||||
|
|
|
@ -221,7 +221,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
|||
];
|
||||
|
||||
$proxy = self::getProxy($options['proxy'], $url);
|
||||
$noProxy = $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? '';
|
||||
$noProxy = $options['no_proxy'] ?? $_SERVER['no_proxy'] ?? $_SERVER['NO_PROXY'] ?? '';
|
||||
$noProxy = $noProxy ? preg_split('/[\s,]+/', $noProxy) : [];
|
||||
|
||||
$resolveRedirect = self::createRedirectResolver($options, $host, $proxy, $noProxy, $info, $onProgress);
|
||||
|
|
|
@ -164,7 +164,7 @@ class HttpClientDataCollectorTest extends TestCase
|
|||
$this->assertEquals(0, $sut->getRequestCount());
|
||||
}
|
||||
|
||||
private function httpClientThatHasTracedRequests($tracedRequests)
|
||||
private function httpClientThatHasTracedRequests($tracedRequests): TraceableHttpClient
|
||||
{
|
||||
$httpClient = new TraceableHttpClient(new NativeHttpClient());
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use Symfony\Contracts\HttpClient\ResponseInterface;
|
|||
*/
|
||||
class HttpExceptionTraitTest extends TestCase
|
||||
{
|
||||
public function provideParseError()
|
||||
public function provideParseError(): iterable
|
||||
{
|
||||
yield ['application/ld+json', '{"hydra:title": "An error occurred", "hydra:description": "Some details"}'];
|
||||
yield ['application/problem+json', '{"title": "An error occurred", "detail": "Some details"}'];
|
||||
|
|
|
@ -24,7 +24,7 @@ class HttpClientTraitTest extends TestCase
|
|||
/**
|
||||
* @dataProvider providePrepareRequestUrl
|
||||
*/
|
||||
public function testPrepareRequestUrl($expected, $url, $query = [])
|
||||
public function testPrepareRequestUrl(string $expected, string $url, array $query = [])
|
||||
{
|
||||
$defaults = [
|
||||
'base_uri' => 'http://example.com?c=c',
|
||||
|
@ -36,7 +36,7 @@ class HttpClientTraitTest extends TestCase
|
|||
$this->assertSame($expected, implode('', $url));
|
||||
}
|
||||
|
||||
public function providePrepareRequestUrl()
|
||||
public function providePrepareRequestUrl(): iterable
|
||||
{
|
||||
yield ['http://example.com/', 'http://example.com/'];
|
||||
yield ['http://example.com/?a=1&b=b', '.'];
|
||||
|
@ -48,7 +48,7 @@ class HttpClientTraitTest extends TestCase
|
|||
/**
|
||||
* @dataProvider provideResolveUrl
|
||||
*/
|
||||
public function testResolveUrl($base, $url, $expected)
|
||||
public function testResolveUrl(string $base, string $url, string $expected)
|
||||
{
|
||||
$this->assertSame($expected, implode('', self::resolveUrl(self::parseUrl($url), self::parseUrl($base))));
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class HttpClientTraitTest extends TestCase
|
|||
/**
|
||||
* From https://github.com/guzzle/psr7/blob/master/tests/UriResoverTest.php.
|
||||
*/
|
||||
public function provideResolveUrl()
|
||||
public function provideResolveUrl(): array
|
||||
{
|
||||
return [
|
||||
[self::RFC3986_BASE, 'http:h', 'http:h'],
|
||||
|
@ -123,14 +123,14 @@ class HttpClientTraitTest extends TestCase
|
|||
/**
|
||||
* @dataProvider provideParseUrl
|
||||
*/
|
||||
public function testParseUrl($expected, $url, $query = [])
|
||||
public function testParseUrl(array $expected, string $url, array $query = [])
|
||||
{
|
||||
$expected = array_combine(['scheme', 'authority', 'path', 'query', 'fragment'], $expected);
|
||||
|
||||
$this->assertSame($expected, self::parseUrl($url, $query));
|
||||
}
|
||||
|
||||
public function provideParseUrl()
|
||||
public function provideParseUrl(): iterable
|
||||
{
|
||||
yield [['http:', '//example.com', null, null, null], 'http://Example.coM:80'];
|
||||
yield [['https:', '//xn--dj-kia8a.example.com:8000', '/', null, null], 'https://DÉjà.Example.com:8000/'];
|
||||
|
|
|
@ -19,7 +19,7 @@ use Symfony\Component\HttpClient\HttpOptions;
|
|||
*/
|
||||
class HttpOptionsTest extends TestCase
|
||||
{
|
||||
public function provideSetAuthBasic()
|
||||
public function provideSetAuthBasic(): iterable
|
||||
{
|
||||
yield ['user:password', 'user', 'password'];
|
||||
yield ['user:password', 'user:password'];
|
||||
|
|
|
@ -456,7 +456,7 @@ class NativeSessionStorage implements SessionStorageInterface
|
|||
|
||||
foreach ($bags as $bag) {
|
||||
$key = $bag->getStorageKey();
|
||||
$session[$key] = isset($session[$key]) ? $session[$key] : [];
|
||||
$session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : [];
|
||||
$bag->initialize($session[$key]);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ class ControllerResolver implements ControllerResolverInterface
|
|||
return new $class();
|
||||
}
|
||||
|
||||
private function getControllerError($callable)
|
||||
private function getControllerError($callable): string
|
||||
{
|
||||
if (\is_string($callable)) {
|
||||
if (false !== strpos($callable, '::')) {
|
||||
|
@ -209,7 +209,7 @@ class ControllerResolver implements ControllerResolverInterface
|
|||
return $message;
|
||||
}
|
||||
|
||||
private function getClassMethodsWithoutMagicMethods($classOrObject)
|
||||
private function getClassMethodsWithoutMagicMethods($classOrObject): array
|
||||
{
|
||||
$methods = get_class_methods($classOrObject);
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
|||
return 'logger';
|
||||
}
|
||||
|
||||
private function getContainerDeprecationLogs()
|
||||
private function getContainerDeprecationLogs(): array
|
||||
{
|
||||
if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) {
|
||||
return [];
|
||||
|
@ -212,7 +212,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
|||
return array_values($sanitizedLogs);
|
||||
}
|
||||
|
||||
private function isSilencedOrDeprecationErrorLog(array $log)
|
||||
private function isSilencedOrDeprecationErrorLog(array $log): bool
|
||||
{
|
||||
if (!isset($log['context']['exception'])) {
|
||||
return false;
|
||||
|
@ -231,7 +231,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
|||
return false;
|
||||
}
|
||||
|
||||
private function computeErrorsCount(array $containerDeprecationLogs)
|
||||
private function computeErrorsCount(array $containerDeprecationLogs): array
|
||||
{
|
||||
$silencedLogs = [];
|
||||
$count = [
|
||||
|
|
|
@ -89,7 +89,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte
|
|||
return 'memory';
|
||||
}
|
||||
|
||||
private function convertToBytes(string $memoryLimit)
|
||||
private function convertToBytes(string $memoryLimit): int
|
||||
{
|
||||
if ('-1' === $memoryLimit) {
|
||||
return -1;
|
||||
|
|
|
@ -82,7 +82,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
|||
return array_unique($expanded);
|
||||
}
|
||||
|
||||
private function getClassesInComposerClassMaps()
|
||||
private function getClassesInComposerClassMaps(): array
|
||||
{
|
||||
$classes = [];
|
||||
|
||||
|
@ -103,7 +103,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
|||
return array_keys($classes);
|
||||
}
|
||||
|
||||
private function patternsToRegexps(array $patterns)
|
||||
private function patternsToRegexps(array $patterns): array
|
||||
{
|
||||
$regexps = [];
|
||||
|
||||
|
@ -125,7 +125,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface
|
|||
return $regexps;
|
||||
}
|
||||
|
||||
private function matchAnyRegexps(string $class, array $regexps)
|
||||
private function matchAnyRegexps(string $class, array $regexps): bool
|
||||
{
|
||||
$blacklisted = false !== strpos($class, 'Test');
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception;
|
|||
*
|
||||
* @author Kris Wallsmith <kris@symfony.com>
|
||||
*/
|
||||
interface HttpExceptionInterface
|
||||
interface HttpExceptionInterface extends \Throwable
|
||||
{
|
||||
/**
|
||||
* Returns the status code.
|
||||
|
|
|
@ -78,12 +78,12 @@ class UriSigner
|
|||
return $this->computeHash($this->buildUrl($url, $params)) === $hash;
|
||||
}
|
||||
|
||||
private function computeHash(string $uri)
|
||||
private function computeHash(string $uri): string
|
||||
{
|
||||
return base64_encode(hash_hmac('sha256', $uri, $this->secret, true));
|
||||
}
|
||||
|
||||
private function buildUrl(array $url, array $params = [])
|
||||
private function buildUrl(array $url, array $params = []): string
|
||||
{
|
||||
ksort($params, SORT_STRING);
|
||||
$url['query'] = http_build_query($params, '', '&');
|
||||
|
|
|
@ -205,7 +205,7 @@ class LanguageDataGenerator extends AbstractDataGenerator
|
|||
return array_keys($alpha3Codes);
|
||||
}
|
||||
|
||||
private function generateAlpha2ToAlpha3Mapping(ArrayAccessibleResourceBundle $metadataBundle)
|
||||
private function generateAlpha2ToAlpha3Mapping(ArrayAccessibleResourceBundle $metadataBundle): array
|
||||
{
|
||||
$aliases = iterator_to_array($metadataBundle['alias']['language']);
|
||||
$alpha2ToAlpha3 = [];
|
||||
|
|
|
@ -125,7 +125,7 @@ final class Intl
|
|||
*/
|
||||
public static function getIcuStubVersion(): string
|
||||
{
|
||||
return '64.2';
|
||||
return '65.1';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Version": "2.1.48.17",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
"Verenigde Arabiese Emirate dirham"
|
||||
"Verenigde Arabiese Emirate-dirham"
|
||||
],
|
||||
"AFN": [
|
||||
"AFN",
|
||||
|
@ -91,11 +91,11 @@
|
|||
],
|
||||
"BWP": [
|
||||
"BWP",
|
||||
"Botswana pula"
|
||||
"Botswana-pula"
|
||||
],
|
||||
"BYN": [
|
||||
"BYN",
|
||||
"Belo-Russiese roebel"
|
||||
"Belarusiese roebel"
|
||||
],
|
||||
"BYR": [
|
||||
"BYR",
|
||||
|
@ -106,7 +106,7 @@
|
|||
"Beliziese dollar"
|
||||
],
|
||||
"CAD": [
|
||||
"CA$",
|
||||
"CAD",
|
||||
"Kanadese dollar"
|
||||
],
|
||||
"CDF": [
|
||||
|
@ -123,11 +123,11 @@
|
|||
],
|
||||
"CNH": [
|
||||
"CNH",
|
||||
"Chinese joean"
|
||||
"Chinese joean (buiteland)"
|
||||
],
|
||||
"CNY": [
|
||||
"CN¥",
|
||||
"Sjinese joean renminbi"
|
||||
"Chinese joean"
|
||||
],
|
||||
"COP": [
|
||||
"COP",
|
||||
|
@ -155,7 +155,7 @@
|
|||
],
|
||||
"DJF": [
|
||||
"DJF",
|
||||
"Djiboeti frank"
|
||||
"Djiboeti-frank"
|
||||
],
|
||||
"DKK": [
|
||||
"DKK",
|
||||
|
@ -191,7 +191,7 @@
|
|||
],
|
||||
"FKP": [
|
||||
"FKP",
|
||||
"Falkland-eilande pond"
|
||||
"Falkland-eilandse pond"
|
||||
],
|
||||
"GBP": [
|
||||
"£",
|
||||
|
@ -235,7 +235,7 @@
|
|||
],
|
||||
"HKD": [
|
||||
"HK$",
|
||||
"Hong Kong dollar"
|
||||
"Hongkongse dollar"
|
||||
],
|
||||
"HNL": [
|
||||
"HNL",
|
||||
|
@ -323,7 +323,7 @@
|
|||
],
|
||||
"KYD": [
|
||||
"KYD",
|
||||
"Cayman-eilande dollar"
|
||||
"Cayman-eilandse dollar"
|
||||
],
|
||||
"KZT": [
|
||||
"KZT",
|
||||
|
@ -335,7 +335,7 @@
|
|||
],
|
||||
"LBP": [
|
||||
"LBP",
|
||||
"Lebanese pond"
|
||||
"Libanese pond"
|
||||
],
|
||||
"LKR": [
|
||||
"LKR",
|
||||
|
@ -399,7 +399,7 @@
|
|||
],
|
||||
"MUR": [
|
||||
"MUR",
|
||||
"Mauritiaanse rupee"
|
||||
"Mauritiaanse roepee"
|
||||
],
|
||||
"MVR": [
|
||||
"MVR",
|
||||
|
@ -447,7 +447,7 @@
|
|||
],
|
||||
"NZD": [
|
||||
"NZ$",
|
||||
"Nieu-Seeland dollar"
|
||||
"Nieu-Seelandse dollar"
|
||||
],
|
||||
"OMR": [
|
||||
"OMR",
|
||||
|
@ -491,7 +491,7 @@
|
|||
],
|
||||
"RSD": [
|
||||
"RSD",
|
||||
"Serbiese dinar"
|
||||
"Serwiese dinar"
|
||||
],
|
||||
"RUB": [
|
||||
"RUB",
|
||||
|
@ -499,7 +499,7 @@
|
|||
],
|
||||
"RWF": [
|
||||
"RWF",
|
||||
"Rwandiese frank"
|
||||
"Rwandese frank"
|
||||
],
|
||||
"SAR": [
|
||||
"SAR",
|
||||
|
@ -507,11 +507,11 @@
|
|||
],
|
||||
"SBD": [
|
||||
"SBD",
|
||||
"Salomonseilande dollar"
|
||||
"Salomonseilandse dollar"
|
||||
],
|
||||
"SCR": [
|
||||
"SCR",
|
||||
"Seychellese rupee"
|
||||
"Seychellese roepee"
|
||||
],
|
||||
"SDG": [
|
||||
"SDG",
|
||||
|
@ -527,11 +527,11 @@
|
|||
],
|
||||
"SGD": [
|
||||
"SGD",
|
||||
"Singapoer dollar"
|
||||
"Singapoer-dollar"
|
||||
],
|
||||
"SHP": [
|
||||
"SHP",
|
||||
"Sint Helena pond"
|
||||
"Sint Helena-pond"
|
||||
],
|
||||
"SLL": [
|
||||
"SLL",
|
||||
|
@ -555,7 +555,7 @@
|
|||
],
|
||||
"STN": [
|
||||
"STN",
|
||||
"São Tomé en Príncipe dobra"
|
||||
"São Tomé en Príncipe-dobra"
|
||||
],
|
||||
"SYP": [
|
||||
"SYP",
|
||||
|
@ -571,7 +571,7 @@
|
|||
],
|
||||
"TJS": [
|
||||
"TJS",
|
||||
"Tadjikse roebel"
|
||||
"Tadjikse somoni"
|
||||
],
|
||||
"TMT": [
|
||||
"TMT",
|
||||
|
@ -591,11 +591,11 @@
|
|||
],
|
||||
"TRY": [
|
||||
"TRY",
|
||||
"Turkse lier"
|
||||
"Turkse lira"
|
||||
],
|
||||
"TTD": [
|
||||
"TTD",
|
||||
"Trinidad en Tobago dollar"
|
||||
"Trinidad en Tobago-dollar"
|
||||
],
|
||||
"TWD": [
|
||||
"NT$",
|
||||
|
@ -614,8 +614,8 @@
|
|||
"Ugandese sjieling"
|
||||
],
|
||||
"USD": [
|
||||
"US$",
|
||||
"Amerikaanse dollar"
|
||||
"USD",
|
||||
"VSA-dollar"
|
||||
],
|
||||
"UYU": [
|
||||
"UYU",
|
||||
|
@ -631,7 +631,7 @@
|
|||
],
|
||||
"VES": [
|
||||
"VES",
|
||||
"Venezolaanse Bolívar"
|
||||
"Venezolaanse bolívar"
|
||||
],
|
||||
"VND": [
|
||||
"₫",
|
||||
|
@ -647,15 +647,15 @@
|
|||
],
|
||||
"XAF": [
|
||||
"FCFA",
|
||||
"CFA frank BEAC"
|
||||
"Sentraal Afrikaanse CFA-frank"
|
||||
],
|
||||
"XCD": [
|
||||
"EC$",
|
||||
"Oos-Karibbiese dollar"
|
||||
"Oos-Karibiese dollar"
|
||||
],
|
||||
"XOF": [
|
||||
"CFA",
|
||||
"CFA frank BCEAO"
|
||||
"Wes-Afrikaanse CFA-frank"
|
||||
],
|
||||
"XPF": [
|
||||
"CFPF",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.22",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"NAD": [
|
||||
"$",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -105,10 +105,6 @@
|
|||
"BEL",
|
||||
"فرنك بلجيكي مالي"
|
||||
],
|
||||
"BGL": [
|
||||
"BGL",
|
||||
"BGL"
|
||||
],
|
||||
"BGN": [
|
||||
"BGN",
|
||||
"ليف بلغاري"
|
||||
|
@ -314,7 +310,7 @@
|
|||
"فرنك فرنسي"
|
||||
],
|
||||
"GBP": [
|
||||
"£",
|
||||
"UK£",
|
||||
"جنيه إسترليني"
|
||||
],
|
||||
"GEL": [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"DJF": [
|
||||
"Fdj",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ERN": [
|
||||
"Nfk",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"KMF": [
|
||||
"CF",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"SDG": [
|
||||
"SDG",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"SOS": [
|
||||
"S",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"GBP": [
|
||||
"GB£",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.17",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -171,7 +171,7 @@
|
|||
],
|
||||
"BSD": [
|
||||
"BSD",
|
||||
"Bahama Dolları"
|
||||
"Baham Dolları"
|
||||
],
|
||||
"BTN": [
|
||||
"BTN",
|
||||
|
@ -347,7 +347,7 @@
|
|||
],
|
||||
"GBP": [
|
||||
"£",
|
||||
"Britaniya Funt"
|
||||
"Britaniya Funtu"
|
||||
],
|
||||
"GEK": [
|
||||
"GEK",
|
||||
|
@ -367,7 +367,7 @@
|
|||
],
|
||||
"GIP": [
|
||||
"GIP",
|
||||
"Gibraltar Funtu"
|
||||
"Cəbəli-Tariq Funtu"
|
||||
],
|
||||
"GMD": [
|
||||
"GMD",
|
||||
|
@ -491,7 +491,7 @@
|
|||
],
|
||||
"KGS": [
|
||||
"KGS",
|
||||
"Kırğızıstan Somu"
|
||||
"Qırğızıstan Somu"
|
||||
],
|
||||
"KHR": [
|
||||
"KHR",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AZN": [
|
||||
"₼",
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
"дырхем ААЭ"
|
||||
"дырхам ААЭ"
|
||||
],
|
||||
"AFN": [
|
||||
"AFN",
|
||||
|
@ -47,7 +47,7 @@
|
|||
],
|
||||
"BBD": [
|
||||
"BBD",
|
||||
"барбадоскі долар"
|
||||
"барбадаскі долар"
|
||||
],
|
||||
"BDT": [
|
||||
"BDT",
|
||||
|
@ -263,7 +263,7 @@
|
|||
],
|
||||
"IRR": [
|
||||
"IRR",
|
||||
"іранскі рыал"
|
||||
"іранскі рыял"
|
||||
],
|
||||
"ISK": [
|
||||
"ISK",
|
||||
|
@ -291,7 +291,7 @@
|
|||
],
|
||||
"KHR": [
|
||||
"KHR",
|
||||
"камбаджыйскі рыэль"
|
||||
"камбаджыйскі рыель"
|
||||
],
|
||||
"KMF": [
|
||||
"KMF",
|
||||
|
@ -315,7 +315,7 @@
|
|||
],
|
||||
"KZT": [
|
||||
"KZT",
|
||||
"казахстанскі тэнгэ"
|
||||
"казахстанскі тэнге"
|
||||
],
|
||||
"LAK": [
|
||||
"LAK",
|
||||
|
@ -371,7 +371,7 @@
|
|||
],
|
||||
"MRU": [
|
||||
"MRU",
|
||||
"маўрытанская ўгія"
|
||||
"маўрытанская угія"
|
||||
],
|
||||
"MUR": [
|
||||
"MUR",
|
||||
|
@ -403,7 +403,7 @@
|
|||
],
|
||||
"NGN": [
|
||||
"NGN",
|
||||
"нігерыйская найра"
|
||||
"нігерыйская наіра"
|
||||
],
|
||||
"NIO": [
|
||||
"NIO",
|
||||
|
@ -423,7 +423,7 @@
|
|||
],
|
||||
"OMR": [
|
||||
"OMR",
|
||||
"аманскі рыал"
|
||||
"аманскі рыял"
|
||||
],
|
||||
"PAB": [
|
||||
"PAB",
|
||||
|
@ -435,7 +435,7 @@
|
|||
],
|
||||
"PGK": [
|
||||
"PGK",
|
||||
"кіна"
|
||||
"кіна Папуа-Новай Гвінеі"
|
||||
],
|
||||
"PHP": [
|
||||
"PHP",
|
||||
|
@ -455,7 +455,7 @@
|
|||
],
|
||||
"QAR": [
|
||||
"QAR",
|
||||
"катарскі рыал"
|
||||
"катарскі рыял"
|
||||
],
|
||||
"RON": [
|
||||
"RON",
|
||||
|
@ -499,11 +499,11 @@
|
|||
],
|
||||
"SHP": [
|
||||
"SHP",
|
||||
"фунт Святой Алены"
|
||||
"фунт в-ва Святой Алены"
|
||||
],
|
||||
"SLL": [
|
||||
"SLL",
|
||||
"леонэ"
|
||||
"сьера-леонскі леонэ"
|
||||
],
|
||||
"SOS": [
|
||||
"SOS",
|
||||
|
@ -595,7 +595,7 @@
|
|||
],
|
||||
"VES": [
|
||||
"VES",
|
||||
"венесуальскі балівар"
|
||||
"венесуэльскі балівар"
|
||||
],
|
||||
"VND": [
|
||||
"₫",
|
||||
|
@ -603,7 +603,7 @@
|
|||
],
|
||||
"VUV": [
|
||||
"VUV",
|
||||
"вату"
|
||||
"вануацкі вату"
|
||||
],
|
||||
"WST": [
|
||||
"WST",
|
||||
|
@ -631,7 +631,7 @@
|
|||
],
|
||||
"ZAR": [
|
||||
"ZAR",
|
||||
"паўднёваафрыканскі ранд"
|
||||
"паўднёваафрыканскі рэнд"
|
||||
],
|
||||
"ZMW": [
|
||||
"ZMW",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.42",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -763,7 +763,7 @@
|
|||
],
|
||||
"SAR": [
|
||||
"SAR",
|
||||
"Саудитскоарабски риал"
|
||||
"саудитски риал"
|
||||
],
|
||||
"SBD": [
|
||||
"SBD",
|
||||
|
@ -917,6 +917,14 @@
|
|||
"щ.д.",
|
||||
"Щатски долар"
|
||||
],
|
||||
"USN": [
|
||||
"USN",
|
||||
"USN"
|
||||
],
|
||||
"USS": [
|
||||
"USS",
|
||||
"USS"
|
||||
],
|
||||
"UYI": [
|
||||
"UYI",
|
||||
"Уругвайско песо (индекс на инфлацията)"
|
||||
|
@ -979,7 +987,7 @@
|
|||
],
|
||||
"XPF": [
|
||||
"CFPF",
|
||||
"Френскополинезийски франк"
|
||||
"CFP франк"
|
||||
],
|
||||
"YDD": [
|
||||
"YDD",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.36",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"CNY": [
|
||||
"¥",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"CNY": [
|
||||
"CN¥",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.86",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -45,6 +45,18 @@
|
|||
"AON",
|
||||
"kwanza nevez Angola (1990–2000)"
|
||||
],
|
||||
"AOR": [
|
||||
"AOR",
|
||||
"AOR"
|
||||
],
|
||||
"ARA": [
|
||||
"ARA",
|
||||
"ARA"
|
||||
],
|
||||
"ARL": [
|
||||
"ARL",
|
||||
"ARL"
|
||||
],
|
||||
"ARM": [
|
||||
"ARM",
|
||||
"peso Arcʼhantina (1881–1970)"
|
||||
|
@ -105,9 +117,9 @@
|
|||
"BEF",
|
||||
"lur Belgia"
|
||||
],
|
||||
"BEL": [
|
||||
"BEL",
|
||||
"BEL"
|
||||
"BGL": [
|
||||
"BGL",
|
||||
"BGL"
|
||||
],
|
||||
"BGM": [
|
||||
"BGM",
|
||||
|
@ -149,10 +161,38 @@
|
|||
"BOP",
|
||||
"peso Bolivia"
|
||||
],
|
||||
"BOV": [
|
||||
"BOV",
|
||||
"BOV"
|
||||
],
|
||||
"BRB": [
|
||||
"BRB",
|
||||
"BRB"
|
||||
],
|
||||
"BRC": [
|
||||
"BRC",
|
||||
"BRC"
|
||||
],
|
||||
"BRE": [
|
||||
"BRE",
|
||||
"BRE"
|
||||
],
|
||||
"BRL": [
|
||||
"BRL",
|
||||
"real Brazil"
|
||||
],
|
||||
"BRN": [
|
||||
"BRN",
|
||||
"BRN"
|
||||
],
|
||||
"BRR": [
|
||||
"BRR",
|
||||
"BRR"
|
||||
],
|
||||
"BRZ": [
|
||||
"BRZ",
|
||||
"BRZ"
|
||||
],
|
||||
"BSD": [
|
||||
"BSD",
|
||||
"dollar Bahamas"
|
||||
|
@ -229,6 +269,10 @@
|
|||
"COP",
|
||||
"peso Kolombia"
|
||||
],
|
||||
"COU": [
|
||||
"COU",
|
||||
"COU"
|
||||
],
|
||||
"CRC": [
|
||||
"CRC",
|
||||
"colón Costa Rica"
|
||||
|
@ -237,6 +281,10 @@
|
|||
"CSD",
|
||||
"dinar Serbia (2002–2006)"
|
||||
],
|
||||
"CSK": [
|
||||
"CSK",
|
||||
"CSK"
|
||||
],
|
||||
"CUC": [
|
||||
"CUC",
|
||||
"peso kemmadus Kuba"
|
||||
|
@ -281,6 +329,14 @@
|
|||
"DZD",
|
||||
"dinar Aljeria"
|
||||
],
|
||||
"ECS": [
|
||||
"ECS",
|
||||
"ECS"
|
||||
],
|
||||
"ECV": [
|
||||
"ECV",
|
||||
"ECV"
|
||||
],
|
||||
"EEK": [
|
||||
"EEK",
|
||||
"kurunenn Estonia"
|
||||
|
@ -293,6 +349,10 @@
|
|||
"ERN",
|
||||
"nakfa Eritrea"
|
||||
],
|
||||
"ESA": [
|
||||
"ESA",
|
||||
"ESA"
|
||||
],
|
||||
"ESB": [
|
||||
"ESB",
|
||||
"peseta gemmadus Spagn"
|
||||
|
@ -329,10 +389,18 @@
|
|||
"£ RU",
|
||||
"lur Breizh-Veur"
|
||||
],
|
||||
"GEK": [
|
||||
"GEK",
|
||||
"GEK"
|
||||
],
|
||||
"GEL": [
|
||||
"GEL",
|
||||
"lari Jorjia"
|
||||
],
|
||||
"GHC": [
|
||||
"GHC",
|
||||
"GHC"
|
||||
],
|
||||
"GHS": [
|
||||
"GHS",
|
||||
"cedi Ghana"
|
||||
|
@ -365,6 +433,10 @@
|
|||
"GTQ",
|
||||
"quetzal Guatemala"
|
||||
],
|
||||
"GWE": [
|
||||
"GWE",
|
||||
"GWE"
|
||||
],
|
||||
"GWP": [
|
||||
"GWP",
|
||||
"peso Ginea-Bissau"
|
||||
|
@ -533,6 +605,10 @@
|
|||
"LUF",
|
||||
"lur Luksembourg"
|
||||
],
|
||||
"LUL": [
|
||||
"LUL",
|
||||
"LUL"
|
||||
],
|
||||
"LVL": [
|
||||
"LVL",
|
||||
"lats Latvia"
|
||||
|
@ -557,6 +633,10 @@
|
|||
"MCF",
|
||||
"lur Monaco"
|
||||
],
|
||||
"MDC": [
|
||||
"MDC",
|
||||
"MDC"
|
||||
],
|
||||
"MDL": [
|
||||
"MDL",
|
||||
"leu Moldova"
|
||||
|
@ -633,6 +713,10 @@
|
|||
"MXP",
|
||||
"peso arcʼhant Mecʼhiko (1861–1992)"
|
||||
],
|
||||
"MXV": [
|
||||
"MXV",
|
||||
"MXV"
|
||||
],
|
||||
"MYR": [
|
||||
"MYR",
|
||||
"ringgit Malaysia"
|
||||
|
@ -689,6 +773,10 @@
|
|||
"PAB",
|
||||
"balboa Panamá"
|
||||
],
|
||||
"PEI": [
|
||||
"PEI",
|
||||
"PEI"
|
||||
],
|
||||
"PEN": [
|
||||
"PEN",
|
||||
"sol Perou"
|
||||
|
@ -901,6 +989,10 @@
|
|||
"UAH",
|
||||
"hryvnia Ukraina"
|
||||
],
|
||||
"UAK": [
|
||||
"UAK",
|
||||
"UAK"
|
||||
],
|
||||
"UGS": [
|
||||
"UGS",
|
||||
"shilling Ouganda (1966–1987)"
|
||||
|
@ -913,6 +1005,18 @@
|
|||
"$ SU",
|
||||
"dollar SU"
|
||||
],
|
||||
"USN": [
|
||||
"USN",
|
||||
"USN"
|
||||
],
|
||||
"USS": [
|
||||
"USS",
|
||||
"USS"
|
||||
],
|
||||
"UYI": [
|
||||
"UYI",
|
||||
"UYI"
|
||||
],
|
||||
"UYP": [
|
||||
"UYP",
|
||||
"peso Uruguay (1975–1993)"
|
||||
|
@ -981,6 +1085,10 @@
|
|||
"CFPF",
|
||||
"lur CFP"
|
||||
],
|
||||
"XRE": [
|
||||
"XRE",
|
||||
"XRE"
|
||||
],
|
||||
"YDD": [
|
||||
"YDD",
|
||||
"dinar Yemen"
|
||||
|
@ -989,6 +1097,10 @@
|
|||
"YER",
|
||||
"rial Yemen"
|
||||
],
|
||||
"YUD": [
|
||||
"YUD",
|
||||
"YUD"
|
||||
],
|
||||
"YUM": [
|
||||
"YUM",
|
||||
"dinar nevez Yougoslavia (1994–2002)"
|
||||
|
@ -1001,6 +1113,10 @@
|
|||
"YUR",
|
||||
"dinar adreizhet Yougoslavia (1992–1993)"
|
||||
],
|
||||
"ZAL": [
|
||||
"ZAL",
|
||||
"ZAL"
|
||||
],
|
||||
"ZAR": [
|
||||
"ZAR",
|
||||
"rand Suafrika"
|
||||
|
@ -1013,6 +1129,14 @@
|
|||
"ZMW",
|
||||
"kwacha Zambia"
|
||||
],
|
||||
"ZRN": [
|
||||
"ZRN",
|
||||
"ZRN"
|
||||
],
|
||||
"ZRZ": [
|
||||
"ZRZ",
|
||||
"ZRZ"
|
||||
],
|
||||
"ZWD": [
|
||||
"ZWD",
|
||||
"dollar Zimbabwe (1980–2008)"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -1007,7 +1007,7 @@
|
|||
],
|
||||
"VES": [
|
||||
"VES",
|
||||
"venecuelanski bolivar"
|
||||
"Venecuelanski bolivar"
|
||||
],
|
||||
"VND": [
|
||||
"₫",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"AFN": [
|
||||
"AFN",
|
||||
"Авганистански авган"
|
||||
"Афганистански афгани"
|
||||
],
|
||||
"ALL": [
|
||||
"ALL",
|
||||
|
@ -23,7 +23,7 @@
|
|||
],
|
||||
"AMD": [
|
||||
"AMD",
|
||||
"Јерменски драм"
|
||||
"Арменски драм"
|
||||
],
|
||||
"ANG": [
|
||||
"ANG",
|
||||
|
@ -31,7 +31,7 @@
|
|||
],
|
||||
"AOA": [
|
||||
"AOA",
|
||||
"анголска кванза"
|
||||
"Анголска кванза"
|
||||
],
|
||||
"AOK": [
|
||||
"AOK",
|
||||
|
@ -55,7 +55,7 @@
|
|||
],
|
||||
"ARS": [
|
||||
"ARS",
|
||||
"аргентински пезо"
|
||||
"Аргентински пезос"
|
||||
],
|
||||
"ATS": [
|
||||
"ATS",
|
||||
|
@ -87,7 +87,7 @@
|
|||
],
|
||||
"BBD": [
|
||||
"BBD",
|
||||
"Барбадошки долар"
|
||||
"Барбадоски долар"
|
||||
],
|
||||
"BDT": [
|
||||
"BDT",
|
||||
|
@ -131,7 +131,7 @@
|
|||
],
|
||||
"BOB": [
|
||||
"BOB",
|
||||
"Боливијски Боливиано"
|
||||
"Боливијски боливиано"
|
||||
],
|
||||
"BOP": [
|
||||
"BOP",
|
||||
|
@ -155,7 +155,7 @@
|
|||
],
|
||||
"BRL": [
|
||||
"R$",
|
||||
"Бразилски Реал"
|
||||
"Бразилски реал"
|
||||
],
|
||||
"BRN": [
|
||||
"BRN",
|
||||
|
@ -195,7 +195,7 @@
|
|||
],
|
||||
"BZD": [
|
||||
"BZD",
|
||||
"Белизе долар"
|
||||
"Белизеански долар"
|
||||
],
|
||||
"CAD": [
|
||||
"CA$",
|
||||
|
@ -203,7 +203,7 @@
|
|||
],
|
||||
"CDF": [
|
||||
"CDF",
|
||||
"Конголски франак"
|
||||
"Конгоански франак"
|
||||
],
|
||||
"CHE": [
|
||||
"CHE",
|
||||
|
@ -223,15 +223,19 @@
|
|||
],
|
||||
"CLP": [
|
||||
"CLP",
|
||||
"Чилеански пезо"
|
||||
"Чилеански пезос"
|
||||
],
|
||||
"CNH": [
|
||||
"CNH",
|
||||
"Кинески јуан (острвски)"
|
||||
],
|
||||
"CNY": [
|
||||
"CN¥",
|
||||
"Кинески јуан ренминби"
|
||||
"Кинески јуан"
|
||||
],
|
||||
"COP": [
|
||||
"COP",
|
||||
"Колумбијски пезо"
|
||||
"Колумбијски пезос"
|
||||
],
|
||||
"COU": [
|
||||
"COU",
|
||||
|
@ -251,11 +255,11 @@
|
|||
],
|
||||
"CUC": [
|
||||
"CUC",
|
||||
"кубански конвертибилни песо"
|
||||
"кубански конвертибилни пезос"
|
||||
],
|
||||
"CUP": [
|
||||
"CUP",
|
||||
"Кубански пезо"
|
||||
"Кубански пезос"
|
||||
],
|
||||
"CVE": [
|
||||
"CVE",
|
||||
|
@ -279,7 +283,7 @@
|
|||
],
|
||||
"DJF": [
|
||||
"DJF",
|
||||
"Џибутански франак"
|
||||
"Џибутски франак"
|
||||
],
|
||||
"DKK": [
|
||||
"DKK",
|
||||
|
@ -287,7 +291,7 @@
|
|||
],
|
||||
"DOP": [
|
||||
"DOP",
|
||||
"Доминикански пезо"
|
||||
"Доминикански пезос"
|
||||
],
|
||||
"DZD": [
|
||||
"DZD",
|
||||
|
@ -311,7 +315,7 @@
|
|||
],
|
||||
"ERN": [
|
||||
"ERN",
|
||||
"Еритреанска накфа"
|
||||
"Еритрејска накфа"
|
||||
],
|
||||
"ESA": [
|
||||
"ESA",
|
||||
|
@ -327,7 +331,7 @@
|
|||
],
|
||||
"ETB": [
|
||||
"ETB",
|
||||
"етиопијски бир"
|
||||
"Етиопијски бир"
|
||||
],
|
||||
"EUR": [
|
||||
"€",
|
||||
|
@ -343,7 +347,7 @@
|
|||
],
|
||||
"FKP": [
|
||||
"FKP",
|
||||
"Фокландска острва фунта"
|
||||
"Фолкландска фунта"
|
||||
],
|
||||
"FRF": [
|
||||
"FRF",
|
||||
|
@ -371,7 +375,7 @@
|
|||
],
|
||||
"GIP": [
|
||||
"GIP",
|
||||
"Гибралташка фунта"
|
||||
"Гибралтаска фунта"
|
||||
],
|
||||
"GMD": [
|
||||
"GMD",
|
||||
|
@ -407,7 +411,7 @@
|
|||
],
|
||||
"GYD": [
|
||||
"GYD",
|
||||
"Гујански долар"
|
||||
"Гвајански долар"
|
||||
],
|
||||
"HKD": [
|
||||
"HK$",
|
||||
|
@ -435,7 +439,7 @@
|
|||
],
|
||||
"IDR": [
|
||||
"IDR",
|
||||
"Индонезијска рупиа"
|
||||
"Индонежанска рупија"
|
||||
],
|
||||
"IEP": [
|
||||
"IEP",
|
||||
|
@ -455,7 +459,7 @@
|
|||
],
|
||||
"INR": [
|
||||
"₹",
|
||||
"Индијски Рупи"
|
||||
"Индијска рупија"
|
||||
],
|
||||
"IQD": [
|
||||
"IQD",
|
||||
|
@ -463,7 +467,7 @@
|
|||
],
|
||||
"IRR": [
|
||||
"IRR",
|
||||
"Ирански риал"
|
||||
"Ирански ријал"
|
||||
],
|
||||
"ISJ": [
|
||||
"ISJ",
|
||||
|
@ -499,7 +503,7 @@
|
|||
],
|
||||
"KHR": [
|
||||
"KHR",
|
||||
"Камбоџијски риел"
|
||||
"Камбоџански ријел"
|
||||
],
|
||||
"KMF": [
|
||||
"KMF",
|
||||
|
@ -511,7 +515,7 @@
|
|||
],
|
||||
"KRW": [
|
||||
"₩",
|
||||
"Јужнокорејски Вон"
|
||||
"Јужнокорејски вон"
|
||||
],
|
||||
"KWD": [
|
||||
"KWD",
|
||||
|
@ -519,23 +523,23 @@
|
|||
],
|
||||
"KYD": [
|
||||
"KYD",
|
||||
"Кајманска острва долар"
|
||||
"Кајмански долар"
|
||||
],
|
||||
"KZT": [
|
||||
"KZT",
|
||||
"Казахстански тенџ"
|
||||
"Казахстански тенге"
|
||||
],
|
||||
"LAK": [
|
||||
"LAK",
|
||||
"Лаошки кип"
|
||||
"Лаоски кип"
|
||||
],
|
||||
"LBP": [
|
||||
"LBP",
|
||||
"Лебанска фунта"
|
||||
"Либанска фунта"
|
||||
],
|
||||
"LKR": [
|
||||
"LKR",
|
||||
"Шриланкански рупи"
|
||||
"Шриланканска рупија"
|
||||
],
|
||||
"LRD": [
|
||||
"LRD",
|
||||
|
@ -587,11 +591,11 @@
|
|||
],
|
||||
"MDL": [
|
||||
"MDL",
|
||||
"Молдовски љу"
|
||||
"Молдавски леј"
|
||||
],
|
||||
"MGA": [
|
||||
"MGA",
|
||||
"Малагасијски ариари"
|
||||
"Мадагаскарски аријари"
|
||||
],
|
||||
"MGF": [
|
||||
"MGF",
|
||||
|
@ -607,7 +611,7 @@
|
|||
],
|
||||
"MMK": [
|
||||
"MMK",
|
||||
"Мјанмашки кјат"
|
||||
"Мијанмарски кјат"
|
||||
],
|
||||
"MNT": [
|
||||
"MNT",
|
||||
|
@ -615,7 +619,7 @@
|
|||
],
|
||||
"MOP": [
|
||||
"MOP",
|
||||
"Маканишка патака"
|
||||
"Макаоска патака"
|
||||
],
|
||||
"MRO": [
|
||||
"MRO",
|
||||
|
@ -623,7 +627,7 @@
|
|||
],
|
||||
"MRU": [
|
||||
"MRU",
|
||||
"Мауританијска угвија"
|
||||
"Мауританска огија"
|
||||
],
|
||||
"MTL": [
|
||||
"MTL",
|
||||
|
@ -635,11 +639,11 @@
|
|||
],
|
||||
"MUR": [
|
||||
"MUR",
|
||||
"Маурицијски рупи"
|
||||
"Маурицијска рупија"
|
||||
],
|
||||
"MVR": [
|
||||
"MVR",
|
||||
"Малдивијска руфија"
|
||||
"Малдивска руфија"
|
||||
],
|
||||
"MWK": [
|
||||
"MWK",
|
||||
|
@ -647,7 +651,7 @@
|
|||
],
|
||||
"MXN": [
|
||||
"MX$",
|
||||
"Мексички пезо"
|
||||
"Мексички пезос"
|
||||
],
|
||||
"MXP": [
|
||||
"MXP",
|
||||
|
@ -659,7 +663,7 @@
|
|||
],
|
||||
"MYR": [
|
||||
"MYR",
|
||||
"Малезијски ринггит"
|
||||
"Малезијски рингит"
|
||||
],
|
||||
"MZE": [
|
||||
"MZE",
|
||||
|
@ -675,7 +679,7 @@
|
|||
],
|
||||
"NAD": [
|
||||
"NAD",
|
||||
"намбијски долар"
|
||||
"Намибијски долар"
|
||||
],
|
||||
"NGN": [
|
||||
"NGN",
|
||||
|
@ -699,7 +703,7 @@
|
|||
],
|
||||
"NPR": [
|
||||
"NPR",
|
||||
"Непалски рупи"
|
||||
"Непалска рупија"
|
||||
],
|
||||
"NZD": [
|
||||
"NZ$",
|
||||
|
@ -727,15 +731,15 @@
|
|||
],
|
||||
"PGK": [
|
||||
"PGK",
|
||||
"Папуа ново-гвинејшка кина"
|
||||
"Папуанска кина"
|
||||
],
|
||||
"PHP": [
|
||||
"PHP",
|
||||
"Филипински пезо"
|
||||
"Филипински пезос"
|
||||
],
|
||||
"PKR": [
|
||||
"PKR",
|
||||
"Пакистански рупи"
|
||||
"Пакистанска рупија"
|
||||
],
|
||||
"PLN": [
|
||||
"зл",
|
||||
|
@ -751,11 +755,11 @@
|
|||
],
|
||||
"PYG": [
|
||||
"PYG",
|
||||
"Парагвајски гуарни"
|
||||
"Парагвајски гварани"
|
||||
],
|
||||
"QAR": [
|
||||
"QAR",
|
||||
"Катаршки ријал"
|
||||
"Катарски ријал"
|
||||
],
|
||||
"RHD": [
|
||||
"RHD",
|
||||
|
@ -767,7 +771,7 @@
|
|||
],
|
||||
"RON": [
|
||||
"RON",
|
||||
"Румунски леу"
|
||||
"Румунски леј"
|
||||
],
|
||||
"RSD": [
|
||||
"дин.",
|
||||
|
@ -783,7 +787,7 @@
|
|||
],
|
||||
"RWF": [
|
||||
"RWF",
|
||||
"Руандански франак"
|
||||
"Руандски франак"
|
||||
],
|
||||
"SAR": [
|
||||
"SAR",
|
||||
|
@ -791,7 +795,7 @@
|
|||
],
|
||||
"SBD": [
|
||||
"SBD",
|
||||
"Соломонско-острвски долар"
|
||||
"Соломонски долар"
|
||||
],
|
||||
"SCR": [
|
||||
"SCR",
|
||||
|
@ -819,7 +823,7 @@
|
|||
],
|
||||
"SHP": [
|
||||
"SHP",
|
||||
"Св. јеленска фунта"
|
||||
"Света Јелена фунта"
|
||||
],
|
||||
"SIT": [
|
||||
"SIT",
|
||||
|
@ -831,20 +835,24 @@
|
|||
],
|
||||
"SLL": [
|
||||
"SLL",
|
||||
"Сијера-леоншки леоне"
|
||||
"Сијералеонски леоне"
|
||||
],
|
||||
"SOS": [
|
||||
"SOS",
|
||||
"СОмалијски шилинг"
|
||||
"Сомалијски шилинг"
|
||||
],
|
||||
"SRD": [
|
||||
"SRD",
|
||||
"СУринамски долар"
|
||||
"Суринамски долар"
|
||||
],
|
||||
"SRG": [
|
||||
"SRG",
|
||||
"Суринамски гилдер"
|
||||
],
|
||||
"SSP": [
|
||||
"SSP",
|
||||
"Јужносуданска фунта"
|
||||
],
|
||||
"STD": [
|
||||
"STD",
|
||||
"Сао Томе и Принципе добра (1977–2017)"
|
||||
|
@ -867,11 +875,11 @@
|
|||
],
|
||||
"SZL": [
|
||||
"SZL",
|
||||
"Свази лилангени"
|
||||
"Свазилендски лилангени"
|
||||
],
|
||||
"THB": [
|
||||
"THB",
|
||||
"Таи бахт"
|
||||
"Тајски бахт"
|
||||
],
|
||||
"TJR": [
|
||||
"TJR",
|
||||
|
@ -879,7 +887,7 @@
|
|||
],
|
||||
"TJS": [
|
||||
"TJS",
|
||||
"Таљихистански сомони"
|
||||
"Таџикистански сомони"
|
||||
],
|
||||
"TMM": [
|
||||
"TMM",
|
||||
|
@ -891,11 +899,11 @@
|
|||
],
|
||||
"TND": [
|
||||
"TND",
|
||||
"Тунизијски долар"
|
||||
"Туниски динар"
|
||||
],
|
||||
"TOP": [
|
||||
"TOP",
|
||||
"Тонгоншка Панга"
|
||||
"Тонгоанска панга"
|
||||
],
|
||||
"TPE": [
|
||||
"TPE",
|
||||
|
@ -911,7 +919,7 @@
|
|||
],
|
||||
"TTD": [
|
||||
"TTD",
|
||||
"Тринидад тобагошки долар"
|
||||
"Тринидад-тобагошки долар"
|
||||
],
|
||||
"TWD": [
|
||||
"NT$",
|
||||
|
@ -959,7 +967,7 @@
|
|||
],
|
||||
"UYU": [
|
||||
"UYU",
|
||||
"Уругвајски пезо"
|
||||
"Уругвајски пезос"
|
||||
],
|
||||
"UZS": [
|
||||
"UZS",
|
||||
|
@ -1027,7 +1035,7 @@
|
|||
],
|
||||
"YER": [
|
||||
"YER",
|
||||
"Јеменски риал"
|
||||
"Јеменски ријал"
|
||||
],
|
||||
"YUD": [
|
||||
"YUD",
|
||||
|
@ -1047,7 +1055,7 @@
|
|||
],
|
||||
"ZAR": [
|
||||
"ZAR",
|
||||
"Јужно-афрички ранд"
|
||||
"Јужноафрички ранд"
|
||||
],
|
||||
"ZMK": [
|
||||
"ZMK",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.42",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -527,7 +527,7 @@
|
|||
"dinar jordà"
|
||||
],
|
||||
"JPY": [
|
||||
"JP¥",
|
||||
"¥",
|
||||
"ien japonès"
|
||||
],
|
||||
"KES": [
|
||||
|
@ -928,7 +928,7 @@
|
|||
],
|
||||
"SYP": [
|
||||
"SYP",
|
||||
"lliura síria"
|
||||
"lliura siriana"
|
||||
],
|
||||
"SZL": [
|
||||
"SZL",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.69",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"FRF": [
|
||||
"F",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.47.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.48.44",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"AED": [
|
||||
"AED",
|
||||
|
@ -759,7 +759,7 @@
|
|||
],
|
||||
"PHP": [
|
||||
"PHP",
|
||||
"Peso’r Philipinau"
|
||||
"Peso Philipinas"
|
||||
],
|
||||
"PKR": [
|
||||
"PKR",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"Version": "2.1.49.82",
|
||||
"Version": "36",
|
||||
"Names": {
|
||||
"ADP": [
|
||||
"ADP",
|
||||
|
@ -403,7 +403,7 @@
|
|||
],
|
||||
"HKD": [
|
||||
"HK$",
|
||||
"Hongkong dollar"
|
||||
"hongkongsk dollar"
|
||||
],
|
||||
"HNL": [
|
||||
"HNL",
|
||||
|
@ -918,7 +918,7 @@
|
|||
"ugandisk shilling"
|
||||
],
|
||||
"USD": [
|
||||
"$",
|
||||
"US$",
|
||||
"amerikansk dollar"
|
||||
],
|
||||
"USN": [
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue