Merge branch '4.3' into 4.4
* 4.3: (26 commits) Fix Twig 1.x compatibility [Translator] Improve farsi(persian) translations for Form Improve fa translations Spell "triggering" properly Added tests to cover the possibility of having scalars as services. fixed tests on old PHP versions [FrameworkBundle] Inform the user when save_path will be ignored fixed CS [SecurityBundle] Fix profiler dump for non-invokable security listeners fixed CS [Messenger] Doctrine Transport: Support setting auto_setup from DSN [Translator] Load plurals from po files properly [Serializer]: AbstractObjectNormalizer ignores the property types of discriminated classes [EventDispatcher] Add tag kernel.rest on 'debug.event_dispatcher' service [Console] Update to inherit and add licence Add missing test for workflow dump description [Intl] Remove --dev from intl compile autoloader [Messenger] fix publishing headers set on AmqpStamp Remove call to deprecated method [Intl] Init compile tmp volume ...
This commit is contained in:
commit
2e5a8c80c6
@ -76,7 +76,7 @@ class Deprecation
|
|||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
$line = $trace[$i];
|
$line = $trace[$i];
|
||||||
$this->trigerringFilePathType = $this->getPathType($file);
|
$this->triggeringFilePathType = $this->getPathType($file);
|
||||||
if (isset($line['object']) || isset($line['class'])) {
|
if (isset($line['object']) || isset($line['class'])) {
|
||||||
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
|
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
|
||||||
$parsedMsg = unserialize($this->message);
|
$parsedMsg = unserialize($this->message);
|
||||||
@ -88,7 +88,7 @@ class Deprecation
|
|||||||
// then we need to use the serialized information to determine
|
// then we need to use the serialized information to determine
|
||||||
// if the error has been triggered from vendor code.
|
// if the error has been triggered from vendor code.
|
||||||
if (isset($parsedMsg['triggering_file'])) {
|
if (isset($parsedMsg['triggering_file'])) {
|
||||||
$this->trigerringFilePathType = $this->getPathType($parsedMsg['triggering_file']);
|
$this->triggeringFilePathType = $this->getPathType($parsedMsg['triggering_file']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -177,10 +177,10 @@ class Deprecation
|
|||||||
*/
|
*/
|
||||||
public function getType()
|
public function getType()
|
||||||
{
|
{
|
||||||
if (self::PATH_TYPE_SELF === $this->trigerringFilePathType) {
|
if (self::PATH_TYPE_SELF === $this->triggeringFilePathType) {
|
||||||
return self::TYPE_SELF;
|
return self::TYPE_SELF;
|
||||||
}
|
}
|
||||||
if (self::PATH_TYPE_UNDETERMINED === $this->trigerringFilePathType) {
|
if (self::PATH_TYPE_UNDETERMINED === $this->triggeringFilePathType) {
|
||||||
return self::TYPE_UNDETERMINED;
|
return self::TYPE_UNDETERMINED;
|
||||||
}
|
}
|
||||||
$erroringFile = $erroringPackage = null;
|
$erroringFile = $erroringPackage = null;
|
||||||
|
@ -522,6 +522,12 @@ class Configuration implements ConfigurationInterface
|
|||||||
$rootNode
|
$rootNode
|
||||||
->children()
|
->children()
|
||||||
->arrayNode('session')
|
->arrayNode('session')
|
||||||
|
->validate()
|
||||||
|
->ifTrue(function ($v) {
|
||||||
|
return empty($v['handler_id']) && !empty($v['save_path']);
|
||||||
|
})
|
||||||
|
->thenInvalid('Session save path is ignored without a handler service')
|
||||||
|
->end()
|
||||||
->info('session configuration')
|
->info('session configuration')
|
||||||
->canBeEnabled()
|
->canBeEnabled()
|
||||||
->children()
|
->children()
|
||||||
@ -547,7 +553,7 @@ class Configuration implements ConfigurationInterface
|
|||||||
->scalarNode('gc_divisor')->end()
|
->scalarNode('gc_divisor')->end()
|
||||||
->scalarNode('gc_probability')->defaultValue(1)->end()
|
->scalarNode('gc_probability')->defaultValue(1)->end()
|
||||||
->scalarNode('gc_maxlifetime')->end()
|
->scalarNode('gc_maxlifetime')->end()
|
||||||
->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end()
|
->scalarNode('save_path')->end()
|
||||||
->integerNode('metadata_update_threshold')
|
->integerNode('metadata_update_threshold')
|
||||||
->defaultValue(0)
|
->defaultValue(0)
|
||||||
->info('seconds to wait between 2 session metadata updates')
|
->info('seconds to wait between 2 session metadata updates')
|
||||||
|
@ -900,6 +900,11 @@ class FrameworkExtension extends Extension
|
|||||||
|
|
||||||
// session handler (the internal callback registered with PHP session management)
|
// session handler (the internal callback registered with PHP session management)
|
||||||
if (null === $config['handler_id']) {
|
if (null === $config['handler_id']) {
|
||||||
|
// If the user set a save_path without using a non-default \SessionHandler, it will silently be ignored
|
||||||
|
if (isset($config['save_path'])) {
|
||||||
|
throw new LogicException('Session save path is ignored without a handler service');
|
||||||
|
}
|
||||||
|
|
||||||
// Set the handler class to be null
|
// Set the handler class to be null
|
||||||
$container->getDefinition('session.storage.native')->replaceArgument(1, null);
|
$container->getDefinition('session.storage.native')->replaceArgument(1, null);
|
||||||
$container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null);
|
$container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null);
|
||||||
@ -907,6 +912,10 @@ class FrameworkExtension extends Extension
|
|||||||
$container->setAlias('session.handler', $config['handler_id'])->setPrivate(true);
|
$container->setAlias('session.handler', $config['handler_id'])->setPrivate(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset($config['save_path'])) {
|
||||||
|
$config['save_path'] = ini_get('session.save_path');
|
||||||
|
}
|
||||||
|
|
||||||
$container->setParameter('session.save_path', $config['save_path']);
|
$container->setParameter('session.save_path', $config['save_path']);
|
||||||
|
|
||||||
$container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']);
|
$container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<service id="debug.event_dispatcher" class="Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher" decorates="event_dispatcher">
|
<service id="debug.event_dispatcher" class="Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher" decorates="event_dispatcher">
|
||||||
<tag name="monolog.logger" channel="event" />
|
<tag name="monolog.logger" channel="event" />
|
||||||
|
<tag name="kernel.reset" method="reset" />
|
||||||
<argument type="service" id="debug.event_dispatcher.inner" />
|
<argument type="service" id="debug.event_dispatcher.inner" />
|
||||||
<argument type="service" id="debug.stopwatch" />
|
<argument type="service" id="debug.stopwatch" />
|
||||||
<argument type="service" id="logger" on-invalid="null" />
|
<argument type="service" id="logger" on-invalid="null" />
|
||||||
|
@ -301,7 +301,6 @@ class ConfigurationTest extends TestCase
|
|||||||
'cookie_httponly' => true,
|
'cookie_httponly' => true,
|
||||||
'cookie_samesite' => null,
|
'cookie_samesite' => null,
|
||||||
'gc_probability' => 1,
|
'gc_probability' => 1,
|
||||||
'save_path' => '%kernel.cache_dir%/sessions',
|
|
||||||
'metadata_update_threshold' => 0,
|
'metadata_update_threshold' => 0,
|
||||||
],
|
],
|
||||||
'request' => [
|
'request' => [
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$container->loadFromExtension('framework', [
|
||||||
|
'session' => [
|
||||||
|
'handler_id' => null,
|
||||||
|
'save_path' => '/some/path',
|
||||||
|
],
|
||||||
|
]);
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||||
|
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||||
|
|
||||||
|
<framework:config>
|
||||||
|
<framework:session handler-id="null" save-path="/some/path"/>
|
||||||
|
</framework:config>
|
||||||
|
</container>
|
@ -0,0 +1,4 @@
|
|||||||
|
framework:
|
||||||
|
session:
|
||||||
|
handler_id: null
|
||||||
|
save_path: /some/path
|
@ -563,6 +563,14 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||||||
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
|
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
|
||||||
|
*/
|
||||||
|
public function testNullSessionHandlerWithSavePath()
|
||||||
|
{
|
||||||
|
$this->createContainerFromFile('session_savepath');
|
||||||
|
}
|
||||||
|
|
||||||
public function testRequest()
|
public function testRequest()
|
||||||
{
|
{
|
||||||
$container = $this->createContainerFromFile('full');
|
$container = $this->createContainerFromFile('full');
|
||||||
|
@ -39,10 +39,6 @@ final class WrappedListener implements ListenerInterface
|
|||||||
public function __construct($listener)
|
public function __construct($listener)
|
||||||
{
|
{
|
||||||
$this->listener = $listener;
|
$this->listener = $listener;
|
||||||
|
|
||||||
if (null === self::$hasVarDumper) {
|
|
||||||
self::$hasVarDumper = class_exists(ClassStub::class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,8 +72,25 @@ final class WrappedListener implements ListenerInterface
|
|||||||
|
|
||||||
public function getInfo(): array
|
public function getInfo(): array
|
||||||
{
|
{
|
||||||
if (null === $this->stub) {
|
if (null !== $this->stub) {
|
||||||
$this->stub = self::$hasVarDumper ? new ClassStub(\get_class($this->listener)) : \get_class($this->listener);
|
// no-op
|
||||||
|
} elseif (self::$hasVarDumper ?? self::$hasVarDumper = class_exists(ClassStub::class)) {
|
||||||
|
$this->stub = ClassStub::wrapCallable($this->listener);
|
||||||
|
} elseif (\is_array($this->listener)) {
|
||||||
|
$this->stub = (\is_object($this->listener[0]) ? \get_class($this->listener[0]) : $this->listener[0]).'::'.$this->listener[1];
|
||||||
|
} elseif ($this->listener instanceof \Closure) {
|
||||||
|
$r = new \ReflectionFunction($this->listener);
|
||||||
|
if (false !== strpos($r->name, '{closure}')) {
|
||||||
|
$this->stub = 'closure';
|
||||||
|
} elseif ($class = $r->getClosureScopeClass()) {
|
||||||
|
$this->stub = $class->name.'::'.$r->name;
|
||||||
|
} else {
|
||||||
|
$this->stub = $r->name;
|
||||||
|
}
|
||||||
|
} elseif (\is_string($this->listener)) {
|
||||||
|
$this->stub = $this->listener;
|
||||||
|
} else {
|
||||||
|
$this->stub = \get_class($this->listener).'::__invoke';
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -20,7 +20,6 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||||
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
|
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
|
||||||
use Symfony\Component\VarDumper\Caster\ClassStub;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group time-sensitive
|
* @group time-sensitive
|
||||||
@ -56,9 +55,6 @@ class TraceableFirewallListenerTest extends TestCase
|
|||||||
|
|
||||||
$listeners = $firewall->getWrappedListeners();
|
$listeners = $firewall->getWrappedListeners();
|
||||||
$this->assertCount(1, $listeners);
|
$this->assertCount(1, $listeners);
|
||||||
$this->assertSame($response, $listeners[0]['response']);
|
$this->assertSame($listener, $listeners[0]['stub']);
|
||||||
$this->assertInstanceOf(ClassStub::class, $listeners[0]['stub']);
|
|
||||||
$this->assertSame(\get_class($listener), (string) $listeners[0]['stub']);
|
|
||||||
$this->assertSame(1, $listenerCalled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ class ExceptionController
|
|||||||
$exception = $this->profiler->loadProfile($token)->getCollector('exception')->getException();
|
$exception = $this->profiler->loadProfile($token)->getCollector('exception')->getException();
|
||||||
$template = $this->getTemplate();
|
$template = $this->getTemplate();
|
||||||
|
|
||||||
if (!$this->twig->getLoader()->exists($template)) {
|
if (!$this->templateExists($template)) {
|
||||||
return new Response($this->errorRenderer->getBody($exception), 200, ['Content-Type' => 'text/html']);
|
return new Response($this->errorRenderer->getBody($exception), 200, ['Content-Type' => 'text/html']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
<?php
|
<?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\Console\CommandLoader;
|
namespace Symfony\Component\Console\CommandLoader;
|
||||||
|
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
<?php
|
<?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\Console\CommandLoader;
|
namespace Symfony\Component\Console\CommandLoader;
|
||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
@ -77,11 +77,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets style foreground color.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param string|null $color The color name
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException When the color name isn't defined
|
|
||||||
*/
|
*/
|
||||||
public function setForeground($color = null)
|
public function setForeground($color = null)
|
||||||
{
|
{
|
||||||
@ -99,11 +95,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets style background color.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param string|null $color The color name
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException When the color name isn't defined
|
|
||||||
*/
|
*/
|
||||||
public function setBackground($color = null)
|
public function setBackground($color = null)
|
||||||
{
|
{
|
||||||
@ -126,11 +118,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets some specific style option.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param string $option The option name
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException When the option name isn't defined
|
|
||||||
*/
|
*/
|
||||||
public function setOption($option)
|
public function setOption($option)
|
||||||
{
|
{
|
||||||
@ -144,11 +132,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unsets some specific style option.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param string $option The option name
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException When the option name isn't defined
|
|
||||||
*/
|
*/
|
||||||
public function unsetOption($option)
|
public function unsetOption($option)
|
||||||
{
|
{
|
||||||
@ -175,11 +159,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies the style to a given text.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param string $text The text to style
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function apply($text)
|
public function apply($text)
|
||||||
{
|
{
|
||||||
|
@ -21,7 +21,7 @@ interface OutputFormatterStyleInterface
|
|||||||
/**
|
/**
|
||||||
* Sets style foreground color.
|
* Sets style foreground color.
|
||||||
*
|
*
|
||||||
* @param string $color The color name
|
* @param string|null $color The color name
|
||||||
*/
|
*/
|
||||||
public function setForeground($color = null);
|
public function setForeground($color = null);
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ final class ProgressBar
|
|||||||
*
|
*
|
||||||
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
|
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
|
||||||
*/
|
*/
|
||||||
public function iterate(iterable $iterable, ?int $max = null): iterable
|
public function iterate(iterable $iterable, int $max = null): iterable
|
||||||
{
|
{
|
||||||
$this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0));
|
$this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0));
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
|
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
|
||||||
use Symfony\Component\DependencyInjection\TypedReference;
|
use Symfony\Component\DependencyInjection\TypedReference;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
@ -1601,6 +1602,20 @@ class ContainerBuilderTest extends TestCase
|
|||||||
$this->assertSame(['service_container'], array_keys($container->getDefinitions()));
|
$this->assertSame(['service_container'], array_keys($container->getDefinitions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testScalarService()
|
||||||
|
{
|
||||||
|
$c = new ContainerBuilder();
|
||||||
|
$c->register('foo', 'string')
|
||||||
|
->setPublic(true)
|
||||||
|
->setFactory([ScalarFactory::class, 'getSomeValue'])
|
||||||
|
;
|
||||||
|
|
||||||
|
$c->compile();
|
||||||
|
|
||||||
|
$this->assertTrue($c->has('foo'));
|
||||||
|
$this->assertSame('some value', $c->get('foo'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testWither()
|
public function testWither()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
@ -295,6 +295,16 @@ class ContainerTest extends TestCase
|
|||||||
$this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined');
|
$this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testScalarService()
|
||||||
|
{
|
||||||
|
$c = new Container();
|
||||||
|
|
||||||
|
$c->set('foo', 'some value');
|
||||||
|
|
||||||
|
$this->assertTrue($c->has('foo'));
|
||||||
|
$this->assertSame('some value', $c->get('foo'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testInitialized()
|
public function testInitialized()
|
||||||
{
|
{
|
||||||
$sc = new ProjectServiceContainer();
|
$sc = new ProjectServiceContainer();
|
||||||
|
@ -33,6 +33,7 @@ use Symfony\Component\DependencyInjection\ServiceLocator;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
|
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
|
use Symfony\Component\DependencyInjection\Tests\Compiler\Wither;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
||||||
use Symfony\Component\DependencyInjection\TypedReference;
|
use Symfony\Component\DependencyInjection\TypedReference;
|
||||||
@ -1226,6 +1227,25 @@ class PhpDumperTest extends TestCase
|
|||||||
$this->assertSame($foo5, $locator->get('foo5'));
|
$this->assertSame($foo5, $locator->get('foo5'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testScalarService()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->register('foo', 'string')
|
||||||
|
->setPublic(true)
|
||||||
|
->setFactory([ScalarFactory::class, 'getSomeValue'])
|
||||||
|
;
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
|
||||||
|
$dumper = new PhpDumper($container);
|
||||||
|
eval('?>'.$dumper->dump(['class' => 'Symfony_DI_PhpDumper_Test_Scalar_Service']));
|
||||||
|
|
||||||
|
$container = new \Symfony_DI_PhpDumper_Test_Scalar_Service();
|
||||||
|
|
||||||
|
$this->assertTrue($container->has('foo'));
|
||||||
|
$this->assertSame('some value', $container->get('foo'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testWither()
|
public function testWither()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||||
|
|
||||||
|
final class ScalarFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getSomeValue()
|
||||||
|
{
|
||||||
|
return 'some value';
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,15 @@
|
|||||||
<body>
|
<body>
|
||||||
<trans-unit id="28">
|
<trans-unit id="28">
|
||||||
<source>This form should not contain extra fields.</source>
|
<source>This form should not contain extra fields.</source>
|
||||||
<target>این فرم نباید فیلد اضافی داشته باشد.</target>
|
<target>این فرم نباید شامل فیلد اضافه ای باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="29">
|
<trans-unit id="29">
|
||||||
<source>The uploaded file was too large. Please try to upload a smaller file.</source>
|
<source>The uploaded file was too large. Please try to upload a smaller file.</source>
|
||||||
<target>فایل بارگذاری شده بسیار بزرگ است. لطفا فایل کوچکتری را بارگزاری کنید.</target>
|
<target>فایل بارگذاری شده بسیار بزرگ می باشد. لطفا فایل کوچکتری را بارگذاری نمایید.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="30">
|
<trans-unit id="30">
|
||||||
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
|
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
|
||||||
<target>مقدار CSRF نامعتبر است. لطفا فرم را مجددا ارسال فرمایید..</target>
|
<target>توکن CSRF نامعتبر می باشد. لطفا فرم را مجددا ارسال نمایید.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
|
@ -917,8 +917,8 @@ class Request
|
|||||||
$pos = strrpos($host, ':');
|
$pos = strrpos($host, ':');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== $pos) {
|
if (false !== $pos && $port = substr($host, $pos + 1)) {
|
||||||
return (int) substr($host, $pos + 1);
|
return (int) $port;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'https' === $this->getScheme() ? 443 : 80;
|
return 'https' === $this->getScheme() ? 443 : 80;
|
||||||
|
@ -2319,6 +2319,18 @@ class RequestTest extends TestCase
|
|||||||
|
|
||||||
$this->assertSame(443, $request->getPort());
|
$this->assertSame(443, $request->getPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTrustedPortDoesNotDefaultToZero()
|
||||||
|
{
|
||||||
|
Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL);
|
||||||
|
|
||||||
|
$request = Request::create('/');
|
||||||
|
$request->server->set('REMOTE_ADDR', '1.1.1.1');
|
||||||
|
$request->headers->set('X-Forwarded-Host', 'test.example.com');
|
||||||
|
$request->headers->set('X-Forwarded-Port', '');
|
||||||
|
|
||||||
|
$this->assertSame(80, $request->getPort());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RequestContentProxy extends Request
|
class RequestContentProxy extends Request
|
||||||
|
@ -23,7 +23,7 @@ final class UrlHelper
|
|||||||
private $requestStack;
|
private $requestStack;
|
||||||
private $requestContext;
|
private $requestContext;
|
||||||
|
|
||||||
public function __construct(RequestStack $requestStack, ?RequestContext $requestContext = null)
|
public function __construct(RequestStack $requestStack, RequestContext $requestContext = null)
|
||||||
{
|
{
|
||||||
$this->requestStack = $requestStack;
|
$this->requestStack = $requestStack;
|
||||||
$this->requestContext = $requestContext;
|
$this->requestContext = $requestContext;
|
||||||
|
@ -149,7 +149,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte
|
|||||||
return $logs;
|
return $logs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getContainerCompilerLogs(?string $compilerLogsFilepath = null): array
|
private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array
|
||||||
{
|
{
|
||||||
if (!file_exists($compilerLogsFilepath)) {
|
if (!file_exists($compilerLogsFilepath)) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -63,7 +63,7 @@ class LocaleAwareListener implements EventSubscriberInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setLocale(string $locale, ?string $defaultLocale = null): void
|
private function setLocale(string $locale, string $defaultLocale = null): void
|
||||||
{
|
{
|
||||||
foreach ($this->localeAwareServices as $service) {
|
foreach ($this->localeAwareServices as $service) {
|
||||||
try {
|
try {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
$autoload = __DIR__.'/../../vendor/autoload.php';
|
$autoload = __DIR__.'/../../vendor/autoload.php';
|
||||||
|
|
||||||
if (!file_exists($autoload)) {
|
if (!file_exists($autoload)) {
|
||||||
bailout('You should run "composer install --dev" in the component before running this script.');
|
bailout('You should run "composer install" in the component before running this script.');
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once $autoload;
|
require_once $autoload;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
if [[ $1 == force ]]; then
|
[[ $1 == force ]] && docker pull jakzal/php-intl
|
||||||
docker pull jakzal/php-intl
|
[[ ! -d /tmp/symfony/icu ]] && mkdir -p /tmp/symfony/icu
|
||||||
fi;
|
|
||||||
|
|
||||||
docker run \
|
docker run \
|
||||||
-it --rm --name symfony-intl \
|
-it --rm --name symfony-intl \
|
||||||
|
@ -219,7 +219,7 @@ class MessengerPass implements CompilerPassInterface
|
|||||||
throw new RuntimeException(sprintf('Invalid handler service "%s": type-hint of argument "$%s" in method "%s::__invoke()" must be a class , "%s" given.', $serviceId, $parameters[0]->getName(), $handlerClass->getName(), $type));
|
throw new RuntimeException(sprintf('Invalid handler service "%s": type-hint of argument "$%s" in method "%s::__invoke()" must be a class , "%s" given.', $serviceId, $parameters[0]->getName(), $handlerClass->getName(), $type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return [(string) $parameters[0]->getType()];
|
return [$parameters[0]->getType()->getName()];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function registerReceivers(ContainerBuilder $container, array $busIds)
|
private function registerReceivers(ContainerBuilder $container, array $busIds)
|
||||||
|
@ -418,6 +418,21 @@ class ConnectionTest extends TestCase
|
|||||||
$connection->channel();
|
$connection->channel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAmqpStampHeadersAreUsed()
|
||||||
|
{
|
||||||
|
$factory = new TestAmqpFactory(
|
||||||
|
$this->createMock(\AMQPConnection::class),
|
||||||
|
$this->createMock(\AMQPChannel::class),
|
||||||
|
$this->createMock(\AMQPQueue::class),
|
||||||
|
$amqpExchange = $this->createMock(\AMQPExchange::class)
|
||||||
|
);
|
||||||
|
|
||||||
|
$amqpExchange->expects($this->once())->method('publish')->with('body', null, AMQP_NOPARAM, ['headers' => ['Foo' => 'X', 'Bar' => 'Y']]);
|
||||||
|
|
||||||
|
$connection = Connection::fromDsn('amqp://localhost', [], $factory);
|
||||||
|
$connection->publish('body', ['Foo' => 'X'], 0, new AmqpStamp(null, AMQP_NOPARAM, ['headers' => ['Bar' => 'Y']]));
|
||||||
|
}
|
||||||
|
|
||||||
public function testItCanPublishWithTheDefaultRoutingKey()
|
public function testItCanPublishWithTheDefaultRoutingKey()
|
||||||
{
|
{
|
||||||
$factory = new TestAmqpFactory(
|
$factory = new TestAmqpFactory(
|
||||||
|
@ -157,61 +157,86 @@ class ConnectionTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider buildConfigurationProvider
|
* @dataProvider buildConfigurationProvider
|
||||||
*/
|
*/
|
||||||
public function testBuildConfiguration($dsn, $options, $expectedManager, $expectedTableName, $expectedRedeliverTimeout, $expectedQueue)
|
public function testBuildConfiguration($dsn, $options, $expectedConnection, $expectedTableName, $expectedRedeliverTimeout, $expectedQueue, $expectedAutoSetup)
|
||||||
{
|
{
|
||||||
$config = Connection::buildConfiguration($dsn, $options);
|
$config = Connection::buildConfiguration($dsn, $options);
|
||||||
$this->assertEquals($expectedManager, $config['connection']);
|
$this->assertEquals($expectedConnection, $config['connection']);
|
||||||
$this->assertEquals($expectedTableName, $config['table_name']);
|
$this->assertEquals($expectedTableName, $config['table_name']);
|
||||||
$this->assertEquals($expectedRedeliverTimeout, $config['redeliver_timeout']);
|
$this->assertEquals($expectedRedeliverTimeout, $config['redeliver_timeout']);
|
||||||
$this->assertEquals($expectedQueue, $config['queue_name']);
|
$this->assertEquals($expectedQueue, $config['queue_name']);
|
||||||
|
$this->assertEquals($expectedAutoSetup, $config['auto_setup']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildConfigurationProvider()
|
public function buildConfigurationProvider()
|
||||||
{
|
{
|
||||||
return [
|
yield 'no options' => [
|
||||||
[
|
'dsn' => 'doctrine://default',
|
||||||
'dsn' => 'doctrine://default',
|
'options' => [],
|
||||||
'options' => [],
|
'expectedConnection' => 'default',
|
||||||
'expectedManager' => 'default',
|
'expectedTableName' => 'messenger_messages',
|
||||||
'expectedTableName' => 'messenger_messages',
|
'expectedRedeliverTimeout' => 3600,
|
||||||
'expectedRedeliverTimeout' => 3600,
|
'expectedQueue' => 'default',
|
||||||
'expectedQueue' => 'default',
|
'expectedAutoSetup' => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
yield 'test options array' => [
|
||||||
|
'dsn' => 'doctrine://default',
|
||||||
|
'options' => [
|
||||||
|
'table_name' => 'name_from_options',
|
||||||
|
'redeliver_timeout' => 1800,
|
||||||
|
'queue_name' => 'important',
|
||||||
|
'auto_setup' => false,
|
||||||
],
|
],
|
||||||
// test options from options array
|
'expectedConnection' => 'default',
|
||||||
[
|
'expectedTableName' => 'name_from_options',
|
||||||
'dsn' => 'doctrine://default',
|
'expectedRedeliverTimeout' => 1800,
|
||||||
'options' => [
|
'expectedQueue' => 'important',
|
||||||
'table_name' => 'name_from_options',
|
'expectedAutoSetup' => false,
|
||||||
'redeliver_timeout' => 1800,
|
];
|
||||||
'queue_name' => 'important',
|
|
||||||
],
|
yield 'options from dsn' => [
|
||||||
'expectedManager' => 'default',
|
'dsn' => 'doctrine://default?table_name=name_from_dsn&redeliver_timeout=1200&queue_name=normal&auto_setup=false',
|
||||||
'expectedTableName' => 'name_from_options',
|
'options' => [],
|
||||||
'expectedRedeliverTimeout' => 1800,
|
'expectedConnection' => 'default',
|
||||||
'expectedQueue' => 'important',
|
'expectedTableName' => 'name_from_dsn',
|
||||||
],
|
'expectedRedeliverTimeout' => 1200,
|
||||||
// tests options from dsn
|
'expectedQueue' => 'normal',
|
||||||
[
|
'expectedAutoSetup' => false,
|
||||||
'dsn' => 'doctrine://default?table_name=name_from_dsn&redeliver_timeout=1200&queue_name=normal',
|
];
|
||||||
'options' => [],
|
|
||||||
'expectedManager' => 'default',
|
yield 'options from options array wins over options from dsn' => [
|
||||||
'expectedTableName' => 'name_from_dsn',
|
'dsn' => 'doctrine://default?table_name=name_from_dsn&redeliver_timeout=1200&queue_name=normal&auto_setup=true',
|
||||||
'expectedRedeliverTimeout' => 1200,
|
'options' => [
|
||||||
'expectedQueue' => 'normal',
|
'table_name' => 'name_from_options',
|
||||||
],
|
'redeliver_timeout' => 1800,
|
||||||
// test options from options array wins over options from dsn
|
'queue_name' => 'important',
|
||||||
[
|
'auto_setup' => false,
|
||||||
'dsn' => 'doctrine://default?table_name=name_from_dsn&redeliver_timeout=1200&queue_name=normal',
|
|
||||||
'options' => [
|
|
||||||
'table_name' => 'name_from_options',
|
|
||||||
'redeliver_timeout' => 1800,
|
|
||||||
'queue_name' => 'important',
|
|
||||||
],
|
|
||||||
'expectedManager' => 'default',
|
|
||||||
'expectedTableName' => 'name_from_options',
|
|
||||||
'expectedRedeliverTimeout' => 1800,
|
|
||||||
'expectedQueue' => 'important',
|
|
||||||
],
|
],
|
||||||
|
'expectedConnection' => 'default',
|
||||||
|
'expectedTableName' => 'name_from_options',
|
||||||
|
'expectedRedeliverTimeout' => 1800,
|
||||||
|
'expectedQueue' => 'important',
|
||||||
|
'expectedAutoSetup' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
yield 'options from dsn with falsey boolean' => [
|
||||||
|
'dsn' => 'doctrine://default?auto_setup=0',
|
||||||
|
'options' => [],
|
||||||
|
'expectedConnection' => 'default',
|
||||||
|
'expectedTableName' => 'messenger_messages',
|
||||||
|
'expectedRedeliverTimeout' => 3600,
|
||||||
|
'expectedQueue' => 'default',
|
||||||
|
'expectedAutoSetup' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
yield 'options from dsn with thruthy boolean' => [
|
||||||
|
'dsn' => 'doctrine://default?auto_setup=1',
|
||||||
|
'options' => [],
|
||||||
|
'expectedConnection' => 'default',
|
||||||
|
'expectedTableName' => 'messenger_messages',
|
||||||
|
'expectedRedeliverTimeout' => 3600,
|
||||||
|
'expectedQueue' => 'default',
|
||||||
|
'expectedAutoSetup' => true,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Messenger\Transport\AmqpExt;
|
namespace Symfony\Component\Messenger\Transport\AmqpExt;
|
||||||
|
|
||||||
use Symfony\Component\Messenger\Stamp\StampInterface;
|
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Guillaume Gammelin <ggammelin@gmail.com>
|
* @author Guillaume Gammelin <ggammelin@gmail.com>
|
||||||
* @author Samuel Roze <samuel.roze@gmail.com>
|
* @author Samuel Roze <samuel.roze@gmail.com>
|
||||||
*/
|
*/
|
||||||
final class AmqpStamp implements StampInterface
|
final class AmqpStamp implements NonSendableStampInterface
|
||||||
{
|
{
|
||||||
private $routingKey;
|
private $routingKey;
|
||||||
private $flags;
|
private $flags;
|
||||||
|
@ -189,9 +189,7 @@ class Connection
|
|||||||
$this->exchange(),
|
$this->exchange(),
|
||||||
$body,
|
$body,
|
||||||
$this->getRoutingKeyForMessage($amqpStamp),
|
$this->getRoutingKeyForMessage($amqpStamp),
|
||||||
[
|
$headers,
|
||||||
'headers' => $headers,
|
|
||||||
],
|
|
||||||
$amqpStamp
|
$amqpStamp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -221,20 +219,21 @@ class Connection
|
|||||||
$this->getDelayExchange(),
|
$this->getDelayExchange(),
|
||||||
$body,
|
$body,
|
||||||
$this->getRoutingKeyForDelay($delay, $routingKey),
|
$this->getRoutingKeyForDelay($delay, $routingKey),
|
||||||
[
|
$headers,
|
||||||
'headers' => $headers,
|
|
||||||
],
|
|
||||||
$amqpStamp
|
$amqpStamp
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function publishOnExchange(\AMQPExchange $exchange, string $body, string $routingKey = null, array $attributes = [], AmqpStamp $amqpStamp = null)
|
private function publishOnExchange(\AMQPExchange $exchange, string $body, string $routingKey = null, array $headers = [], AmqpStamp $amqpStamp = null)
|
||||||
{
|
{
|
||||||
|
$attributes = $amqpStamp ? $amqpStamp->getAttributes() : [];
|
||||||
|
$attributes['headers'] = array_merge($headers, $attributes['headers'] ?? []);
|
||||||
|
|
||||||
$exchange->publish(
|
$exchange->publish(
|
||||||
$body,
|
$body,
|
||||||
$routingKey,
|
$routingKey,
|
||||||
$amqpStamp ? $amqpStamp->getFlags() : AMQP_NOPARAM,
|
$amqpStamp ? $amqpStamp->getFlags() : AMQP_NOPARAM,
|
||||||
array_merge($amqpStamp ? $amqpStamp->getAttributes() : [], $attributes)
|
$attributes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,22 +74,19 @@ class Connection
|
|||||||
parse_str($components['query'], $query);
|
parse_str($components['query'], $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
$configuration = [
|
$configuration = ['connection' => $components['host']];
|
||||||
'connection' => $components['host'],
|
$configuration += $options + $query + self::DEFAULT_OPTIONS;
|
||||||
'table_name' => $options['table_name'] ?? ($query['table_name'] ?? self::DEFAULT_OPTIONS['table_name']),
|
|
||||||
'queue_name' => $options['queue_name'] ?? ($query['queue_name'] ?? self::DEFAULT_OPTIONS['queue_name']),
|
$configuration['auto_setup'] = filter_var($configuration['auto_setup'], FILTER_VALIDATE_BOOLEAN);
|
||||||
'redeliver_timeout' => $options['redeliver_timeout'] ?? ($query['redeliver_timeout'] ?? self::DEFAULT_OPTIONS['redeliver_timeout']),
|
|
||||||
'auto_setup' => $options['auto_setup'] ?? ($query['auto_setup'] ?? self::DEFAULT_OPTIONS['auto_setup']),
|
|
||||||
];
|
|
||||||
|
|
||||||
// check for extra keys in options
|
// check for extra keys in options
|
||||||
$optionsExtraKeys = array_diff(array_keys($options), array_keys($configuration));
|
$optionsExtraKeys = array_diff(array_keys($options), array_keys(self::DEFAULT_OPTIONS));
|
||||||
if (0 < \count($optionsExtraKeys)) {
|
if (0 < \count($optionsExtraKeys)) {
|
||||||
throw new InvalidArgumentException(sprintf('Unknown option found : [%s]. Allowed options are [%s]', implode(', ', $optionsExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
|
throw new InvalidArgumentException(sprintf('Unknown option found : [%s]. Allowed options are [%s]', implode(', ', $optionsExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for extra keys in options
|
// check for extra keys in options
|
||||||
$queryExtraKeys = array_diff(array_keys($query), array_keys($configuration));
|
$queryExtraKeys = array_diff(array_keys($query), array_keys(self::DEFAULT_OPTIONS));
|
||||||
if (0 < \count($queryExtraKeys)) {
|
if (0 < \count($queryExtraKeys)) {
|
||||||
throw new InvalidArgumentException(sprintf('Unknown option found in DSN: [%s]. Allowed options are [%s]', implode(', ', $queryExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
|
throw new InvalidArgumentException(sprintf('Unknown option found in DSN: [%s]. Allowed options are [%s]', implode(', ', $queryExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class AuthenticationTrustResolver implements AuthenticationTrustResolverInterfac
|
|||||||
private $anonymousClass;
|
private $anonymousClass;
|
||||||
private $rememberMeClass;
|
private $rememberMeClass;
|
||||||
|
|
||||||
public function __construct(?string $anonymousClass = null, ?string $rememberMeClass = null)
|
public function __construct(string $anonymousClass = null, string $rememberMeClass = null)
|
||||||
{
|
{
|
||||||
$this->anonymousClass = $anonymousClass;
|
$this->anonymousClass = $anonymousClass;
|
||||||
$this->rememberMeClass = $rememberMeClass;
|
$this->rememberMeClass = $rememberMeClass;
|
||||||
|
@ -21,7 +21,7 @@ final class ObjectPropertyListExtractor implements ObjectPropertyListExtractorIn
|
|||||||
private $propertyListExtractor;
|
private $propertyListExtractor;
|
||||||
private $objectClassResolver;
|
private $objectClassResolver;
|
||||||
|
|
||||||
public function __construct(PropertyListExtractorInterface $propertyListExtractor, ?callable $objectClassResolver = null)
|
public function __construct(PropertyListExtractorInterface $propertyListExtractor, callable $objectClassResolver = null)
|
||||||
{
|
{
|
||||||
$this->propertyListExtractor = $propertyListExtractor;
|
$this->propertyListExtractor = $propertyListExtractor;
|
||||||
$this->objectClassResolver = $objectClassResolver;
|
$this->objectClassResolver = $objectClassResolver;
|
||||||
|
@ -330,13 +330,14 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
|||||||
|
|
||||||
$reflectionClass = new \ReflectionClass($class);
|
$reflectionClass = new \ReflectionClass($class);
|
||||||
$object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes, $format);
|
$object = $this->instantiateObject($normalizedData, $class, $context, $reflectionClass, $allowedAttributes, $format);
|
||||||
|
$resolvedClass = $this->objectClassResolver ? ($this->objectClassResolver)($object) : \get_class($object);
|
||||||
|
|
||||||
foreach ($normalizedData as $attribute => $value) {
|
foreach ($normalizedData as $attribute => $value) {
|
||||||
if ($this->nameConverter) {
|
if ($this->nameConverter) {
|
||||||
$attribute = $this->nameConverter->denormalize($attribute, $class, $format, $context);
|
$attribute = $this->nameConverter->denormalize($attribute, $resolvedClass, $format, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($class, $attribute, $format, $context)) {
|
if ((false !== $allowedAttributes && !\in_array($attribute, $allowedAttributes)) || !$this->isAllowedAttribute($resolvedClass, $attribute, $format, $context)) {
|
||||||
if (!($context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES])) {
|
if (!($context[self::ALLOW_EXTRA_ATTRIBUTES] ?? $this->defaultContext[self::ALLOW_EXTRA_ATTRIBUTES])) {
|
||||||
$extraAttributes[] = $attribute;
|
$extraAttributes[] = $attribute;
|
||||||
}
|
}
|
||||||
@ -351,7 +352,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = $this->validateAndDenormalize($class, $attribute, $value, $format, $context);
|
$value = $this->validateAndDenormalize($resolvedClass, $attribute, $value, $format, $context);
|
||||||
try {
|
try {
|
||||||
$this->setAttributeValue($object, $attribute, $value, $format, $context);
|
$this->setAttributeValue($object, $attribute, $value, $format, $context);
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
|
@ -15,10 +15,23 @@ class AbstractDummyFirstChild extends AbstractDummy
|
|||||||
{
|
{
|
||||||
public $bar;
|
public $bar;
|
||||||
|
|
||||||
|
/** @var DummyFirstChildQuux|null */
|
||||||
|
public $quux;
|
||||||
|
|
||||||
public function __construct($foo = null, $bar = null)
|
public function __construct($foo = null, $bar = null)
|
||||||
{
|
{
|
||||||
parent::__construct($foo);
|
parent::__construct($foo);
|
||||||
|
|
||||||
$this->bar = $bar;
|
$this->bar = $bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getQuux(): ?DummyFirstChildQuux
|
||||||
|
{
|
||||||
|
return $this->quux;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuux(DummyFirstChildQuux $quux): void
|
||||||
|
{
|
||||||
|
$this->quux = $quux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,23 @@ class AbstractDummySecondChild extends AbstractDummy
|
|||||||
{
|
{
|
||||||
public $baz;
|
public $baz;
|
||||||
|
|
||||||
|
/** @var DummySecondChildQuux|null */
|
||||||
|
public $quux;
|
||||||
|
|
||||||
public function __construct($foo = null, $baz = null)
|
public function __construct($foo = null, $baz = null)
|
||||||
{
|
{
|
||||||
parent::__construct($foo);
|
parent::__construct($foo);
|
||||||
|
|
||||||
$this->baz = $baz;
|
$this->baz = $baz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getQuux(): ?DummySecondChildQuux
|
||||||
|
{
|
||||||
|
return $this->quux;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuux(DummySecondChildQuux $quux): void
|
||||||
|
{
|
||||||
|
$this->quux = $quux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
<?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\Serializer\Tests\Fixtures;
|
||||||
|
|
||||||
|
class DummyFirstChildQuux
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
public function __construct(string $value)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?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\Serializer\Tests\Fixtures;
|
||||||
|
|
||||||
|
class DummySecondChildQuux
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
public function __construct(string $value)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
}
|
@ -16,13 +16,22 @@ use PHPUnit\Framework\TestCase;
|
|||||||
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||||
use Symfony\Component\PropertyInfo\Type;
|
use Symfony\Component\PropertyInfo\Type;
|
||||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||||
|
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
||||||
|
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
|
||||||
|
use Symfony\Component\Serializer\Mapping\ClassMetadata;
|
||||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||||
|
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
|
||||||
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
|
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
|
||||||
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
||||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Serializer;
|
||||||
use Symfony\Component\Serializer\SerializerAwareInterface;
|
use Symfony\Component\Serializer\SerializerAwareInterface;
|
||||||
use Symfony\Component\Serializer\SerializerInterface;
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummy;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\DummySecondChildQuux;
|
||||||
|
|
||||||
class AbstractObjectNormalizerTest extends TestCase
|
class AbstractObjectNormalizerTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -147,6 +156,39 @@ class AbstractObjectNormalizerTest extends TestCase
|
|||||||
return $denormalizer;
|
return $denormalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeWithDiscriminatorMapUsesCorrectClassname()
|
||||||
|
{
|
||||||
|
$factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
|
||||||
|
$loaderMock = $this->getMockBuilder(ClassMetadataFactoryInterface::class)->getMock();
|
||||||
|
$loaderMock->method('hasMetadataFor')->willReturnMap([
|
||||||
|
[
|
||||||
|
AbstractDummy::class,
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$loaderMock->method('getMetadataFor')->willReturnMap([
|
||||||
|
[
|
||||||
|
AbstractDummy::class,
|
||||||
|
new ClassMetadata(
|
||||||
|
AbstractDummy::class,
|
||||||
|
new ClassDiscriminatorMapping('type', [
|
||||||
|
'first' => AbstractDummyFirstChild::class,
|
||||||
|
'second' => AbstractDummySecondChild::class,
|
||||||
|
])
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock);
|
||||||
|
$normalizer = new AbstractObjectNormalizerDummy($factory, null, new PhpDocExtractor(), $discriminatorResolver);
|
||||||
|
$serializer = new Serializer([$normalizer]);
|
||||||
|
$normalizer->setSerializer($serializer);
|
||||||
|
$normalizedData = $normalizer->denormalize(['foo' => 'foo', 'baz' => 'baz', 'quux' => ['value' => 'quux'], 'type' => 'second'], AbstractDummy::class);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(DummySecondChildQuux::class, $normalizedData->quux);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that additional attributes throw an exception if no metadata factory is specified.
|
* Test that additional attributes throw an exception if no metadata factory is specified.
|
||||||
*
|
*
|
||||||
@ -180,7 +222,7 @@ class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer
|
|||||||
|
|
||||||
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = [])
|
protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = [])
|
||||||
{
|
{
|
||||||
return \in_array($attribute, ['foo', 'baz']);
|
return \in_array($attribute, ['foo', 'baz', 'quux', 'value']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null)
|
public function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null)
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Serializer\Tests;
|
|||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
|
||||||
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
|
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
|
||||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
||||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
||||||
@ -34,6 +35,7 @@ use Symfony\Component\Serializer\Serializer;
|
|||||||
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummy;
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummy;
|
||||||
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild;
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild;
|
||||||
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild;
|
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummySecondChild;
|
||||||
|
use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux;
|
||||||
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface;
|
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface;
|
||||||
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne;
|
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne;
|
||||||
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
|
use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo;
|
||||||
@ -382,6 +384,7 @@ class SerializerTest extends TestCase
|
|||||||
public function testDeserializeAndSerializeAbstractObjectsWithTheClassMetadataDiscriminatorResolver()
|
public function testDeserializeAndSerializeAbstractObjectsWithTheClassMetadataDiscriminatorResolver()
|
||||||
{
|
{
|
||||||
$example = new AbstractDummyFirstChild('foo-value', 'bar-value');
|
$example = new AbstractDummyFirstChild('foo-value', 'bar-value');
|
||||||
|
$example->setQuux(new DummyFirstChildQuux('quux'));
|
||||||
|
|
||||||
$loaderMock = $this->getMockBuilder(ClassMetadataFactoryInterface::class)->getMock();
|
$loaderMock = $this->getMockBuilder(ClassMetadataFactoryInterface::class)->getMock();
|
||||||
$loaderMock->method('hasMetadataFor')->willReturnMap([
|
$loaderMock->method('hasMetadataFor')->willReturnMap([
|
||||||
@ -405,9 +408,9 @@ class SerializerTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock);
|
$discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock);
|
||||||
$serializer = new Serializer([new ObjectNormalizer(null, null, null, null, $discriminatorResolver)], ['json' => new JsonEncoder()]);
|
$serializer = new Serializer([new ObjectNormalizer(null, null, null, new PhpDocExtractor(), $discriminatorResolver)], ['json' => new JsonEncoder()]);
|
||||||
|
|
||||||
$jsonData = '{"type":"first","bar":"bar-value","foo":"foo-value"}';
|
$jsonData = '{"type":"first","quux":{"value":"quux"},"bar":"bar-value","foo":"foo-value"}';
|
||||||
|
|
||||||
$deserialized = $serializer->deserialize($jsonData, AbstractDummy::class, 'json');
|
$deserialized = $serializer->deserialize($jsonData, AbstractDummy::class, 'json');
|
||||||
$this->assertEquals($example, $deserialized);
|
$this->assertEquals($example, $deserialized);
|
||||||
|
@ -111,17 +111,12 @@ class MoFileLoader extends FileLoader
|
|||||||
$ids = ['singular' => $singularId, 'plural' => $pluralId];
|
$ids = ['singular' => $singularId, 'plural' => $pluralId];
|
||||||
$item = compact('ids', 'translated');
|
$item = compact('ids', 'translated');
|
||||||
|
|
||||||
if (\is_array($item['translated'])) {
|
if (!empty($item['ids']['singular'])) {
|
||||||
$messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]);
|
$id = $item['ids']['singular'];
|
||||||
if (isset($item['ids']['plural'])) {
|
if (isset($item['ids']['plural'])) {
|
||||||
$plurals = [];
|
$id .= '|'.$item['ids']['plural'];
|
||||||
foreach ($item['translated'] as $plural => $translated) {
|
|
||||||
$plurals[] = sprintf('{%d} %s', $plural, $translated);
|
|
||||||
}
|
|
||||||
$messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
|
|
||||||
}
|
}
|
||||||
} elseif (!empty($item['ids']['singular'])) {
|
$messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
|
||||||
$messages[$item['ids']['singular']] = stripcslashes($item['translated']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,23 +126,24 @@ class PoFileLoader extends FileLoader
|
|||||||
*/
|
*/
|
||||||
private function addMessage(array &$messages, array $item)
|
private function addMessage(array &$messages, array $item)
|
||||||
{
|
{
|
||||||
if (\is_array($item['translated'])) {
|
if (!empty($item['ids']['singular'])) {
|
||||||
$messages[stripcslashes($item['ids']['singular'])] = stripcslashes($item['translated'][0]);
|
$id = stripcslashes($item['ids']['singular']);
|
||||||
if (isset($item['ids']['plural'])) {
|
if (isset($item['ids']['plural'])) {
|
||||||
$plurals = $item['translated'];
|
$id .= '|'.stripcslashes($item['ids']['plural']);
|
||||||
// PO are by definition indexed so sort by index.
|
|
||||||
ksort($plurals);
|
|
||||||
// Make sure every index is filled.
|
|
||||||
end($plurals);
|
|
||||||
$count = key($plurals);
|
|
||||||
// Fill missing spots with '-'.
|
|
||||||
$empties = array_fill(0, $count + 1, '-');
|
|
||||||
$plurals += $empties;
|
|
||||||
ksort($plurals);
|
|
||||||
$messages[stripcslashes($item['ids']['plural'])] = stripcslashes(implode('|', $plurals));
|
|
||||||
}
|
}
|
||||||
} elseif (!empty($item['ids']['singular'])) {
|
|
||||||
$messages[stripcslashes($item['ids']['singular'])] = stripcslashes($item['translated']);
|
$translated = (array) $item['translated'];
|
||||||
|
// PO are by definition indexed so sort by index.
|
||||||
|
ksort($translated);
|
||||||
|
// Make sure every index is filled.
|
||||||
|
end($translated);
|
||||||
|
$count = key($translated);
|
||||||
|
// Fill missing spots with '-'.
|
||||||
|
$empties = array_fill(0, $count + 1, '-');
|
||||||
|
$translated += $empties;
|
||||||
|
ksort($translated);
|
||||||
|
|
||||||
|
$messages[$id] = stripcslashes(implode('|', $translated));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,10 @@ class MoFileLoaderTest extends TestCase
|
|||||||
$resource = __DIR__.'/../fixtures/plurals.mo';
|
$resource = __DIR__.'/../fixtures/plurals.mo';
|
||||||
$catalogue = $loader->load($resource, 'en', 'domain1');
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
$this->assertEquals(['foo' => 'bar', 'foos' => '{0} bar|{1} bars'], $catalogue->all('domain1'));
|
$this->assertEquals([
|
||||||
|
'foo|foos' => 'bar|bars',
|
||||||
|
'{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars',
|
||||||
|
], $catalogue->all('domain1'));
|
||||||
$this->assertEquals('en', $catalogue->getLocale());
|
$this->assertEquals('en', $catalogue->getLocale());
|
||||||
$this->assertEquals([new FileResource($resource)], $catalogue->getResources());
|
$this->assertEquals([new FileResource($resource)], $catalogue->getResources());
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,7 @@ class PoFileLoaderTest extends TestCase
|
|||||||
$catalogue = $loader->load($resource, 'en', 'domain1');
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
$this->assertEquals([
|
$this->assertEquals([
|
||||||
'foo' => 'bar',
|
'foo|foos' => 'bar|bars',
|
||||||
'foos' => 'bar|bars',
|
|
||||||
'{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars',
|
'{0} no foos|one foo|%count% foos' => '{0} no bars|one bar|%count% bars',
|
||||||
], $catalogue->all('domain1'));
|
], $catalogue->all('domain1'));
|
||||||
$this->assertEquals('en', $catalogue->getLocale());
|
$this->assertEquals('en', $catalogue->getLocale());
|
||||||
@ -93,10 +92,8 @@ class PoFileLoaderTest extends TestCase
|
|||||||
$catalogue = $loader->load($resource, 'en', 'domain1');
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
$messages = $catalogue->all('domain1');
|
$messages = $catalogue->all('domain1');
|
||||||
$this->assertArrayHasKey('escaped "foo"', $messages);
|
$this->assertArrayHasKey('escaped "foo"|escaped "foos"', $messages);
|
||||||
$this->assertArrayHasKey('escaped "foos"', $messages);
|
$this->assertEquals('escaped "bar"|escaped "bars"', $messages['escaped "foo"|escaped "foos"']);
|
||||||
$this->assertEquals('escaped "bar"', $messages['escaped "foo"']);
|
|
||||||
$this->assertEquals('escaped "bar"|escaped "bars"', $messages['escaped "foos"']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSkipFuzzyTranslations()
|
public function testSkipFuzzyTranslations()
|
||||||
@ -110,4 +107,16 @@ class PoFileLoaderTest extends TestCase
|
|||||||
$this->assertArrayNotHasKey('foo2', $messages);
|
$this->assertArrayNotHasKey('foo2', $messages);
|
||||||
$this->assertArrayHasKey('foo3', $messages);
|
$this->assertArrayHasKey('foo3', $messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testMissingPlurals()
|
||||||
|
{
|
||||||
|
$loader = new PoFileLoader();
|
||||||
|
$resource = __DIR__.'/../fixtures/missing-plurals.po';
|
||||||
|
$catalogue = $loader->load($resource, 'en', 'domain1');
|
||||||
|
|
||||||
|
$this->assertEquals([
|
||||||
|
'foo|foos' => '-|bar|-|bars',
|
||||||
|
], $catalogue->all('domain1'));
|
||||||
|
$this->assertEquals('en', $catalogue->getLocale());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
4
src/Symfony/Component/Translation/Tests/fixtures/missing-plurals.po
vendored
Normal file
4
src/Symfony/Component/Translation/Tests/fixtures/missing-plurals.po
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
msgid "foo"
|
||||||
|
msgid_plural "foos"
|
||||||
|
msgstr[3] "bars"
|
||||||
|
msgstr[1] "bar"
|
Binary file not shown.
@ -16,19 +16,19 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="4">
|
<trans-unit id="4">
|
||||||
<source>This value should be blank.</source>
|
<source>This value should be blank.</source>
|
||||||
<target>این فیلد باید خالی باشد.</target>
|
<target>این مقدار باید خالی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="5">
|
<trans-unit id="5">
|
||||||
<source>The value you selected is not a valid choice.</source>
|
<source>The value you selected is not a valid choice.</source>
|
||||||
<target>گزینه انتخابی معتبر نیست.</target>
|
<target>مقدار انتخاب شده شامل گزینه های معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="6">
|
<trans-unit id="6">
|
||||||
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
|
<source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
|
||||||
<target>باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید.</target>
|
<target>باید حداقل {{ limit }} گزینه انتخاب نمایید.|باید حداقل {{ limit }} گزینه انتخاب نمایید.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="7">
|
<trans-unit id="7">
|
||||||
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
|
<source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
|
||||||
<target>حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید.</target>
|
<target>حداکثر {{ limit }} گزینه می توانید انتخاب نمایید.|حداکثر {{ limit }} گزینه می توانید انتخاب نمایید.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="8">
|
<trans-unit id="8">
|
||||||
<source>One or more of the given values is invalid.</source>
|
<source>One or more of the given values is invalid.</source>
|
||||||
@ -44,87 +44,87 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="11">
|
<trans-unit id="11">
|
||||||
<source>This value is not a valid date.</source>
|
<source>This value is not a valid date.</source>
|
||||||
<target>این مقدار یک تاریخ معتبر نیست.</target>
|
<target>این مقدار یک تاریخ معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="12">
|
<trans-unit id="12">
|
||||||
<source>This value is not a valid datetime.</source>
|
<source>This value is not a valid datetime.</source>
|
||||||
<target>این مقدار یک تاریخ و زمان معتبر نیست.</target>
|
<target>این مقدار یک تاریخ و زمان معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="13">
|
<trans-unit id="13">
|
||||||
<source>This value is not a valid email address.</source>
|
<source>This value is not a valid email address.</source>
|
||||||
<target>این یک رایانامه معتبر نیست.</target>
|
<target>این یک رایانامه معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="14">
|
<trans-unit id="14">
|
||||||
<source>The file could not be found.</source>
|
<source>The file could not be found.</source>
|
||||||
<target>فایل پیدا نشد.</target>
|
<target>فایل یافت نشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="15">
|
<trans-unit id="15">
|
||||||
<source>The file is not readable.</source>
|
<source>The file is not readable.</source>
|
||||||
<target>فایل قابلیت خواندن ندارد.</target>
|
<target>فایل قابلیت خوانده شدن ندارد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="16">
|
<trans-unit id="16">
|
||||||
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
<source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||||
<target>فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
|
<target>فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر با {{ limit }} {{ suffix }} می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="17">
|
<trans-unit id="17">
|
||||||
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
|
<source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
|
||||||
<target>این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند.</target>
|
<target>این نوع فایل مجاز نمی باشد({{ type }}). نوع های مجاز شامل {{ types }} می باشند.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="18">
|
<trans-unit id="18">
|
||||||
<source>This value should be {{ limit }} or less.</source>
|
<source>This value should be {{ limit }} or less.</source>
|
||||||
<target>این مقدار باید کوچکتر یا مساوی {{ limit }} باشد.</target>
|
<target>این مقدار باید کوچکتر و یا مساوی {{ limit }} باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="19">
|
<trans-unit id="19">
|
||||||
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
|
<source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
|
||||||
<target>بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.</target>
|
<target>بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} می باشد.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="20">
|
<trans-unit id="20">
|
||||||
<source>This value should be {{ limit }} or more.</source>
|
<source>This value should be {{ limit }} or more.</source>
|
||||||
<target>این مقدار باید برابر و یا بیشتر از {{ limit }} باشد.</target>
|
<target>این مقدار باید بزرگتر و یا مساوی {{ limit }} باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="21">
|
<trans-unit id="21">
|
||||||
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
|
<source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
|
||||||
<target>بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.</target>
|
<target>مقدار وارد شده بسیار کوتاه است.تعداد حروف وارد شده، باید حداقل شامل {{ limit }} کاراکتر باشد.|مقدار وارد شده بسیار کوتاه است.تعداد حروف وارد شده، باید حداقل شامل {{ limit }} کاراکتر باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="22">
|
<trans-unit id="22">
|
||||||
<source>This value should not be blank.</source>
|
<source>This value should not be blank.</source>
|
||||||
<target>این مقدار نباید تهی باشد.</target>
|
<target>این مقدار نباید خالی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="23">
|
<trans-unit id="23">
|
||||||
<source>This value should not be null.</source>
|
<source>This value should not be null.</source>
|
||||||
<target>باید مقداری داشته باشد..</target>
|
<target>این مقدار باید شامل چیزی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="24">
|
<trans-unit id="24">
|
||||||
<source>This value should be null.</source>
|
<source>This value should be null.</source>
|
||||||
<target>نباید مقداری داشته باشد.</target>
|
<target>این مقدار باید شامل چیزی نباشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="25">
|
<trans-unit id="25">
|
||||||
<source>This value is not valid.</source>
|
<source>This value is not valid.</source>
|
||||||
<target>این مقدار معتبر نیست.</target>
|
<target>این مقدار معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="26">
|
<trans-unit id="26">
|
||||||
<source>This value is not a valid time.</source>
|
<source>This value is not a valid time.</source>
|
||||||
<target>این مقدار یک زمان صحیح نیست.</target>
|
<target>این مقدار یک زمان صحیح نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="27">
|
<trans-unit id="27">
|
||||||
<source>This value is not a valid URL.</source>
|
<source>This value is not a valid URL.</source>
|
||||||
<target>این یک URL معتبر نیست.</target>
|
<target>این مقدار شامل یک URL معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="31">
|
<trans-unit id="31">
|
||||||
<source>The two values should be equal.</source>
|
<source>The two values should be equal.</source>
|
||||||
<target>دو مقدار باید برابر باشند.</target>
|
<target>دو مقدار باید با یکدیگر برابر باشند.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="32">
|
<trans-unit id="32">
|
||||||
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
<source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
|
||||||
<target>فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
|
<target>فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر با {{ limit }} {{ suffix }} می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="33">
|
<trans-unit id="33">
|
||||||
<source>The file is too large.</source>
|
<source>The file is too large.</source>
|
||||||
<target>فایل بیش از اندازه بزرگ است.</target>
|
<target>فایل بیش از اندازه بزرگ می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="34">
|
<trans-unit id="34">
|
||||||
<source>The file could not be uploaded.</source>
|
<source>The file could not be uploaded.</source>
|
||||||
<target>بارگذاری فایل با شکست مواجه شد.</target>
|
<target>بارگذاری فایل با شکست مواجه گردید.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="35">
|
<trans-unit id="35">
|
||||||
<source>This value should be a valid number.</source>
|
<source>This value should be a valid number.</source>
|
||||||
@ -132,23 +132,23 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="36">
|
<trans-unit id="36">
|
||||||
<source>This file is not a valid image.</source>
|
<source>This file is not a valid image.</source>
|
||||||
<target>این فایل یک تصویر نیست.</target>
|
<target>این فایل یک تصویر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="37">
|
<trans-unit id="37">
|
||||||
<source>This is not a valid IP address.</source>
|
<source>This is not a valid IP address.</source>
|
||||||
<target>این مقدار یک IP معتبر نیست.</target>
|
<target>این مقدار یک IP معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="38">
|
<trans-unit id="38">
|
||||||
<source>This value is not a valid language.</source>
|
<source>This value is not a valid language.</source>
|
||||||
<target>این مقدار یک زبان صحیح نیست.</target>
|
<target>این مقدار یک زبان صحیح نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="39">
|
<trans-unit id="39">
|
||||||
<source>This value is not a valid locale.</source>
|
<source>This value is not a valid locale.</source>
|
||||||
<target>این مقدار یک محل صحیح نیست.</target>
|
<target>این مقدار یک محل صحیح نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="40">
|
<trans-unit id="40">
|
||||||
<source>This value is not a valid country.</source>
|
<source>This value is not a valid country.</source>
|
||||||
<target>این مقدار یک کشور صحیح نیست.</target>
|
<target>این مقدار یک کشور صحیح نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="41">
|
<trans-unit id="41">
|
||||||
<source>This value is already used.</source>
|
<source>This value is already used.</source>
|
||||||
@ -156,23 +156,23 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="42">
|
<trans-unit id="42">
|
||||||
<source>The size of the image could not be detected.</source>
|
<source>The size of the image could not be detected.</source>
|
||||||
<target>اندازه تصویر قابل شناسایی نیست.</target>
|
<target>اندازه تصویر قابل شناسایی نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="43">
|
<trans-unit id="43">
|
||||||
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
|
<source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
|
||||||
<target>طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است.</target>
|
<target>طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="44">
|
<trans-unit id="44">
|
||||||
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
|
<source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
|
||||||
<target>طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است.</target>
|
<target>طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="45">
|
<trans-unit id="45">
|
||||||
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
|
<source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
|
||||||
<target>ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است.</target>
|
<target>ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="46">
|
<trans-unit id="46">
|
||||||
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
|
<source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
|
||||||
<target>ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است.</target>
|
<target>ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="47">
|
<trans-unit id="47">
|
||||||
<source>This value should be the user's current password.</source>
|
<source>This value should be the user's current password.</source>
|
||||||
@ -184,67 +184,67 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="49">
|
<trans-unit id="49">
|
||||||
<source>The file was only partially uploaded.</source>
|
<source>The file was only partially uploaded.</source>
|
||||||
<target>فایل به صورت جزیی بارگذاری شده است.</target>
|
<target>پرونده به صورت جزیی بارگذاری گردیده است.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="50">
|
<trans-unit id="50">
|
||||||
<source>No file was uploaded.</source>
|
<source>No file was uploaded.</source>
|
||||||
<target>هیچ فایلی بارگذاری نشد.</target>
|
<target>هیچ پرونده ای بارگذاری نگردیده است.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="51">
|
<trans-unit id="51">
|
||||||
<source>No temporary folder was configured in php.ini.</source>
|
<source>No temporary folder was configured in php.ini.</source>
|
||||||
<target>فولدر موقت در php.ini پیکربندی نشده است.</target>
|
<target>فولدر موقت در php.ini پیکربندی نگردیده است.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="52">
|
<trans-unit id="52">
|
||||||
<source>Cannot write temporary file to disk.</source>
|
<source>Cannot write temporary file to disk.</source>
|
||||||
<target>فایل موقت را نمی توان در دیسک نوشت.</target>
|
<target>فایل موقتی را نمی توان در دیسک نوشت.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="53">
|
<trans-unit id="53">
|
||||||
<source>A PHP extension caused the upload to fail.</source>
|
<source>A PHP extension caused the upload to fail.</source>
|
||||||
<target>اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود.</target>
|
<target>یک اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه گردد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="54">
|
<trans-unit id="54">
|
||||||
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
|
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
|
||||||
<target>این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.</target>
|
<target>این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا بیشتر باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="55">
|
<trans-unit id="55">
|
||||||
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
|
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
|
||||||
<target>این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد.</target>
|
<target>این مجموعه می بایست دارای حداکثر {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای حداکثر {{ limit }} عنصر یا کمتر باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="56">
|
<trans-unit id="56">
|
||||||
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
|
<source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
|
||||||
<target>این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد.</target>
|
<target>این مجموعه می بایست به طور دقیق دارای {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} عنصر باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="57">
|
<trans-unit id="57">
|
||||||
<source>Invalid card number.</source>
|
<source>Invalid card number.</source>
|
||||||
<target>شماره کارت نامعتبر است.</target>
|
<target>شماره کارت نامعتبر می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="58">
|
<trans-unit id="58">
|
||||||
<source>Unsupported card type or invalid card number.</source>
|
<source>Unsupported card type or invalid card number.</source>
|
||||||
<target>نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است.</target>
|
<target>نوع کارت پشتیبانی نمی شود و یا شماره کارت نامعتبر می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="59">
|
<trans-unit id="59">
|
||||||
<source>This is not a valid International Bank Account Number (IBAN).</source>
|
<source>This is not a valid International Bank Account Number (IBAN).</source>
|
||||||
<target>این یک شماره حساب بین المللی بانک (IBAN) درست نیست.</target>
|
<target>این یک شماره حساب بانک بین المللی معتبر نمی باشد (IBAN).</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="60">
|
<trans-unit id="60">
|
||||||
<source>This value is not a valid ISBN-10.</source>
|
<source>This value is not a valid ISBN-10.</source>
|
||||||
<target>این مقدار یک ISBN-10 درست نیست.</target>
|
<target>این مقدار یک ISBN-10 معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="61">
|
<trans-unit id="61">
|
||||||
<source>This value is not a valid ISBN-13.</source>
|
<source>This value is not a valid ISBN-13.</source>
|
||||||
<target>این مقدار یک ISBN-13 درست نیست.</target>
|
<target>این مقدار یک ISBN-13 معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="62">
|
<trans-unit id="62">
|
||||||
<source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
|
<source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
|
||||||
<target>این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست.</target>
|
<target>این مقدار یک ISBN-10 صحیح و یا ISBN-13 معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="63">
|
<trans-unit id="63">
|
||||||
<source>This value is not a valid ISSN.</source>
|
<source>This value is not a valid ISSN.</source>
|
||||||
<target>این مقدار یک ISSN درست نیست.</target>
|
<target>این مقدار یک ISSN معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="64">
|
<trans-unit id="64">
|
||||||
<source>This value is not a valid currency.</source>
|
<source>This value is not a valid currency.</source>
|
||||||
<target>این مقدار یک یکای پول درست نیست.</target>
|
<target>این مقدار یک واحد پول معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="65">
|
<trans-unit id="65">
|
||||||
<source>This value should be equal to {{ compared_value }}.</source>
|
<source>This value should be equal to {{ compared_value }}.</source>
|
||||||
@ -256,11 +256,11 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="67">
|
<trans-unit id="67">
|
||||||
<source>This value should be greater than or equal to {{ compared_value }}.</source>
|
<source>This value should be greater than or equal to {{ compared_value }}.</source>
|
||||||
<target>این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد.</target>
|
<target>این مقدار باید بزرگتر و یا مساوی با {{ compared_value }} باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="68">
|
<trans-unit id="68">
|
||||||
<source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
<source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||||
<target>این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
|
<target>این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکسان باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="69">
|
<trans-unit id="69">
|
||||||
<source>This value should be less than {{ compared_value }}.</source>
|
<source>This value should be less than {{ compared_value }}.</source>
|
||||||
@ -268,7 +268,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="70">
|
<trans-unit id="70">
|
||||||
<source>This value should be less than or equal to {{ compared_value }}.</source>
|
<source>This value should be less than or equal to {{ compared_value }}.</source>
|
||||||
<target>این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد.</target>
|
<target>این مقدار باید کمتر و یا مساوی با {{ compared_value }} باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="71">
|
<trans-unit id="71">
|
||||||
<source>This value should not be equal to {{ compared_value }}.</source>
|
<source>This value should not be equal to {{ compared_value }}.</source>
|
||||||
@ -276,43 +276,43 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="72">
|
<trans-unit id="72">
|
||||||
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
|
||||||
<target>این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
|
<target>این مقدار نباید با {{ compared_value_type }} {{ compared_value }} یکسان باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="73">
|
<trans-unit id="73">
|
||||||
<source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
|
<source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
|
||||||
<target>ابعاد {{ ratio }} عکس بیش از حد بزرگ است.حداکثر ابعاد مجاز {{ max_ratio }} است.</target>
|
<target>ابعاد {{ ratio }} عکس بیش از حد بزرگ است.حداکثر ابعاد مجاز {{ max_ratio }} می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="74">
|
<trans-unit id="74">
|
||||||
<source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
|
<source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
|
||||||
<target>ابعاد {{ ratio }} عکس بیش از حد کوچک است.حداقل ابعاد مجاز {{ min_ratio }} است.</target>
|
<target>ابعاد {{ ratio }} عکس بیش از حد کوچک است.حداقل ابعاد مجاز {{ min_ratio }} می باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="75">
|
<trans-unit id="75">
|
||||||
<source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
|
<source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
|
||||||
<target>این عکس مربع width }}x{{ height }}px}} می باشد.عکس مربع مجاز نمی باشد.</target>
|
<target>این تصویر یک مربع width }}x{{ height }}px}} می باشد.تصویر مربع مجاز نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="76">
|
<trans-unit id="76">
|
||||||
<source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
|
<source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
|
||||||
<target>این عکس افقی width }}x{{ height }}px}} می باشد.عکس افقی مجاز نمی باشد.</target>
|
<target>این تصویر افقی width }}x{{ height }}px}} می باشد.تصویر افقی مجاز نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="77">
|
<trans-unit id="77">
|
||||||
<source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
|
<source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
|
||||||
<target>این عکس عمودی width }}x{{ height }}px}} می باشد.عکس عمودی مجاز نمی باشد.</target>
|
<target>این تصویر عمودی width }}x{{ height }}px}} می باشد.تصویر عمودی مجاز نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="78">
|
<trans-unit id="78">
|
||||||
<source>An empty file is not allowed.</source>
|
<source>An empty file is not allowed.</source>
|
||||||
<target>فایل خالی مجاز نمی باشد.</target>
|
<target>پرونده خالی مجاز نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="79">
|
<trans-unit id="79">
|
||||||
<source>The host could not be resolved.</source>
|
<source>The host could not be resolved.</source>
|
||||||
<target>هاست قابل حل نیست.</target>
|
<target>میزبان قابل حل نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="80">
|
<trans-unit id="80">
|
||||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||||
<target>این مقدار مورد نظر نمی باشد. مقدار مورد نظر {{ charset }} می باشد.</target>
|
<target>این مقدار مطابق با مقدار مورد انتظار {{ charset }} نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="81">
|
<trans-unit id="81">
|
||||||
<source>This is not a valid Business Identifier Code (BIC).</source>
|
<source>This is not a valid Business Identifier Code (BIC).</source>
|
||||||
<target>این مقدار یک BIC درست نیست.</target>
|
<target>این مقدار یک BIC معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="82">
|
<trans-unit id="82">
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
@ -320,7 +320,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="83">
|
<trans-unit id="83">
|
||||||
<source>This is not a valid UUID.</source>
|
<source>This is not a valid UUID.</source>
|
||||||
<target>این مقدار یک UUID درست نیست.</target>
|
<target>این مقدار یک UUID معتبر نمی باشد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="84">
|
<trans-unit id="84">
|
||||||
<source>This value should be a multiple of {{ compared_value }}.</source>
|
<source>This value should be a multiple of {{ compared_value }}.</source>
|
||||||
@ -328,7 +328,7 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="85">
|
<trans-unit id="85">
|
||||||
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
|
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
|
||||||
<target>این BIC با IBAN ارتباط ندارد.</target>
|
<target>این BIC با IBAN ارتباطی ندارد.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
|
@ -56,6 +56,7 @@ trait WorkflowBuilderTrait
|
|||||||
$placesMetadata = [];
|
$placesMetadata = [];
|
||||||
$placesMetadata['c'] = [
|
$placesMetadata['c'] = [
|
||||||
'bg_color' => 'DeepSkyBlue',
|
'bg_color' => 'DeepSkyBlue',
|
||||||
|
'description' => 'My custom place description',
|
||||||
];
|
];
|
||||||
|
|
||||||
$transitionsMetadata = new \SplObjectStorage();
|
$transitionsMetadata = new \SplObjectStorage();
|
||||||
|
@ -17,7 +17,8 @@ skinparam agent {
|
|||||||
}
|
}
|
||||||
state "a" <<initial>>
|
state "a" <<initial>>
|
||||||
state "b" <<marked>>
|
state "b" <<marked>>
|
||||||
state "c" <<DeepSkyBlue>>
|
state "c" <<DeepSkyBlue>> as c
|
||||||
|
c : My custom place description
|
||||||
agent "t1"
|
agent "t1"
|
||||||
agent "t2"
|
agent "t2"
|
||||||
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
|
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
|
||||||
|
@ -17,7 +17,8 @@ skinparam agent {
|
|||||||
}
|
}
|
||||||
state "a" <<initial>>
|
state "a" <<initial>>
|
||||||
state "b"
|
state "b"
|
||||||
state "c" <<DeepSkyBlue>>
|
state "c" <<DeepSkyBlue>> as c
|
||||||
|
c : My custom place description
|
||||||
agent "t1"
|
agent "t1"
|
||||||
agent "t2"
|
agent "t2"
|
||||||
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
|
"a" -[#Purple]-> "t1": "<font color=Grey>My custom transition label 2</font>"
|
||||||
|
Reference in New Issue
Block a user