Merge branch '4.4'
* 4.4: [travis] Fix build-packages script Add types to constructors and private/final/internal methods (Batch III) [HttpClient] Async HTTPlug client [Messenger] Allow to configure the db index on Redis transport [HttpClient] bugfix exploding values of headers [VarDumper] Made all casters final [VarDumper] Added a support for casting Ramsey/Uuid Remove useless testCanCheckIfTerminalIsInteractive test case [Validator] Add the missing translations for the Thai (\"th\") locale [Routing] gracefully handle docref_root ini setting [Validator] Fix ValidValidator group cascading usage
This commit is contained in:
commit
4e5c6ba0d3
|
@ -47,7 +47,7 @@ foreach ($dirs as $k => $dir) {
|
|||
if (isset($preferredInstall[$package->name]) && 'source' === $preferredInstall[$package->name]) {
|
||||
passthru("cd $dir && tar -cf package.tar --exclude='package.tar' *");
|
||||
} else {
|
||||
passthru("cd $dir && git init && git add . && git commit -m - && git archive -o package.tar HEAD && rm .git/ -Rf");
|
||||
passthru("cd $dir && git init && git add . && git commit --author \"Symfony <>\" -m - && git archive -o package.tar HEAD && rm .git/ -Rf");
|
||||
}
|
||||
|
||||
if (!isset($package->extra->{'branch-alias'}->{'dev-master'})) {
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
"doctrine/orm": "~2.4,>=2.4.5",
|
||||
"doctrine/reflection": "~1.0",
|
||||
"doctrine/doctrine-bundle": "^1.5|^2.0",
|
||||
"guzzlehttp/promises": "^1.3.1",
|
||||
"masterminds/html5": "^2.6",
|
||||
"monolog/monolog": "^1.25.1|^2",
|
||||
"nyholm/psr7": "^1.0",
|
||||
|
|
|
@ -68,7 +68,7 @@ class DbalLogger implements SQLLogger
|
|||
$this->logger->debug($message, $params);
|
||||
}
|
||||
|
||||
private function normalizeParams(array $params)
|
||||
private function normalizeParams(array $params): array
|
||||
{
|
||||
foreach ($params as $index => $param) {
|
||||
// normalize recursively
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
namespace Symfony\Bridge\Doctrine\Security\User;
|
||||
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\Common\Persistence\ObjectRepository;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
|
@ -124,17 +127,17 @@ class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInter
|
|||
}
|
||||
}
|
||||
|
||||
private function getObjectManager()
|
||||
private function getObjectManager(): ObjectManager
|
||||
{
|
||||
return $this->registry->getManager($this->managerName);
|
||||
}
|
||||
|
||||
private function getRepository()
|
||||
private function getRepository(): ObjectRepository
|
||||
{
|
||||
return $this->getObjectManager()->getRepository($this->classOrAlias);
|
||||
}
|
||||
|
||||
private function getClass()
|
||||
private function getClass(): string
|
||||
{
|
||||
if (null === $this->class) {
|
||||
$class = $this->classOrAlias;
|
||||
|
@ -149,7 +152,7 @@ class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInter
|
|||
return $this->class;
|
||||
}
|
||||
|
||||
private function getClassMetadata()
|
||||
private function getClassMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->getObjectManager()->getClassMetadata($this->classOrAlias);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,11 @@
|
|||
|
||||
namespace Symfony\Bridge\Doctrine\Tests\Security\User;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Common\Persistence\ObjectRepository;
|
||||
use Doctrine\ORM\Tools\SchemaTool;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\Doctrine\Security\User\EntityUserProvider;
|
||||
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
|
||||
use Symfony\Bridge\Doctrine\Test\DoctrineTestHelper;
|
||||
use Symfony\Bridge\Doctrine\Tests\Fixtures\User;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
|
@ -60,9 +61,7 @@ class EntityUserProviderTest extends TestCase
|
|||
{
|
||||
$user = new User(1, 1, 'user1');
|
||||
|
||||
$repository = $this->getMockBuilder('Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$repository = $this->createMock([ObjectRepository::class, UserLoaderInterface::class]);
|
||||
$repository
|
||||
->expects($this->once())
|
||||
->method('loadUserByUsername')
|
||||
|
@ -148,7 +147,7 @@ class EntityUserProviderTest extends TestCase
|
|||
|
||||
public function testLoadUserByUserNameShouldLoadUserWhenProperInterfaceProvided()
|
||||
{
|
||||
$repository = $this->getMockBuilder('\Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface')->getMock();
|
||||
$repository = $this->createMock([ObjectRepository::class, UserLoaderInterface::class]);
|
||||
$repository->expects($this->once())
|
||||
->method('loadUserByUsername')
|
||||
->with('name')
|
||||
|
@ -167,7 +166,7 @@ class EntityUserProviderTest extends TestCase
|
|||
public function testLoadUserByUserNameShouldDeclineInvalidInterface()
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$repository = $this->getMockBuilder(EntityRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$repository = $this->createMock(ObjectRepository::class);
|
||||
|
||||
$provider = new EntityUserProvider(
|
||||
$this->getManager($this->getObjectManager($repository)),
|
||||
|
@ -181,7 +180,7 @@ class EntityUserProviderTest extends TestCase
|
|||
{
|
||||
$user = new User(1, 1, 'user1');
|
||||
|
||||
$repository = $this->getMockBuilder(PasswordUpgraderInterface::class)->getMock();
|
||||
$repository = $this->createMock([ObjectRepository::class, PasswordUpgraderInterface::class]);
|
||||
$repository->expects($this->once())
|
||||
->method('upgradePassword')
|
||||
->with($user, 'foobar');
|
||||
|
|
|
@ -143,7 +143,7 @@ class ConsoleFormatter implements FormatterInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function castObject($v, array $a, Stub $s, bool $isNested)
|
||||
public function castObject($v, array $a, Stub $s, bool $isNested): array
|
||||
{
|
||||
if ($this->options['multiline']) {
|
||||
return $a;
|
||||
|
@ -157,7 +157,7 @@ class ConsoleFormatter implements FormatterInterface
|
|||
return $a;
|
||||
}
|
||||
|
||||
private function replacePlaceHolder(array $record)
|
||||
private function replacePlaceHolder(array $record): array
|
||||
{
|
||||
$message = $record['message'];
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ class ServerLogHandler extends AbstractHandler
|
|||
return $socket;
|
||||
}
|
||||
|
||||
private function formatRecord(array $record)
|
||||
private function formatRecord(array $record): string
|
||||
{
|
||||
if ($this->processors) {
|
||||
foreach ($this->processors as $processor) {
|
||||
|
|
|
@ -350,7 +350,7 @@ EOF
|
|||
return null;
|
||||
}
|
||||
|
||||
private function getPrettyMetadata(string $type, $entity, bool $decorated)
|
||||
private function getPrettyMetadata(string $type, $entity, bool $decorated): ?string
|
||||
{
|
||||
if ('tests' === $type) {
|
||||
return '';
|
||||
|
|
|
@ -112,7 +112,7 @@ EOF
|
|||
return $template;
|
||||
}
|
||||
|
||||
private function getFilesInfo(array $filenames)
|
||||
private function getFilesInfo(array $filenames): array
|
||||
{
|
||||
$filesInfo = [];
|
||||
foreach ($filenames as $filename) {
|
||||
|
|
|
@ -65,7 +65,7 @@ class UndefinedCallableHandler
|
|||
'workflow' => 'enable "framework.workflows"',
|
||||
];
|
||||
|
||||
public static function onUndefinedFilter(string $name)
|
||||
public static function onUndefinedFilter(string $name): bool
|
||||
{
|
||||
if (!isset(self::$filterComponents[$name])) {
|
||||
return false;
|
||||
|
@ -76,7 +76,7 @@ class UndefinedCallableHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
public static function onUndefinedFunction(string $name)
|
||||
public static function onUndefinedFunction(string $name): bool
|
||||
{
|
||||
if (!isset(self::$functionComponents[$name])) {
|
||||
return false;
|
||||
|
@ -87,7 +87,7 @@ class UndefinedCallableHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
private static function onUndefined($name, $type, $component)
|
||||
private static function onUndefined(string $name, string $type, string $component)
|
||||
{
|
||||
if (class_exists(FullStack::class) && isset(self::$fullStackEnable[$component])) {
|
||||
throw new SyntaxError(sprintf('Did you forget to %s? Unknown %s "%s".', self::$fullStackEnable[$component], $type, $name));
|
||||
|
|
|
@ -233,7 +233,7 @@ EOF
|
|||
return $this->containerBuilder = $container;
|
||||
}
|
||||
|
||||
private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden)
|
||||
private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden): string
|
||||
{
|
||||
$name = ltrim($name, '\\');
|
||||
|
||||
|
@ -253,7 +253,7 @@ EOF
|
|||
return $io->choice('Select one of the following services to display its information', $matchingServices);
|
||||
}
|
||||
|
||||
private function findServiceIdsContaining(ContainerBuilder $builder, string $name, bool $showHidden)
|
||||
private function findServiceIdsContaining(ContainerBuilder $builder, string $name, bool $showHidden): array
|
||||
{
|
||||
$serviceIds = $builder->getServiceIds();
|
||||
$foundServiceIds = $foundServiceIdsIgnoringBackslashes = [];
|
||||
|
@ -275,7 +275,7 @@ EOF
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function filterToServiceTypes($serviceId)
|
||||
public function filterToServiceTypes(string $serviceId): bool
|
||||
{
|
||||
// filter out things that could not be valid class names
|
||||
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^(?&V)(?:\\\\(?&V))*+(?: \$(?&V))?$/', $serviceId)) {
|
||||
|
|
|
@ -62,7 +62,7 @@ abstract class AbstractController implements ServiceSubscriberInterface
|
|||
* @internal
|
||||
* @required
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container)
|
||||
public function setContainer(ContainerInterface $container): ?ContainerInterface
|
||||
{
|
||||
$previous = $this->container;
|
||||
$this->container = $container;
|
||||
|
|
|
@ -187,7 +187,7 @@ EOF
|
|||
return base64_encode(random_bytes(30));
|
||||
}
|
||||
|
||||
private function getUserClass(InputInterface $input, SymfonyStyle $io)
|
||||
private function getUserClass(InputInterface $input, SymfonyStyle $io): string
|
||||
{
|
||||
if (null !== $userClass = $input->getArgument('user-class')) {
|
||||
return $userClass;
|
||||
|
|
|
@ -92,7 +92,7 @@ class GuardAuthenticationFactory implements SecurityFactoryInterface
|
|||
return [$providerId, $listenerId, $entryPointId];
|
||||
}
|
||||
|
||||
private function determineEntryPoint(?string $defaultEntryPointId, array $config)
|
||||
private function determineEntryPoint(?string $defaultEntryPointId, array $config): string
|
||||
{
|
||||
if ($defaultEntryPointId) {
|
||||
// explode if they've configured the entry_point, but there is already one
|
||||
|
|
|
@ -560,7 +560,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
}
|
||||
|
||||
// Parses user providers and returns an array of their ids
|
||||
private function createUserProviders(array $config, ContainerBuilder $container)
|
||||
private function createUserProviders(array $config, ContainerBuilder $container): array
|
||||
{
|
||||
$providerIds = [];
|
||||
foreach ($config['providers'] as $name => $provider) {
|
||||
|
@ -572,7 +572,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
}
|
||||
|
||||
// Parses a <provider> tag and returns the id for the related user provider service
|
||||
private function createUserDaoProvider(string $name, array $provider, ContainerBuilder $container)
|
||||
private function createUserDaoProvider(string $name, array $provider, ContainerBuilder $container): string
|
||||
{
|
||||
$name = $this->getUserProviderId($name);
|
||||
|
||||
|
@ -611,12 +611,12 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
throw new InvalidConfigurationException(sprintf('Unable to create definition for "%s" user provider', $name));
|
||||
}
|
||||
|
||||
private function getUserProviderId(string $name)
|
||||
private function getUserProviderId(string $name): string
|
||||
{
|
||||
return 'security.user.provider.concrete.'.strtolower($name);
|
||||
}
|
||||
|
||||
private function createExceptionListener(ContainerBuilder $container, array $config, string $id, ?string $defaultEntryPoint, bool $stateless)
|
||||
private function createExceptionListener(ContainerBuilder $container, array $config, string $id, ?string $defaultEntryPoint, bool $stateless): string
|
||||
{
|
||||
$exceptionListenerId = 'security.exception_listener.'.$id;
|
||||
$listener = $container->setDefinition($exceptionListenerId, new ChildDefinition('security.exception_listener'));
|
||||
|
@ -634,7 +634,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
return $exceptionListenerId;
|
||||
}
|
||||
|
||||
private function createSwitchUserListener(ContainerBuilder $container, string $id, array $config, string $defaultProvider, bool $stateless)
|
||||
private function createSwitchUserListener(ContainerBuilder $container, string $id, array $config, string $defaultProvider, bool $stateless): string
|
||||
{
|
||||
$userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider;
|
||||
|
||||
|
@ -654,7 +654,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
return $switchUserListenerId;
|
||||
}
|
||||
|
||||
private function createExpression(ContainerBuilder $container, string $expression)
|
||||
private function createExpression(ContainerBuilder $container, string $expression): Reference
|
||||
{
|
||||
if (isset($this->expressions[$id = '.security.expression.'.ContainerBuilder::hash($expression)])) {
|
||||
return $this->expressions[$id];
|
||||
|
@ -673,7 +673,7 @@ class SecurityExtension extends Extension implements PrependExtensionInterface
|
|||
return $this->expressions[$id] = new Reference($id);
|
||||
}
|
||||
|
||||
private function createRequestMatcher(ContainerBuilder $container, string $path = null, string $host = null, int $port = null, array $methods = [], array $ips = null, array $attributes = [])
|
||||
private function createRequestMatcher(ContainerBuilder $container, string $path = null, string $host = null, int $port = null, array $methods = [], array $ips = null, array $attributes = []): Reference
|
||||
{
|
||||
if ($methods) {
|
||||
$methods = array_map('strtoupper', (array) $methods);
|
||||
|
|
|
@ -42,7 +42,7 @@ EOF
|
|||
;
|
||||
}
|
||||
|
||||
protected function findFiles(string $filename)
|
||||
protected function findFiles(string $filename): iterable
|
||||
{
|
||||
if (0 === strpos($filename, '@')) {
|
||||
$dir = $this->getApplication()->getKernel()->locateResource($filename);
|
||||
|
|
|
@ -150,7 +150,7 @@ class TwigExtension extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
private function getBundleTemplatePaths(ContainerBuilder $container, array $config)
|
||||
private function getBundleTemplatePaths(ContainerBuilder $container, array $config): array
|
||||
{
|
||||
$bundleHierarchy = [];
|
||||
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
|
||||
|
@ -170,7 +170,7 @@ class TwigExtension extends Extension
|
|||
return $bundleHierarchy;
|
||||
}
|
||||
|
||||
private function normalizeBundleName(string $name)
|
||||
private function normalizeBundleName(string $name): string
|
||||
{
|
||||
if ('Bundle' === substr($name, -6)) {
|
||||
$name = substr($name, 0, -6);
|
||||
|
|
|
@ -391,7 +391,7 @@ class ProfilerController
|
|||
$this->profiler->disable();
|
||||
}
|
||||
|
||||
private function renderWithCspNonces(Request $request, string $template, array $variables, int $code = 200, array $headers = ['Content-Type' => 'text/html'])
|
||||
private function renderWithCspNonces(Request $request, string $template, array $variables, int $code = 200, array $headers = ['Content-Type' => 'text/html']): Response
|
||||
{
|
||||
$response = new Response('', $code, $headers);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Symfony\Bundle\WebProfilerBundle\Csp;
|
|||
*/
|
||||
class NonceGenerator
|
||||
{
|
||||
public function generate()
|
||||
public function generate(): string
|
||||
{
|
||||
return bin2hex(random_bytes(16));
|
||||
}
|
||||
|
|
|
@ -1641,23 +1641,6 @@ class ApplicationTest extends TestCase
|
|||
$this->assertStringContainsString('The foo:bar command', $tester->getDisplay());
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires function posix_isatty
|
||||
*/
|
||||
public function testCanCheckIfTerminalIsInteractive()
|
||||
{
|
||||
$application = new CustomDefaultCommandApplication();
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(['command' => 'help']);
|
||||
|
||||
$this->assertFalse($tester->getInput()->hasParameterOption(['--no-interaction', '-n']));
|
||||
|
||||
$inputStream = $tester->getInput()->getStream();
|
||||
$this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream));
|
||||
}
|
||||
|
||||
public function testRunLazyCommandService()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
|
|
@ -5,7 +5,7 @@ CHANGELOG
|
|||
-----
|
||||
|
||||
* added `StreamWrapper`
|
||||
* added `HttplugClient`
|
||||
* added `HttplugClient` with support for sync and async requests
|
||||
* added `max_duration` option
|
||||
* added support for NTLM authentication
|
||||
* added `$response->toStream()` to cast responses to regular PHP streams
|
||||
|
|
|
@ -76,17 +76,20 @@ class CachingHttpClient implements HttpClientInterface
|
|||
$request = Request::create($url, $method);
|
||||
$request->attributes->set('http_client_options', $options);
|
||||
|
||||
foreach ($options['headers'] as $name => $values) {
|
||||
foreach ($options['normalized_headers'] as $name => $values) {
|
||||
if ('cookie' !== $name) {
|
||||
$request->headers->set($name, $values);
|
||||
foreach ($values as $value) {
|
||||
$request->headers->set($name, substr($value, 2 + \strlen($name)), false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($values as $cookies) {
|
||||
foreach (explode('; ', $cookies) as $cookie) {
|
||||
foreach (explode('; ', substr($cookies, \strlen('Cookie: '))) as $cookie) {
|
||||
if ('' !== $cookie) {
|
||||
$cookie = explode('=', $cookie, 2);
|
||||
$request->cookies->set($cookie[0], $cookie[1] ?? null);
|
||||
$request->cookies->set($cookie[0], $cookie[1] ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,10 +199,21 @@ trait HttpClientTrait
|
|||
$normalizedHeaders = [];
|
||||
|
||||
foreach ($headers as $name => $values) {
|
||||
if (\is_object($values) && method_exists('__toString')) {
|
||||
$values = (string) $values;
|
||||
}
|
||||
|
||||
if (\is_int($name)) {
|
||||
if (!\is_string($values)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid value for header "%s": expected string, %s given.', $name, \gettype($values)));
|
||||
}
|
||||
[$name, $values] = explode(':', $values, 2);
|
||||
$values = [ltrim($values)];
|
||||
} elseif (!is_iterable($values)) {
|
||||
if (\is_object($values)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid value for header "%s": expected string, %s given.', $name, \get_class($values)));
|
||||
}
|
||||
|
||||
$values = (array) $values;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,31 +11,38 @@
|
|||
|
||||
namespace Symfony\Component\HttpClient;
|
||||
|
||||
use GuzzleHttp\Promise\Promise as GuzzlePromise;
|
||||
use Http\Client\Exception\NetworkException;
|
||||
use Http\Client\Exception\RequestException;
|
||||
use Http\Client\HttpClient;
|
||||
use Http\Client\HttpAsyncClient;
|
||||
use Http\Client\HttpClient as HttplugInterface;
|
||||
use Http\Message\RequestFactory;
|
||||
use Http\Message\StreamFactory;
|
||||
use Http\Message\UriFactory;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Client\NetworkExceptionInterface;
|
||||
use Psr\Http\Client\RequestExceptionInterface;
|
||||
use Http\Promise\Promise;
|
||||
use Http\Promise\RejectedPromise;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Nyholm\Psr7\Request;
|
||||
use Nyholm\Psr7\Uri;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseFactoryInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
||||
use Psr\Http\Message\StreamFactoryInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriFactoryInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use Symfony\Component\HttpClient\Response\HttplugPromise;
|
||||
use Symfony\Component\HttpClient\Response\ResponseTrait;
|
||||
use Symfony\Component\HttpClient\Response\StreamWrapper;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
|
||||
if (!interface_exists(HttpClient::class)) {
|
||||
if (!interface_exists(HttplugInterface::class)) {
|
||||
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/httplug" package is not installed. Try running "composer require php-http/httplug".');
|
||||
}
|
||||
|
||||
if (!interface_exists(ClientInterface::class)) {
|
||||
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "psr/http-client" package is not installed. Try running "composer require psr/http-client".');
|
||||
}
|
||||
|
||||
if (!interface_exists(RequestFactory::class)) {
|
||||
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/message-factory" package is not installed. Try running "composer require nyholm/psr7".');
|
||||
}
|
||||
|
@ -43,42 +50,166 @@ if (!interface_exists(RequestFactory::class)) {
|
|||
/**
|
||||
* An adapter to turn a Symfony HttpClientInterface into an Httplug client.
|
||||
*
|
||||
* Run "composer require psr/http-client" to install the base ClientInterface. Run
|
||||
* "composer require nyholm/psr7" to install an efficient implementation of response
|
||||
* Run "composer require nyholm/psr7" to install an efficient implementation of response
|
||||
* and stream factories with flex-provided autowiring aliases.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class HttplugClient implements HttpClient, RequestFactory, StreamFactory, UriFactory
|
||||
final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestFactory, StreamFactory, UriFactory
|
||||
{
|
||||
private $client;
|
||||
private $responseFactory;
|
||||
private $streamFactory;
|
||||
private $promisePool = [];
|
||||
private $pendingResponse;
|
||||
|
||||
public function __construct(HttpClientInterface $client = null, ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null)
|
||||
{
|
||||
$this->client = new Psr18Client($client, $responseFactory, $streamFactory);
|
||||
$this->client = $client ?? HttpClient::create();
|
||||
$this->responseFactory = $responseFactory;
|
||||
$this->streamFactory = $streamFactory ?? ($responseFactory instanceof StreamFactoryInterface ? $responseFactory : null);
|
||||
$this->promisePool = new \SplObjectStorage();
|
||||
|
||||
if (null !== $this->responseFactory && null !== $this->streamFactory) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!class_exists(Psr17Factory::class)) {
|
||||
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
||||
}
|
||||
|
||||
$psr17Factory = new Psr17Factory();
|
||||
$this->responseFactory = $this->responseFactory ?? $psr17Factory;
|
||||
$this->streamFactory = $this->streamFactory ?? $psr17Factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sendRequest(RequestInterface $request): ResponseInterface
|
||||
public function sendRequest(RequestInterface $request): Psr7ResponseInterface
|
||||
{
|
||||
try {
|
||||
return $this->client->sendRequest($request);
|
||||
} catch (RequestExceptionInterface $e) {
|
||||
throw new RequestException($e->getMessage(), $request, $e);
|
||||
} catch (NetworkExceptionInterface $e) {
|
||||
return $this->createPsr7Response($this->sendPsr7Request($request));
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
throw new NetworkException($e->getMessage(), $request, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return HttplugPromise
|
||||
*/
|
||||
public function sendAsyncRequest(RequestInterface $request): Promise
|
||||
{
|
||||
if (!class_exists(GuzzlePromise::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use "%s()" as the "guzzlehttp/promises" package is not installed. Try running "composer require guzzlehttp/promises".', __METHOD__));
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->sendPsr7Request($request, true);
|
||||
} catch (NetworkException $e) {
|
||||
return new RejectedPromise($e);
|
||||
}
|
||||
|
||||
$cancel = function () use ($response) {
|
||||
$response->cancel();
|
||||
unset($this->promisePool[$response]);
|
||||
};
|
||||
|
||||
$promise = new GuzzlePromise(function () use ($response) {
|
||||
$this->pendingResponse = $response;
|
||||
$this->wait();
|
||||
}, $cancel);
|
||||
|
||||
$this->promisePool[$response] = [$request, $promise];
|
||||
|
||||
return new HttplugPromise($promise, $cancel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve pending promises that complete before the timeouts are reached.
|
||||
*
|
||||
* When $maxDuration is null and $idleTimeout is reached, promises are rejected.
|
||||
*
|
||||
* @return int The number of remaining pending promises
|
||||
*/
|
||||
public function wait(float $maxDuration = null, float $idleTimeout = null): int
|
||||
{
|
||||
$pendingResponse = $this->pendingResponse;
|
||||
$this->pendingResponse = null;
|
||||
|
||||
if (null !== $maxDuration) {
|
||||
$startTime = microtime(true);
|
||||
$idleTimeout = max(0.0, min($maxDuration / 5, $idleTimeout ?? $maxDuration));
|
||||
$remainingDuration = $maxDuration;
|
||||
}
|
||||
|
||||
do {
|
||||
foreach ($this->client->stream($this->promisePool, $idleTimeout) as $response => $chunk) {
|
||||
try {
|
||||
if (null !== $maxDuration && $chunk->isTimeout()) {
|
||||
goto check_duration;
|
||||
}
|
||||
|
||||
if ($chunk->isFirst()) {
|
||||
// Deactivate throwing on 3/4/5xx
|
||||
$response->getStatusCode();
|
||||
}
|
||||
|
||||
if (!$chunk->isLast()) {
|
||||
goto check_duration;
|
||||
}
|
||||
|
||||
if ([$request, $promise] = $this->promisePool[$response] ?? null) {
|
||||
unset($this->promisePool[$response]);
|
||||
$promise->resolve($this->createPsr7Response($response, true));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
if ([$request, $promise] = $this->promisePool[$response] ?? null) {
|
||||
unset($this->promisePool[$response]);
|
||||
|
||||
if ($e instanceof TransportExceptionInterface) {
|
||||
$e = new NetworkException($e->getMessage(), $request, $e);
|
||||
}
|
||||
|
||||
$promise->reject($e);
|
||||
}
|
||||
}
|
||||
|
||||
if ($pendingResponse === $response) {
|
||||
return \count($this->promisePool);
|
||||
}
|
||||
|
||||
check_duration:
|
||||
if (null !== $maxDuration && $idleTimeout && $idleTimeout > $remainingDuration = max(0.0, $maxDuration - microtime(true) + $startTime)) {
|
||||
$idleTimeout = $remainingDuration / 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$count = \count($this->promisePool)) {
|
||||
return 0;
|
||||
}
|
||||
} while (null !== $maxDuration && 0 < $remainingDuration);
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createRequest($method, $uri, array $headers = [], $body = null, $protocolVersion = '1.1'): RequestInterface
|
||||
{
|
||||
$request = $this->client
|
||||
->createRequest($method, $uri)
|
||||
if ($this->responseFactory instanceof RequestFactoryInterface) {
|
||||
$request = $this->responseFactory->createRequest($method, $uri);
|
||||
} elseif (!class_exists(Request::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
||||
} else {
|
||||
$request = new Request($method, $uri);
|
||||
}
|
||||
|
||||
$request = $request
|
||||
->withProtocolVersion($protocolVersion)
|
||||
->withBody($this->createStream($body))
|
||||
;
|
||||
|
@ -100,27 +231,84 @@ final class HttplugClient implements HttpClient, RequestFactory, StreamFactory,
|
|||
}
|
||||
|
||||
if (\is_string($body ?? '')) {
|
||||
$body = $this->client->createStream($body ?? '');
|
||||
|
||||
if ($body->isSeekable()) {
|
||||
$body->seek(0);
|
||||
}
|
||||
|
||||
return $body;
|
||||
$stream = $this->streamFactory->createStream($body ?? '');
|
||||
} elseif (\is_resource($body)) {
|
||||
$stream = $this->streamFactory->createStreamFromResource($body);
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('%s() expects string, resource or StreamInterface, %s given.', __METHOD__, \gettype($body)));
|
||||
}
|
||||
|
||||
if (\is_resource($body)) {
|
||||
return $this->client->createStreamFromResource($body);
|
||||
if ($stream->isSeekable()) {
|
||||
$stream->seek(0);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('%s() expects string, resource or StreamInterface, %s given.', __METHOD__, \gettype($body)));
|
||||
return $stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createUri($uri = ''): UriInterface
|
||||
public function createUri($uri): UriInterface
|
||||
{
|
||||
return $uri instanceof UriInterface ? $uri : $this->client->createUri($uri);
|
||||
if ($uri instanceof UriInterface) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
if ($this->responseFactory instanceof UriFactoryInterface) {
|
||||
return $this->responseFactory->createUri($uri);
|
||||
}
|
||||
|
||||
if (!class_exists(Uri::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
|
||||
}
|
||||
|
||||
return new Uri($uri);
|
||||
}
|
||||
|
||||
private function sendPsr7Request(RequestInterface $request, bool $buffer = null): ResponseInterface
|
||||
{
|
||||
try {
|
||||
$body = $request->getBody();
|
||||
|
||||
if ($body->isSeekable()) {
|
||||
$body->seek(0);
|
||||
}
|
||||
|
||||
return $this->client->request($request->getMethod(), (string) $request->getUri(), [
|
||||
'headers' => $request->getHeaders(),
|
||||
'body' => $body->getContents(),
|
||||
'http_version' => '1.0' === $request->getProtocolVersion() ? '1.0' : null,
|
||||
'buffer' => $buffer,
|
||||
]);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
throw new RequestException($e->getMessage(), $request, $e);
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
throw new NetworkException($e->getMessage(), $request, $e);
|
||||
}
|
||||
}
|
||||
|
||||
private function createPsr7Response(ResponseInterface $response, bool $buffer = false): Psr7ResponseInterface
|
||||
{
|
||||
$psrResponse = $this->responseFactory->createResponse($response->getStatusCode());
|
||||
|
||||
foreach ($response->getHeaders(false) as $name => $values) {
|
||||
foreach ($values as $value) {
|
||||
$psrResponse = $psrResponse->withAddedHeader($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset(class_uses($response)[ResponseTrait::class])) {
|
||||
$body = $this->streamFactory->createStreamFromResource($response->toStream(false));
|
||||
} elseif (!$buffer) {
|
||||
$body = $this->streamFactory->createStreamFromResource(StreamWrapper::createResource($response, $this->client));
|
||||
} else {
|
||||
$body = $this->streamFactory->createStream($response->getContent(false));
|
||||
}
|
||||
|
||||
if ($body->isSeekable()) {
|
||||
$body->seek(0);
|
||||
}
|
||||
|
||||
return $psrResponse->withBody($body);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
<?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\HttpClient\Response;
|
||||
|
||||
use GuzzleHttp\Promise\PromiseInterface as GuzzlePromiseInterface;
|
||||
use Http\Promise\Promise as HttplugPromiseInterface;
|
||||
use Psr\Http\Message\ResponseInterface as Psr7ResponseInterface;
|
||||
|
||||
/**
|
||||
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class HttplugPromise implements HttplugPromiseInterface
|
||||
{
|
||||
private $promise;
|
||||
private $cancel;
|
||||
|
||||
public function __construct(GuzzlePromiseInterface $promise, callable $cancel = null)
|
||||
{
|
||||
$this->promise = $promise;
|
||||
$this->cancel = $cancel;
|
||||
}
|
||||
|
||||
public function then(callable $onFulfilled = null, callable $onRejected = null): self
|
||||
{
|
||||
return new self($this->promise->then($onFulfilled, $onRejected));
|
||||
}
|
||||
|
||||
public function cancel(): void
|
||||
{
|
||||
$this->promise->cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getState(): string
|
||||
{
|
||||
return $this->promise->getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return Psr7ResponseInterface|mixed
|
||||
*/
|
||||
public function wait($unwrap = true)
|
||||
{
|
||||
return $this->promise->wait($unwrap);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->cancel) {
|
||||
($this->cancel)();
|
||||
}
|
||||
}
|
||||
|
||||
public function __wakeup()
|
||||
{
|
||||
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\HttpClient\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpClient\CachingHttpClient;
|
||||
use Symfony\Component\HttpClient\MockHttpClient;
|
||||
use Symfony\Component\HttpClient\Response\MockResponse;
|
||||
use Symfony\Component\HttpKernel\HttpCache\Store;
|
||||
|
||||
class CachingHttpClientTest extends TestCase
|
||||
{
|
||||
public function testRequestHeaders()
|
||||
{
|
||||
$options = [
|
||||
'headers' => [
|
||||
'Application-Name' => 'test1234',
|
||||
'Test-Name-Header' => 'test12345',
|
||||
],
|
||||
];
|
||||
|
||||
$mockClient = new MockHttpClient();
|
||||
$store = new Store(sys_get_temp_dir().'/sf_http_cache');
|
||||
$client = new CachingHttpClient($mockClient, $store, $options);
|
||||
|
||||
$response = $client->request('GET', 'http://example.com/foo-bar');
|
||||
|
||||
rmdir(sys_get_temp_dir().'/sf_http_cache');
|
||||
self::assertInstanceOf(MockResponse::class, $response);
|
||||
self::assertSame($response->getRequestOptions()['normalized_headers']['application-name'][0], 'Application-Name: test1234');
|
||||
self::assertSame($response->getRequestOptions()['normalized_headers']['test-name-header'][0], 'Test-Name-Header: test12345');
|
||||
}
|
||||
}
|
|
@ -13,7 +13,9 @@ namespace Symfony\Component\HttpClient\Tests;
|
|||
|
||||
use Http\Client\Exception\NetworkException;
|
||||
use Http\Client\Exception\RequestException;
|
||||
use Http\Promise\Promise;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\HttpClient\HttplugClient;
|
||||
use Symfony\Component\HttpClient\NativeHttpClient;
|
||||
use Symfony\Contracts\HttpClient\Test\TestHttpServer;
|
||||
|
@ -41,6 +43,38 @@ class HttplugClientTest extends TestCase
|
|||
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
|
||||
}
|
||||
|
||||
public function testSendAsyncRequest()
|
||||
{
|
||||
$client = new HttplugClient(new NativeHttpClient());
|
||||
|
||||
$promise = $client->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8057'));
|
||||
$successCallableCalled = false;
|
||||
$failureCallableCalled = false;
|
||||
$promise->then(function (ResponseInterface $response) use (&$successCallableCalled) {
|
||||
$successCallableCalled = true;
|
||||
|
||||
return $response;
|
||||
}, function (\Exception $exception) use (&$failureCallableCalled) {
|
||||
$failureCallableCalled = true;
|
||||
|
||||
throw $exception;
|
||||
});
|
||||
|
||||
$this->assertEquals(Promise::PENDING, $promise->getState());
|
||||
|
||||
$response = $promise->wait(true);
|
||||
$this->assertTrue($successCallableCalled, '$promise->then() was never called.');
|
||||
$this->assertFalse($failureCallableCalled, 'Failure callable should not be called when request is successful.');
|
||||
$this->assertEquals(Promise::FULFILLED, $promise->getState());
|
||||
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$this->assertSame('application/json', $response->getHeaderLine('content-type'));
|
||||
|
||||
$body = json_decode((string) $response->getBody(), true);
|
||||
|
||||
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
|
||||
}
|
||||
|
||||
public function testPostRequest()
|
||||
{
|
||||
$client = new HttplugClient(new NativeHttpClient());
|
||||
|
@ -62,6 +96,32 @@ class HttplugClientTest extends TestCase
|
|||
$client->sendRequest($client->createRequest('GET', 'http://localhost:8058'));
|
||||
}
|
||||
|
||||
public function testAsyncNetworkException()
|
||||
{
|
||||
$client = new HttplugClient(new NativeHttpClient());
|
||||
|
||||
$promise = $client->sendAsyncRequest($client->createRequest('GET', 'http://localhost:8058'));
|
||||
$successCallableCalled = false;
|
||||
$failureCallableCalled = false;
|
||||
$promise->then(function (ResponseInterface $response) use (&$successCallableCalled) {
|
||||
$successCallableCalled = true;
|
||||
|
||||
return $response;
|
||||
}, function (\Exception $exception) use (&$failureCallableCalled) {
|
||||
$failureCallableCalled = true;
|
||||
|
||||
throw $exception;
|
||||
});
|
||||
|
||||
$promise->wait(false);
|
||||
$this->assertFalse($successCallableCalled, 'Success callable should not be called when request fails.');
|
||||
$this->assertTrue($failureCallableCalled, 'Failure callable was never called.');
|
||||
$this->assertEquals(Promise::REJECTED, $promise->getState());
|
||||
|
||||
$this->expectException(NetworkException::class);
|
||||
$promise->wait(true);
|
||||
}
|
||||
|
||||
public function testRequestException()
|
||||
{
|
||||
$client = new HttplugClient(new NativeHttpClient());
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"symfony/polyfill-php73": "^1.11"
|
||||
},
|
||||
"require-dev": {
|
||||
"guzzlehttp/promises": "^1.3.1",
|
||||
"nyholm/psr7": "^1.0",
|
||||
"php-http/httplug": "^1.0|^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
|
|
|
@ -16,6 +16,7 @@ CHANGELOG
|
|||
* `InMemoryTransport` handle acknowledged and rejected messages.
|
||||
* Made all dispatched worker event classes final.
|
||||
* Added support for `from_transport` attribute on `messenger.message_handler` tag.
|
||||
* Added support for passing `dbindex` as a query parameter to the redis transport DSN.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
|
|
@ -104,6 +104,15 @@ class ConnectionTest extends TestCase
|
|||
Connection::fromDsn('redis://password@localhost/queue', [], $redis);
|
||||
}
|
||||
|
||||
public function testDbIndex()
|
||||
{
|
||||
$redis = new \Redis();
|
||||
|
||||
Connection::fromDsn('redis://password@localhost/queue?dbindex=2', [], $redis);
|
||||
|
||||
$this->assertSame(2, $redis->getDbNum());
|
||||
}
|
||||
|
||||
public function testFirstGetPendingMessagesThenNewMessages()
|
||||
{
|
||||
$redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock();
|
||||
|
|
|
@ -32,6 +32,7 @@ class Connection
|
|||
'consumer' => 'consumer',
|
||||
'auto_setup' => true,
|
||||
'stream_max_entries' => 0, // any value higher than 0 defines an approximate maximum number of stream entries
|
||||
'dbindex' => 0,
|
||||
];
|
||||
|
||||
private $connection;
|
||||
|
@ -56,6 +57,10 @@ class Connection
|
|||
$this->connection->auth($connectionCredentials['auth']);
|
||||
}
|
||||
|
||||
if (($dbIndex = $configuration['dbindex'] ?? self::DEFAULT_OPTIONS['dbindex']) && !$this->connection->select($dbIndex)) {
|
||||
throw new InvalidArgumentException(sprintf('Redis connection failed: %s', $redis->getLastError()));
|
||||
}
|
||||
|
||||
$this->stream = $configuration['stream'] ?? self::DEFAULT_OPTIONS['stream'];
|
||||
$this->group = $configuration['group'] ?? self::DEFAULT_OPTIONS['group'];
|
||||
$this->consumer = $configuration['consumer'] ?? self::DEFAULT_OPTIONS['consumer'];
|
||||
|
@ -97,12 +102,19 @@ class Connection
|
|||
unset($redisOptions['stream_max_entries']);
|
||||
}
|
||||
|
||||
$dbIndex = null;
|
||||
if (\array_key_exists('dbindex', $redisOptions)) {
|
||||
$dbIndex = filter_var($redisOptions['dbindex'], FILTER_VALIDATE_INT);
|
||||
unset($redisOptions['dbindex']);
|
||||
}
|
||||
|
||||
return new self([
|
||||
'stream' => $stream,
|
||||
'group' => $group,
|
||||
'consumer' => $consumer,
|
||||
'auto_setup' => $autoSetup,
|
||||
'stream_max_entries' => $maxEntries,
|
||||
'dbindex' => $dbIndex,
|
||||
], $connectionCredentials, $redisOptions, $redis);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ EOF;
|
|||
|
||||
while (true) {
|
||||
try {
|
||||
$this->signalingException = new \RuntimeException('preg_match(): Compilation failed: regular expression is too large');
|
||||
$this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large');
|
||||
$compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions));
|
||||
|
||||
break;
|
||||
|
@ -349,7 +349,7 @@ EOF;
|
|||
$state->markTail = 0;
|
||||
|
||||
// if the regex is too large, throw a signaling exception to recompute with smaller chunk size
|
||||
set_error_handler(function ($type, $message) { throw 0 === strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); });
|
||||
set_error_handler(function ($type, $message) { throw false !== strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); });
|
||||
try {
|
||||
preg_match($state->regex, '');
|
||||
} finally {
|
||||
|
|
|
@ -197,6 +197,6 @@ class StaticPrefixCollection
|
|||
|
||||
public static function handleError($type, $msg)
|
||||
{
|
||||
return 0 === strpos($msg, 'preg_match(): Compilation failed: lookbehind assertion is not fixed length');
|
||||
return false !== strpos($msg, 'Compilation failed: lookbehind assertion is not fixed length');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ abstract class AbstractComparisonValidator extends ConstraintValidator
|
|||
}
|
||||
}
|
||||
|
||||
private function getPropertyAccessor()
|
||||
private function getPropertyAccessor(): PropertyAccessorInterface
|
||||
{
|
||||
if (null === $this->propertyAccessor) {
|
||||
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
|
||||
|
|
|
@ -50,7 +50,7 @@ class ExpressionValidator extends ConstraintValidator
|
|||
}
|
||||
}
|
||||
|
||||
private function getExpressionLanguage()
|
||||
private function getExpressionLanguage(): ExpressionLanguage
|
||||
{
|
||||
if (null === $this->expressionLanguage) {
|
||||
$this->expressionLanguage = new ExpressionLanguage();
|
||||
|
|
|
@ -208,7 +208,7 @@ class FileValidator extends ConstraintValidator
|
|||
* Convert the limit to the smallest possible number
|
||||
* (i.e. try "MB", then "kB", then "bytes").
|
||||
*/
|
||||
private function factorizeSizes(int $size, int $limit, bool $binaryFormat)
|
||||
private function factorizeSizes(int $size, int $limit, bool $binaryFormat): array
|
||||
{
|
||||
if ($binaryFormat) {
|
||||
$coef = self::MIB_BYTES;
|
||||
|
|
|
@ -225,7 +225,7 @@ class IbanValidator extends ConstraintValidator
|
|||
}
|
||||
}
|
||||
|
||||
private static function toBigInt($string)
|
||||
private static function toBigInt(string $string): string
|
||||
{
|
||||
$chars = str_split($string);
|
||||
$bigInt = '';
|
||||
|
@ -245,7 +245,7 @@ class IbanValidator extends ConstraintValidator
|
|||
return $bigInt;
|
||||
}
|
||||
|
||||
private static function bigModulo97($bigInt)
|
||||
private static function bigModulo97(string $bigInt): int
|
||||
{
|
||||
$parts = str_split($bigInt, 7);
|
||||
$rest = 0;
|
||||
|
|
|
@ -33,6 +33,6 @@ class ValidValidator extends ConstraintValidator
|
|||
$this->context
|
||||
->getValidator()
|
||||
->inContext($this->context)
|
||||
->validate($value, null, [$this->context->getGroup()]);
|
||||
->validate($value, null, $this->context->getGroup());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Context;
|
|||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintViolation;
|
||||
use Symfony\Component\Validator\ConstraintViolationList;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Symfony\Component\Validator\Mapping\ClassMetadataInterface;
|
||||
use Symfony\Component\Validator\Mapping\MemberMetadata;
|
||||
use Symfony\Component\Validator\Mapping\MetadataInterface;
|
||||
|
@ -21,6 +22,7 @@ use Symfony\Component\Validator\Mapping\PropertyMetadataInterface;
|
|||
use Symfony\Component\Validator\Util\PropertyPath;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Validator\Violation\ConstraintViolationBuilder;
|
||||
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
|
@ -188,7 +190,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildViolation(string $message, array $parameters = [])
|
||||
public function buildViolation(string $message, array $parameters = []): ConstraintViolationBuilderInterface
|
||||
{
|
||||
return new ConstraintViolationBuilder(
|
||||
$this->violations,
|
||||
|
@ -206,7 +208,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getViolations()
|
||||
public function getViolations(): ConstraintViolationListInterface
|
||||
{
|
||||
return $this->violations;
|
||||
}
|
||||
|
@ -214,7 +216,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getValidator()
|
||||
public function getValidator(): ValidatorInterface
|
||||
{
|
||||
return $this->validator;
|
||||
}
|
||||
|
@ -246,7 +248,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMetadata()
|
||||
public function getMetadata(): ?MetadataInterface
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
@ -254,12 +256,12 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGroup()
|
||||
public function getGroup(): ?string
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function getConstraint()
|
||||
public function getConstraint(): ?Constraint
|
||||
{
|
||||
return $this->constraint;
|
||||
}
|
||||
|
@ -267,7 +269,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getClassName()
|
||||
public function getClassName(): ?string
|
||||
{
|
||||
return $this->metadata instanceof MemberMetadata || $this->metadata instanceof ClassMetadataInterface ? $this->metadata->getClassName() : null;
|
||||
}
|
||||
|
@ -275,7 +277,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPropertyName()
|
||||
public function getPropertyName(): ?string
|
||||
{
|
||||
return $this->metadata instanceof PropertyMetadataInterface ? $this->metadata->getPropertyName() : null;
|
||||
}
|
||||
|
@ -283,7 +285,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPropertyPath(string $subPath = '')
|
||||
public function getPropertyPath(string $subPath = ''): string
|
||||
{
|
||||
return PropertyPath::append($this->propertyPath, $subPath);
|
||||
}
|
||||
|
@ -303,7 +305,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isGroupValidated(string $cacheKey, string $groupHash)
|
||||
public function isGroupValidated(string $cacheKey, string $groupHash): bool
|
||||
{
|
||||
return isset($this->validatedObjects[$cacheKey][$groupHash]);
|
||||
}
|
||||
|
@ -319,7 +321,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isConstraintValidated(string $cacheKey, string $constraintHash)
|
||||
public function isConstraintValidated(string $cacheKey, string $constraintHash): bool
|
||||
{
|
||||
return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]);
|
||||
}
|
||||
|
@ -335,7 +337,7 @@ class ExecutionContext implements ExecutionContextInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isObjectInitialized(string $cacheKey)
|
||||
public function isObjectInitialized(string $cacheKey): bool
|
||||
{
|
||||
return isset($this->initializedObjects[$cacheKey]);
|
||||
}
|
||||
|
|
|
@ -204,7 +204,7 @@
|
|||
</trans-unit>
|
||||
<trans-unit id="54">
|
||||
<source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
|
||||
<target>คอเล็กชั่นนี้ควรจะประกอบไปด้วยอ่างน้อย {{ limit }} สมาชิก</target>
|
||||
<target>คอเล็กชั่นนี้ควรจะประกอบไปด้วยอย่างน้อย {{ limit }} สมาชิก</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="55">
|
||||
<source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
|
||||
|
@ -298,6 +298,74 @@
|
|||
<source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
|
||||
<target>ภาพนี้เป็นแนวตั้ง ({{ width }}x{{ height }}px) ไม่อนุญาตภาพที่เป็นแนวตั้ง</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="78">
|
||||
<source>An empty file is not allowed.</source>
|
||||
<target>ไม่อนุญาตให้ใช้ไฟล์ว่าง</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="79">
|
||||
<source>The host could not be resolved.</source>
|
||||
<target>ไม่สามารถแก้ไขชื่อโฮสต์</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="80">
|
||||
<source>This value does not match the expected {{ charset }} charset.</source>
|
||||
<target>ค่านี้ไม่ตรงกับการเข้ารหัส {{ charset }}</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="81">
|
||||
<source>This is not a valid Business Identifier Code (BIC).</source>
|
||||
<target>นี่ไม่ถูกต้องตามรหัสสำหรับระบุธุรกิจนี้ (BIC)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="82">
|
||||
<source>Error</source>
|
||||
<target>เกิดข้อผิดพลาด</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="83">
|
||||
<source>This is not a valid UUID.</source>
|
||||
<target>นี่ไม่ใช่ UUID ที่ถูกต้อง</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="84">
|
||||
<source>This value should be a multiple of {{ compared_value }}.</source>
|
||||
<target>ค่านี้ควรเป็น {{ compared_value }} หลายตัว</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="85">
|
||||
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
|
||||
<target>รหัสสำหรับระบุธุรกิจนี้ (BIC) ไม่เกี่ยวข้องกับ IBAN {{ iban }}</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="86">
|
||||
<source>This value should be valid JSON.</source>
|
||||
<target>ค่านี้ควรอยู่ในรูปแบบ JSON ที่ถูกต้อง</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="87">
|
||||
<source>This collection should contain only unique elements.</source>
|
||||
<target>คอเล็กชั่นนี้ควรมีเฉพาะสมาชิกที่ไม่ซ้ำกันเท่านั้น</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="88">
|
||||
<source>This value should be positive.</source>
|
||||
<target>ค่านี้ควรเป็นค่าบวก</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="89">
|
||||
<source>This value should be either positive or zero.</source>
|
||||
<target>ค่านี้ควรเป็นค่าบวกหรือค่าศูนย์</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="90">
|
||||
<source>This value should be negative.</source>
|
||||
<target>ค่านี้ควรเป็นค่าลบ</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="91">
|
||||
<source>This value should be either negative or zero.</source>
|
||||
<target>ค่านี้ควรเป็นค่าลบหรือค่าศูนย์</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="92">
|
||||
<source>This value is not a valid timezone.</source>
|
||||
<target>ค่าเขตเวลาไม่ถูกต้อง</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="93">
|
||||
<source>This password has been leaked in a data breach, it must not be used. Please use another password.</source>
|
||||
<target>รหัสผ่านนี้ได้เคยรั่วไหลออกไปโดยถูกการละเมิดข้อมูล ซึ่งไม่ควรนำกลับมาใช้ กรุณาใช้รหัสผ่านอื่น</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="94">
|
||||
<source>This value should be between {{ min }} and {{ max }}.</source>
|
||||
<target>ค่านี้ควรอยู่ระหว่าง {{ min }} ถึง {{ max }}</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
|
@ -234,7 +234,7 @@ class ConstraintViolationAssertion
|
|||
private $constraint;
|
||||
private $cause;
|
||||
|
||||
public function __construct(ExecutionContextInterface $context, $message, Constraint $constraint = null, array $assertions = [])
|
||||
public function __construct(ExecutionContextInterface $context, string $message, Constraint $constraint = null, array $assertions = [])
|
||||
{
|
||||
$this->context = $context;
|
||||
$this->message = $message;
|
||||
|
@ -242,14 +242,14 @@ class ConstraintViolationAssertion
|
|||
$this->assertions = $assertions;
|
||||
}
|
||||
|
||||
public function atPath($path)
|
||||
public function atPath(string $path)
|
||||
{
|
||||
$this->propertyPath = $path;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setParameter($key, $value)
|
||||
public function setParameter(string $key, $value)
|
||||
{
|
||||
$this->parameters[$key] = $value;
|
||||
|
||||
|
@ -277,14 +277,14 @@ class ConstraintViolationAssertion
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setPlural($number)
|
||||
public function setPlural(int $number)
|
||||
{
|
||||
$this->plural = $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCode($code)
|
||||
public function setCode(string $code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
|
@ -298,7 +298,7 @@ class ConstraintViolationAssertion
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function buildNextViolation($message)
|
||||
public function buildNextViolation(string $message): self
|
||||
{
|
||||
$assertions = $this->assertions;
|
||||
$assertions[] = $this;
|
||||
|
@ -326,7 +326,7 @@ class ConstraintViolationAssertion
|
|||
}
|
||||
}
|
||||
|
||||
private function getViolation()
|
||||
private function getViolation(): ConstraintViolation
|
||||
{
|
||||
return new ConstraintViolation(
|
||||
$this->message,
|
||||
|
|
|
@ -31,6 +31,9 @@ final class Validation
|
|||
return self::createValidatorBuilder()->getValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configurable builder for validator objects.
|
||||
*/
|
||||
public static function createValidatorBuilder(): ValidatorBuilder
|
||||
{
|
||||
return new ValidatorBuilder();
|
||||
|
|
|
@ -8,6 +8,8 @@ CHANGELOG
|
|||
to configure casters & flags to use in tests
|
||||
* added `ImagineCaster` and infrastructure to dump images
|
||||
* added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data
|
||||
* added `UuidCaster`
|
||||
* made all casters final
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts Amqp related classes to array representation.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class AmqpCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts DOM related classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class DOMCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts DateTimeInterface related classes to array representation.
|
||||
*
|
||||
* @author Dany Maillard <danymaillard93b@gmail.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class DateCaster
|
||||
{
|
||||
|
@ -52,7 +54,7 @@ class DateCaster
|
|||
return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a;
|
||||
}
|
||||
|
||||
private static function formatInterval(\DateInterval $i)
|
||||
private static function formatInterval(\DateInterval $i): string
|
||||
{
|
||||
$format = '%R ';
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts Doctrine related classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class DoctrineCaster
|
||||
{
|
||||
|
|
|
@ -20,6 +20,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts Ds extension classes to array representation.
|
||||
*
|
||||
* @author Jáchym Toušek <enumag@gmail.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class DsCaster
|
||||
{
|
||||
|
|
|
@ -19,6 +19,8 @@ use Symfony\Component\VarDumper\Exception\ThrowingCasterException;
|
|||
* Casts common Exception classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class ExceptionCaster
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
*
|
||||
* @author Hamza Amrouche <hamza.simperfit@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class GmpCaster
|
||||
{
|
||||
|
|
|
@ -17,9 +17,9 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class ImagineCaster
|
||||
final class ImagineCaster
|
||||
{
|
||||
public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested)
|
||||
public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array
|
||||
{
|
||||
$imgData = $c->get('png');
|
||||
if (\strlen($imgData) > 1 * 1000 * 1000) {
|
||||
|
|
|
@ -16,6 +16,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
* @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class IntlCaster
|
||||
{
|
||||
|
|
|
@ -15,6 +15,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
|
||||
/**
|
||||
* @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class MemcachedCaster
|
||||
{
|
||||
|
@ -33,7 +35,7 @@ class MemcachedCaster
|
|||
return $a;
|
||||
}
|
||||
|
||||
private static function getNonDefaultOptions(\Memcached $c)
|
||||
private static function getNonDefaultOptions(\Memcached $c): array
|
||||
{
|
||||
self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions();
|
||||
self::$optionConstants = self::$optionConstants ?? self::getOptionConstants();
|
||||
|
@ -48,7 +50,7 @@ class MemcachedCaster
|
|||
return $nonDefaultOptions;
|
||||
}
|
||||
|
||||
private static function discoverDefaultOptions()
|
||||
private static function discoverDefaultOptions(): array
|
||||
{
|
||||
$defaultMemcached = new \Memcached();
|
||||
$defaultMemcached->addServer('127.0.0.1', 11211);
|
||||
|
@ -63,7 +65,7 @@ class MemcachedCaster
|
|||
return $defaultOptions;
|
||||
}
|
||||
|
||||
private static function getOptionConstants()
|
||||
private static function getOptionConstants(): array
|
||||
{
|
||||
$reflectedMemcached = new \ReflectionClass(\Memcached::class);
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts PDO related classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class PdoCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts pqsql resources to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class PgSqlCaster
|
||||
{
|
||||
|
|
|
@ -16,6 +16,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class ProxyManagerCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts Redis class from ext-redis to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class RedisCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts Reflector related classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class ReflectionCaster
|
||||
{
|
||||
|
@ -361,7 +363,7 @@ class ReflectionCaster
|
|||
return $signature;
|
||||
}
|
||||
|
||||
private static function addExtra(&$a, \Reflector $c)
|
||||
private static function addExtra(array &$a, \Reflector $c)
|
||||
{
|
||||
$x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : [];
|
||||
|
||||
|
@ -377,7 +379,7 @@ class ReflectionCaster
|
|||
}
|
||||
}
|
||||
|
||||
private static function addMap(&$a, \Reflector $c, $map, $prefix = Caster::PREFIX_VIRTUAL)
|
||||
private static function addMap(array &$a, \Reflector $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL)
|
||||
{
|
||||
foreach ($map as $k => $m) {
|
||||
if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) {
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts common resource types to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class ResourceCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts SPL related classes to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class SplCaster
|
||||
{
|
||||
|
|
|
@ -14,6 +14,9 @@ namespace Symfony\Component\VarDumper\Caster;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
|
||||
/**
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class SymfonyCaster
|
||||
{
|
||||
private static $requestGetters = [
|
||||
|
|
|
@ -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\VarDumper\Caster;
|
||||
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
final class UuidCaster
|
||||
{
|
||||
public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array
|
||||
{
|
||||
$a += [
|
||||
Caster::PREFIX_VIRTUAL.'uuid' => (string) $c,
|
||||
];
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts XmlReader class to array representation.
|
||||
*
|
||||
* @author Baptiste Clavié <clavie.b@gmail.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class XmlReaderCaster
|
||||
{
|
||||
|
|
|
@ -17,6 +17,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
|
|||
* Casts XML resources to array representation.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*
|
||||
* @final since Symfony 4.4
|
||||
*/
|
||||
class XmlResourceCaster
|
||||
{
|
||||
|
|
|
@ -89,6 +89,8 @@ abstract class AbstractCloner implements ClonerInterface
|
|||
|
||||
'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'],
|
||||
|
||||
'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'],
|
||||
|
||||
'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'],
|
||||
'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
|
|
|
@ -76,7 +76,7 @@ trait VarDumperTestTrait
|
|||
return rtrim($dumper->dump($data, true));
|
||||
}
|
||||
|
||||
private function prepareExpectation($expected, int $filter)
|
||||
private function prepareExpectation($expected, int $filter): string
|
||||
{
|
||||
if (!\is_string($expected)) {
|
||||
$expected = $this->getDump($expected, null, $filter);
|
||||
|
|
|
@ -61,7 +61,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function findPlaces(Definition $definition, Marking $marking = null)
|
||||
protected function findPlaces(Definition $definition, Marking $marking = null): array
|
||||
{
|
||||
$workflowMetadata = $definition->getMetadataStore();
|
||||
|
||||
|
@ -96,7 +96,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function findTransitions(Definition $definition)
|
||||
protected function findTransitions(Definition $definition): array
|
||||
{
|
||||
$workflowMetadata = $definition->getMetadataStore();
|
||||
|
||||
|
@ -124,7 +124,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function addPlaces(array $places)
|
||||
protected function addPlaces(array $places): string
|
||||
{
|
||||
$code = '';
|
||||
|
||||
|
@ -145,7 +145,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function addTransitions(array $transitions)
|
||||
protected function addTransitions(array $transitions): string
|
||||
{
|
||||
$code = '';
|
||||
|
||||
|
@ -159,7 +159,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function findEdges(Definition $definition)
|
||||
protected function findEdges(Definition $definition): array
|
||||
{
|
||||
$workflowMetadata = $definition->getMetadataStore();
|
||||
|
||||
|
@ -192,7 +192,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function addEdges(array $edges)
|
||||
protected function addEdges(array $edges): string
|
||||
{
|
||||
$code = '';
|
||||
|
||||
|
@ -216,7 +216,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function startDot(array $options)
|
||||
protected function startDot(array $options): string
|
||||
{
|
||||
return sprintf("digraph workflow {\n %s\n node [%s];\n edge [%s];\n\n",
|
||||
$this->addOptions($options['graph']),
|
||||
|
@ -228,7 +228,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function endDot()
|
||||
protected function endDot(): string
|
||||
{
|
||||
return "}\n";
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ class GraphvizDumper implements DumperInterface
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function dotize(string $id)
|
||||
protected function dotize(string $id): string
|
||||
{
|
||||
return hash('sha1', $id);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class StateMachineGraphvizDumper extends GraphvizDumper
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function findEdges(Definition $definition)
|
||||
protected function findEdges(Definition $definition): array
|
||||
{
|
||||
$workflowMetadata = $definition->getMetadataStore();
|
||||
|
||||
|
@ -82,7 +82,7 @@ class StateMachineGraphvizDumper extends GraphvizDumper
|
|||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected function addEdges(array $edges)
|
||||
protected function addEdges(array $edges): string
|
||||
{
|
||||
$code = '';
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ class Workflow implements WorkflowInterface
|
|||
return $this->definition->getMetadataStore();
|
||||
}
|
||||
|
||||
private function buildTransitionBlockerListForTransition(object $subject, Marking $marking, Transition $transition)
|
||||
private function buildTransitionBlockerListForTransition(object $subject, Marking $marking, Transition $transition): TransitionBlockerList
|
||||
{
|
||||
foreach ($transition->getFroms() as $place) {
|
||||
if (!$marking->has($place)) {
|
||||
|
|
|
@ -130,7 +130,7 @@ EOF
|
|||
return ['file' => $file, 'valid' => true];
|
||||
}
|
||||
|
||||
private function display(SymfonyStyle $io, array $files)
|
||||
private function display(SymfonyStyle $io, array $files): int
|
||||
{
|
||||
switch ($this->format) {
|
||||
case 'txt':
|
||||
|
@ -142,7 +142,7 @@ EOF
|
|||
}
|
||||
}
|
||||
|
||||
private function displayTxt(SymfonyStyle $io, array $filesInfo)
|
||||
private function displayTxt(SymfonyStyle $io, array $filesInfo): int
|
||||
{
|
||||
$countFiles = \count($filesInfo);
|
||||
$erroredFiles = 0;
|
||||
|
@ -171,7 +171,7 @@ EOF
|
|||
return min($erroredFiles, 1);
|
||||
}
|
||||
|
||||
private function displayJson(SymfonyStyle $io, array $filesInfo)
|
||||
private function displayJson(SymfonyStyle $io, array $filesInfo): int
|
||||
{
|
||||
$errors = 0;
|
||||
|
||||
|
@ -191,7 +191,7 @@ EOF
|
|||
return min($errors, 1);
|
||||
}
|
||||
|
||||
private function getFiles(string $fileOrDirectory)
|
||||
private function getFiles(string $fileOrDirectory): iterable
|
||||
{
|
||||
if (is_file($fileOrDirectory)) {
|
||||
yield new \SplFileInfo($fileOrDirectory);
|
||||
|
@ -218,7 +218,7 @@ EOF
|
|||
return $yaml;
|
||||
}
|
||||
|
||||
private function getParser()
|
||||
private function getParser(): Parser
|
||||
{
|
||||
if (!$this->parser) {
|
||||
$this->parser = new Parser();
|
||||
|
@ -227,7 +227,7 @@ EOF
|
|||
return $this->parser;
|
||||
}
|
||||
|
||||
private function getDirectoryIterator(string $directory)
|
||||
private function getDirectoryIterator(string $directory): iterable
|
||||
{
|
||||
$default = function ($directory) {
|
||||
return new \RecursiveIteratorIterator(
|
||||
|
@ -243,7 +243,7 @@ EOF
|
|||
return $default($directory);
|
||||
}
|
||||
|
||||
private function isReadable(string $fileOrDirectory)
|
||||
private function isReadable(string $fileOrDirectory): bool
|
||||
{
|
||||
$default = function ($fileOrDirectory) {
|
||||
return is_readable($fileOrDirectory);
|
||||
|
|
|
@ -1134,7 +1134,7 @@ class Parser
|
|||
throw new ParseException(sprintf('Tags support is not enabled. You must use the flag "Yaml::PARSE_CUSTOM_TAGS" to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename);
|
||||
}
|
||||
|
||||
private function parseQuotedString($yaml)
|
||||
private function parseQuotedString(string $yaml): ?string
|
||||
{
|
||||
if ('' === $yaml || ('"' !== $yaml[0] && "'" !== $yaml[0])) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a quoted string.', $yaml));
|
||||
|
@ -1223,7 +1223,7 @@ class Parser
|
|||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
private function lexInlineSequence($yaml)
|
||||
private function lexInlineSequence(string $yaml): string
|
||||
{
|
||||
if ('' === $yaml || '[' !== $yaml[0]) {
|
||||
throw new \InvalidArgumentException(sprintf('"%s" is not a sequence.', $yaml));
|
||||
|
|
Reference in New Issue